--- a/src/client.py Fri Mar 08 10:05:28 2013 -0800
+++ b/src/client.py Mon Mar 11 15:15:21 2013 -0700
@@ -21,7 +21,7 @@
#
#
-# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -72,6 +72,7 @@
import pkg.client.progress as progress
import pkg.client.linkedimage as li
import pkg.client.publisher as publisher
+ import pkg.client.options as options
import pkg.fmri as fmri
import pkg.misc as misc
import pkg.pipeutils as pipeutils
@@ -625,16 +626,16 @@
elif global_settings.client_output_quiet:
progresstracker = progress.QuietProgressTracker()
elif global_settings.client_output_progfd:
- # This logic handles linked images: for linked children
- # we elide the progress output.
+ # This logic handles linked images: for linked children
+ # we elide the progress output.
output_file = os.fdopen(global_settings.client_output_progfd,
- "w")
+ "w")
child_tracker = progress.LinkedChildProgressTracker(
output_file=output_file)
- dot_tracker = progress.DotProgressTracker(
- output_file=output_file)
- progresstracker = progress.MultiProgressTracker(
- [child_tracker, dot_tracker])
+ dot_tracker = progress.DotProgressTracker(
+ output_file=output_file)
+ progresstracker = progress.MultiProgressTracker(
+ [child_tracker, dot_tracker])
else:
try:
progresstracker = progress.FancyUNIXProgressTracker()
@@ -1039,12 +1040,12 @@
bool_str(plan.update_boot_archive)))
# Right-justify all status strings based on length of longest string.
- if status:
- rjust_status = max(len(s[0]) for s in status)
- rjust_value = max(len(s[1]) for s in status)
- for s in status:
- logger.info("%s %s" % (s[0].rjust(rjust_status),
- s[1].rjust(rjust_value)))
+ if status:
+ rjust_status = max(len(s[0]) for s in status)
+ rjust_value = max(len(s[1]) for s in status)
+ for s in status:
+ logger.info("%s %s" % (s[0].rjust(rjust_status),
+ s[1].rjust(rjust_value)))
# Ensure there is a blank line between status information and
# remainder.
logger.info("")
@@ -1804,627 +1805,6 @@
return ret_code
-def opts_err_opt1_req_opt2(opt1, opt2, op):
- txt = _("%(opt1)s may only be used in combination with %(opt2)s") % \
- {"opt1": opt1, "opt2": opt2}
- usage(txt, cmd=op)
-
-def opts_err_incompat(opt1, opt2, op):
- txt = _("the %(opt1)s and %(opt2)s options may not be combined") % \
- {"opt1": opt1, "opt2": opt2}
- usage(txt, cmd=op)
-
-def opts_err_repeated(opt1, op):
- txt = _("option '%s' repeated") % (opt1)
- usage(txt, cmd=op)
-
-def opts_table_cb_beopts(op, api_inst, opts, opts_new):
-
- # synthesize require_new_be and deny_new_be into new_be
- del opts_new["require_new_be"]
- del opts_new["deny_new_be"]
- opts_new["new_be"] = None
-
- if (opts["be_name"] or opts["require_new_be"]) and opts["deny_new_be"]:
- opts_err_incompat("--require-new-be", "--deny-new-be", op)
-
- # create a new key called "backup_be" in the options array
- if opts["require_new_be"] or opts["be_name"]:
- opts_new["new_be"] = True
- if opts["deny_new_be"]:
- opts_new["new_be"] = False
-
- # synthesize require_backup_be and no_backup_be into backup_be
- del opts_new["require_backup_be"]
- del opts_new["no_backup_be"]
- opts_new["backup_be"] = None
-
- if (opts["require_backup_be"] or opts["backup_be_name"]) and \
- opts["no_backup_be"]:
- opts_err_incompat("--require-backup-be", "--no-backup-be", op)
-
- if (opts["require_backup_be"] or opts["backup_be_name"]) and \
- (opts["require_new_be"] or opts["be_name"]):
- opts_err_incompat("--require-backup-be", "--require-new-be", op)
-
- # create a new key called "backup_be" in the options array
- if opts["require_backup_be"] or opts["backup_be_name"]:
- opts_new["backup_be"] = True
- if opts["no_backup_be"]:
- opts_new["backup_be"] = False
-
-def opts_table_cb_li_ignore(op, api_inst, opts, opts_new):
-
- # synthesize li_ignore_all and li_ignore_list into li_ignore
- del opts_new["li_ignore_all"]
- del opts_new["li_ignore_list"]
- opts_new["li_ignore"] = None
-
- # check if there's nothing to ignore
- if not opts["li_ignore_all"] and not opts["li_ignore_list"]:
- return
-
- if opts["li_ignore_all"]:
-
- # can't ignore all and specific images
- if opts["li_ignore_list"]:
- opts_err_incompat("-I", "-i", op)
-
- # can't ignore all and target anything.
- if "li_target_all" in opts and opts["li_target_all"]:
- opts_err_incompat("-I", "-a", op)
- if "li_target_list" in opts and opts["li_target_list"]:
- opts_err_incompat("-I", "-l", op)
- if "li_name" in opts and opts["li_name"]:
- opts_err_incompat("-I", "-l", op)
-
- opts_new["li_ignore"] = []
- return
-
- assert opts["li_ignore_list"]
-
- # it doesn't make sense to specify images to ignore if the
- # user is already specifying images to operate on.
- if "li_target_all" in opts and opts["li_target_all"]:
- opts_err_incompat("-i", "-a", op)
- if "li_target_list" in opts and opts["li_target_list"]:
- opts_err_incompat("-i", "-l", op)
- if "li_name" in opts and opts["li_name"]:
- opts_err_incompat("-i", "-l", op)
-
- li_ignore = []
- for li_name in opts["li_ignore_list"]:
- # check for repeats
- if li_name in li_ignore:
- opts_err_repeated("-i %s" % (li_name), op)
- # add to ignore list
- li_ignore.append(li_name)
-
- opts_new["li_ignore"] = api_inst.parse_linked_name_list(li_ignore)
-
-def opts_table_cb_li_no_psync(op, api_inst, opts, opts_new):
- # if a target child linked image was specified, the no-parent-sync
- # option doesn't make sense since we know that both the parent and
- # child image are accessible
-
- if "li_target_all" not in opts:
- # we don't accept linked image target options
- assert "li_target_list" not in opts
- return
-
- if opts["li_target_all"] and not opts["li_parent_sync"]:
- opts_err_incompat("-a", "--no-parent-sync", op)
- if opts["li_target_list"] and not opts["li_parent_sync"]:
- opts_err_incompat("-l", "--no-parent-sync", op)
-
-def opts_table_cb_li_props(op, api_inst, opts, opts_new):
- """convert linked image prop list into a dictionary"""
-
- opts_new["li_props"] = __parse_linked_props(opts["li_props"], op)
-
-def opts_table_cb_li_target(op, api_inst, opts, opts_new):
- # figure out which option the user specified
- if opts["li_target_all"] and opts["li_target_list"]:
- opts_err_incompat("-a", "-l", op)
- elif opts["li_target_all"]:
- arg1 = "-a"
- elif opts["li_target_list"]:
- arg1 = "-l"
- else:
- return
-
- if "be_activate" in opts and not opts["be_activate"]:
- opts_err_incompat(arg1, "--no-be-activate", op)
- if "be_name" in opts and opts["be_name"]:
- opts_err_incompat(arg1, "--be-name", op)
- if "deny_new_be" in opts and opts["deny_new_be"]:
- opts_err_incompat(arg1, "--deny-new-be", op)
- if "require_new_be" in opts and opts["require_new_be"]:
- opts_err_incompat(arg1, "--require-new-be", op)
- if "reject_pats" in opts and opts["reject_pats"]:
- opts_err_incompat(arg1, "--reject", op)
- if "origins" in opts and opts["origins"]:
- opts_err_incompat(arg1, "-g", op)
-
- # validate linked image name
- li_target_list = []
- for li_name in opts["li_target_list"]:
- # check for repeats
- if li_name in li_target_list:
- opts_err_repeated("-l %s" % (li_name), op)
- # add to ignore list
- li_target_list.append(li_name)
-
- opts_new["li_target_list"] = \
- api_inst.parse_linked_name_list(li_target_list)
-
-def opts_table_cb_li_target1(op, api_inst, opts, opts_new):
- # figure out which option the user specified
- if opts["li_name"]:
- arg1 = "-l"
- else:
- return
-
- if "be_activate" in opts and not opts["be_activate"]:
- opts_err_incompat(arg1, "--no-be-activate", op)
- if "be_name" in opts and opts["be_name"]:
- opts_err_incompat(arg1, "--be-name", op)
- if "deny_new_be" in opts and opts["deny_new_be"]:
- opts_err_incompat(arg1, "--deny-new-be", op)
- if "require_new_be" in opts and opts["require_new_be"]:
- opts_err_incompat(arg1, "--require-new-be", op)
- if "reject_pats" in opts and opts["reject_pats"]:
- opts_err_incompat(arg1, "--require", op)
- if "origins" in opts and opts["origins"]:
- opts_err_incompat(arg1, "-g", op)
-
-def opts_table_cb_no_headers_vs_quiet(op, api_inst, opts, opts_new):
- # check if we accept the -q option
- if "quiet" not in opts:
- return
-
- # -q implies -H
- if opts["quiet"]:
- opts_new["omit_headers"] = True
-
-def opts_table_cb_q(op, api_inst, opts, opts_new):
- # Be careful not to overwrite global_settings.client_output_quiet
- # because it might be set "True" from elsewhere, e.g. in
- # opts_table_cb_parsable.
- if opts["quiet"] is True:
- global_settings.client_output_quiet = True
-
-def opts_table_cb_v(op, api_inst, opts, opts_new):
- global_settings.client_output_verbose = opts["verbose"]
-
-def opts_table_cb_nqv(op, api_inst, opts, opts_new):
- if opts["verbose"] and opts["quiet"]:
- opts_err_incompat("-v", "-q", op)
-
-def opts_table_cb_parsable(op, api_inst, opts, opts_new):
- if opts["parsable_version"] and opts.get("verbose", False):
- opts_err_incompat("--parsable", "-v", op)
- if opts["parsable_version"]:
- try:
- opts_new["parsable_version"] = int(
- opts["parsable_version"])
- except ValueError:
- usage(_("--parsable expects an integer argument."),
- cmd=op)
- global_settings.client_output_parsable_version = \
- opts_new["parsable_version"]
- opts_new["quiet"] = True
- global_settings.client_output_quiet = True
-
-def opts_table_cb_origins(op, api_inst, opts, opts_new):
- origins = set()
- for o in opts["origins"]:
- origins.add(misc.parse_uri(o, cwd=orig_cwd))
- opts_new["origins"] = origins
-
-def opts_table_cb_stage(op, api_inst, opts, opts_new):
- if opts["stage"] == None:
- opts_new["stage"] = API_STAGE_DEFAULT
- return
-
- if opts_new["stage"] not in api_stage_values:
- usage(_("invalid operation stage: '%s'") % opts["stage"],
- cmd=op)
-
-def opts_cb_li_attach(op, api_inst, opts, opts_new):
- if opts["attach_parent"] and opts["attach_child"]:
- opts_err_incompat("-c", "-p", op)
-
- if not opts["attach_parent"] and not opts["attach_child"]:
- usage(_("either -c or -p must be specified"), cmd=op)
-
- if opts["attach_child"]:
- # if we're attaching a new child then that doesn't affect
- # any other children, so ignoring them doesn't make sense.
- if opts["li_ignore_all"]:
- opts_err_incompat("-c", "-I", op)
- if opts["li_ignore_list"]:
- opts_err_incompat("-c", "-i", op)
-
-def opts_table_cb_md_only(op, api_inst, opts, opts_new):
- # if the user didn't specify linked-md-only we're done
- if not opts["li_md_only"]:
- return
-
- # li_md_only implies no li_pkg_updates
- if "li_pkg_updates" in opts:
- opts_new["li_pkg_updates"] = False
-
- #
- # if li_md_only is false that means we're not updating any packages
- # within the current image so there are a ton of options that no
- # longer apply to the current operation, and hence are incompatible
- # with li_md_only.
- #
- arg1 = "--linked-md-only"
- if "be_name" in opts and opts["be_name"]:
- opts_err_incompat(arg1, "--be-name", op)
- if "deny_new_be" in opts and opts["deny_new_be"]:
- opts_err_incompat(arg1, "--deny-new-be", op)
- if "require_new_be" in opts and opts["require_new_be"]:
- opts_err_incompat(arg1, "--require-new-be", op)
- if "li_parent_sync" in opts and not opts["li_parent_sync"]:
- opts_err_incompat(arg1, "--no-parent-sync", op)
- if "reject_pats" in opts and opts["reject_pats"]:
- opts_err_incompat(arg1, "--reject", op)
-
-def opts_cb_list(op, api_inst, opts, opts_new):
- if opts_new["origins"] and opts_new["list_upgradable"]:
- opts_err_incompat("-g", "-u", op)
-
- if opts_new["origins"] and not opts_new["list_newest"]:
- # Use of -g implies -a unless -n is provided.
- opts_new["list_installed_newest"] = True
-
- if opts_new["list_all"] and not opts_new["list_installed_newest"]:
- opts_err_opt1_req_opt2("-f", "-a", op)
-
- if opts_new["list_installed_newest"] and opts_new["list_newest"]:
- opts_err_incompat("-a", "-n", op)
-
- if opts_new["list_installed_newest"] and opts_new["list_upgradable"]:
- opts_err_incompat("-a", "-u", op)
-
- if opts_new["summary"] and opts_new["verbose"]:
- opts_err_incompat("-s", "-v", op)
-
-def opts_cb_int(k, op, api_inst, opts, opts_new, minimum=None):
- if k not in opts:
- usage(_("missing required parameter: %s" % k), cmd=op)
- return
-
- # get the original argument value
- v = opts[k]
-
- # make sure it is an integer
- try:
- v = int(v)
- except (ValueError, TypeError):
- # not a valid integer
- err = _("invalid '%(opt)s' value: %(val)s") % \
- {"opt": k, "val": v}
- usage(err, cmd=op)
-
- # check the minimum bounds
- if minimum is not None and v < minimum:
- err = _("'%(opt)s' must be >= %(minimum)d") % \
- {"opt": k, "minimum": minimum}
- usage(err, cmd=op)
-
- # update the new options array to make the value an integer
- opts_new[k] = v
-
-def opts_cb_fd(k, op, api_inst, opts, opts_new):
- opts_cb_int(k, op, api_inst, opts, opts_new, minimum=0)
-
- err = _("invalid '%(opt)s' value: %(optval)s") % \
- {"opt": k, "optval": opts_new[k]}
- try:
- os.fstat(opts_new[k])
- except OSError:
- # not a valid file descriptor
- usage(err, cmd=op)
-
-def opts_cb_remote(op, api_inst, opts, opts_new):
- opts_cb_fd("ctlfd", op, api_inst, opts, opts_new)
- opts_cb_fd("progfd", op, api_inst, opts, opts_new)
-
- # move progfd from opts_new into a global
- global_settings.client_output_progfd = opts_new["progfd"]
- del opts_new["progfd"]
-
-def opts_table_cb_concurrency(op, api_inst, opts, opts_new):
- if opts["concurrency"] is None:
- # remove concurrency from parameters dict
- del opts_new["concurrency"]
- return
-
- # make sure we have an integer
- opts_cb_int("concurrency", op, api_inst, opts, opts_new)
-
- # update global concurrency setting
- global_settings.client_concurrency = opts_new["concurrency"]
-
- # remove concurrency from parameters dict
- del opts_new["concurrency"]
-
-#
-# options common to multiple pkg(1) subcommands. The format for specifying
-# options is a list which can contain:
-#
-# - Function pointers which define callbacks that are invoked after all
-# options (aside from extra pargs) have been parsed. These callbacks can
-# verify the the contents and combinations of different options.
-#
-# - Tuples formatted as:
-# (s, l, k, v)
-# where the values are:
-# s: a short option, ex: -f
-# l: a long option, ex: --foo
-# k: the key value for the options dictionary
-# v: the default value. valid values are: True/False, None, [], 0
-#
-opts_table_beopts = [
- opts_table_cb_beopts,
- ("", "backup-be-name=", "backup_be_name", None),
- ("", "be-name=", "be_name", None),
- ("", "deny-new-be", "deny_new_be", False),
- ("", "no-backup-be", "no_backup_be", False),
- ("", "no-be-activate", "be_activate", True),
- ("", "require-backup-be", "require_backup_be", False),
- ("", "require-new-be", "require_new_be", False),
-]
-
-opts_table_concurrency = [
- opts_table_cb_concurrency,
- ("C", "concurrency=", "concurrency", None),
-]
-
-opts_table_force = [
- ("f", "", "force", False),
-]
-
-opts_table_li_ignore = [
- opts_table_cb_li_ignore,
- ("I", "", "li_ignore_all", False),
- ("i", "", "li_ignore_list", []),
-]
-
-opts_table_li_md_only = [
- opts_table_cb_md_only,
- ("", "linked-md-only", "li_md_only", False),
-]
-
-opts_table_li_no_pkg_updates = [
- ("", "no-pkg-updates", "li_pkg_updates", True),
-]
-
-opts_table_li_no_psync = [
- opts_table_cb_li_no_psync,
- ("", "no-parent-sync", "li_parent_sync", True),
-]
-
-opts_table_li_props = [
- opts_table_cb_li_props,
- ("", "prop-linked", "li_props", []),
-]
-
-opts_table_li_target = [
- opts_table_cb_li_target,
- ("a", "", "li_target_all", False),
- ("l", "", "li_target_list", []),
-]
-
-opts_table_li_target1 = [
- opts_table_cb_li_target1,
- ("l", "", "li_name", None),
-]
-
-opts_table_licenses = [
- ("", "accept", "accept", False),
- ("", "licenses", "show_licenses", False),
-]
-
-opts_table_no_headers = [
- opts_table_cb_no_headers_vs_quiet,
- ("H", "", "omit_headers", False),
-]
-
-opts_table_no_index = [
- ("", "no-index", "update_index", True),
-]
-
-opts_table_no_refresh = [
- ("", "no-refresh", "refresh_catalogs", True),
-]
-
-opts_table_reject = [
- ("", "reject=", "reject_pats", []),
-]
-
-opts_table_verbose = [
- opts_table_cb_v,
- ("v", "", "verbose", 0),
-]
-
-opts_table_quiet = [
- opts_table_cb_q,
- ("q", "", "quiet", False),
-]
-
-opts_table_parsable = [
- opts_table_cb_parsable,
- ("", "parsable=", "parsable_version", None),
-]
-
-opts_table_nqv = \
- opts_table_quiet + \
- opts_table_verbose + \
- [
- opts_table_cb_nqv,
- ("n", "", "noexecute", False),
-]
-
-opts_table_origins = [
- opts_table_cb_origins,
- ("g", "", "origins", []),
-]
-
-opts_table_stage = [
- opts_table_cb_stage,
- ("", "stage", "stage", None),
-]
-
-#
-# Options for pkg(1) subcommands. Built by combining the option tables above,
-# with some optional subcommand unique options defined below.
-#
-opts_install = \
- opts_table_beopts + \
- opts_table_concurrency + \
- opts_table_li_ignore + \
- opts_table_li_no_psync + \
- opts_table_licenses + \
- opts_table_reject + \
- opts_table_no_index + \
- opts_table_no_refresh + \
- opts_table_nqv + \
- opts_table_parsable + \
- opts_table_origins + \
- []
-
-# "update" cmd inherits all "install" cmd options
-opts_update = \
- opts_install + \
- opts_table_force + \
- opts_table_stage + \
- []
-
-# "attach-linked" cmd inherits all "install" cmd options
-opts_attach_linked = \
- opts_install + \
- opts_table_force + \
- opts_table_li_md_only + \
- opts_table_li_no_pkg_updates + \
- opts_table_li_props + \
- [
- opts_cb_li_attach,
- ("", "allow-relink", "allow_relink", False),
- ("c", "", "attach_child", False),
- ("p", "", "attach_parent", False),
-]
-
-opts_list_mediator = \
- opts_table_no_headers + \
- [
- ("a", "", "list_available", False),
- ("F", "output-format", "output_format", None)
-]
-
-opts_revert = \
- opts_table_beopts + \
- opts_table_nqv + \
- opts_table_parsable + \
- [
- ("", "tagged", "tagged", False),
-]
-
-opts_set_mediator = \
- opts_table_beopts + \
- opts_table_no_index + \
- opts_table_nqv + \
- opts_table_parsable + \
- [
- ("I", "implementation", "med_implementation", None),
- ("V", "version", "med_version", None)
-]
-
-opts_unset_mediator = \
- opts_table_beopts + \
- opts_table_no_index + \
- opts_table_nqv + \
- opts_table_parsable + \
- [
- ("I", "", "med_implementation", False),
- ("V", "", "med_version", False)
-]
-
-# "set-property-linked" cmd inherits all "install" cmd options
-opts_set_property_linked = \
- opts_install + \
- opts_table_li_md_only + \
- opts_table_li_no_pkg_updates + \
- opts_table_li_target1 + \
- []
-
-# "sync-linked" cmd inherits all "install" cmd options
-opts_sync_linked = \
- opts_install + \
- opts_table_li_md_only + \
- opts_table_li_no_pkg_updates + \
- opts_table_li_target + \
- opts_table_stage + \
- []
-
-opts_uninstall = \
- opts_table_beopts + \
- opts_table_concurrency + \
- opts_table_li_ignore + \
- opts_table_no_index + \
- opts_table_nqv + \
- opts_table_parsable + \
- opts_table_stage
-
-opts_audit_linked = \
- opts_table_li_no_psync + \
- opts_table_li_target + \
- opts_table_no_headers + \
- opts_table_quiet + \
- []
-
-opts_detach_linked = \
- opts_table_force + \
- opts_table_li_target + \
- opts_table_nqv + \
- []
-
-opts_list_linked = \
- opts_table_li_ignore + \
- opts_table_no_headers + \
- []
-
-opts_list_property_linked = \
- opts_table_li_target1 + \
- opts_table_no_headers + \
- []
-
-opts_list_inventory = \
- opts_table_li_no_psync + \
- opts_table_no_refresh + \
- opts_table_no_headers + \
- opts_table_origins + \
- opts_table_verbose + \
- [
- opts_cb_list,
- ("a", "", "list_installed_newest", False),
- ("f", "", "list_all", False),
- ("n", "", "list_newest", False),
- ("s", "", "summary", False),
- ("u", "", "list_upgradable", False),
-]
-
-opts_remote = [
- opts_cb_remote,
- ("", "ctlfd", "ctlfd", None),
- ("", "progfd", "progfd", None),
-]
-
-
class RemoteDispatch(object):
"""RPC Server Class which invoked by the PipedRPCServer when a RPC
request is recieved."""
@@ -5583,8 +4963,8 @@
update_index=update_index)
# sync the requested child image(s)
- api_inst.progresstracker.set_major_phase(
- api_inst.progresstracker.PHASE_UTILITY)
+ api_inst.progresstracker.set_major_phase(
+ api_inst.progresstracker.PHASE_UTILITY)
rvdict = api_inst.sync_linked_children(li_target_list,
noexecute=noexecute, accept=accept, show_licenses=show_licenses,
refresh_catalogs=refresh_catalogs, update_index=update_index,
@@ -5654,8 +5034,8 @@
reject_list=reject_pats, update_index=update_index)
# attach the requested child image
- api_inst.progresstracker.set_major_phase(
- api_inst.progresstracker.PHASE_UTILITY)
+ api_inst.progresstracker.set_major_phase(
+ api_inst.progresstracker.PHASE_UTILITY)
(rv, err, p_dict) = api_inst.attach_linked_child(lin, li_path, li_props,
accept=accept, allow_relink=allow_relink, force=force,
li_md_only=li_md_only, li_pkg_updates=li_pkg_updates,
@@ -5687,8 +5067,8 @@
return __api_op(op, api_inst, _noexecute=noexecute,
_quiet=quiet, _verbose=verbose, force=force)
- api_inst.progresstracker.set_major_phase(
- api_inst.progresstracker.PHASE_UTILITY)
+ api_inst.progresstracker.set_major_phase(
+ api_inst.progresstracker.PHASE_UTILITY)
rvdict = api_inst.detach_linked_children(li_target_list, force=force,
noexecute=noexecute)
@@ -6264,79 +5644,196 @@
orig_cwd = None
#
+# Mapping of the internal option name to short and long CLI options.
+#
+# {option_name: (short, long)}
+#
+#
+
+opts_mapping = {
+ "backup_be_name" : ("", "backup-be-name"),
+ "be_name" : ("", "be-name"),
+ "deny_new_be" : ("", "deny-new-be"),
+ "no_backup_be" : ("", "no-backup-be"),
+ "be_activate" : ("", "no-be-activate"),
+ "require_backup_be" : ("", "require-backup-be"),
+ "require_new_be" : ("", "require-new-be"),
+
+ "concurrency" : ("C", "concurrency"),
+
+ "force" : ("f", ""),
+
+ "li_ignore_all" : ("I", ""),
+ "li_ignore_list" : ("i", ""),
+ "li_md_only" : ("", "linked-md-only"),
+
+ "li_pkg_updates" : ("", "no-pkg-updates"),
+
+ "li_parent_sync" : ("", "no-parent-sync"),
+
+ "li_props" : ("", "prop-linked"),
+
+ "li_target_all" : ("a", ""),
+ "li_target_list" : ("l", ""),
+
+ "li_name" : ("l", ""),
+
+ "accept" : ("", "accept"),
+ "show_licenses" : ("", "licenses"),
+
+ "omit_headers" : ("H", ""),
+
+ "update_index" : ("", "no-index"),
+
+ "refresh_catalogs" : ("", "no-refresh"),
+
+ "reject_pats" : ("", "reject"),
+
+ "verbose" : ("v", ""),
+
+ "quiet" : ("q", ""),
+
+ "parsable_version" : ("", "parsable"),
+
+ "noexecute" : ("n", ""),
+
+ "origins" : ("g", ""),
+
+ "stage" : ("", "stage"),
+
+ "allow_relink" : ("", "allow-relink"),
+ "attach_child" : ("c", ""),
+ "attach_parent" : ("p", ""),
+
+ "list_available" : ("a", ""),
+ "output_format" : ("F", "output-format"),
+
+ "tagged" : ("", "tagged"),
+
+ # These options are used in set-mediator and unset-mediator but
+ # the long options are only valid in set_mediator (as per the previous
+ # implementation). However, the long options are not documented in the
+ # manpage for set-mediator either, so I think we're good.
+ "med_implementation" : ("I", "implementation"),
+ "med_version" : ("V", "version"),
+
+ "list_installed_newest" : ("a", ""),
+ "list_all" : ("f", ""),
+ "list_newest" : ("n", ""),
+ "summary" : ("s", ""),
+ "list_upgradable" : ("u", ""),
+
+ "ctlfd" : ("", "ctlfd"),
+ "progfd" : ("", "progfd"),
+}
+
+#
# cmds dictionary is used to dispatch subcommands. The format of this
# dictionary is:
#
-# "subcommand-name" : (
-# subcommand-cb,
-# subcommand-opts-table,
-# arguments-allowed
-# )
+# "subcommand-name" : subcommand-cb
#
# subcommand-cb: the callback function invoked for this subcommand
-# subcommand-opts-table: an arguments options table that is passed to
-# the common options processing function misc.opts_parse().
-# if None then misc.opts_parse() is not invoked.
-#
-# arguments-allowed (optional): the number of additional arguments
-# allowed to this function, which is also passed to
-# misc.opts_parse()
#
# placeholders in this lookup table for image-create, help and version
# which don't have dedicated methods
#
cmds = {
- "add-property-value" : (property_add_value, None),
- "attach-linked" : (attach_linked, opts_attach_linked, 2),
- "avoid" : (avoid, None),
- "audit-linked" : (audit_linked, opts_audit_linked),
- "change-facet" : (change_facet, opts_install, -1),
- "change-variant" : (change_variant, opts_install, -1),
- "contents" : (list_contents, None),
- "detach-linked" : (detach_linked, opts_detach_linked),
- "facet" : (facet_list, None),
- "fix" : (fix_image, None),
- "freeze" : (freeze, None),
- "help" : (None, None),
- "history" : (history_list, None),
- "image-create" : (None, None),
- "info" : (info, None),
- "install" : (install, opts_install, -1),
- "list" : (list_inventory, opts_list_inventory, -1),
- "list-linked" : (list_linked, opts_list_linked),
- "mediator" : (list_mediators, opts_list_mediator, -1),
- "property" : (property_list, None),
- "property-linked" : (list_property_linked,
- opts_list_property_linked, -1),
- "pubcheck-linked" : (pubcheck_linked, []),
- "publisher" : (publisher_list, None),
- "purge-history" : (history_purge, None),
- "rebuild-index" : (rebuild_index, None),
- "refresh" : (publisher_refresh, None),
- "remote" : (remote, opts_remote, 0),
- "remove-property-value" : (property_remove_value, None),
- "revert" : (revert, opts_revert, -1),
- "search" : (search, None),
- "set-mediator" : (set_mediator, opts_set_mediator, -1),
- "set-property" : (property_set, None),
- "set-property-linked" : (set_property_linked,
- opts_set_property_linked, -1),
- "set-publisher" : (publisher_set, None),
- "sync-linked" : (sync_linked, opts_sync_linked),
- "unavoid" : (unavoid, None),
- "unfreeze" : (unfreeze, None),
- "uninstall" : (uninstall, opts_uninstall, -1),
- "unset-property" : (property_unset, None),
- "update-format" : (update_format, None),
- "unset-mediator" : (unset_mediator, opts_unset_mediator, -1),
- "unset-publisher" : (publisher_unset, None),
- "update" : (update, opts_update, -1),
- "update-format" : (update_format, None),
- "variant" : (variant_list, None),
- "verify" : (verify_image, None),
- "version" : (None, None),
+ "add-property-value" : [property_add_value],
+ "attach-linked" : [attach_linked, 2],
+ "avoid" : [avoid],
+ "audit-linked" : [audit_linked, 0],
+ "authority" : [publisher_list],
+ "change-facet" : [change_facet],
+ "change-variant" : [change_variant],
+ "contents" : [list_contents],
+ "detach-linked" : [detach_linked, 0],
+ "facet" : [facet_list],
+ "fix" : [fix_image],
+ "freeze" : [freeze],
+ "help" : [None],
+ "history" : [history_list],
+ "image-create" : [None],
+ "info" : [info],
+ "install" : [install],
+ "list" : [list_inventory],
+ "list-linked" : [list_linked, 0],
+ "mediator" : [list_mediators],
+ "property" : [property_list],
+ "property-linked" : [list_property_linked],
+ "pubcheck-linked" : [pubcheck_linked, 0],
+ "publisher" : [publisher_list],
+ "purge-history" : [history_purge],
+ "rebuild-index" : [rebuild_index],
+ "refresh" : [publisher_refresh],
+ "remote" : [remote, 0],
+ "remove-property-value" : [property_remove_value],
+ "revert" : [revert],
+ "search" : [search],
+ "set-authority" : [publisher_set],
+ "set-mediator" : [set_mediator],
+ "set-property" : [property_set],
+ "set-property-linked" : [set_property_linked],
+ "set-publisher" : [publisher_set],
+ "sync-linked" : [sync_linked, 0],
+ "unavoid" : [unavoid],
+ "unfreeze" : [unfreeze],
+ "uninstall" : [uninstall],
+ "unset-authority" : [publisher_unset],
+ "unset-property" : [property_unset],
+ "update-format" : [update_format],
+ "unset-mediator" : [unset_mediator],
+ "unset-publisher" : [publisher_unset],
+ "update" : [update],
+ "update-format" : [update_format],
+ "variant" : [variant_list],
+ "verify" : [verify_image],
+ "version" : [None],
}
+# These tables are an addendum to the the pkg_op_opts/opts_* lists in
+# modules/client/options.py. They contain all the options for functions which
+# are not represented in options.py but go through common option processing.
+# This list should get shortened and eventually removed by moving more/all
+# functions out of client.py.
+
+def opts_cb_remote(api_inst, opts, opts_new):
+ options.opts_cb_fd("ctlfd", api_inst, opts, opts_new)
+ options.opts_cb_fd("progfd", api_inst, opts, opts_new)
+
+ # move progfd from opts_new into a global
+ global_settings.client_output_progfd = opts_new["progfd"]
+ del opts_new["progfd"]
+
+opts_remote = [
+ opts_cb_remote,
+ ("ctlfd", None),
+ ("progfd", None),
+]
+
+opts_list_mediator = \
+ options.opts_table_no_headers + \
+ [
+ ("list_available", False),
+ ("output_format", None)
+]
+opts_unset_mediator = \
+ options.opts_table_beopts + \
+ options.opts_table_no_index + \
+ options.opts_table_nqv + \
+ options.opts_table_parsable + \
+ [
+ ("med_implementation", False),
+ ("med_version", False)
+]
+
+cmd_opts = {
+ "mediator" : opts_list_mediator,
+ "unset-mediator" : opts_unset_mediator,
+ "remote" : opts_remote,
+}
+
+
def main_func():
global_settings.client_name = PKG_CLIENT_NAME
@@ -6469,28 +5966,101 @@
img = api_inst.img
# Find subcommand and execute operation.
- pargs_limit = 0
func = cmds[subcommand][0]
- opts_cmd = cmds[subcommand][1]
- if len(cmds[subcommand]) > 2:
- pargs_limit = cmds[subcommand][2]
- try:
- if opts_cmd == None:
+ pargs_limit = None
+ if len(cmds[subcommand]) > 1:
+ pargs_limit = cmds[subcommand][1]
+
+ pkg_timer.record("client startup", logger=logger)
+
+ # Get the available options for the requested operation to create the
+ # getopt parsing strings.
+ valid_opts = options.get_pkg_opts(subcommand, add_table=cmd_opts)
+ if not valid_opts:
+ # if there are no options for an op, it has its own processing
+ try:
return func(api_inst, pargs)
-
- opts, pargs = misc.opts_parse(subcommand, api_inst, pargs,
- opts_cmd, pargs_limit, usage)
-
- # Reset the progress tracker here, because we may have
- # to switch to a different tracker due to the options parse.
- _api_inst.progresstracker = get_tracker()
-
- pkg_timer.record("client startup", logger=logger)
- return func(op=subcommand, api_inst=api_inst,
- pargs=pargs, **opts)
-
- except getopt.GetoptError, e:
- usage(_("illegal option -- %s") % e.opt, cmd=subcommand)
+ except getopt.GetoptError, e:
+ usage(_("illegal option -- %s") % e.opt,
+ cmd=subcommand)
+
+ try:
+ # Parse CLI arguments into dictionary containing corresponding
+ # options and values.
+ opt_dict, pargs = misc.opts_parse(subcommand, pargs, valid_opts,
+ opts_mapping, usage)
+
+ if pargs_limit is not None and len(pargs) > pargs_limit:
+ usage(_("illegal argument -- %s") % pargs[pargs_limit],
+ cmd=subcommand)
+
+ opts = options.opts_assemble(subcommand, api_inst, opt_dict,
+ add_table=cmd_opts, cwd=orig_cwd)
+
+ except api_errors.InvalidOptionError, e:
+
+ # We can't use the string representation of the exception since
+ # it references internal option names. We substitute the CLI
+ # options and create a new exception to make sure the messages
+ # are correct.
+
+ # Convert the internal options to CLI options. We make sure that
+ # when there is a short and a long version for the same option
+ # we print both to avoid confusion.
+ def get_cli_opt(option):
+ out = ""
+ try:
+ s, l = opts_mapping[option]
+ if l and not s:
+ return "--%s" % l
+ elif s and not l:
+ return "-%s" % s
+ else:
+ return("-%s/--%s" % (s,l))
+ except KeyError:
+ # ignore if we can't find a match
+ # (happens for repeated arguments)
+ return option
+
+ cli_opts = []
+ opt_def = []
+
+ for o in e.options:
+ cli_opts.append(get_cli_opt(o))
+
+ # collect the default value (see comment below)
+ opt_def.append(options.get_pkg_opts_defaults(subcommand,
+ o, add_table=cmd_opts))
+
+ # Prepare for headache:
+ # If we have an option 'b' which is set to True by default it
+ # will be toggled to False if the users specifies the according
+ # option on the CLI.
+ # If we now have an option 'a' which requires option 'b' to be
+ # set, we can't say "'a' requires 'b'" because the user can only
+ # specify 'not b'. So the correct message would be:
+ # "'a' is incompatible with 'not b'".
+ # We can get there by just changing the type of the exception
+ # for all cases where the default value of one of the options is
+ # True.
+ if e.err_type == api_errors.InvalidOptionError.REQUIRED:
+ if len(opt_def) == 2 and (opt_def[0] or opt_def[1]):
+ e.err_type = \
+ api_errors.InvalidOptionError.INCOMPAT
+
+ # This new exception will have the CLI options, so can be passed
+ # directly to usage().
+ new_e = api_errors.InvalidOptionError(err_type=e.err_type,
+ options=cli_opts, msg=e.msg)
+
+ usage(str(new_e), cmd=subcommand)
+
+ # Reset the progress tracker here, because we may have
+ # to switch to a different tracker due to the options parse.
+ _api_inst.progresstracker = get_tracker()
+
+ return func(op=subcommand, api_inst=api_inst,
+ pargs=pargs, **opts)
#
# Establish a specific exit status which means: "python barfed an exception"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/client/options.py Mon Mar 11 15:15:21 2013 -0700
@@ -0,0 +1,834 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+
+import os
+
+import pkg.client.pkgdefs as pkgdefs
+import pkg.client.linkedimage as li
+import pkg.misc as misc
+
+from pkg.client.api_errors import InvalidOptionError
+from pkg.client import global_settings
+
+_orig_cwd = None
+
+# List of available options for common option processing.
+ACCEPT = "accept"
+ALLOW_RELINK = "allow_relink"
+ATTACH_CHILD = "attach_child"
+ATTACH_PARENT = "attach_parent"
+BACKUP_BE = "backup_be"
+BACKUP_BE_NAME = "backup_be_name"
+BE_ACTIVATE = "be_activate"
+BE_NAME = "be_name"
+CONCURRENCY = "concurrency"
+DENY_NEW_BE = "deny_new_be"
+FORCE = "force"
+LI_IGNORE = "li_ignore"
+LI_IGNORE_ALL = "li_ignore_all"
+LI_IGNORE_LIST = "li_ignore_list"
+LI_MD_ONLY = "li_md_only"
+LI_NAME = "li_name"
+LI_PARENT_SYNC = "li_parent_sync"
+LI_PKG_UPDATES = "li_pkg_updates"
+LI_PROPS = "li_props"
+LI_TARGET_ALL = "li_target_all"
+LI_TARGET_LIST = "li_target_list"
+LIST_ALL = "list_all"
+LIST_INSTALLED_NEWEST = "list_installed_newest"
+LIST_NEWEST = "list_newest"
+LIST_UPGRADABLE = "list_upgradable"
+MED_IMPLEMENTATION = "med_implementation"
+MED_VERSION = "med_version"
+NEW_BE = "new_be"
+NO_BACKUP_BE = "no_backup_be"
+NOEXECUTE = "noexecute"
+OMIT_HEADERS = "omit_headers"
+ORIGINS = "origins"
+PARSABLE_VERSION = "parsable_version"
+QUIET = "quiet"
+REFRESH_CATALOGS = "refresh_catalogs"
+REJECT_PATS = "reject_pats"
+REQUIRE_BACKUP_BE = "require_backup_be"
+REQUIRE_NEW_BE = "require_new_be"
+SHOW_LICENSES = "show_licenses"
+STAGE = "stage"
+SUMMARY = "summary"
+TAGGED = "tagged"
+UPDATE_INDEX = "update_index"
+VERBOSE = "verbose"
+
+
+
+def opts_table_cb_beopts(api_inst, opts, opts_new):
+
+ # synthesize require_new_be and deny_new_be into new_be
+ del opts_new[REQUIRE_NEW_BE]
+ del opts_new[DENY_NEW_BE]
+ opts_new[NEW_BE] = None
+
+ if (opts[BE_NAME] or opts[REQUIRE_NEW_BE]) and opts[DENY_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [REQUIRE_NEW_BE, DENY_NEW_BE])
+
+ # create a new key called BACKUP_BE in the options array
+ if opts[REQUIRE_NEW_BE] or opts[BE_NAME]:
+ opts_new[NEW_BE] = True
+ if opts[DENY_NEW_BE]:
+ opts_new[NEW_BE] = False
+
+ # synthesize require_backup_be and no_backup_be into backup_be
+ del opts_new[REQUIRE_BACKUP_BE]
+ del opts_new[NO_BACKUP_BE]
+ opts_new[BACKUP_BE] = None
+
+ if (opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]) and \
+ opts[NO_BACKUP_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [REQUIRE_BACKUP_BE, NO_BACKUP_BE])
+
+ if (opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]) and \
+ (opts[REQUIRE_NEW_BE] or opts[BE_NAME]):
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [REQUIRE_BACKUP_BE, REQUIRE_NEW_BE])
+
+ # create a new key called BACKUP_BE in the options array
+ if opts[REQUIRE_BACKUP_BE] or opts[BACKUP_BE_NAME]:
+ opts_new[BACKUP_BE] = True
+ if opts[NO_BACKUP_BE]:
+ opts_new[BACKUP_BE] = False
+
+def opts_table_cb_li_ignore(api_inst, opts, opts_new):
+
+ # synthesize li_ignore_all and li_ignore_list into li_ignore
+ del opts_new[LI_IGNORE_ALL]
+ del opts_new[LI_IGNORE_LIST]
+ opts_new[LI_IGNORE] = None
+
+ # check if there's nothing to ignore
+ if not opts[LI_IGNORE_ALL] and not opts[LI_IGNORE_LIST]:
+ return
+
+ if opts[LI_IGNORE_ALL]:
+
+ # can't ignore all and specific images
+ if opts[LI_IGNORE_LIST]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_ALL, LI_IGNORE_LIST])
+
+ # can't ignore all and target anything.
+ if LI_TARGET_ALL in opts and opts[LI_TARGET_ALL]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_ALL, LI_TARGET_ALL])
+ if LI_TARGET_LIST in opts and opts[LI_TARGET_LIST]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_ALL, LI_TARGET_LIST])
+ if LI_NAME in opts and opts[LI_NAME]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_ALL, LI_NAME])
+ opts_new[LI_IGNORE] = []
+ return
+
+ assert opts[LI_IGNORE_LIST]
+
+ # it doesn't make sense to specify images to ignore if the
+ # user is already specifying images to operate on.
+ if LI_TARGET_ALL in opts and opts[LI_TARGET_ALL]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_LIST, LI_TARGET_ALL])
+ if LI_TARGET_LIST in opts and opts[LI_TARGET_LIST]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_LIST, LI_TARGET_LIST])
+ if LI_NAME in opts and opts[LI_NAME]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_IGNORE_LIST, LI_NAME])
+
+ li_ignore = []
+ for li_name in opts[LI_IGNORE_LIST]:
+ # check for repeats
+ if li_name in li_ignore:
+ raise InvalidOptionError(
+ InvalidOptionError.ARG_REPEAT, [li_name,
+ LI_IGNORE_LIST])
+ # add to ignore list
+ li_ignore.append(li_name)
+
+ opts_new[LI_IGNORE] = api_inst.parse_linked_name_list(li_ignore)
+
+def opts_table_cb_li_no_psync(api_inst, opts, opts_new):
+ # if a target child linked image was specified, the no-parent-sync
+ # option doesn't make sense since we know that both the parent and
+ # child image are accessible
+
+ if LI_TARGET_ALL not in opts:
+ # we don't accept linked image target options
+ assert LI_TARGET_LIST not in opts
+ return
+
+ if opts[LI_TARGET_ALL] and not opts[LI_PARENT_SYNC]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [LI_TARGET_ALL, LI_PARENT_SYNC])
+
+ if opts[LI_TARGET_LIST] and not opts[LI_PARENT_SYNC]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [LI_TARGET_LIST, LI_PARENT_SYNC])
+
+
+def __parse_linked_props(args):
+ """"Parse linked image property options that were specified on the
+ command line into a dictionary. Make sure duplicate properties were
+ not specified."""
+
+ linked_props = dict()
+ for pv in args:
+ try:
+ p, v = pv.split("=", 1)
+ except ValueError:
+ raise InvalidOptionError(msg=_("linked image "
+ "property arguments must be of the form "
+ "'<name>=<value>'."))
+
+ if p not in li.prop_values:
+ raise InvalidOptionError(msg=_("invalid linked "
+ "image property: '%s'.") % p)
+
+ if p in linked_props:
+ raise InvalidOptionError(msg=_("linked image "
+ "property specified multiple times: '%s'.") % p)
+
+ linked_props[p] = v
+
+ return linked_props
+
+def opts_table_cb_li_props(api_inst, opts, opts_new):
+ """convert linked image prop list into a dictionary"""
+
+ opts_new[LI_PROPS] = __parse_linked_props(opts[LI_PROPS])
+
+def opts_table_cb_li_target(api_inst, opts, opts_new):
+ # figure out which option the user specified
+ if opts[LI_TARGET_ALL] and opts[LI_TARGET_LIST]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LI_TARGET_ALL, LI_TARGET_LIST])
+ elif opts[LI_TARGET_ALL]:
+ arg1 = LI_TARGET_ALL
+ elif opts[LI_TARGET_LIST]:
+ arg1 = LI_TARGET_LIST
+ else:
+ return
+
+ if BE_ACTIVATE in opts and not opts[BE_ACTIVATE]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [arg1, BE_ACTIVATE])
+ if BE_NAME in opts and opts[BE_NAME]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, BE_NAME])
+ if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, DENY_NEW_BE])
+ if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REQUIRE_NEW_BE])
+ if REJECT_PATS in opts and opts[REJECT_PATS]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REJECT_PATS])
+ if ORIGINS in opts and opts[ORIGINS]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, ORIGINS])
+
+ # validate linked image name
+ li_target_list = []
+ for li_name in opts[LI_TARGET_LIST]:
+ # check for repeats
+ if li_name in li_target_list:
+ raise InvalidOptionError(
+ InvalidOptionError.ARG_REPEAT, [li_name,
+ LI_TARGET_LIST])
+ # add to ignore list
+ li_target_list.append(li_name)
+
+ opts_new[LI_TARGET_LIST] = \
+ api_inst.parse_linked_name_list(li_target_list)
+
+def opts_table_cb_li_target1(api_inst, opts, opts_new):
+ # figure out which option the user specified
+ if opts[LI_NAME]:
+ arg1 = LI_NAME
+ else:
+ return
+
+ if BE_ACTIVATE in opts and not opts[BE_ACTIVATE]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [arg1, BE_ACTIVATE])
+ if BE_NAME in opts and opts[BE_NAME]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, BE_NAME])
+ if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, DENY_NEW_BE])
+ if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REQUIRE_NEW_BE])
+ if REJECT_PATS in opts and opts[REJECT_PATS]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REJECT_PATS])
+ if ORIGINS in opts and opts[ORIGINS]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, ORIGINS])
+
+def opts_table_cb_no_headers_vs_quiet(api_inst, opts, opts_new):
+ # check if we accept the -q option
+ if QUIET not in opts:
+ return
+
+ # -q implies -H
+ if opts[QUIET]:
+ opts_new[OMIT_HEADERS] = True
+
+def opts_table_cb_q(api_inst, opts, opts_new):
+ # Be careful not to overwrite global_settings.client_output_quiet
+ # because it might be set "True" from elsewhere, e.g. in
+ # opts_table_cb_parsable.
+ if opts[QUIET] is True:
+ global_settings.client_output_quiet = True
+
+def opts_table_cb_v(api_inst, opts, opts_new):
+ global_settings.client_output_verbose = opts[VERBOSE]
+
+def opts_table_cb_nqv(api_inst, opts, opts_new):
+ if opts[VERBOSE] and opts[QUIET]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [VERBOSE, QUIET])
+
+def opts_table_cb_parsable(api_inst, opts, opts_new):
+ if opts[PARSABLE_VERSION] and opts.get(VERBOSE, False):
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [VERBOSE, PARSABLE_VERSION])
+ if opts[PARSABLE_VERSION]:
+ try:
+ opts_new[PARSABLE_VERSION] = int(
+ opts[PARSABLE_VERSION])
+ except ValueError:
+ raise InvalidOptionError(
+ options=[PARSABLE_VERSION],
+ msg=_("integer argument expected"))
+
+ global_settings.client_output_parsable_version = \
+ opts_new[PARSABLE_VERSION]
+ opts_new[QUIET] = True
+ global_settings.client_output_quiet = True
+
+def opts_table_cb_origins(api_inst, opts, opts_new):
+ origins = set()
+ for o in opts[ORIGINS]:
+ origins.add(misc.parse_uri(o, cwd=_orig_cwd))
+ opts_new[ORIGINS] = origins
+
+def opts_table_cb_stage(api_inst, opts, opts_new):
+ if opts[STAGE] == None:
+ opts_new[STAGE] = pkgdefs.API_STAGE_DEFAULT
+ return
+
+ if opts_new[STAGE] not in pkgdefs.api_stage_values:
+ raise InvalidOptionError(msg=_("invalid operation stage: "
+ "'%s'") % opts[STAGE])
+
+def opts_cb_li_attach(api_inst, opts, opts_new):
+ if opts[ATTACH_PARENT] and opts[ATTACH_CHILD]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [ATTACH_PARENT, ATTACH_CHILD])
+
+ if not opts[ATTACH_PARENT] and not opts[ATTACH_CHILD]:
+ raise InvalidOptionError(InvalidOptionError.XOR,
+ [ATTACH_PARENT, ATTACH_CHILD])
+
+ if opts[ATTACH_CHILD]:
+ # if we're attaching a new child then that doesn't affect
+ # any other children, so ignoring them doesn't make sense.
+ if opts[LI_IGNORE_ALL]:
+ raise InvalidOptionError(
+ InvalidOptionError.INCOMPAT,
+ [ATTACH_CHILD, LI_IGNORE_ALL])
+ if opts[LI_IGNORE_LIST]:
+ raise InvalidOptionError(
+ InvalidOptionError.INCOMPAT,
+ [ATTACH_CHILD, LI_IGNORE_LIST])
+
+def opts_table_cb_md_only(api_inst, opts, opts_new):
+ # if the user didn't specify linked-md-only we're done
+ if not opts[LI_MD_ONLY]:
+ return
+
+ # li_md_only implies no li_pkg_updates
+ if LI_PKG_UPDATES in opts:
+ opts_new[LI_PKG_UPDATES] = False
+
+ #
+ # if li_md_only is false that means we're not updating any packages
+ # within the current image so there are a ton of options that no
+ # longer apply to the current operation, and hence are incompatible
+ # with li_md_only.
+ #
+ arg1 = LI_MD_ONLY
+ if BE_NAME in opts and opts[BE_NAME]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, BE_NAME])
+ if DENY_NEW_BE in opts and opts[DENY_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, DENY_NEW_BE])
+ if REQUIRE_NEW_BE in opts and opts[REQUIRE_NEW_BE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REQUIRE_NEW_BE])
+ if LI_PARENT_SYNC in opts and not opts[LI_PARENT_SYNC]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [arg1, LI_PARENT_SYNC])
+ if REJECT_PATS in opts and opts[REJECT_PATS]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [arg1, REJECT_PATS])
+
+def opts_cb_list(api_inst, opts, opts_new):
+ if opts_new[ORIGINS] and opts_new[LIST_UPGRADABLE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [ORIGINS, LIST_UPGRADABLE])
+
+ if opts_new[ORIGINS] and not opts_new[LIST_NEWEST]:
+ # Use of -g implies -a unless -n is provided.
+ opts_new[LIST_INSTALLED_NEWEST] = True
+
+ if opts_new[LIST_ALL] and not opts_new[LIST_INSTALLED_NEWEST]:
+ raise InvalidOptionError(InvalidOptionError.REQUIRED,
+ [LIST_ALL, LIST_INSTALLED_NEWEST])
+
+ if opts_new[LIST_INSTALLED_NEWEST] and opts_new[LIST_NEWEST]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LIST_INSTALLED_NEWEST, LIST_NEWEST])
+
+ if opts_new[LIST_INSTALLED_NEWEST] and opts_new[LIST_UPGRADABLE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [LIST_INSTALLED_NEWEST, LIST_UPGRADABLE])
+
+ if opts_new[SUMMARY] and opts_new[VERBOSE]:
+ raise InvalidOptionError(InvalidOptionError.INCOMPAT,
+ [SUMMARY, VERBOSE])
+
+def opts_cb_int(k, api_inst, opts, opts_new, minimum=None):
+
+ if k not in opts or opts[k] == None:
+ err = _("missing required parameter")
+ raise InvalidOptionError(msg=err, options=[k])
+
+ # get the original argument value
+ v = opts[k]
+
+ # make sure it is an integer
+ try:
+ v = int(v)
+ except (ValueError, TypeError):
+ # not a valid integer
+ err = _("value '%s' invalid") % (v)
+ raise InvalidOptionError(msg=err, options=[k])
+
+ # check the minimum bounds
+ if minimum is not None and v < minimum:
+ err = _("value must be >= %d") % (minimum)
+ raise InvalidOptionError(msg=err, options=[k])
+
+ # update the new options array to make the value an integer
+ opts_new[k] = v
+
+def opts_cb_fd(k, api_inst, opts, opts_new):
+ opts_cb_int(k, api_inst, opts, opts_new, minimum=0)
+
+ err = _("value '%s' invalid") % (opts_new[k])
+ try:
+ os.fstat(opts_new[k])
+ except OSError:
+ # not a valid file descriptor
+ raise InvalidOptionError(msg=err, options=[k])
+
+def opts_table_cb_concurrency(api_inst, opts, opts_new):
+ if opts[CONCURRENCY] is None:
+ # remove concurrency from parameters dict
+ del opts_new[CONCURRENCY]
+ return
+
+ # make sure we have an integer
+ opts_cb_int(CONCURRENCY, api_inst, opts, opts_new)
+
+ # update global concurrency setting
+ global_settings.client_concurrency = opts_new[CONCURRENCY]
+
+ # remove concurrency from parameters dict
+ del opts_new[CONCURRENCY]
+
+#
+# options common to multiple pkg(1) operations. The format for specifying
+# options is a list which can contain:
+#
+# - Tuples formatted as:
+# (k, v)
+# where the values are:
+# k: the key value for the options dictionary
+# v: the default value. valid values are: True/False, None, [], 0
+#
+
+
+opts_table_beopts = [
+ opts_table_cb_beopts,
+ (BACKUP_BE_NAME, None),
+ (BE_NAME, None),
+ (DENY_NEW_BE, False),
+ (NO_BACKUP_BE, False),
+ (BE_ACTIVATE, True),
+ (REQUIRE_BACKUP_BE, False),
+ (REQUIRE_NEW_BE, False),
+]
+
+opts_table_concurrency = [
+ opts_table_cb_concurrency,
+ (CONCURRENCY, None),
+]
+
+opts_table_force = [
+ (FORCE, False),
+]
+
+opts_table_li_ignore = [
+ opts_table_cb_li_ignore,
+ (LI_IGNORE_ALL, False),
+ (LI_IGNORE_LIST, []),
+]
+
+opts_table_li_md_only = [
+ opts_table_cb_md_only,
+ (LI_MD_ONLY, False),
+]
+
+opts_table_li_no_pkg_updates = [
+ (LI_PKG_UPDATES, True),
+]
+
+opts_table_li_no_psync = [
+ opts_table_cb_li_no_psync,
+ (LI_PARENT_SYNC, True),
+]
+
+opts_table_li_props = [
+ opts_table_cb_li_props,
+ (LI_PROPS, []),
+]
+
+opts_table_li_target = [
+ opts_table_cb_li_target,
+ (LI_TARGET_ALL, False),
+ (LI_TARGET_LIST, []),
+]
+
+opts_table_li_target1 = [
+ opts_table_cb_li_target1,
+ (LI_NAME, None),
+]
+
+opts_table_licenses = [
+ (ACCEPT, False),
+ (SHOW_LICENSES, False),
+]
+
+opts_table_no_headers = [
+ opts_table_cb_no_headers_vs_quiet,
+ (OMIT_HEADERS, False),
+]
+
+opts_table_no_index = [
+ (UPDATE_INDEX, True),
+]
+
+opts_table_no_refresh = [
+ (REFRESH_CATALOGS, True),
+]
+
+opts_table_reject = [
+ (REJECT_PATS, []),
+]
+
+opts_table_verbose = [
+ opts_table_cb_v,
+ (VERBOSE, 0),
+]
+
+opts_table_quiet = [
+ opts_table_cb_q,
+ (QUIET, False),
+]
+
+opts_table_parsable = [
+ opts_table_cb_parsable,
+ (PARSABLE_VERSION, None),
+]
+
+opts_table_nqv = \
+ opts_table_quiet + \
+ opts_table_verbose + \
+ [
+ opts_table_cb_nqv,
+ (NOEXECUTE, False),
+]
+
+opts_table_origins = [
+ opts_table_cb_origins,
+ (ORIGINS, []),
+]
+
+opts_table_stage = [
+ opts_table_cb_stage,
+ (STAGE, None),
+]
+
+#
+# Options for pkg(1) subcommands. Built by combining the option tables above,
+# with some optional subcommand unique options defined below.
+#
+opts_install = \
+ opts_table_beopts + \
+ opts_table_concurrency + \
+ opts_table_li_ignore + \
+ opts_table_li_no_psync + \
+ opts_table_licenses + \
+ opts_table_reject + \
+ opts_table_no_index + \
+ opts_table_no_refresh + \
+ opts_table_nqv + \
+ opts_table_parsable + \
+ opts_table_origins + \
+ []
+
+# "update" cmd inherits all "install" cmd options
+opts_update = \
+ opts_install + \
+ opts_table_force + \
+ opts_table_stage + \
+ []
+
+# "attach-linked" cmd inherits all "install" cmd options
+opts_attach_linked = \
+ opts_install + \
+ opts_table_force + \
+ opts_table_li_md_only + \
+ opts_table_li_no_pkg_updates + \
+ opts_table_li_props + \
+ [
+ opts_cb_li_attach,
+ (ALLOW_RELINK, False),
+ (ATTACH_CHILD, False),
+ (ATTACH_PARENT, False),
+]
+
+opts_revert = \
+ opts_table_beopts + \
+ opts_table_nqv + \
+ opts_table_parsable + \
+ [
+ (TAGGED, False),
+]
+
+opts_set_mediator = \
+ opts_table_beopts + \
+ opts_table_no_index + \
+ opts_table_nqv + \
+ opts_table_parsable + \
+ [
+ (MED_IMPLEMENTATION, None),
+ (MED_VERSION, None)
+]
+
+# "set-property-linked" cmd inherits all "install" cmd options
+opts_set_property_linked = \
+ opts_install + \
+ opts_table_li_md_only + \
+ opts_table_li_no_pkg_updates + \
+ opts_table_li_target1 + \
+ []
+
+# "sync-linked" cmd inherits all "install" cmd options
+opts_sync_linked = \
+ opts_install + \
+ opts_table_li_md_only + \
+ opts_table_li_no_pkg_updates + \
+ opts_table_li_target + \
+ opts_table_stage + \
+ []
+
+opts_uninstall = \
+ opts_table_beopts + \
+ opts_table_concurrency + \
+ opts_table_li_ignore + \
+ opts_table_no_index + \
+ opts_table_nqv + \
+ opts_table_parsable + \
+ opts_table_stage
+
+opts_audit_linked = \
+ opts_table_li_no_psync + \
+ opts_table_li_target + \
+ opts_table_no_headers + \
+ opts_table_quiet + \
+ []
+
+opts_detach_linked = \
+ opts_table_force + \
+ opts_table_li_target + \
+ opts_table_nqv + \
+ []
+
+opts_list_linked = \
+ opts_table_li_ignore + \
+ opts_table_no_headers + \
+ []
+
+opts_list_property_linked = \
+ opts_table_li_target1 + \
+ opts_table_no_headers + \
+ []
+
+opts_list_inventory = \
+ opts_table_li_no_psync + \
+ opts_table_no_refresh + \
+ opts_table_no_headers + \
+ opts_table_origins + \
+ opts_table_verbose + \
+ [
+ opts_cb_list,
+ (LIST_INSTALLED_NEWEST, False),
+ (LIST_ALL, False),
+ (LIST_NEWEST, False),
+ (SUMMARY, False),
+ (LIST_UPGRADABLE, False),
+]
+
+pkg_op_opts = {
+
+ pkgdefs.PKG_OP_ATTACH : opts_attach_linked,
+ pkgdefs.PKG_OP_AUDIT_LINKED : opts_audit_linked,
+ pkgdefs.PKG_OP_CHANGE_FACET : opts_install,
+ pkgdefs.PKG_OP_CHANGE_VARIANT : opts_install,
+ pkgdefs.PKG_OP_DETACH : opts_detach_linked,
+ pkgdefs.PKG_OP_INSTALL : opts_install,
+ pkgdefs.PKG_OP_LIST : opts_list_inventory,
+ pkgdefs.PKG_OP_LIST_LINKED : opts_list_linked,
+ pkgdefs.PKG_OP_PROP_LINKED : opts_list_property_linked,
+ pkgdefs.PKG_OP_PUBCHECK : [],
+ pkgdefs.PKG_OP_REVERT : opts_revert,
+ pkgdefs.PKG_OP_SET_MEDIATOR : opts_set_mediator,
+ pkgdefs.PKG_OP_SET_PROP_LINKED: opts_set_property_linked,
+ pkgdefs.PKG_OP_SYNC : opts_sync_linked,
+ pkgdefs.PKG_OP_UNINSTALL : opts_uninstall,
+ pkgdefs.PKG_OP_UPDATE : opts_update
+}
+
+def get_pkg_opts(op, add_table=None):
+ """Get the available options for a particular operation specified by
+ 'op'. If the client uses custom pkg_op_opts tables they can be specified
+ by 'add_table'."""
+
+ popts = pkg_op_opts.copy()
+ if add_table is not None:
+ popts.update(add_table)
+
+ try:
+ opts = popts[op]
+ except KeyError:
+ opts = None
+ return opts
+
+def get_pkg_opts_defaults(op, opt, add_table=None):
+ """ Get the default value for a certain option 'opt' of a certain
+ operation 'op'. This is useful for clients which toggle boolean options.
+ """
+ popts = get_pkg_opts(op, add_table)
+
+ for o in popts:
+ if type(o) != tuple:
+ continue
+ opt_name, default = o
+ if opt_name == opt:
+ return default
+
+def opts_assemble(op, api_inst, opts, add_table=None, cwd=None):
+ """Assembly of the options for a specific operation. Options are read in
+ from a dict (see explanation below) and sanity tested.
+
+ This is the common interface to supply options to the functions of the
+ API.
+
+ 'op' is the operation for which the options need to be assembled and
+ verified. The currently supported operations are listed in
+ pkgdefs.pkg_op_values.
+
+ 'api_inst' is a reference to the API instance, required for some of the
+ verification steps.
+
+ 'opts' is the raw options table to be processed. It needs to be a dict
+ in the format: { option_name: argument, ... }
+ """
+
+ global _orig_cwd
+
+ if cwd is not None:
+ _orig_cwd = cwd
+ else:
+ _orig_cwd = None
+
+ popts = get_pkg_opts(op, add_table)
+
+ rv = {}
+ callbacks = []
+
+ for o in popts:
+ if type(o) != tuple:
+ callbacks.append(o)
+ continue
+
+ avail_opt, default = o
+ # for options not given we substitue the default value
+ if avail_opt not in opts:
+ rv[avail_opt] = default
+ continue
+
+ if type(default) == int:
+ assert type(opts[avail_opt]) == int, opts[avail_opt]
+ elif type(default) == list:
+ assert type(opts[avail_opt]) == list, opts[avail_opt]
+ elif type(default) == bool:
+ assert type(opts[avail_opt]) == bool, opts[avail_opt]
+
+ rv[avail_opt] = opts[avail_opt]
+
+ rv_updated = rv.copy()
+
+ # run the option verification callbacks
+ for cb in callbacks:
+ cb(api_inst, rv, rv_updated)
+
+ return rv_updated
+