diff options
Diffstat (limited to 'src/lib/Bcfg2/Options.py')
-rw-r--r-- | src/lib/Bcfg2/Options.py | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Options.py b/src/lib/Bcfg2/Options.py new file mode 100644 index 000000000..bbbbec343 --- /dev/null +++ b/src/lib/Bcfg2/Options.py @@ -0,0 +1,880 @@ +"""Option parsing library for utilities.""" + +import re +import os +import sys +import copy +import shlex +import getopt +import Bcfg2.Client.Tools +# Compatibility imports +from Bcfg2.Bcfg2Py3k import ConfigParser + + +class OptionFailure(Exception): + pass + +DEFAULT_CONFIG_LOCATION = '/etc/bcfg2.conf' +DEFAULT_INSTALL_PREFIX = '/usr' + + +class DefaultConfigParser(ConfigParser.ConfigParser): + def get(self, section, option, **kwargs): + """ convenience method for getting config items """ + default = None + if 'default' in kwargs: + default = kwargs['default'] + del kwargs['default'] + try: + return ConfigParser.ConfigParser.get(self, section, option, + **kwargs) + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + if default is not None: + return default + else: + raise + + def getboolean(self, section, option, **kwargs): + """ convenience method for getting boolean config items """ + default = None + if 'default' in kwargs: + default = kwargs['default'] + del kwargs['default'] + try: + return ConfigParser.ConfigParser.getboolean(self, section, + option, **kwargs) + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, + ValueError): + if default is not None: + return default + else: + raise + + +class Option(object): + def get_cooked_value(self, value): + if self.boolean: + return True + if self.cook: + return self.cook(value) + else: + return value + + def __init__(self, desc, default, cmd=False, odesc=False, + env=False, cf=False, cook=False, long_arg=False): + self.desc = desc + self.default = default + self.cmd = cmd + self.long = long_arg + if not self.long: + if cmd and (cmd[0] != '-' or len(cmd) != 2): + raise OptionFailure("Poorly formed command %s" % cmd) + else: + if cmd and (not cmd.startswith('--')): + raise OptionFailure("Poorly formed command %s" % cmd) + self.odesc = odesc + self.env = env + self.cf = cf + self.boolean = False + if not odesc and not cook and isinstance(self.default, bool): + self.boolean = True + self.cook = cook + + def buildHelpMessage(self): + vals = [] + if not self.cmd: + return '' + if self.odesc: + if self.long: + vals.append("%s=%s" % (self.cmd, self.odesc)) + else: + vals.append("%s %s" % (self.cmd, self.odesc)) + else: + vals.append(self.cmd) + vals.append(self.desc) + return " %-28s %s\n" % tuple(vals) + + def buildGetopt(self): + gstr = '' + if self.long: + return gstr + if self.cmd: + gstr = self.cmd[1] + if self.odesc: + gstr += ':' + return gstr + + def buildLongGetopt(self): + if self.odesc: + return self.cmd[2:] + '=' + else: + return self.cmd[2:] + + def parse(self, opts, rawopts, configparser=None): + if self.cmd and opts: + # Processing getopted data + optinfo = [opt[1] for opt in opts if opt[0] == self.cmd] + if optinfo: + if optinfo[0]: + self.value = self.get_cooked_value(optinfo[0]) + else: + self.value = True + return + if self.cmd and self.cmd in rawopts: + data = rawopts[rawopts.index(self.cmd) + 1] + self.value = self.get_cooked_value(data) + return + # No command line option found + if self.env and self.env in os.environ: + self.value = self.get_cooked_value(os.environ[self.env]) + return + if self.cf and configparser: + try: + self.value = self.get_cooked_value(configparser.get(*self.cf)) + return + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + pass + # Default value not cooked + self.value = self.default + + +class OptionSet(dict): + def __init__(self, *args, **kwargs): + dict.__init__(self, *args) + self.hm = self.buildHelpMessage() + if 'configfile' in kwargs: + self.cfile = kwargs['configfile'] + else: + self.cfile = DEFAULT_CONFIG_LOCATION + self.cfp = DefaultConfigParser() + if (len(self.cfp.read(self.cfile)) == 0 and + ('quiet' not in kwargs or not kwargs['quiet'])): + print("Warning! Unable to read specified configuration file: %s" % + self.cfile) + + def buildGetopt(self): + return ''.join([opt.buildGetopt() for opt in list(self.values())]) + + def buildLongGetopt(self): + return [opt.buildLongGetopt() for opt in list(self.values()) + if opt.long] + + def buildHelpMessage(self): + if hasattr(self, 'hm'): + return self.hm + hlist = [] # list of _non-empty_ help messages + for opt in list(self.values()): + hm = opt.buildHelpMessage() + if hm: + hlist.append(hm) + return ''.join(hlist) + + def helpExit(self, msg='', code=1): + if msg: + print(msg) + print("Usage:") + print(self.buildHelpMessage()) + raise SystemExit(code) + + def parse(self, argv, do_getopt=True): + '''Parse options from command line.''' + if do_getopt: + try: + opts, args = getopt.getopt(argv, self.buildGetopt(), + self.buildLongGetopt()) + except getopt.GetoptError: + err = sys.exc_info()[1] + self.helpExit(err) + if '-h' in argv: + self.helpExit('', 0) + self['args'] = args + for key in list(self.keys()): + if key == 'args': + continue + option = self[key] + if do_getopt: + option.parse(opts, [], configparser=self.cfp) + else: + option.parse([], argv, configparser=self.cfp) + if hasattr(option, 'value'): + val = option.value + self[key] = val + + +def list_split(c_string): + if c_string: + return re.split("\s*,\s*", c_string) + return [] + + +def colon_split(c_string): + if c_string: + return c_string.split(':') + return [] + + +def get_bool(s): + # these values copied from ConfigParser.RawConfigParser.getboolean + # with the addition of True and False + truelist = ["1", "yes", "True", "true", "on"] + falselist = ["0", "no", "False", "false", "off"] + if s in truelist: + return True + elif s in falselist: + return False + else: + raise ValueError + +""" +Options: + + Accepts keyword argument list with the following values: + + default: default value for the option + cmd: command line switch + odesc: option description + cf: tuple containing section/option + cook: method for parsing option + long_arg: (True|False) specifies whether cmd is a long argument +""" +# General options +CFILE = \ + Option('Specify configuration file', + default=DEFAULT_CONFIG_LOCATION, + cmd='-C', + odesc='<conffile>') +LOCKFILE = \ + Option('Specify lockfile', + default='/var/lock/bcfg2.run', + odesc='<Path to lockfile>', + cf=('components', 'lockfile')) +HELP = \ + Option('Print this usage message', + default=False, + cmd='-h') +DEBUG = \ + Option("Enable debugging output", + default=False, + cmd='-d') +VERBOSE = \ + Option("Enable verbose output", + default=False, + cmd='-v') +DAEMON = \ + Option("Daemonize process, storing pid", + default=None, + cmd='-D', + odesc='<pidfile>') +INSTALL_PREFIX = \ + Option('Installation location', + default=DEFAULT_INSTALL_PREFIX, + odesc='</path>', + cf=('server', 'prefix')) +SENDMAIL_PATH = \ + Option('Path to sendmail', + default='/usr/lib/sendmail', + cf=('reports', 'sendmailpath')) +INTERACTIVE = \ + Option('Run interactively, prompting the user for each change', + default=False, + cmd='-I', ) +ENCODING = \ + Option('Encoding of cfg files', + default='UTF-8', + cmd='-E', + odesc='<encoding>', + cf=('components', 'encoding')) +PARANOID_PATH = \ + Option('Specify path for paranoid file backups', + default='/var/cache/bcfg2', + odesc='<paranoid backup path>', + cf=('paranoid', 'path')) +PARANOID_MAX_COPIES = \ + Option('Specify the number of paranoid copies you want', + default=1, + odesc='<max paranoid copies>', + cf=('paranoid', 'max_copies')) +OMIT_LOCK_CHECK = \ + Option('Omit lock check', + default=False, + cmd='-O') +CORE_PROFILE = \ + Option('profile', + default=False, + cmd='-p') +SCHEMA_PATH = \ + Option('Path to XML Schema files', + default='%s/share/bcfg2/schemas' % DEFAULT_INSTALL_PREFIX, + cmd='--schema', + odesc='<schema path>', + long_arg=True) + +# Metadata options (mdata section) +MDATA_OWNER = \ + Option('Default Path owner', + default='root', + odesc='owner permissions', + cf=('mdata', 'owner')) +MDATA_GROUP = \ + Option('Default Path group', + default='root', + odesc='group permissions', + cf=('mdata', 'group')) +MDATA_IMPORTANT = \ + Option('Default Path priority (importance)', + default='False', + odesc='Important entries are installed first', + cf=('mdata', 'important')) +MDATA_PERMS = \ + Option('Default Path permissions', + default='644', + odesc='octal permissions', + cf=('mdata', 'perms')) +MDATA_PARANOID = \ + Option('Default Path paranoid setting', + default='true', + odesc='Path paranoid setting', + cf=('mdata', 'paranoid')) +MDATA_SENSITIVE = \ + Option('Default Path sensitive setting', + default='false', + odesc='Path sensitive setting', + cf=('mdata', 'sensitive')) + +# Server options +SERVER_REPOSITORY = \ + Option('Server repository path', + default='/var/lib/bcfg2', + cmd='-Q', + odesc='<repository path>', + cf=('server', 'repository')) +SERVER_PLUGINS = \ + Option('Server plugin list', + # default server plugins + default=['Bundler', 'Cfg', 'Metadata', 'Pkgmgr', 'Rules', 'SSHbase'], + cf=('server', 'plugins'), + cook=list_split) +SERVER_MCONNECT = \ + Option('Server Metadata Connector list', + default=['Probes'], + cf=('server', 'connectors'), + cook=list_split) +SERVER_FILEMONITOR = \ + Option('Server file monitor', + default='default', + odesc='File monitoring driver', + cf=('server', 'filemonitor')) +SERVER_FAM_IGNORE = \ + Option('File globs to ignore', + default=['*~', '*#', '.#*', '*.swp', '.*.swx', 'SCCS', '.svn', + '4913', '.gitignore',], + cf=('server', 'ignore_files'), + cook=list_split) +SERVER_LISTEN_ALL = \ + Option('Listen on all interfaces', + default=False, + cmd='--listen-all', + cf=('server', 'listen_all'), + cook=get_bool, + long_arg=True) +SERVER_LOCATION = \ + Option('Server Location', + default='https://localhost:6789', + cmd='-S', + odesc='https://server:port', + cf=('components', 'bcfg2')) +SERVER_STATIC = \ + Option('Server runs on static port', + default=False, + cf=('components', 'bcfg2')) +SERVER_KEY = \ + Option('Path to SSL key', + default=None, + cmd='--ssl-key', + odesc='<ssl key>', + cf=('communication', 'key'), + long_arg=True) +SERVER_CERT = \ + Option('Path to SSL certificate', + default='/etc/bcfg2.key', + odesc='<ssl cert>', + cf=('communication', 'certificate')) +SERVER_CA = \ + Option('Path to SSL CA Cert', + default=None, + odesc='<ca cert>', + cf=('communication', 'ca')) +SERVER_PASSWORD = \ + Option('Communication Password', + default=None, + cmd='-x', + odesc='<password>', + cf=('communication', 'password')) +SERVER_PROTOCOL = \ + Option('Server Protocol', + default='xmlrpc/ssl', + cf=('communication', 'procotol')) + +# Client options +CLIENT_KEY = \ + Option('Path to SSL key', + default=None, + cmd='--ssl-key', + odesc='<ssl key>', + cf=('communication', 'key'), + long_arg=True) +CLIENT_CERT = \ + Option('Path to SSL certificate', + default=None, + cmd='--ssl-cert', + odesc='<ssl cert>', + cf=('communication', 'certificate'), + long_arg=True) +CLIENT_CA = \ + Option('Path to SSL CA Cert', + default=None, + cmd='--ca-cert', + odesc='<ca cert>', + cf=('communication', 'ca'), + long_arg=True) +CLIENT_SCNS = \ + Option('List of server commonNames', + default=None, + cmd='--ssl-cns', + odesc='<CN1:CN2>', + cf=('communication', 'serverCommonNames'), + cook=list_split, + long_arg=True) +CLIENT_PROFILE = \ + Option('Assert the given profile for the host', + default=None, + cmd='-p', + odesc='<profile>') +CLIENT_RETRIES = \ + Option('The number of times to retry network communication', + default='3', + cmd='-R', + odesc='<retry count>', + cf=('communication', 'retries')) +CLIENT_DRYRUN = \ + Option('Do not actually change the system', + default=False, + cmd='-n') +CLIENT_EXTRA_DISPLAY = \ + Option('enable extra entry output', + default=False, + cmd='-e') +CLIENT_PARANOID = \ + Option('Make automatic backups of config files', + default=False, + cmd='-P', + cf=('client', 'paranoid'), + cook=get_bool) +CLIENT_DRIVERS = \ + Option('Specify tool driver set', + default=Bcfg2.Client.Tools.default, + cmd='-D', + odesc='<driver1,driver2>', + cf=('client', 'drivers'), + cook=list_split) +CLIENT_CACHE = \ + Option('Store the configuration in a file', + default=None, + cmd='-c', + odesc='<cache path>') +CLIENT_REMOVE = \ + Option('Force removal of additional configuration items', + default=None, + cmd='-r', + odesc='<entry type|all>') +CLIENT_BUNDLE = \ + Option('Only configure the given bundle(s)', + default=[], + cmd='-b', + odesc='<bundle:bundle>', + cook=colon_split) +CLIENT_SKIPBUNDLE = \ + Option('Configure everything except the given bundle(s)', + default=[], + cmd='-B', + odesc='<bundle:bundle>', + cook=colon_split) +CLIENT_BUNDLEQUICK = \ + Option('Only verify/configure the given bundle(s)', + default=False, + cmd='-Q') +CLIENT_INDEP = \ + Option('Only configure independent entries, ignore bundles', + default=False, + cmd='-z') +CLIENT_SKIPINDEP = \ + Option('Do not configure independent entries', + default=False, + cmd='-Z') +CLIENT_KEVLAR = \ + Option('Run in kevlar (bulletproof) mode', + default=False, + cmd='-k', ) +CLIENT_FILE = \ + Option('Configure from a file rather than querying the server', + default=None, + cmd='-f', + odesc='<specification path>') +CLIENT_QUICK = \ + Option('Disable some checksum verification', + default=False, + cmd='-q') +CLIENT_USER = \ + Option('The user to provide for authentication', + default='root', + cmd='-u', + odesc='<user>', + cf=('communication', 'user')) +CLIENT_SERVICE_MODE = \ + Option('Set client service mode', + default='default', + cmd='-s', + odesc='<default|disabled|build>') +CLIENT_TIMEOUT = \ + Option('Set the client XML-RPC timeout', + default=90, + cmd='-t', + odesc='<timeout>', + cf=('communication', 'timeout')) +CLIENT_DLIST = \ + Option('Run client in server decision list mode', + default='none', + cmd='-l', + odesc='<whitelist|blacklist|none>', + cf=('client', 'decision')) +CLIENT_DECISION_LIST = \ + Option('Decision List', + default=False, + cmd='--decision-list', + odesc='<file>', + long_arg=True) + +# bcfg2-test and bcfg2-lint options +TEST_NOSEOPTS = \ + Option('Options to pass to nosetests', + default=[], + cmd='--nose-options', + odesc='<opts>', + cf=('bcfg2_test', 'nose_options'), + cook=shlex.split, + long_arg=True) +TEST_IGNORE = \ + Option('Ignore these entries if they fail to build.', + default=[], + cmd='--ignore', + odesc='<Type>:<name>,<Type>:<name>', + cf=('bcfg2_test', 'ignore_entries'), + cook=list_split, + long_arg=True) +LINT_CONFIG = \ + Option('Specify bcfg2-lint configuration file', + default='/etc/bcfg2-lint.conf', + cmd='--lint-config', + odesc='<conffile>', + long_arg=True) +LINT_SHOW_ERRORS = \ + Option('Show error handling', + default=False, + cmd='--list-errors', + long_arg=True) +LINT_FILES_ON_STDIN = \ + Option('Operate on a list of files supplied on stdin', + default=False, + cmd='--stdin', + long_arg=True) + +# individual client tool options +CLIENT_APT_TOOLS_INSTALL_PATH = \ + Option('Apt tools install path', + default='/usr', + cf=('APT', 'install_path')) +CLIENT_APT_TOOLS_VAR_PATH = \ + Option('Apt tools var path', + default='/var', + cf=('APT', 'var_path')) +CLIENT_SYSTEM_ETC_PATH = \ + Option('System etc path', + default='/etc', + cf=('APT', 'etc_path')) +CLIENT_PORTAGE_BINPKGONLY = \ + Option('Portage binary packages only', + default=False, + cf=('Portage', 'binpkgonly'), + cook=get_bool) +CLIENT_RPMNG_INSTALLONLY = \ + Option('RPMng install-only packages', + default=['kernel', 'kernel-bigmem', 'kernel-enterprise', + 'kernel-smp', 'kernel-modules', 'kernel-debug', + 'kernel-unsupported', 'kernel-devel', 'kernel-source', + 'kernel-default', 'kernel-largesmp-devel', + 'kernel-largesmp', 'kernel-xen', 'gpg-pubkey'], + cf=('RPMng', 'installonlypackages'), + cook=list_split) +CLIENT_RPMNG_PKG_CHECKS = \ + Option("Perform RPMng package checks", + default=True, + cf=('RPMng', 'pkg_checks'), + cook=get_bool) +CLIENT_RPMNG_PKG_VERIFY = \ + Option("Perform RPMng package verify", + default=True, + cf=('RPMng', 'pkg_verify'), + cook=get_bool) +CLIENT_RPMNG_INSTALLED_ACTION = \ + Option("RPMng installed action", + default="install", + cf=('RPMng', 'installed_action')) +CLIENT_RPMNG_ERASE_FLAGS = \ + Option("RPMng erase flags", + default=["allmatches"], + cf=('RPMng', 'erase_flags'), + cook=list_split) +CLIENT_RPMNG_VERSION_FAIL_ACTION = \ + Option("RPMng version fail action", + default="upgrade", + cf=('RPMng', 'version_fail_action')) +CLIENT_RPMNG_VERIFY_FAIL_ACTION = \ + Option("RPMng verify fail action", + default="reinstall", + cf=('RPMng', 'verify_fail_action')) +CLIENT_RPMNG_VERIFY_FLAGS = \ + Option("RPMng verify flags", + default=[], + cf=('RPMng', 'verify_flags'), + cook=list_split) +CLIENT_YUM24_INSTALLONLY = \ + Option('RPMng install-only packages', + default=['kernel', 'kernel-bigmem', 'kernel-enterprise', + 'kernel-smp', 'kernel-modules', 'kernel-debug', + 'kernel-unsupported', 'kernel-devel', 'kernel-source', + 'kernel-default', 'kernel-largesmp-devel', + 'kernel-largesmp', 'kernel-xen', 'gpg-pubkey'], + cf=('RPMng', 'installonlypackages'), + cook=list_split) +CLIENT_YUM24_PKG_CHECKS = \ + Option("Perform YUM24 package checks", + default=True, + cf=('YUM24', 'pkg_checks'), + cook=get_bool) +CLIENT_YUM24_PKG_VERIFY = \ + Option("Perform YUM24 package verify", + default=True, + cf=('YUM24', 'pkg_verify'), + cook=get_bool) +CLIENT_YUM24_INSTALLED_ACTION = \ + Option("YUM24 installed action", + default="install", + cf=('YUM24', 'installed_action')) +CLIENT_YUM24_ERASE_FLAGS = \ + Option("YUM24 erase flags", + default=["allmatches"], + cf=('YUM24', 'erase_flags'), + cook=list_split) +CLIENT_YUM24_VERSION_FAIL_ACTION = \ + Option("YUM24 version fail action", + cf=('YUM24', 'version_fail_action'), + default="upgrade") +CLIENT_YUM24_VERIFY_FAIL_ACTION = \ + Option("YUM24 verify fail action", + default="reinstall", + cf=('YUM24', 'verify_fail_action')) +CLIENT_YUM24_VERIFY_FLAGS = \ + Option("YUM24 verify flags", + default=[], + cf=('YUM24', 'verify_flags'), + cook=list_split) +CLIENT_YUM24_AUTODEP = \ + Option("YUM24 autodependency processing", + default=True, + cf=('YUM24', 'autodep'), + cook=get_bool) +CLIENT_YUMNG_PKG_CHECKS = \ + Option("Perform YUMng package checks", + default=True, + cf=('YUMng', 'pkg_checks'), + cook=get_bool) +CLIENT_YUMNG_PKG_VERIFY = \ + Option("Perform YUMng package verify", + default=True, + cf=('YUMng', 'pkg_verify'), + cook=get_bool) +CLIENT_YUMNG_INSTALLED_ACTION = \ + Option("YUMng installed action", + default="install", + cf=('YUMng', 'installed_action')) +CLIENT_YUMNG_VERSION_FAIL_ACTION = \ + Option("YUMng version fail action", + default="upgrade", + cf=('YUMng', 'version_fail_action')) +CLIENT_YUMNG_VERIFY_FAIL_ACTION = \ + Option("YUMng verify fail action", + default="reinstall", + cf=('YUMng', 'verify_fail_action')) +CLIENT_YUMNG_VERIFY_FLAGS = \ + Option("YUMng verify flags", + default=[], + cf=('YUMng', 'verify_flags'), + cook=list_split) + +# Logging options +LOGGING_FILE_PATH = \ + Option('Set path of file log', + default=None, + cmd='-o', + odesc='<path>', + cf=('logging', 'path')) + +# Plugin-specific options +CFG_VALIDATION = \ + Option('Run validation on Cfg files', + default=True, + cmd='--cfg-validation', + cf=('cfg', 'validation'), + long_arg=True, + cook=get_bool) + +# bcfg2-crypt options +ENCRYPT = \ + Option('Encrypt the specified file', + default=False, + cmd='--encrypt', + long_arg=True) +DECRYPT = \ + Option('Decrypt the specified file', + default=False, + cmd='--decrypt', + long_arg=True) +CRYPT_PASSPHRASE = \ + Option('Encryption passphrase (name or passphrase)', + default=None, + cmd='-p', + odesc='<passphrase>') +CRYPT_XPATH = \ + Option('XPath expression to select elements to encrypt', + default=None, + cmd='--xpath', + odesc='<xpath>', + long_arg=True) +CRYPT_PROPERTIES = \ + Option('Encrypt the specified file as a Properties file', + default=False, + cmd="--properties", + long_arg=True) +CRYPT_CFG = \ + Option('Encrypt the specified file as a Cfg file', + default=False, + cmd="--cfg", + long_arg=True) +CRYPT_REMOVE = \ + Option('Remove the plaintext file after encrypting', + default=False, + cmd="--remove", + long_arg=True) + +# Option groups +CLI_COMMON_OPTIONS = dict(configfile=CFILE, + debug=DEBUG, + help=HELP, + verbose=VERBOSE, + encoding=ENCODING, + logging=LOGGING_FILE_PATH) + +DAEMON_COMMON_OPTIONS = dict(daemon=DAEMON, + listen_all=SERVER_LISTEN_ALL) + +SERVER_COMMON_OPTIONS = dict(repo=SERVER_REPOSITORY, + plugins=SERVER_PLUGINS, + password=SERVER_PASSWORD, + filemonitor=SERVER_FILEMONITOR, + ignore=SERVER_FAM_IGNORE, + location=SERVER_LOCATION, + static=SERVER_STATIC, + key=SERVER_KEY, + cert=SERVER_CERT, + ca=SERVER_CA, + protocol=SERVER_PROTOCOL) + +CRYPT_OPTIONS = dict(encrypt=ENCRYPT, + decrypt=DECRYPT, + passphrase=CRYPT_PASSPHRASE, + xpath=CRYPT_XPATH, + properties=CRYPT_PROPERTIES, + cfg=CRYPT_CFG, + remove=CRYPT_REMOVE) + +DRIVER_OPTIONS = \ + dict(apt_install_path=CLIENT_APT_TOOLS_INSTALL_PATH, + apt_var_path=CLIENT_APT_TOOLS_VAR_PATH, + apt_etc_path=CLIENT_SYSTEM_ETC_PATH, + portage_binpkgonly=CLIENT_PORTAGE_BINPKGONLY, + rpmng_installonly=CLIENT_RPMNG_INSTALLONLY, + rpmng_pkg_checks=CLIENT_RPMNG_PKG_CHECKS, + rpmng_pkg_verify=CLIENT_RPMNG_PKG_VERIFY, + rpmng_installed_action=CLIENT_RPMNG_INSTALLED_ACTION, + rpmng_erase_flags=CLIENT_RPMNG_ERASE_FLAGS, + rpmng_version_fail_action=CLIENT_RPMNG_VERSION_FAIL_ACTION, + rpmng_verify_fail_action=CLIENT_RPMNG_VERIFY_FAIL_ACTION, + rpmng_verify_flags=CLIENT_RPMNG_VERIFY_FLAGS, + yum24_installonly=CLIENT_YUM24_INSTALLONLY, + yum24_pkg_checks=CLIENT_YUM24_PKG_CHECKS, + yum24_pkg_verify=CLIENT_YUM24_PKG_VERIFY, + yum24_installed_action=CLIENT_YUM24_INSTALLED_ACTION, + yum24_erase_flags=CLIENT_YUM24_ERASE_FLAGS, + yum24_version_fail_action=CLIENT_YUM24_VERSION_FAIL_ACTION, + yum24_verify_fail_action=CLIENT_YUM24_VERIFY_FAIL_ACTION, + yum24_verify_flags=CLIENT_YUM24_VERIFY_FLAGS, + yum24_autodep=CLIENT_YUM24_AUTODEP, + yumng_pkg_checks=CLIENT_YUMNG_PKG_CHECKS, + yumng_pkg_verify=CLIENT_YUMNG_PKG_VERIFY, + yumng_installed_action=CLIENT_YUMNG_INSTALLED_ACTION, + yumng_version_fail_action=CLIENT_YUMNG_VERSION_FAIL_ACTION, + yumng_verify_fail_action=CLIENT_YUMNG_VERIFY_FAIL_ACTION, + yumng_verify_flags=CLIENT_YUMNG_VERIFY_FLAGS) + +class OptionParser(OptionSet): + """ + OptionParser bootstraps option parsing, + getting the value of the config file + """ + def __init__(self, args): + self.Bootstrap = OptionSet([('configfile', CFILE)], quiet=True) + self.Bootstrap.parse(sys.argv[1:], do_getopt=False) + OptionSet.__init__(self, args, configfile=self.Bootstrap['configfile']) + self.optinfo = copy.copy(args) + + def HandleEvent(self, event): + if 'configfile' not in self or not isinstance(self['configfile'], str): + # we haven't parsed options yet, or CFILE wasn't included + # in the options + return + if event.filename != self['configfile']: + print("Got event for unknown file: %s" % event.filename) + return + if event.code2str() == 'deleted': + return + self.reparse() + + def reparse(self): + for key, opt in self.optinfo.items(): + self[key] = opt + if "args" not in self.optinfo: + del self['args'] + self.parse(self.argv, self.do_getopt) + + def parse(self, argv, do_getopt=True): + self.argv = argv + self.do_getopt = do_getopt + OptionSet.parse(self, self.argv, do_getopt=self.do_getopt) + + def add_option(self, name, opt): + self[name] = opt + self.optinfo[name] = opt + + def update(self, optdict): + dict.update(self, optdict) + self.optinfo.update(optdict) |