diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/Server/Plugin.py | 13 | ||||
-rw-r--r-- | src/lib/Server/Plugins/SGenshi.py | 81 | ||||
-rw-r--r-- | src/lib/Server/Plugins/TGenshi.py | 14 |
3 files changed, 50 insertions, 58 deletions
diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 10bc4f1fc..4a973ba1c 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -446,6 +446,10 @@ class EntrySet: pattern += '(G(?P<prio>\d+)_(?P<group>\S+))))?$' self.specific = re.compile(pattern) + def get_matching(self, metadata): + return [item for item in self.entries.values() \ + if item.specific.matches(metadata)] + def handle_event(self, event): '''Handle FAM events for the TemplateSet''' action = event.code2str() @@ -547,8 +551,7 @@ class EntrySet: def bind_entry(self, entry, metadata): '''Return the appropriate interpreted template from the set of available templates''' self.bind_info_to_entry(entry, metadata) - matching = [ent for ent in self.entries.values() if \ - ent.specific.matches(metadata)] + matching = self.get_matching(metadata) hspec = [ent for ent in matching if ent.specific.hostname] if hspec: @@ -645,14 +648,12 @@ class GroupSpool(Plugin): def AddDirectoryMonitor(self, relative): '''Add new directory to FAM structures''' - if not relative: - relative = '/' - if relative[-1] != '/': + if not relative.endswith('/'): relative += '/' name = self.data + relative if relative not in self.handles.values(): if not posixpath.isdir(name): - print "Genshi: Failed to open directory %s" % (name) + print "Failed to open directory %s" % (name) return reqid = self.core.fam.AddMonitor(name, self) self.handles[reqid] = relative diff --git a/src/lib/Server/Plugins/SGenshi.py b/src/lib/Server/Plugins/SGenshi.py index 76d1dd6bf..469cd493e 100644 --- a/src/lib/Server/Plugins/SGenshi.py +++ b/src/lib/Server/Plugins/SGenshi.py @@ -1,69 +1,52 @@ '''This module implements a templating generator based on Genshi''' __revision__ = '$Revision$' -import Bcfg2.Server.Plugin +import Bcfg2.Server.Plugin, Bcfg2.Server.Plugins.TGenshi import lxml.etree, logging logger = logging.getLogger('Bcfg2.Plugins.SGenshi') -try: - import genshi.template, genshi.core, genshi.template.base -except: - logger.error("Failed to load Genshi; disabling SGenshi") - raise - -def removecomment(stream): - """A genshi filter that removes comments from the stream.""" - for kind, data, pos in stream: - if kind is genshi.core.COMMENT: - continue - yield kind, data, pos - -class TemplateFile(Bcfg2.Server.Plugin.FileBacked): - '''Genshi template file object''' - loader = genshi.template.TemplateLoader(auto_reload=True, - max_cache_size=64) - def HandleEvent(self, _=None): - '''Process FAM/GAMIN event''' - try: - self.template = self.loader.load(self.name, - cls=genshi.template.MarkupTemplate) - except genshi.template.base.TemplateSyntaxError, e: - logger.error("SGenshi: Parse failure due to %s" % (e)) - - def GetValue(self, metadata): - '''Build actual structure contents''' - if not hasattr(self, 'template'): - logger.error("Template data for %s could not be loaded" % self.name) - raise Bcfg2.Server.Plugin.PluginExecutionError - stream = self.template.generate(metadata=metadata).filter(removecomment) +class SGenshiTemplateFile(Bcfg2.Server.Plugins.TGenshi.TemplateFile): + def get_xml_value(self, metadata): + stream = self.template.generate(metadata=metadata, + properties=self.properties).filter( \ + Bcfg2.Server.Plugins.TGenshi.removecomment) data = stream.render('xml') return lxml.etree.XML(data) -class SGenshi(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.XMLDirectoryBacked): - '''SGenshi is a structure plugin that provides direct plugin access to templated structures''' - __child__ = TemplateFile +class SGenshiEntrySet(Bcfg2.Server.Plugin.EntrySet): + def __init__(self, path, fam): + fpattern = '[A-Za-z]+\.xml' + Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, + True, SGenshiTemplateFile) + fam.AddMonitor(path, self) + + def HandleEvent(self, event): + if event.filename != self.path: + return self.handle_event(event) + + def BuildStructures(self, metadata): + '''Build SGenshi structures''' + ret = [] + for entry in self.get_matching(metadata): + try: + ret.append(entry.get_xml_value(metadata)) + except Bcfg2.Server.Plugin.PluginExecutionError: + logger.error("SGenshi: Failed to template file %s" % entry.name) + return ret + +class SGenshi(SGenshiEntrySet, Bcfg2.Server.Plugin.Plugin): + '''The SGenshi plugin provides templated structures''' __name__ = 'SGenshi' __version__ = '$Id$' + __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) try: - Bcfg2.Server.Plugin.XMLDirectoryBacked.__init__(self, - self.data, - self.core.fam) + SGenshiEntrySet.__init__(self, self.data, self.core.fam) except: logger.error("Failed to load SGenshi repository; disabling SGenshi") raise Bcfg2.Server.Plugin.PluginInitError - def BuildStructures(self, metadata): - '''Build SGenshi structures''' - ret = [] - for entry in self.entries.values(): - try: - ret.append(entry.GetValue(metadata)) - except Bcfg2.Server.Plugin.PluginExecutionError: - logger.error("SGenshi: Failed to template file %s" % entry.name) - return ret - + diff --git a/src/lib/Server/Plugins/TGenshi.py b/src/lib/Server/Plugins/TGenshi.py index d7199d78c..0b9acfe58 100644 --- a/src/lib/Server/Plugins/TGenshi.py +++ b/src/lib/Server/Plugins/TGenshi.py @@ -4,9 +4,17 @@ __revision__ = '$Revision$' from genshi.template import TemplateLoader, TextTemplate, MarkupTemplate, TemplateError import logging import Bcfg2.Server.Plugin +import genshi.core logger = logging.getLogger('Bcfg2.Plugins.TGenshi') +def removecomment(stream): + """A genshi filter that removes comments from the stream.""" + for kind, data, pos in stream: + if kind is genshi.core.COMMENT: + continue + yield kind, data, pos + class TemplateFile: '''Template file creates Genshi template structures for the loaded file''' def __init__(self, name, properties, specific): @@ -38,9 +46,9 @@ class TemplateFile: '''Build literal file information''' fname = entry.get('realname', entry.get('name')) try: - stream = self.template.generate(name=fname, - metadata=metadata, - properties=self.properties) + stream = self.template.generate( \ + name=fname, metadata=metadata, + properties=self.properties).filter(removecomment) if isinstance(self.template, TextTemplate): entry.text = stream.render('text') else: |