diff options
author | Fabian Affolter <fabian@bernewireless.net> | 2010-12-08 23:27:15 +0100 |
---|---|---|
committer | Fabian Affolter <fabian@bernewireless.net> | 2010-12-08 23:27:15 +0100 |
commit | e833a7a76b231cd346f09c9a422ecb855d1cc6b4 (patch) | |
tree | e2762fc31e1162a6859dbd6cd7b5c28208296d9d /build/lib/Bcfg2/Options.py | |
parent | baf5854f414c2a35887e3fbbcfd094e12e7c6ee7 (diff) | |
download | bcfg2-e833a7a76b231cd346f09c9a422ecb855d1cc6b4.tar.gz bcfg2-e833a7a76b231cd346f09c9a422ecb855d1cc6b4.tar.bz2 bcfg2-e833a7a76b231cd346f09c9a422ecb855d1cc6b4.zip |
Merge with upstream
Diffstat (limited to 'build/lib/Bcfg2/Options.py')
-rw-r--r-- | build/lib/Bcfg2/Options.py | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/build/lib/Bcfg2/Options.py b/build/lib/Bcfg2/Options.py new file mode 100644 index 000000000..1dcad6427 --- /dev/null +++ b/build/lib/Bcfg2/Options.py @@ -0,0 +1,334 @@ +"""Option parsing library for utilities.""" +__revision__ = '$Revision$' + +import ConfigParser +import getopt +import os +import sys +import Bcfg2.Client.Tools + +def bool_cook(x): + if x: + return True + else: + return False + +class OptionFailure(Exception): + pass + +DEFAULT_CONFIG_LOCATION = '/etc/bcfg2.conf' #/etc/bcfg2.conf +DEFAULT_INSTALL_PREFIX = '/usr' #/usr + +class Option(object): + cfpath = DEFAULT_CONFIG_LOCATION + __cfp = False + + def getCFP(self): + if not self.__cfp: + self.__cfp = ConfigParser.ConfigParser() + self.__cfp.readfp(open(self.cfpath)) + return self.__cfp + cfp = property(getCFP) + + 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: + self.boolean = True + self.cook = cook + + def buildHelpMessage(self): + msg = '' + if self.cmd: + if not self.long: + msg = self.cmd.ljust(3) + else: + msg = self.cmd + if self.odesc: + if self.long: + msg = "%-28s" % ("%s=%s" % (self.cmd, self.odesc)) + else: + msg += '%-25s' % (self.odesc) + else: + msg += '%-25s' % ('') + msg += "%s\n" % self.desc + return msg + + 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): + 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: + try: + self.value = self.get_cooked_value(self.cfp.get(*self.cf)) + return + except: + pass + # default value not cooked + self.value = self.default + +class OptionSet(dict): + def __init__(self, *args): + dict.__init__(self, *args) + self.hm = self.buildHelpMessage() + + 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 + return ' '.join([opt.buildHelpMessage() for opt in list(self.values())]) + + def helpExit(self, msg='', code=1): + if msg: + print(msg) + print("Usage:\n %s" % self.buildHelpMessage()) + raise SystemExit(code) + + def parse(self, argv, do_getopt=True): + '''Parse options''' + if do_getopt: + try: + opts, args = getopt.getopt(argv, self.buildGetopt(), + self.buildLongGetopt()) + except getopt.GetoptError, err: + 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, []) + else: + option.parse([], argv) + if hasattr(option, 'value'): + val = option.value + self[key] = val + +list_split = lambda x:x.replace(' ','').split(',') +flist_split = lambda x:list_split(x.replace(':', '').lower()) + +def colon_split(c_string): + if c_string: + return c_string.split(':') + return [] + +#General options +CFILE = Option('Specify configuration file', DEFAULT_CONFIG_LOCATION, cmd='-C', + odesc='<conffile>') +LOCKFILE = Option('Specify lockfile', + "/var/lock/bcfg2.run", + cf=('components', 'lockfile'), + odesc='<Path to lockfile>') +HELP = Option('Print this usage message', False, cmd='-h') +DEBUG = Option("Enable debugging output", False, cmd='-d') +VERBOSE = Option("Enable verbose output", False, cmd='-v') +DAEMON = Option("Daemonize process, storing pid", False, + cmd='-D', odesc="<pidfile>") +INSTALL_PREFIX = Option('Installation location', cf=('server', 'prefix'), + default=DEFAULT_INSTALL_PREFIX, odesc='</path>') +SENDMAIL_PATH = Option('Path to sendmail', cf=('reports', 'sendmailpath'), + default='/usr/lib/sendmail') +INTERACTIVE = Option('prompt the user for each change', default=False, + cmd='-I', ) +ENCODING = Option('Encoding of cfg files', default=sys.getdefaultencoding(), + cmd='-E', odesc='<encoding>', + cf=('components', 'encoding')) +PARANOID_PATH = Option('Specify path for paranoid file backups', + default='/var/cache/bcfg2', cf=('paranoid', 'path'), + odesc='<paranoid backup path>') +PARANOID_MAX_COPIES = Option('Specify the number of paranoid copies you want', + default=1, cf=('paranoid', 'max_copies'), + odesc='<max paranoid copies>') +OMIT_LOCK_CHECK = Option('Omit lock check', default=False, cmd='-O') +CORE_PROFILE = Option('profile', + default=False, cmd='-p', ) + +#Metadata options +MDATA_OWNER = Option('Default Path owner', + default='root', cf=('mdata', 'owner'), + odesc='owner permissions') +MDATA_GROUP = Option('Default Path group', + default='root', cf=('mdata', 'group'), + odesc='group permissions') +MDATA_IMPORTANT = Option('Default Path priority (importance)', + default='False', cf=('mdata', 'important'), + odesc='Important entries are installed first') +MDATA_PERMS = Option('Default Path permissions', + '644', cf=('mdata', 'perms'), + odesc='octal permissions') +MDATA_PARANOID = Option('Default Path paranoid setting', + 'false', cf=('mdata', 'paranoid'), + odesc='Path paranoid setting') + +#Server options +SERVER_REPOSITORY = Option('Server repository path', '/var/lib/bcfg2', + cf=('server', 'repository'), cmd='-Q', + odesc='<repository path>') +SERVER_PLUGINS = Option('Server plugin list', cf=('server', 'plugins'), + # default server plugins + default=[ + 'Base', + 'Bundler', + 'Cfg', + 'Metadata', + 'Pkgmgr', + 'Rules', + 'SSHbase', + ], + cook=list_split) +SERVER_MCONNECT = Option('Server Metadata Connector list', cook=list_split, + cf=('server', 'connectors'), default=['Probes'], ) +SERVER_FILEMONITOR = Option('Server file monitor', cf=('server', 'filemonitor'), + default='default', odesc='File monitoring driver') +SERVER_LOCATION = Option('Server Location', cf=('components', 'bcfg2'), + default='https://localhost:6789', cmd='-S', + odesc='https://server:port') +SERVER_STATIC = Option('Server runs on static port', cf=('components', 'bcfg2'), + default=False, cook=bool_cook) +SERVER_KEY = Option('Path to SSL key', cf=('communication', 'key'), + default=False, cmd='--ssl-key', odesc='<ssl key>', + long_arg=True) +SERVER_CERT = Option('Path to SSL certificate', default='/etc/bcfg2.key', + cf=('communication', 'certificate'), odesc='<ssl cert>') +SERVER_CA = Option('Path to SSL CA Cert', default=None, + cf=('communication', 'ca'), odesc='<ca cert>') +SERVER_PASSWORD = Option('Communication Password', cmd='-x', odesc='<password>', + cf=('communication', 'password'), default=False) +SERVER_PROTOCOL = Option('Server Protocol', cf=('communication', 'procotol'), + default='xmlrpc/ssl') +#Client options +CLIENT_KEY = Option('Path to SSL key', cf=('communication', 'key'), + default=None, cmd="--ssl-key", odesc='<ssl key>', + long_arg=True) +CLIENT_CERT = Option('Path to SSL certificate', default=None, cmd="--ssl-cert", + cf=('communication', 'certificate'), odesc='<ssl cert>', + long_arg=True) +CLIENT_CA = Option('Path to SSL CA Cert', default=None, cmd="--ca-cert", + cf=('communication', 'ca'), odesc='<ca cert>', + long_arg=True) +CLIENT_SCNS = Option('list of server commonNames', default=None, cmd="--ssl-cns", + cf=('communication', 'serverCommonNames'), + odesc='<commonName1:commonName2>', cook=list_split, + long_arg=True) +CLIENT_PROFILE = Option('assert the given profile for the host', + default=False, cmd='-p', odesc="<profile>") +CLIENT_RETRIES = Option('the number of times to retry network communication', + default='3', cmd='-R', cf=('communication', 'retries'), + odesc="<retry count>") +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')) +CLIENT_DRIVERS = Option('Specify tool driver set', cmd='-D', + cf=('client', 'drivers'), + odesc="<driver1,driver2>", cook=list_split, + default=Bcfg2.Client.Tools.default) +CLIENT_CACHE = Option('store the configuration in a file', + default=False, cmd='-c', odesc="<cache path>") +CLIENT_REMOVE = Option('force removal of additional configuration items', + default=False, 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_BUNDLEQUICK = Option('only verify/configure the given bundle(s)', default=False, + cmd='-Q') +CLIENT_INDEP = Option('only configure the given bundle(s)', default=False, + cmd='-z') +CLIENT_KEVLAR = Option('run in kevlar (bulletproof) mode', default=False, + cmd='-k', ) +CLIENT_DLIST = Option('run client in server decision list mode', default=False, + cmd='-l', odesc='<whitelist|blacklist>') +CLIENT_FILE = Option('configure from a file rather than querying the server', + default=False, 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', cf=('communication', 'user'), odesc='<user>') +CLIENT_SERVICE_MODE = Option('Set client service mode', default='default', + cmd='-s', odesc='<default|disabled|build>') + +# APT client tool options +CLIENT_APT_TOOLS_INSTALL_PATH = Option('Apt tools install path', + cf=('APT', 'install_path'), + default='/usr') +CLIENT_APT_TOOLS_VAR_PATH = Option('Apt tools var path', + cf=('APT', 'var_path'), default='/var') +CLIENT_SYSTEM_ETC_PATH = Option('System etc path', cf=('APT', 'etc_path'), + default='/etc') + +#Logging options +LOGGING_FILE_PATH = Option('Set path of file log', default=None, + cmd='-o', odesc='<path>', cf=('logging', 'path')) + +class OptionParser(OptionSet): + """ + OptionParser bootstraps option parsing, + getting the value of the config file + """ + def __init__(self, args): + self.Bootstrap = OptionSet([('configfile', CFILE)]) + self.Bootstrap.parse(sys.argv[1:], do_getopt=False) + if self.Bootstrap['configfile'] != Option.cfpath: + Option.cfpath = self.Bootstrap['configfile'] + Option.__cfp = False + OptionSet.__init__(self, args) |