diff options
Diffstat (limited to 'src/lib/Bcfg2/Client/Tools/__init__.py')
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/__init__.py | 117 |
1 files changed, 78 insertions, 39 deletions
diff --git a/src/lib/Bcfg2/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py index c6cb6e239..026c7ade0 100644 --- a/src/lib/Bcfg2/Client/Tools/__init__.py +++ b/src/lib/Bcfg2/Client/Tools/__init__.py @@ -1,16 +1,27 @@ """This contains all Bcfg2 Tool modules""" import os -import stat import sys -from subprocess import Popen, PIPE +import stat import time +import pkgutil +from subprocess import Popen, PIPE import Bcfg2.Client.XML - -__all__ = [tool.split('.')[0] \ - for tool in os.listdir(os.path.dirname(__file__)) \ - if tool.endswith(".py") and tool != "__init__.py"] - +from Bcfg2.Bcfg2Py3k import input + +if hasattr(pkgutil, 'walk_packages'): + submodules = pkgutil.walk_packages(path=__path__) +else: + # python 2.4 + import glob + submodules = [] + for path in __path__: + for submodule in glob.glob(os.path.join(path, "*.py")): + mod = os.path.splitext(os.path.basename(submodule))[0] + if mod not in ['__init__']: + submodules.append((None, mod, True)) + +__all__ = [m[1] for m in submodules] drivers = [item for item in __all__ if item not in ['rpmtools']] default = [item for item in drivers if item not in ['RPM', 'Yum']] @@ -36,7 +47,7 @@ class executor: return (p.returncode, output.splitlines()) -class Tool: +class Tool(object): """ All tools subclass this. It defines all interfaces that need to be defined. """ @@ -47,10 +58,6 @@ class Tool: __important__ = [] def __init__(self, logger, setup, config): - self.__important__ = [entry.get('name') \ - for struct in config for entry in struct \ - if entry.tag == 'Path' and \ - entry.get('important') in ['true', 'True']] self.setup = setup self.logger = logger if not hasattr(self, '__ireq__'): @@ -59,8 +66,15 @@ class Tool: self.cmd = executor(logger) self.modified = [] self.extra = [] - self.handled = [entry for struct in self.config for entry in struct \ - if self.handlesEntry(entry)] + self.__important__ = [] + self.handled = [] + for struct in config: + for entry in struct: + if (entry.tag == 'Path' and + entry.get('important', 'false').lower() == 'true'): + self.__important__.append(entry.get('name')) + if self.handlesEntry(entry): + self.handled.append(entry) for filename in self.__execs__: try: mode = stat.S_IMODE(os.stat(filename)[stat.ST_MODE]) @@ -130,12 +144,24 @@ class Tool: '''Build a list of potentially modified POSIX paths for this entry''' return [entry.get('name') for struct in self.config.getchildren() \ for entry in struct.getchildren() \ - if entry.tag in ['Ignore', 'Path']] + if entry.tag == 'Path'] def gatherCurrentData(self, entry): """Default implementation of the information gathering routines.""" pass + def missing_attrs(self, entry): + required = self.__req__[entry.tag] + if isinstance(required, dict): + required = ["type"] + try: + required.extend(self.__req__[entry.tag][entry.get("type")]) + except KeyError: + pass + + return [attr for attr in required + if attr not in entry.attrib or not entry.attrib[attr]] + def canVerify(self, entry): """Test if entry has enough information to be verified.""" if not self.handlesEntry(entry): @@ -148,13 +174,12 @@ class Tool: entry.get('failure'))) return False - missing = [attr for attr in self.__req__[entry.tag] \ - if attr not in entry.attrib] + missing = self.missing_attrs(entry) if missing: - self.logger.error("Incomplete information for entry %s:%s; cannot verify" \ - % (entry.tag, entry.get('name'))) - self.logger.error("\t... due to absence of %s attribute(s)" % \ - (":".join(missing))) + self.logger.error("Cannot verify entry %s:%s due to missing " + "required attribute(s): %s" % + (entry.tag, entry.get('name'), + ", ".join(missing))) try: self.gatherCurrentData(entry) except: @@ -167,6 +192,11 @@ class Tool: """Return a list of extra entries.""" return [] + def primarykey(self, entry): + """ return a string that should be unique amongst all entries + in the specification """ + return "%s:%s" % (entry.tag, entry.get("name")) + def canInstall(self, entry): """Test if entry has enough information to be installed.""" if not self.handlesEntry(entry): @@ -177,13 +207,12 @@ class Tool: (entry.tag, entry.get('name'))) return False - missing = [attr for attr in self.__ireq__[entry.tag] \ - if attr not in entry.attrib or not entry.attrib[attr]] + missing = self.missing_attrs(entry) if missing: - self.logger.error("Incomplete information for entry %s:%s; cannot install" \ - % (entry.tag, entry.get('name'))) - self.logger.error("\t... due to absence of %s attribute" % \ - (":".join(missing))) + self.logger.error("Incomplete information for entry %s:%s; cannot " + "install due to absence of attribute(s): %s" % + (entry.tag, entry.get('name'), + ", ".join(missing))) return False return True @@ -305,8 +334,7 @@ class SvcTool(Tool): return self.cmd.run(self.get_svc_command(service, restart_target))[0] def check_service(self, service): - # not supported for this driver - return 0 + return self.cmd.run(self.get_svc_command(service, 'status'))[0] == 0 def Remove(self, services): """ Dummy implementation of service removal method """ @@ -321,13 +349,12 @@ class SvcTool(Tool): return for entry in [ent for ent in bundle if self.handlesEntry(ent)]: - mode = entry.get('mode', 'default') - if (mode == 'manual' or - (mode == 'interactive_only' and + restart = entry.get("restart", "true") + if (restart.lower() == "false" or + (restart.lower == "interactive" and not self.setup['interactive'])): continue - # need to handle servicemode = (build|default) - # need to handle mode = (default|supervised) + rc = None if entry.get('status') == 'on': if self.setup['servicemode'] == 'build': @@ -336,11 +363,7 @@ class SvcTool(Tool): if self.setup['interactive']: prompt = ('Restart service %s?: (y/N): ' % entry.get('name')) - # py3k compatibility - try: - ans = raw_input(prompt) - except NameError: - ans = input(prompt) + ans = input(prompt) if ans not in ['y', 'Y']: continue rc = self.restart_service(entry) @@ -351,3 +374,19 @@ class SvcTool(Tool): if rc: self.logger.error("Failed to manipulate service %s" % (entry.get('name'))) + + def Install(self, entries, states): + """Install all entries in sublist.""" + for entry in entries: + if entry.get('install', 'true').lower() == 'false': + self.logger.info("Service %s installation is false. Skipping " + "installation." % (entry.get('name'))) + continue + try: + func = getattr(self, "Install%s" % (entry.tag)) + states[entry] = func(entry) + if states[entry]: + self.modified.append(entry) + except: + self.logger.error("Unexpected failure of install method for entry type %s" + % (entry.tag), exc_info=1) |