diff options
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py')
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py index 6c7585993..fe993ab54 100644 --- a/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg/__init__.py @@ -6,11 +6,11 @@ import sys import stat import pkgutil import logging -import binascii import lxml.etree import Bcfg2.Options import Bcfg2.Server.Plugin -from Bcfg2.Bcfg2Py3k import u_str +from Bcfg2.Bcfg2Py3k import u_str, unicode, b64encode +import Bcfg2.Server.Lint logger = logging.getLogger(__name__) @@ -113,7 +113,8 @@ class CfgInfo(CfgBaseFileMatcher): def _set_info(self, entry, info): for key, value in list(info.items()): - entry.attrib.__setitem__(key, value) + if not key.startswith("__"): + entry.attrib.__setitem__(key, value) class CfgVerifier(CfgBaseFileMatcher): @@ -152,7 +153,19 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): global PROCESSORS if PROCESSORS is None: PROCESSORS = [] - for submodule in pkgutil.walk_packages(path=__path__): + 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 = '.'.join(submodule.split("/")[-1].split('.')[:-1]) + if mod != '__init__': + submodules.append((None, mod, True)) + + for submodule in submodules: module = getattr(__import__("%s.%s" % (__name__, submodule[1])).Server.Plugins.Cfg, @@ -185,6 +198,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): return elif action == 'changed': self.entries[event.filename].handle_event(event) + return elif action == 'deleted': del self.entries[event.filename] return @@ -192,6 +206,11 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): logger.error("Could not process event %s for %s; ignoring" % (action, event.filename)) + def get_matching(self, metadata): + return [item for item in list(self.entries.values()) + if (isinstance(item, CfgGenerator) and + item.specific.matches(metadata))] + def entry_init(self, event, proc): if proc.__specific__: Bcfg2.Server.Plugin.EntrySet.entry_init( @@ -270,10 +289,11 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): raise Bcfg2.Server.Plugin.PluginExecutionError(msg) if entry.get('encoding') == 'base64': - data = binascii.b2a_base64(data) + data = b64encode(data) else: try: - data = u_str(data, self.encoding) + if not isinstance(data, unicode): + data = u_str(data, self.encoding) except UnicodeDecodeError: msg = "Failed to decode %s: %s" % (entry.get('name'), sys.exc_info()[1]) @@ -287,6 +307,10 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): logger.error("You need to specify base64 encoding for %s." % entry.get('name')) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) + except TypeError: + # data is already unicode; newer versions of Cheetah + # seem to return unicode + pass if data: entry.text = data @@ -298,7 +322,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): generators = [ent for ent in list(self.entries.values()) if (isinstance(ent, CfgGenerator) and ent.specific.matches(metadata))] - if not matching: + if not generators: msg = "No base file found for %s" % entry.get('name') logger.error(msg) raise Bcfg2.Server.Plugin.PluginExecutionError(msg) @@ -347,26 +371,26 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): if attr in new_entry] if badattr: # check for info files and inform user of their removal - if os.path.exists(self.path + "/:info"): - logger.info("Removing :info file and replacing with " - "info.xml") - os.remove(self.path + "/:info") - if os.path.exists(self.path + "/info"): - logger.info("Removing info file and replacing with " - "info.xml") - os.remove(self.path + "/info") + for ifile in ['info', ':info']: + info = os.path.join(self.path, ifile) + if os.path.exists(info): + logger.info("Removing %s and replacing with info.xml" % + info) + os.remove(info) metadata_updates = {} metadata_updates.update(self.metadata) for attr in badattr: metadata_updates[attr] = new_entry.get(attr) infoxml = lxml.etree.Element('FileInfo') infotag = lxml.etree.SubElement(infoxml, 'Info') - [infotag.attrib.__setitem__(attr, metadata_updates[attr]) \ - for attr in metadata_updates] + [infotag.attrib.__setitem__(attr, metadata_updates[attr]) + for attr in metadata_updates] ofile = open(self.path + "/info.xml", "w") - ofile.write(lxml.etree.tostring(infoxml, pretty_print=True)) + ofile.write(lxml.etree.tostring(infoxml, xml_declaration=False, + pretty_print=True).decode('UTF-8')) ofile.close() - self.debug_log("Wrote file %s" % (self.path + "/info.xml"), + self.debug_log("Wrote file %s" % os.path.join(self.path, + "info.xml"), flag=log) @@ -385,9 +409,22 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, SETUP = core.setup if 'validate' not in SETUP: - SETUP['validate'] = Bcfg2.Options.CFG_VALIDATION + SETUP.add_option('validate', Bcfg2.Options.CFG_VALIDATION) SETUP.reparse() + def has_generator(self, entry, metadata): + """ return True if the given entry can be generated for the + given metadata; False otherwise """ + if entry.get('name') not in self.entries: + return False + + for ent in self.entries[entry.get('name')].entries.values(): + if ent.__specific__ and not ent.specific.matches(metadata): + continue + if isinstance(ent, CfgGenerator): + return True + return False + def AcceptChoices(self, entry, metadata): return self.entries[entry.get('name')].list_accept_choices(entry, metadata) @@ -396,3 +433,26 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, return self.entries[new_entry.get('name')].write_update(specific, new_entry, log) + +class CfgLint(Bcfg2.Server.Lint.ServerPlugin): + """ warn about usage of .cat and .diff files """ + + def Run(self): + for basename, entry in list(self.core.plugins['Cfg'].entries.items()): + self.check_entry(basename, entry) + + + @classmethod + def Errors(cls): + return {"cat-file-used":"warning", + "diff-file-used":"warning"} + + def check_entry(self, basename, entry): + cfg = self.core.plugins['Cfg'] + for basename, entry in list(cfg.entries.items()): + for fname, processor in entry.entries.items(): + if self.HandlesFile(fname) and isinstance(processor, CfgFilter): + extension = fname.split(".")[-1] + self.LintError("%s-file-used" % extension, + "%s file used on %s: %s" % + (extension, basename, fname)) |