From ebe7542db7217c2fac3d7111e80f94caedfb69e2 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 16 Jan 2013 13:28:06 -0500 Subject: added module-level OptionParser to avoid passing it as an argument or global all over --- src/lib/Bcfg2/Server/Admin/Compare.py | 4 +- src/lib/Bcfg2/Server/Admin/Init.py | 24 ++++---- src/lib/Bcfg2/Server/Admin/Perf.py | 22 ++++---- src/lib/Bcfg2/Server/Admin/Pull.py | 4 +- src/lib/Bcfg2/Server/Admin/Reports.py | 4 +- src/lib/Bcfg2/Server/Admin/Snapshots.py | 4 +- src/lib/Bcfg2/Server/Admin/Syncdb.py | 10 ++-- src/lib/Bcfg2/Server/Admin/Xcmd.py | 29 +++++----- src/lib/Bcfg2/Server/Admin/__init__.py | 20 +++---- src/lib/Bcfg2/Server/BuiltinCore.py | 4 +- src/lib/Bcfg2/Server/CherryPyCore.py | 4 +- src/lib/Bcfg2/Server/Core.py | 65 +++++++++++----------- src/lib/Bcfg2/Server/Plugin/helpers.py | 33 ++++++----- src/lib/Bcfg2/Server/Plugins/Bundler.py | 19 +++---- .../Plugins/Cfg/CfgAuthorizedKeysGenerator.py | 8 +-- .../Server/Plugins/Cfg/CfgCheetahGenerator.py | 4 +- .../Server/Plugins/Cfg/CfgEncryptedGenerator.py | 8 +-- .../Plugins/Cfg/CfgEncryptedGenshiGenerator.py | 7 +-- .../Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py | 14 ++--- .../Server/Plugins/Cfg/CfgPrivateKeyCreator.py | 34 +++++------ src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py | 29 ++++------ src/lib/Bcfg2/Server/Plugins/Properties.py | 22 +++----- src/lib/Bcfg2/Server/models.py | 13 ++--- 23 files changed, 179 insertions(+), 206 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Admin/Compare.py b/src/lib/Bcfg2/Server/Admin/Compare.py index c56dd0a8f..820271a2f 100644 --- a/src/lib/Bcfg2/Server/Admin/Compare.py +++ b/src/lib/Bcfg2/Server/Admin/Compare.py @@ -9,8 +9,8 @@ class Compare(Bcfg2.Server.Admin.Mode): __usage__ = (" \n\n" " -r\trecursive") - def __init__(self, setup): - Bcfg2.Server.Admin.Mode.__init__(self, setup) + def __init__(self): + Bcfg2.Server.Admin.Mode.__init__(self) self.important = {'Path': ['name', 'type', 'owner', 'group', 'mode', 'important', 'paranoid', 'sensitive', 'dev_type', 'major', 'minor', 'prune', diff --git a/src/lib/Bcfg2/Server/Admin/Init.py b/src/lib/Bcfg2/Server/Admin/Init.py index 14065980d..cf4bd4c0c 100644 --- a/src/lib/Bcfg2/Server/Admin/Init.py +++ b/src/lib/Bcfg2/Server/Admin/Init.py @@ -143,14 +143,9 @@ def create_conf(confpath, confdata): class Init(Bcfg2.Server.Admin.Mode): """Interactively initialize a new repository.""" - options = {'configfile': Bcfg2.Options.CFILE, - 'plugins': Bcfg2.Options.SERVER_PLUGINS, - 'proto': Bcfg2.Options.SERVER_PROTOCOL, - 'repo': Bcfg2.Options.SERVER_REPOSITORY, - 'sendmail': Bcfg2.Options.SENDMAIL_PATH} - - def __init__(self, setup): - Bcfg2.Server.Admin.Mode.__init__(self, setup) + + def __init__(self): + Bcfg2.Server.Admin.Mode.__init__(self) self.data = dict() self.plugins = Bcfg2.Options.SERVER_PLUGINS.default @@ -177,9 +172,16 @@ class Init(Bcfg2.Server.Admin.Mode): Bcfg2.Server.Admin.Mode.__call__(self, args) # Parse options - opts = Bcfg2.Options.OptionParser(self.options) - opts.parse(args) - self._set_defaults(opts) + setup = Bcfg2.Options.get_option_parser() + setup.add_options(dict(configfile=Bcfg2.Options.CFILE, + plugins=Bcfg2.Options.SERVER_PLUGINS, + proto=Bcfg2.Options.SERVER_PROTOCOL, + repo=Bcfg2.Options.SERVER_REPOSITORY, + sendmail=Bcfg2.Options.SENDMAIL_PATH)) + opts = sys.argv[1:] + opts.remove(self.__class__.__name__.lower()) + setup.reparse(argv=opts) + self._set_defaults(setup) # Prompt the user for input self._prompt_config() diff --git a/src/lib/Bcfg2/Server/Admin/Perf.py b/src/lib/Bcfg2/Server/Admin/Perf.py index 86eb6810d..7448855ce 100644 --- a/src/lib/Bcfg2/Server/Admin/Perf.py +++ b/src/lib/Bcfg2/Server/Admin/Perf.py @@ -11,17 +11,17 @@ class Perf(Bcfg2.Server.Admin.Mode): def __call__(self, args): output = [('Name', 'Min', 'Max', 'Mean', 'Count')] - optinfo = { - 'ca': Bcfg2.Options.CLIENT_CA, - 'certificate': Bcfg2.Options.CLIENT_CERT, - 'key': Bcfg2.Options.SERVER_KEY, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'server': Bcfg2.Options.SERVER_LOCATION, - 'user': Bcfg2.Options.CLIENT_USER, - 'timeout': Bcfg2.Options.CLIENT_TIMEOUT, - } - setup = Bcfg2.Options.OptionParser(optinfo) - setup.parse(sys.argv[1:]) + setup = Bcfg2.Options.get_option_parser() + setup.add_options(dict(ca=Bcfg2.Options.CLIENT_CA, + certificate=Bcfg2.Options.CLIENT_CERT, + key=Bcfg2.Options.SERVER_KEY, + password=Bcfg2.Options.SERVER_PASSWORD, + server=Bcfg2.Options.SERVER_LOCATION, + user=Bcfg2.Options.CLIENT_USER, + timeout=Bcfg2.Options.CLIENT_TIMEOUT)) + opts = sys.argv[1:] + opts.remove(self.__class__.__name__.lower()) + setup.reparse(argv=opts) proxy = Bcfg2.Proxy.ComponentProxy(setup['server'], setup['user'], setup['password'], diff --git a/src/lib/Bcfg2/Server/Admin/Pull.py b/src/lib/Bcfg2/Server/Admin/Pull.py index 130e85b67..1905fac3c 100644 --- a/src/lib/Bcfg2/Server/Admin/Pull.py +++ b/src/lib/Bcfg2/Server/Admin/Pull.py @@ -22,8 +22,8 @@ class Pull(Bcfg2.Server.Admin.MetadataCore): "-I", "interactive", "-s", "stdin")) - def __init__(self, setup): - Bcfg2.Server.Admin.MetadataCore.__init__(self, setup) + def __init__(self): + Bcfg2.Server.Admin.MetadataCore.__init__(self) self.log = False self.mode = 'interactive' diff --git a/src/lib/Bcfg2/Server/Admin/Reports.py b/src/lib/Bcfg2/Server/Admin/Reports.py index 6e313e84b..bb5ee352b 100644 --- a/src/lib/Bcfg2/Server/Admin/Reports.py +++ b/src/lib/Bcfg2/Server/Admin/Reports.py @@ -69,8 +69,8 @@ class Reports(Bcfg2.Server.Admin.Mode): " Django commands:\n " \ + "\n ".join(django_commands)) - def __init__(self, setup): - Bcfg2.Server.Admin.Mode.__init__(self, setup) + def __init__(self): + Bcfg2.Server.Admin.Mode.__init__(self) try: import south except ImportError: diff --git a/src/lib/Bcfg2/Server/Admin/Snapshots.py b/src/lib/Bcfg2/Server/Admin/Snapshots.py index c2d279391..bf44d1451 100644 --- a/src/lib/Bcfg2/Server/Admin/Snapshots.py +++ b/src/lib/Bcfg2/Server/Admin/Snapshots.py @@ -21,8 +21,8 @@ class Snapshots(Bcfg2.Server.Admin.Mode): 'package': Package, 'snapshot': Snapshot} - def __init__(self, setup): - Bcfg2.Server.Admin.Mode.__init__(self, setup) + def __init__(self): + Bcfg2.Server.Admin.Mode.__init__(self) self.session = Bcfg2.Server.Snapshots.setup_session(self.configfile) self.cfile = self.configfile diff --git a/src/lib/Bcfg2/Server/Admin/Syncdb.py b/src/lib/Bcfg2/Server/Admin/Syncdb.py index 4ba840b86..84ad93ae0 100644 --- a/src/lib/Bcfg2/Server/Admin/Syncdb.py +++ b/src/lib/Bcfg2/Server/Admin/Syncdb.py @@ -8,15 +8,17 @@ from django.core.management import setup_environ, call_command class Syncdb(Bcfg2.Server.Admin.Mode): """ Sync the Django ORM with the configured database """ - options = {'configfile': Bcfg2.Options.WEB_CFILE} def __call__(self, args): # Parse options - opts = Bcfg2.Options.OptionParser(self.options) - opts.parse(args) + setup = Bcfg2.Options.get_option_parser() + setup.add_option("web_configfile", Bcfg2.Options.WEB_CFILE) + opts = sys.argv[1:] + opts.remove(self.__class__.__name__.lower()) + setup.reparse(argv=opts) setup_environ(Bcfg2.settings) - Bcfg2.Server.models.load_models(cfile=opts['configfile']) + Bcfg2.Server.models.load_models(cfile=setup['web_configfile']) try: call_command("syncdb", interactive=False, verbosity=0) diff --git a/src/lib/Bcfg2/Server/Admin/Xcmd.py b/src/lib/Bcfg2/Server/Admin/Xcmd.py index 79eeebc7c..7f9f32816 100644 --- a/src/lib/Bcfg2/Server/Admin/Xcmd.py +++ b/src/lib/Bcfg2/Server/Admin/Xcmd.py @@ -12,17 +12,17 @@ class Xcmd(Bcfg2.Server.Admin.Mode): __usage__ = "" def __call__(self, args): - optinfo = { - 'server': Bcfg2.Options.SERVER_LOCATION, - 'user': Bcfg2.Options.CLIENT_USER, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'key': Bcfg2.Options.SERVER_KEY, - 'certificate': Bcfg2.Options.CLIENT_CERT, - 'ca': Bcfg2.Options.CLIENT_CA, - 'timeout': Bcfg2.Options.CLIENT_TIMEOUT, - } - setup = Bcfg2.Options.OptionParser(optinfo) - setup.parse(args) + setup = Bcfg2.Options.get_option_parser() + setup.add_options(dict(ca=Bcfg2.Options.CLIENT_CA, + certificate=Bcfg2.Options.CLIENT_CERT, + key=Bcfg2.Options.SERVER_KEY, + password=Bcfg2.Options.SERVER_PASSWORD, + server=Bcfg2.Options.SERVER_LOCATION, + user=Bcfg2.Options.CLIENT_USER, + timeout=Bcfg2.Options.CLIENT_TIMEOUT)) + opts = sys.argv[1:] + opts.remove(self.__class__.__name__.lower()) + setup.reparse(argv=opts) Bcfg2.Proxy.RetryMethod.max_retries = 1 proxy = Bcfg2.Proxy.ComponentProxy(setup['server'], setup['user'], @@ -34,12 +34,9 @@ class Xcmd(Bcfg2.Server.Admin.Mode): if len(setup['args']) == 0: print("Usage: xcmd ") return - cmd = setup['args'][0] - args = () - if len(setup['args']) > 1: - args = tuple(setup['args'][1:]) + cmd = args[0] try: - data = getattr(proxy, cmd)(*args) + data = getattr(proxy, cmd)(*setup['args']) except xmlrpclib.Fault: flt = sys.exc_info()[1] if flt.faultCode == 7: diff --git a/src/lib/Bcfg2/Server/Admin/__init__.py b/src/lib/Bcfg2/Server/Admin/__init__.py index 19175533f..20577633a 100644 --- a/src/lib/Bcfg2/Server/Admin/__init__.py +++ b/src/lib/Bcfg2/Server/Admin/__init__.py @@ -35,15 +35,15 @@ class Mode(object): __usage__ = None __args__ = [] - def __init__(self, setup): - self.setup = setup - self.configfile = setup['configfile'] + def __init__(self): + self.setup = Bcfg2.Options.get_option_parser() + self.configfile = self.setup['configfile'] self.__cfp = False self.log = logging.getLogger('Bcfg2.Server.Admin.Mode') usage = "bcfg2-admin %s" % self.__class__.__name__.lower() if self.__usage__ is not None: usage += " " + self.__usage__ - setup.hm = usage + self.setup.hm = usage def getCFP(self): """ get a config parser for the Bcfg2 config file """ @@ -129,19 +129,19 @@ class MetadataCore(Mode): __plugin_whitelist__ = None __plugin_blacklist__ = None - def __init__(self, setup): - Mode.__init__(self, setup) + def __init__(self): + Mode.__init__(self) if self.__plugin_whitelist__ is not None: - setup['plugins'] = [p for p in setup['plugins'] + self.setup['plugins'] = [p for p in self.setup['plugins'] if p in self.__plugin_whitelist__] elif self.__plugin_blacklist__ is not None: - setup['plugins'] = [p for p in setup['plugins'] + self.setup['plugins'] = [p for p in self.setup['plugins'] if p not in self.__plugin_blacklist__] # admin modes don't need to watch for changes. one shot is fine here. - setup['filemonitor'] = 'pseudo' + self.setup['filemonitor'] = 'pseudo' try: - self.bcore = Bcfg2.Server.Core.BaseCore(setup) + self.bcore = Bcfg2.Server.Core.BaseCore() except Bcfg2.Server.Core.CoreInitError: msg = sys.exc_info()[1] self.errExit("Core load failed: %s" % msg) diff --git a/src/lib/Bcfg2/Server/BuiltinCore.py b/src/lib/Bcfg2/Server/BuiltinCore.py index 4d7453840..14b64ff40 100644 --- a/src/lib/Bcfg2/Server/BuiltinCore.py +++ b/src/lib/Bcfg2/Server/BuiltinCore.py @@ -22,8 +22,8 @@ class Core(BaseCore): """ The built-in server core """ name = 'bcfg2-server' - def __init__(self, setup): - BaseCore.__init__(self, setup) + def __init__(self): + BaseCore.__init__(self) #: The :class:`Bcfg2.SSLServer.XMLRPCServer` instance powering #: this server core diff --git a/src/lib/Bcfg2/Server/CherryPyCore.py b/src/lib/Bcfg2/Server/CherryPyCore.py index d097fd08f..79768df20 100644 --- a/src/lib/Bcfg2/Server/CherryPyCore.py +++ b/src/lib/Bcfg2/Server/CherryPyCore.py @@ -36,8 +36,8 @@ class Core(BaseCore): _cp_config = {'tools.xmlrpc_error.on': True, 'tools.bcfg2_authn.on': True} - def __init__(self, setup): - BaseCore.__init__(self, setup) + def __init__(self): + BaseCore.__init__(self) cherrypy.tools.bcfg2_authn = cherrypy.Tool('on_start_resource', self.do_authn) diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py index 37da4a4b6..0ef20dfac 100644 --- a/src/lib/Bcfg2/Server/Core.py +++ b/src/lib/Bcfg2/Server/Core.py @@ -2,21 +2,22 @@ implementations inherit from. """ import os -import atexit -import logging -import select import sys -import threading import time +import select +import atexit +import logging import inspect +import threading import lxml.etree -import Bcfg2.settings import Bcfg2.Server import Bcfg2.Logger -import Bcfg2.Server.FileMonitor -from Bcfg2.Cache import Cache +import Bcfg2.settings import Bcfg2.Statistics +import Bcfg2.Server.FileMonitor from itertools import chain +from Bcfg2.Cache import Cache +from Bcfg2.Options import get_option_parser from Bcfg2.Compat import xmlrpclib # pylint: disable=W0622 from Bcfg2.Server.Plugin import PluginInitError, PluginExecutionError, \ track_statistics @@ -85,23 +86,23 @@ class BaseCore(object): and modules. All core implementations must inherit from ``BaseCore``. """ - def __init__(self, setup): # pylint: disable=R0912,R0915 + def __init__(self): # pylint: disable=R0912,R0915 """ - :param setup: A Bcfg2 options dict - :type setup: Bcfg2.Options.OptionParser - .. automethod:: _daemonize .. automethod:: _run .. automethod:: _block .. ----- .. automethod:: _file_monitor_thread """ + #: The Bcfg2 options dict + self.setup = get_option_parser() + #: The Bcfg2 repository directory - self.datastore = setup['repo'] + self.datastore = self.setup['repo'] - if setup['debug']: + if self.setup['debug']: level = logging.DEBUG - elif setup['verbose']: + elif self.setup['verbose']: level = logging.INFO else: level = logging.WARNING @@ -112,8 +113,8 @@ class BaseCore(object): # setup_logging and the console will get DEBUG output. Bcfg2.Logger.setup_logging('bcfg2-server', to_console=logging.INFO, - to_syslog=setup['syslog'], - to_file=setup['logging'], + to_syslog=self.setup['syslog'], + to_file=self.setup['logging'], level=level) #: A :class:`logging.Logger` object for use by the core @@ -121,16 +122,16 @@ class BaseCore(object): try: filemonitor = \ - Bcfg2.Server.FileMonitor.available[setup['filemonitor']] + Bcfg2.Server.FileMonitor.available[self.setup['filemonitor']] except KeyError: self.logger.error("File monitor driver %s not available; " - "forcing to default" % setup['filemonitor']) + "forcing to default" % self.setup['filemonitor']) filemonitor = Bcfg2.Server.FileMonitor.available['default'] famargs = dict(ignore=[], debug=False) - if 'ignore' in setup: - famargs['ignore'] = setup['ignore'] - if 'debug' in setup: - famargs['debug'] = setup['debug'] + if 'ignore' in self.setup: + famargs['ignore'] = self.setup['ignore'] + if 'debug' in self.setup: + famargs['debug'] = self.setup['debug'] try: #: The :class:`Bcfg2.Server.FileMonitor.FileMonitor` @@ -138,12 +139,13 @@ class BaseCore(object): #: changes. self.fam = filemonitor(**famargs) except IOError: - msg = "Failed to instantiate fam driver %s" % setup['filemonitor'] + msg = "Failed to instantiate fam driver %s" % \ + self.setup['filemonitor'] self.logger.error(msg, exc_info=1) raise CoreInitError(msg) #: Path to bcfg2.conf - self.cfile = setup['configfile'] + self.cfile = self.setup['configfile'] #: Dict of plugins that are enabled. Keys are the plugin #: names (just the plugin name, in the correct case; e.g., @@ -161,9 +163,6 @@ class BaseCore(object): #: :class:`Bcfg2.Server.Plugin.interfaces.Version` plugin. self.revision = '-1' - #: The Bcfg2 options dict - self.setup = setup - atexit.register(self.shutdown) #: Threading event to signal worker threads (e.g., @@ -217,10 +216,10 @@ class BaseCore(object): self.logger.error("Failed to set ownership of database " "at %s: %s" % (db_settings['NAME'], err)) - if '' in setup['plugins']: - setup['plugins'].remove('') + if '' in self.setup['plugins']: + self.setup['plugins'].remove('') - for plugin in setup['plugins']: + for plugin in self.setup['plugins']: if not plugin in self.plugins: self.init_plugin(plugin) # Remove blacklisted plugins @@ -283,12 +282,12 @@ class BaseCore(object): self.connectors = self.plugins_by_type(Bcfg2.Server.Plugin.Connector) #: The CA that signed the server cert - self.ca = setup['ca'] + self.ca = self.setup['ca'] #: The FAM :class:`threading.Thread`, #: :func:`_file_monitor_thread` self.fam_thread = \ - threading.Thread(name="%sFAMThread" % setup['filemonitor'], + threading.Thread(name="%sFAMThread" % self.setup['filemonitor'], target=self._file_monitor_thread) #: A :func:`threading.Lock` for use by @@ -393,8 +392,10 @@ class BaseCore(object): """ Get the client :attr:`metadata_cache` mode. Options are off, initial, cautious, aggressive, on (synonym for cautious). See :ref:`server-caching` for more details. """ + # pylint: disable=E1103 mode = self.setup.cfp.get("caching", "client_metadata", default="off").lower() + # pylint: enable=E1103 if mode == "on": return "cautious" else: diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py index acf6af1f8..7b22d52ca 100644 --- a/src/lib/Bcfg2/Server/Plugin/helpers.py +++ b/src/lib/Bcfg2/Server/Plugin/helpers.py @@ -23,18 +23,6 @@ try: except ImportError: HAS_DJANGO = False -#: A dict containing default metadata for Path entries from bcfg2.conf -DEFAULT_FILE_METADATA = Bcfg2.Options.OptionParser(dict( - owner=Bcfg2.Options.MDATA_OWNER, - group=Bcfg2.Options.MDATA_GROUP, - mode=Bcfg2.Options.MDATA_MODE, - secontext=Bcfg2.Options.MDATA_SECONTEXT, - important=Bcfg2.Options.MDATA_IMPORTANT, - paranoid=Bcfg2.Options.MDATA_PARANOID, - sensitive=Bcfg2.Options.MDATA_SENSITIVE)) -DEFAULT_FILE_METADATA.parse(sys.argv[1:]) -del DEFAULT_FILE_METADATA['args'] - LOGGER = logging.getLogger(__name__) #: a compiled regular expression for parsing info and :info files @@ -49,7 +37,20 @@ INFO_REGEX = re.compile('owner:(\s)*(?P\S+)|' + 'mtime:(\s)*(?P\w+)|') -def bind_info(entry, metadata, infoxml=None, default=DEFAULT_FILE_METADATA): +def default_path_metadata(): + """ Get the default Path entry metadata from the config. + + :returns: dict of metadata attributes and their default values + """ + attrs = Bcfg2.Options.PATH_METADATA_OPTIONS.keys() + setup = Bcfg2.Options.get_option_parser() + if not set(attrs).issubset(setup.keys()): + setup.add_options(Bcfg2.Options.PATH_METADATA_OPTIONS) + setup.reparse() + return dict([(k, setup[k]) for k in attrs]) + + +def bind_info(entry, metadata, infoxml=None, default=None): """ Bind the file metadata in the given :class:`Bcfg2.Server.Plugin.helpers.InfoXML` object to the given entry. @@ -66,6 +67,8 @@ def bind_info(entry, metadata, infoxml=None, default=DEFAULT_FILE_METADATA): :returns: None :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError` """ + if default is None: + default = default_path_metadata() for attr, val in list(default.items()): entry.set(attr, val) if infoxml: @@ -1154,7 +1157,7 @@ class EntrySet(Debuggable): self.path = path self.entry_type = entry_type self.entries = {} - self.metadata = DEFAULT_FILE_METADATA.copy() + self.metadata = default_path_metadata() self.infoxml = None self.encoding = encoding @@ -1376,7 +1379,7 @@ class EntrySet(Debuggable): if event.filename == 'info.xml': self.infoxml = None elif event.filename in [':info', 'info']: - self.metadata = DEFAULT_FILE_METADATA.copy() + self.metadata = default_path_metadata() def bind_info_to_entry(self, entry, metadata): """ Shortcut to call :func:`bind_info` with the base diff --git a/src/lib/Bcfg2/Server/Plugins/Bundler.py b/src/lib/Bcfg2/Server/Plugins/Bundler.py index b200346bc..6dc3c2b1d 100644 --- a/src/lib/Bcfg2/Server/Plugins/Bundler.py +++ b/src/lib/Bcfg2/Server/Plugins/Bundler.py @@ -1,15 +1,15 @@ """This provides bundle clauses with translation functionality.""" -import copy -import logging -import lxml.etree import os -import os.path import re import sys +import copy +import logging +import lxml.etree import Bcfg2.Server import Bcfg2.Server.Plugin import Bcfg2.Server.Lint +from Bcfg2.Options import get_option_parser try: import genshi.template.base @@ -19,9 +19,6 @@ except ImportError: HAS_GENSHI = False -SETUP = None - - class BundleFile(Bcfg2.Server.Plugin.StructFile): """ Representation of a bundle XML file """ def get_xml_value(self, metadata): @@ -52,8 +49,9 @@ if HAS_GENSHI: msg = "No parsed template information for %s" % self.name self.logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) - stream = self.template.generate(metadata=metadata, - repo=SETUP['repo']).filter( + stream = self.template.generate( + metadata=metadata, + repo=get_option_parser()['repo']).filter( Bcfg2.Server.Plugins.TGenshi.removecomment) data = lxml.etree.XML(stream.render('xml', strip_whitespace=False), @@ -102,9 +100,6 @@ class Bundler(Bcfg2.Server.Plugin.Plugin, self.logger.error(msg) raise Bcfg2.Server.Plugin.PluginInitError(msg) - global SETUP - SETUP = core.setup - def template_dispatch(self, name, _): """ Add the correct child entry type to Bundler depending on whether the XML file in question is a plain XML file or a diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgAuthorizedKeysGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgAuthorizedKeysGenerator.py index 824d01023..11c60ad2c 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgAuthorizedKeysGenerator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgAuthorizedKeysGenerator.py @@ -4,7 +4,7 @@ access. """ import lxml.etree from Bcfg2.Server.Plugin import StructFile, PluginExecutionError -from Bcfg2.Server.Plugins.Cfg import CfgGenerator, SETUP, CFG +from Bcfg2.Server.Plugins.Cfg import CfgGenerator, CFG from Bcfg2.Server.Plugins.Metadata import ClientMetadata @@ -35,9 +35,9 @@ class CfgAuthorizedKeysGenerator(CfgGenerator, StructFile): def category(self): """ The name of the metadata category that generated keys are specific to """ - if (SETUP.cfp.has_section("sshkeys") and - SETUP.cfp.has_option("sshkeys", "category")): - return SETUP.cfp.get("sshkeys", "category") + if (self.setup.cfp.has_section("sshkeys") and + self.setup.cfp.has_option("sshkeys", "category")): + return self.setup.cfp.get("sshkeys", "category") return None def handle_event(self, event): diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgCheetahGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgCheetahGenerator.py index 724164cf5..4c8adceec 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgCheetahGenerator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgCheetahGenerator.py @@ -3,7 +3,7 @@ :ref:`server-plugins-generators-cfg` files. """ from Bcfg2.Server.Plugin import PluginExecutionError -from Bcfg2.Server.Plugins.Cfg import CfgGenerator, SETUP +from Bcfg2.Server.Plugins.Cfg import CfgGenerator try: from Cheetah.Template import Template @@ -40,6 +40,6 @@ class CfgCheetahGenerator(CfgGenerator): template.name = entry.get('realname', entry.get('name')) template.path = entry.get('realname', entry.get('name')) template.source_path = self.name - template.repo = SETUP['repo'] + template.repo = self.setup['repo'] return template.respond() get_data.__doc__ = CfgGenerator.get_data.__doc__ diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenerator.py index 3b4703ddb..3b3b95ff5 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenerator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenerator.py @@ -2,10 +2,9 @@ :ref:`server-plugins-generators-cfg` files on the server. """ from Bcfg2.Server.Plugin import PluginExecutionError -from Bcfg2.Server.Plugins.Cfg import CfgGenerator, SETUP +from Bcfg2.Server.Plugins.Cfg import CfgGenerator try: - from Bcfg2.Encryption import bruteforce_decrypt, EVPError, \ - get_algorithm + from Bcfg2.Encryption import bruteforce_decrypt, EVPError HAS_CRYPTO = True except ImportError: HAS_CRYPTO = False @@ -34,8 +33,7 @@ class CfgEncryptedGenerator(CfgGenerator): return # todo: let the user specify a passphrase by name try: - self.data = bruteforce_decrypt(self.data, setup=SETUP, - algorithm=get_algorithm(SETUP)) + self.data = bruteforce_decrypt(self.data) except EVPError: raise PluginExecutionError("Failed to decrypt %s" % self.name) handle_event.__doc__ = CfgGenerator.handle_event.__doc__ diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenshiGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenshiGenerator.py index 130652aef..215e4c1f1 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenshiGenerator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgEncryptedGenshiGenerator.py @@ -3,11 +3,10 @@ files) """ from Bcfg2.Compat import StringIO from Bcfg2.Server.Plugin import PluginExecutionError -from Bcfg2.Server.Plugins.Cfg import SETUP from Bcfg2.Server.Plugins.Cfg.CfgGenshiGenerator import CfgGenshiGenerator try: - from Bcfg2.Encryption import bruteforce_decrypt, get_algorithm + from Bcfg2.Encryption import bruteforce_decrypt HAS_CRYPTO = True except ImportError: HAS_CRYPTO = False @@ -24,9 +23,7 @@ class EncryptedTemplateLoader(TemplateLoader): the data on the fly as it's read in using :func:`Bcfg2.Encryption.bruteforce_decrypt` """ def _instantiate(self, cls, fileobj, filepath, filename, encoding=None): - plaintext = \ - StringIO(bruteforce_decrypt(fileobj.read(), - algorithm=get_algorithm(SETUP))) + plaintext = StringIO(bruteforce_decrypt(fileobj.read())) return TemplateLoader._instantiate(self, cls, plaintext, filepath, filename, encoding=encoding) diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py index 73550cd9d..b58349fe0 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py @@ -6,7 +6,7 @@ import re import sys import traceback from Bcfg2.Server.Plugin import PluginExecutionError -from Bcfg2.Server.Plugins.Cfg import CfgGenerator, SETUP +from Bcfg2.Server.Plugins.Cfg import CfgGenerator try: import genshi.core @@ -102,12 +102,12 @@ class CfgGenshiGenerator(CfgGenerator): def get_data(self, entry, metadata): fname = entry.get('realname', entry.get('name')) - stream = \ - self.template.generate(name=fname, - metadata=metadata, - path=self.name, - source_path=self.name, - repo=SETUP['repo']).filter(removecomment) + stream = self.template.generate( + name=fname, + metadata=metadata, + path=self.name, + source_path=self.name, + repo=self.setup['repo']).filter(removecomment) try: try: return stream.render('text', encoding=self.encoding, diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py index aaeb65cd6..54fa75b41 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgPrivateKeyCreator.py @@ -4,8 +4,9 @@ import os import shutil import tempfile import subprocess +from Bcfg2.Options import get_option_parser from Bcfg2.Server.Plugin import PluginExecutionError, StructFile -from Bcfg2.Server.Plugins.Cfg import CfgCreator, CfgCreationError, SETUP +from Bcfg2.Server.Plugins.Cfg import CfgCreator, CfgCreationError from Bcfg2.Server.Plugins.Cfg.CfgPublicKeyCreator import CfgPublicKeyCreator try: import Bcfg2.Encryption @@ -31,24 +32,25 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile): pubkey_path = os.path.dirname(self.name) + ".pub" pubkey_name = os.path.join(pubkey_path, os.path.basename(pubkey_path)) self.pubkey_creator = CfgPublicKeyCreator(pubkey_name) + self.setup = get_option_parser() __init__.__doc__ = CfgCreator.__init__.__doc__ @property def category(self): """ The name of the metadata category that generated keys are specific to """ - if (SETUP.cfp.has_section("sshkeys") and - SETUP.cfp.has_option("sshkeys", "category")): - return SETUP.cfp.get("sshkeys", "category") + if (self.setup.cfp.has_section("sshkeys") and + self.setup.cfp.has_option("sshkeys", "category")): + return self.setup.cfp.get("sshkeys", "category") return None @property def passphrase(self): """ The passphrase used to encrypt private keys """ if (HAS_CRYPTO and - SETUP.cfp.has_section("sshkeys") and - SETUP.cfp.has_option("sshkeys", "passphrase")): - return Bcfg2.Encryption.get_passphrases(SETUP)[SETUP.cfp.get( + self.setup.cfp.has_section("sshkeys") and + self.setup.cfp.has_option("sshkeys", "passphrase")): + return Bcfg2.Encryption.get_passphrases()[self.setup.cfp.get( "sshkeys", "passphrase")] return None @@ -196,10 +198,8 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile): privkey = open(filename).read() if HAS_CRYPTO and self.passphrase: self.debug_log("Cfg: Encrypting key data at %s" % filename) - privkey = Bcfg2.Encryption.ssl_encrypt( - privkey, - self.passphrase, - algorithm=Bcfg2.Encryption.get_algorithm(SETUP)) + privkey = Bcfg2.Encryption.ssl_encrypt(privkey, + self.passphrase) specificity['ext'] = '.crypt' self.write_data(privkey, **specificity) @@ -239,22 +239,16 @@ class CfgPrivateKeyCreator(CfgCreator, StructFile): """ Decrypt a single encrypted element """ if not element.text or not element.text.strip(): return - passes = Bcfg2.Encryption.get_passphrases(SETUP) + passes = Bcfg2.Encryption.get_passphrases() try: passphrase = passes[element.get("encrypted")] try: - return Bcfg2.Encryption.ssl_decrypt( - element.text, - passphrase, - algorithm=Bcfg2.Encryption.get_algorithm(SETUP)) + return Bcfg2.Encryption.ssl_decrypt(element.text, passphrase) except Bcfg2.Encryption.EVPError: # error is raised below pass except KeyError: # bruteforce_decrypt raises an EVPError with a sensible # error message, so we just let it propagate up the stack - return Bcfg2.Encryption.bruteforce_decrypt( - element.text, - passphrases=passes.values(), - algorithm=Bcfg2.Encryption.get_algorithm(SETUP)) + return Bcfg2.Encryption.bruteforce_decrypt(element.text) raise Bcfg2.Encryption.EVPError("Failed to decrypt") diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py index fcfaa393b..53cc90094 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py @@ -16,17 +16,6 @@ from Bcfg2.Compat import u_str, unicode, b64encode, walk_packages, \ any, oct_mode # pylint: enable=W0622 -#: SETUP contains a reference to the -#: :class:`Bcfg2.Options.OptionParser` created by the Bcfg2 core for -#: parsing command-line and config file options. -#: :class:`Bcfg2.Server.Plugins.Cfg.Cfg` stores it in a module global -#: so that the handler objects can access it, because there is no other -#: facility for passing a setup object from a -#: :class:`Bcfg2.Server.Plugin.helpers.GroupSpool` to its -#: :class:`Bcfg2.Server.Plugin.helpers.EntrySet` objects and thence to -#: the EntrySet children. -SETUP = None - #: CFG is a reference to the :class:`Bcfg2.Server.Plugins.Cfg.Cfg` #: plugin object created by the Bcfg2 core. This is provided so that #: the handler objects can access it as necessary, since the existing @@ -86,6 +75,7 @@ class CfgBaseFileMatcher(Bcfg2.Server.Plugin.SpecificData, encoding) Bcfg2.Server.Plugin.Debuggable.__init__(self) self.encoding = encoding + self.setup = Bcfg2.Options.get_option_parser() __init__.__doc__ = Bcfg2.Server.Plugin.SpecificData.__init__.__doc__ + \ """ .. ----- @@ -442,11 +432,11 @@ class CfgDefaultInfo(CfgInfo): bind_info_to_entry.__doc__ = CfgInfo.bind_info_to_entry.__doc__ #: A :class:`CfgDefaultInfo` object instantiated with -#: :attr:`Bcfg2.Server.Plugin.helper.DEFAULT_FILE_METADATA` as its +#: :func:`Bcfg2.Server.Plugin.helper.default_path_metadata` as its #: default metadata. This is used to set a default file metadata set #: on an entry before a "real" :class:`CfgInfo` handler applies its #: metadata to the entry. -DEFAULT_INFO = CfgDefaultInfo(Bcfg2.Server.Plugin.DEFAULT_FILE_METADATA) +DEFAULT_INFO = CfgDefaultInfo(Bcfg2.Server.Plugin.default_path_metadata()) class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet, @@ -460,6 +450,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet, Bcfg2.Server.Plugin.Debuggable.__init__(self) self.specific = None self._handlers = None + self.setup = Bcfg2.Options.get_option_parser() __init__.__doc__ = Bcfg2.Server.Plugin.EntrySet.__doc__ def set_debug(self, debug): @@ -585,7 +576,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet, for fltr in self.get_handlers(metadata, CfgFilter): data = fltr.modify_data(entry, metadata, data) - if SETUP['validate']: + if self.setup['validate']: try: self._validate_data(entry, metadata, data) except CfgVerificationError: @@ -833,16 +824,16 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, es_child_cls = Bcfg2.Server.Plugin.SpecificData def __init__(self, core, datastore): - global SETUP, CFG # pylint: disable=W0603 + global CFG # pylint: disable=W0603 Bcfg2.Server.Plugin.GroupSpool.__init__(self, core, datastore) Bcfg2.Server.Plugin.PullTarget.__init__(self) CFG = self - SETUP = core.setup - if 'validate' not in SETUP: - SETUP.add_option('validate', Bcfg2.Options.CFG_VALIDATION) - SETUP.reparse() + setup = Bcfg2.Options.get_option_parser() + if 'validate' not in setup: + setup.add_option('validate', Bcfg2.Options.CFG_VALIDATION) + setup.reparse() __init__.__doc__ = Bcfg2.Server.Plugin.GroupSpool.__init__.__doc__ def has_generator(self, entry, metadata): diff --git a/src/lib/Bcfg2/Server/Plugins/Properties.py b/src/lib/Bcfg2/Server/Plugins/Properties.py index a51dd8adc..c5b5ea2d1 100644 --- a/src/lib/Bcfg2/Server/Plugins/Properties.py +++ b/src/lib/Bcfg2/Server/Plugins/Properties.py @@ -7,6 +7,7 @@ import sys import copy import logging import lxml.etree +from Bcfg2.Options import get_option_parser import Bcfg2.Server.Plugin from Bcfg2.Server.Plugin import PluginExecutionError try: @@ -33,8 +34,6 @@ except ImportError: LOGGER = logging.getLogger(__name__) -SETUP = None - class PropertyFile(object): """ Base Properties file handler """ @@ -46,13 +45,14 @@ class PropertyFile(object): .. automethod:: _write """ self.name = name + self.setup = get_option_parser() def write(self): """ Write the data in this data structure back to the property file. This public method performs checking to ensure that writing is possible and then calls :func:`_write`. """ - if not SETUP.cfp.getboolean("properties", "writes_enabled", - default=True): + if not self.setup.cfp.getboolean("properties", "writes_enabled", + default=True): msg = "Properties files write-back is disabled in the " + \ "configuration" LOGGER.error(msg) @@ -232,26 +232,22 @@ class XMLPropertyFile(Bcfg2.Server.Plugin.StructFile, PropertyFile): """ Decrypt a single encrypted properties file element """ if not element.text or not element.text.strip(): return - passes = Bcfg2.Encryption.get_passphrases(SETUP) + passes = Bcfg2.Encryption.get_passphrases() try: passphrase = passes[element.get("encrypted")] try: - return Bcfg2.Encryption.ssl_decrypt( - element.text, passphrase, - algorithm=Bcfg2.Encryption.get_algorithm(SETUP)) + return Bcfg2.Encryption.ssl_decrypt(element.text, passphrase) except Bcfg2.Encryption.EVPError: # error is raised below pass except KeyError: # bruteforce_decrypt raises an EVPError with a sensible # error message, so we just let it propagate up the stack - return Bcfg2.Encryption.bruteforce_decrypt( - element.text, passphrases=passes.values(), - algorithm=Bcfg2.Encryption.get_algorithm(SETUP)) + return Bcfg2.Encryption.bruteforce_decrypt(element.text) raise Bcfg2.Encryption.EVPError("Failed to decrypt") def get_additional_data(self, metadata): - if SETUP.cfp.getboolean("properties", "automatch", default=False): + if self.setup.cfp.getboolean("properties", "automatch", default=False): default_automatch = "true" else: default_automatch = "false" @@ -323,10 +319,8 @@ class Properties(Bcfg2.Server.Plugin.Plugin, instances. """ def __init__(self, core, datastore): - global SETUP # pylint: disable=W0603 Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Connector.__init__(self) - SETUP = core.setup try: self.store = PropDirectoryBacked(self.data, core.fam) except OSError: diff --git a/src/lib/Bcfg2/Server/models.py b/src/lib/Bcfg2/Server/models.py index 0328c6bea..4ac2be43b 100644 --- a/src/lib/Bcfg2/Server/models.py +++ b/src/lib/Bcfg2/Server/models.py @@ -1,6 +1,7 @@ """ Django database models for all plugins """ import sys +import copy import logging import Bcfg2.Options import Bcfg2.Server.Plugins @@ -19,14 +20,12 @@ def load_models(plugins=None, cfile='/etc/bcfg2.conf', quiet=True): # we want to provide a different default plugin list -- # namely, _all_ plugins, so that the database is guaranteed to # work, even if /etc/bcfg2.conf isn't set up properly - plugin_opt = Bcfg2.Options.SERVER_PLUGINS + plugin_opt = copy.deepcopy(Bcfg2.Options.SERVER_PLUGINS) plugin_opt.default = Bcfg2.Server.Plugins.__all__ - - setup = \ - Bcfg2.Options.OptionParser(dict(plugins=plugin_opt, - configfile=Bcfg2.Options.CFILE), - quiet=quiet) - setup.parse([Bcfg2.Options.CFILE.cmd, cfile]) + setup = Bcfg2.Options.get_option_parser() + setup.add_option("plugins", plugin_opt) + setup.add_option("configfile", Bcfg2.Options.CFILE) + setup.reparse(argv=[Bcfg2.Options.CFILE.cmd, cfile]) plugins = setup['plugins'] if MODELS: -- cgit v1.2.3-1-g7c22