options.py revision 3031
#
# 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
# 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
#
import os
_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"
IGNORE_MISSING = "ignore_missing"
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"
# options for explicit recursion; see description in client.py
LI_ERECURSE_ALL = "li_erecurse_all"
LI_ERECURSE_INCL = "li_erecurse_list"
LI_ERECURSE_EXCL = "li_erecurse_excl"
LI_ERECURSE = "li_erecurse"
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"
SYNC_ACT = "sync_act"
ACT_TIMEOUT = "act_timeout"
# synthesize require_new_be and deny_new_be into new_be
del opts_new[REQUIRE_NEW_BE]
del opts_new[DENY_NEW_BE]
# create a new key called BACKUP_BE in the options array
if opts[DENY_NEW_BE]:
# synthesize require_backup_be and no_backup_be into backup_be
del opts_new[NO_BACKUP_BE]
# create a new key called BACKUP_BE in the options array
if opts[NO_BACKUP_BE]:
# synthesize li_ignore_all and li_ignore_list into li_ignore
del opts_new[LI_IGNORE_ALL]
del opts_new[LI_IGNORE_LIST]
# check if there's nothing to ignore
return
if opts[LI_IGNORE_ALL]:
# can't ignore all and specific images
if opts[LI_IGNORE_LIST]:
# can't ignore all and target anything.
[LI_IGNORE_ALL, LI_NAME])
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.
li_ignore = []
# check for repeats
raise InvalidOptionError(
# add to ignore list
# 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
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()
try:
except ValueError:
"property arguments must be of the form "
"'<name>=<value>'."))
if p not in li.prop_values:
"image property: '%s'.") % p)
if p in linked_props:
"property specified multiple times: '%s'.") % p)
linked_props[p] = v
return linked_props
"""convert linked image prop list into a dictionary"""
# figure out which option the user specified
elif opts[LI_TARGET_ALL]:
elif opts[LI_TARGET_LIST]:
else:
return
[arg1, BE_ACTIVATE])
[arg1, DENY_NEW_BE])
[arg1, REQUIRE_NEW_BE])
[arg1, REJECT_PATS])
# validate linked image name
li_target_list = []
# check for repeats
if li_name in li_target_list:
raise InvalidOptionError(
# add to ignore list
opts_new[LI_TARGET_LIST] = \
# figure out which option the user specified
else:
return
[arg1, BE_ACTIVATE])
[arg1, DENY_NEW_BE])
[arg1, REQUIRE_NEW_BE])
[arg1, REJECT_PATS])
del opts_new[LI_ERECURSE_INCL]
del opts_new[LI_ERECURSE_EXCL]
del opts_new[LI_ERECURSE_ALL]
if not opts[LI_ERECURSE_ALL]:
opts_new[LI_ERECURSE] = None
return
# Go through all children and check if they are in the recurse list.
li_child_targets = []
li_child_list = set([
if rel == "child"
])
lin = None
try:
except LinkedImageException, e:
try:
except LinkedImageException, e:
pass
raise InvalidOptionError(msg=
_("invalid linked image or zone name '%s'.") % ulin)
return lin
if opts[LI_ERECURSE_INCL]:
# include list specified
else:
# exclude list specified
# If we use image recursion we need to make sure uninstall and update
# ignore non-existing packages in the parent image.
# check if we accept the -q option
return
# -q implies -H
# 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[PARSABLE_VERSION]:
try:
except ValueError:
raise InvalidOptionError(
msg=_("integer argument expected"))
return
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(
if opts[LI_IGNORE_LIST]:
raise InvalidOptionError(
# 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:
#
# 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, DENY_NEW_BE])
[arg1, REQUIRE_NEW_BE])
[arg1, LI_PARENT_SYNC])
[arg1, REJECT_PATS])
# Use of -g implies -a unless -n is provided.
err = _("missing required parameter")
# 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)
# check the minimum bounds
# update the new options array to make the value an integer
opts_new[k] = v
try:
except OSError:
# not a valid file descriptor
if opts[CONCURRENCY] is None:
# remove concurrency from parameters dict
del opts_new[CONCURRENCY]
return
# make sure we have an integer
# update global concurrency setting
# remove concurrency from parameters dict
del opts_new[CONCURRENCY]
del opts_new[ACT_TIMEOUT]
if opts[ACT_TIMEOUT]:
# make sure we have an integer
# -1 is no timeout
else:
# 0 is no sync actuators are used (timeout=0)
#
# options common to multiple pkg(1) operations. The format for specifying
# options is a list which can contain:
#
# - Tuples formatted as:
# (k, v, [val])
# where the values are:
# k: the key value for the options dictionary
# val: the valid argument list. It should be a list,
# and it is optional.
#
(BACKUP_BE_NAME, None),
(BE_NAME, None),
(DENY_NEW_BE, False),
(NO_BACKUP_BE, False),
(BE_ACTIVATE, True),
(REQUIRE_NEW_BE, False),
]
(CONCURRENCY, None),
]
opts_table_force = [
]
(LI_IGNORE_ALL, False),
(LI_IGNORE_LIST, []),
]
(LI_MD_ONLY, False),
]
(LI_PKG_UPDATES, True),
]
(LI_PARENT_SYNC, True),
]
(LI_PROPS, []),
]
(LI_TARGET_ALL, False),
(LI_TARGET_LIST, []),
]
(LI_NAME, None),
]
(LI_ERECURSE_ALL, False),
(LI_ERECURSE_INCL, []),
(LI_ERECURSE_EXCL, []),
]
(SHOW_LICENSES, False),
]
(OMIT_HEADERS, False),
]
(UPDATE_INDEX, True),
]
(REFRESH_CATALOGS, True),
]
(REJECT_PATS, []),
]
(VERBOSE, 0),
]
opts_table_quiet = [
]
(PARSABLE_VERSION, None),
]
opts_table_nqv = \
opts_table_quiet + \
[
]
(ORIGINS, []),
]
opts_table_stage = [
(STAGE, None),
]
(IGNORE_MISSING, False),
]
(ACT_TIMEOUT, None)
]
#
# Options for pkg(1) subcommands. Built by combining the option tables above,
# with some optional subcommand unique options defined below.
#
opts_main = \
opts_table_nqv + \
[]
opts_install = \
opts_main + \
opts_table_stage + \
[]
# "update" cmd inherits all main cmd options
opts_update = \
opts_main + \
opts_table_force + \
opts_table_stage + \
[]
# "attach-linked" cmd inherits all main cmd options
opts_main + \
opts_table_force + \
[
(ALLOW_RELINK, False),
(ATTACH_CHILD, False),
(ATTACH_PARENT, False),
]
opts_revert = \
opts_table_nqv + \
[
]
opts_table_nqv + \
[
(MED_IMPLEMENTATION, None),
(MED_VERSION, None)
]
# "set-property-linked" cmd inherits all main cmd options
opts_main + \
[]
# "sync-linked" cmd inherits all main cmd options
opts_sync_linked = \
opts_main + \
opts_table_stage + \
[]
opts_uninstall = \
opts_table_nqv + \
opts_table_stage + \
[]
opts_table_quiet + \
[]
opts_table_force + \
opts_table_nqv + \
[]
opts_list_linked = \
[]
[]
opts_table_quiet + \
[
(LIST_NEWEST, False),
(LIST_UPGRADABLE, False),
]
pkg_op_opts = {
pkgdefs.PKG_OP_PUBCHECK : [],
}
"""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'."""
if add_table is not None:
try:
except KeyError:
opts = None
return opts
""" Get the default value for a certain option 'opt' of a certain
operation 'op'. This is useful for clients which toggle boolean options.
"""
for o in popts:
continue
if len(o) == 2:
elif len(o) == 3:
return default
"""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:
else:
_orig_cwd = None
rv = {}
callbacks = []
for o in popts:
continue
valid_args = []
# If no valid argument list specified.
if len(o) == 2:
elif len(o) == 3:
# for options not given we substitue the default value
continue
if valid_args:
set(valid_args)):
else:
if raise_error:
raise InvalidOptionError(
# run the option verification callbacks
return rv_updated