diff options
-rw-r--r-- | src/lib/Server/Core.py | 95 | ||||
-rw-r--r-- | src/lib/Server/Plugin.py | 5 | ||||
-rw-r--r-- | src/lib/Server/Plugins/Metadata.py | 1 |
3 files changed, 60 insertions, 41 deletions
diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py index 5adfa5381..91b6a3555 100644 --- a/src/lib/Server/Core.py +++ b/src/lib/Server/Core.py @@ -90,42 +90,49 @@ class Core(Component): "Unloading %s" % (p, bl)) for plug in bl: del self.plugins[plug] - # This section loads the experimental plugins + # This section logs the experimental plugins expl = [plug for (name, plug) in list(self.plugins.items()) if plug.experimental] if expl: logger.info("Loading experimental plugin(s): %s" % \ (" ".join([x.name for x in expl]))) logger.info("NOTE: Interfaces subject to change") + # This section logs the deprecated plugins depr = [plug for (name, plug) in list(self.plugins.items()) if plug.deprecated] - # This section loads the deprecated plugins if depr: logger.info("Loading deprecated plugin(s): %s" % \ (" ".join([x.name for x in depr]))) - mlist = [p for p in list(self.plugins.values()) if \ - isinstance(p, Bcfg2.Server.Plugin.Metadata)] + mlist = self.plugins_by_type(Bcfg2.Server.Plugin.Metadata) if len(mlist) == 1: self.metadata = mlist[0] else: logger.error("No Metadata Plugin loaded; failed to instantiate Core") raise CoreInitError("No Metadata Plugin") - self.statistics = [plugin for plugin in list(self.plugins.values()) - if isinstance(plugin, Bcfg2.Server.Plugin.Statistics)] - self.pull_sources = [plugin for plugin in self.statistics - if isinstance(plugin, Bcfg2.Server.Plugin.PullSource)] - self.generators = [plugin for plugin in list(self.plugins.values()) - if isinstance(plugin, Bcfg2.Server.Plugin.Generator)] - self.structures = [plugin for plugin in list(self.plugins.values()) - if isinstance(plugin, Bcfg2.Server.Plugin.Structure)] - self.connectors = [plugin for plugin in list(self.plugins.values()) - if isinstance(plugin, Bcfg2.Server.Plugin.Connector)] + self.statistics = self.plugins_by_type(Bcfg2.Server.Plugin.Statistics) + self.pull_sources = self.plugins_by_type(Bcfg2.Server.Plugin.PullSource) + self.generators = self.plugins_by_type(Bcfg2.Server.Plugin.Generator) + self.structures = self.plugins_by_type(Bcfg2.Server.Plugin.Structure) + self.connectors = self.plugins_by_type(Bcfg2.Server.Plugin.Connector) self.ca = ca self.fam_thread = threading.Thread(target=self._file_monitor_thread) if start_fam_thread: self.fam_thread.start() + def plugins_by_type(self, base_cls): + """Return a list of loaded plugins that match the passed type. + + The returned list is sorted in ascending order by the Plugins' + sort_order value. The sort_order defaults to 500 in Plugin.py, + but can be overridden by individual plugins. Plugins with the + same numerical sort_order value are sorted in alphabetical + order by their name. + """ + return sorted([plugin for plugin in self.plugins.values() + if isinstance(plugin, base_cls)], + key=lambda p: (p.sort_order, p.name)) + def _file_monitor_thread(self): """The thread for monitor the files.""" famfd = self.fam.fileno() @@ -141,9 +148,8 @@ class Core(Component): except: continue # VCS plugin periodic updates - for plugin in list(self.plugins.values()): - if isinstance(plugin, Bcfg2.Server.Plugin.Version): - self.revision = plugin.get_revision() + for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Version): + self.revision = plugin.get_revision() def init_plugins(self, plugin): """Handling for the plugins.""" @@ -176,23 +182,33 @@ class Core(Component): for plugin in list(self.plugins.values()): plugin.shutdown() - def validate_data(self, metadata, data, base_cls): + def validate_structures(self, metadata, data): """Checks the data structure.""" - for plugin in list(self.plugins.values()): - if isinstance(plugin, base_cls): - try: - if base_cls == Bcfg2.Server.Plugin.StructureValidator: - plugin.validate_structures(metadata, data) - elif base_cls == Bcfg2.Server.Plugin.GoalValidator: - plugin.validate_goals(metadata, data) - except Bcfg2.Server.Plugin.ValidationError: - err = sys.exc_info()[1] - logger.error("Plugin %s structure validation failed: %s" \ - % (plugin.name, err.message)) - raise - except: - logger.error("Plugin %s: unexpected structure validation failure" \ - % (plugin.name), exc_info=1) + for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.StructureValidator): + try: + plugin.validate_structures(metadata, data) + except Bcfg2.Server.Plugin.ValidationError: + err = sys.exc_info()[1] + logger.error("Plugin %s structure validation failed: %s" \ + % (plugin.name, err.message)) + raise + except: + logger.error("Plugin %s: unexpected structure validation failure" \ + % (plugin.name), exc_info=1) + + def validate_goals(self, metadata, data): + """Checks that the config matches the goals enforced by the plugins.""" + for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.GoalValidator): + try: + plugin.validate_goals(metadata, data) + except Bcfg2.Server.Plugin.ValidationError: + err = sys.exc_info()[1] + logger.error("Plugin %s goal validation failed: %s" \ + % (plugin.name, err.message)) + raise + except: + logger.error("Plugin %s: unexpected goal validation failure" \ + % (plugin.name), exc_info=1) def GetStructures(self, metadata): """Get all structures for client specified by metadata.""" @@ -276,8 +292,7 @@ class Core(Component): logger.error("error in GetStructures", exc_info=1) return lxml.etree.Element("error", type='structure error') - self.validate_data(meta, structures, - Bcfg2.Server.Plugin.StructureValidator) + self.validate_structures(meta, structures) # Perform altsrc consistency checking esrcs = {} @@ -297,7 +312,7 @@ class Core(Component): config.append(astruct) except: logger.error("error in BindStructure", exc_info=1) - self.validate_data(meta, config, Bcfg2.Server.Plugin.GoalValidator) + self.validate_goals(meta, config) logger.info("Generated config for %s in %.03fs" % \ (client, time.time() - start)) return config @@ -305,10 +320,9 @@ class Core(Component): def GetDecisions(self, metadata, mode): """Get data for the decision list.""" result = [] - for plugin in list(self.plugins.values()): + for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Decision): try: - if isinstance(plugin, Bcfg2.Server.Plugin.Decision): - result += plugin.GetDecisions(metadata, mode) + result += plugin.GetDecisions(metadata, mode) except: logger.error("Plugin: %s failed to generate decision list" \ % plugin.name, exc_info=1) @@ -354,8 +368,7 @@ class Core(Component): name = self.metadata.resolve_client(address) meta = self.build_metadata(name) - for plugin in [p for p in list(self.plugins.values()) \ - if isinstance(p, Bcfg2.Server.Plugin.Probing)]: + for plugin in self.plugins_by_type(Bcfg2.Server.Plugin.Probing): for probe in plugin.GetProbes(meta): resp.append(probe) return lxml.etree.tostring(resp, encoding='UTF-8', diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 17547be13..108e2d89f 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -81,6 +81,11 @@ class Plugin(object): deprecated = False conflicts = [] + # Default sort_order to 500. Plugins of the same type are + # processed in order of ascending sort_order value. Plugins with + # the same sort_order are sorted alphabetically by their name. + sort_order = 500 + def __init__(self, core, datastore): object.__init__(self) self.Entries = {} diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Server/Plugins/Metadata.py index 7fc34f178..bfe1ac053 100644 --- a/src/lib/Server/Plugins/Metadata.py +++ b/src/lib/Server/Plugins/Metadata.py @@ -222,6 +222,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' name = "Metadata" + sort_order = 500 def __init__(self, core, datastore, watch_clients=True): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) |