From a9388f7859586d5d98e815efdcf8d6a85b973bef Mon Sep 17 00:00:00 2001 From: Narayan Desai Date: Mon, 5 Jan 2009 03:24:50 +0000 Subject: This patch is stage 1 of the plugin capabilities rework - define new plugin base classes - switch Plugin.__name__ => Plugin.name git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5004 ce84e21b-d406-0410-9b95-82705330c041 --- src/lib/Server/Core.py | 19 +++++++------- src/lib/Server/Plugin.py | 43 ++++++++++++++++---------------- src/lib/Server/Plugins/Account.py | 6 +++-- src/lib/Server/Plugins/BB.py | 28 ++++++++++----------- src/lib/Server/Plugins/Base.py | 16 ++++++++---- src/lib/Server/Plugins/Bundler.py | 6 +++-- src/lib/Server/Plugins/Cfg.py | 2 +- src/lib/Server/Plugins/DBStats.py | 22 +++++++++++------ src/lib/Server/Plugins/Decisions.py | 9 ++++--- src/lib/Server/Plugins/Deps.py | 2 +- src/lib/Server/Plugins/Editor.py | 7 +++--- src/lib/Server/Plugins/Hostbase.py | 48 +++++++++--------------------------- src/lib/Server/Plugins/Metadata.py | 8 +++--- src/lib/Server/Plugins/NagiosGen.py | 6 +++-- src/lib/Server/Plugins/Pkgmgr.py | 2 +- src/lib/Server/Plugins/Probes.py | 16 ++++++------ src/lib/Server/Plugins/Rules.py | 4 +-- src/lib/Server/Plugins/SGenshi.py | 7 ++++-- src/lib/Server/Plugins/SSHbase.py | 25 +++++++++++++------ src/lib/Server/Plugins/Statistics.py | 42 +++++++++++++++++++------------ src/lib/Server/Plugins/Svcmgr.py | 2 +- src/lib/Server/Plugins/TCheetah.py | 2 +- src/lib/Server/Plugins/TGenshi.py | 2 +- src/sbin/bcfg2-info | 2 +- src/sbin/bcfg2-server | 2 +- 25 files changed, 172 insertions(+), 156 deletions(-) diff --git a/src/lib/Server/Core.py b/src/lib/Server/Core.py index 3c8a8c429..d4f9b9f6e 100644 --- a/src/lib/Server/Core.py +++ b/src/lib/Server/Core.py @@ -63,7 +63,7 @@ class Core(object): while True: try: plugin = chk_plugins.pop() - if isinstance(plugin, Bcfg2.Server.Plugin.MetadataPlugin): + if isinstance(plugin, Bcfg2.Server.Plugin.Metadata): self.metadata = plugin break except: @@ -77,7 +77,7 @@ class Core(object): while True: try: plugin = chk_plugins.pop() - if isinstance(plugin, Bcfg2.Server.Plugin.StatisticsPlugin): + if isinstance(plugin, Bcfg2.Server.Plugin.Statistics): self.stats = plugin break except: @@ -88,11 +88,11 @@ class Core(object): break for plug_names, plug_tname, plug_type, collection in \ - [(structures, 'structure', Bcfg2.Server.Plugin.StructurePlugin, + [(structures, 'structure', Bcfg2.Server.Plugin.Structure, self.structures), - (generators, 'generator', Bcfg2.Server.Plugin.GeneratorPlugin, + (generators, 'generator', Bcfg2.Server.Plugin.Generator, self.generators), - (connectors, 'connector', Bcfg2.Server.Plugin.MetadataConnectorPlugin, + (connectors, 'connector', Bcfg2.Server.Plugin.Connector, self.connectors), ]: for plugin in plug_names: @@ -170,7 +170,7 @@ class Core(object): if len(glist) == 1: return glist[0].Entries[entry.tag][entry.get('name')](entry, metadata) elif len(glist) > 1: - generators = ", ".join([gen.__name__ for gen in glist]) + generators = ", ".join([gen.name for gen in glist]) logger.error("%s %s served by multiple generators: %s" % \ (entry.tag, entry.get('name'), generators)) g2list = [gen for gen in self.generators if gen.HandlesEntry(entry)] @@ -246,17 +246,16 @@ class Core(object): result = [] for plugin in self.plugins.values(): try: - if isinstance(plugin, Bcfg2.Server.Plugin.DecisionPlugin): + if isinstance(plugin, Bcfg2.Server.Plugin.Decision): result += plugin.GetDecisions(metadata, mode) except: - logger.error("Plugin: %s failed to generate decision list" % plugin.__name__, exc_info=1) + logger.error("Plugin: %s failed to generate decision list" % plugin.name, exc_info=1) return result def build_metadata(self, client_name): imd = self.metadata.get_initial_metadata(client_name) for conn in self.connectors: grps, data = conn.get_additional_metadata(imd) - self.metadata.merge_additional_metadata(imd, conn.__name__, - grps, data) + self.metadata.merge_additional_metadata(imd, conn.name, grps, data) return imd diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 5a8731606..49f498a5e 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -26,7 +26,7 @@ class PluginExecutionError(Exception): class Plugin(object): '''This is the base class for all Bcfg2 Server plugins. Several attributes must be defined in the subclass: - __name__ : the name of the plugin + name : the name of the plugin __version__ : a version string __author__ : the author/contact for the plugin @@ -35,7 +35,7 @@ class Plugin(object): - Configuration entry binding (overloading HandlesEntry, or loads the Entries table) - Data collection (overloading GetProbes/ReceiveData) ''' - __name__ = 'Plugin' + name = 'Plugin' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __rmi__ = [] @@ -45,10 +45,10 @@ class Plugin(object): object.__init__(self) self.Entries = {} self.core = core - self.data = "%s/%s" % (datastore, self.__name__) - self.logger = logging.getLogger('Bcfg2.Plugins.%s' % (self.__name__)) + self.data = "%s/%s" % (datastore, self.name) + self.logger = logging.getLogger('Bcfg2.Plugins.%s' % (self.name)) -class GeneratorPlugin(Plugin): +class Generator(object): '''Generator plugins contribute to literal client configurations''' def HandlesEntry(self, entry): '''This is the slow path method for routing configuration binding requests''' @@ -66,18 +66,13 @@ class GeneratorPlugin(Plugin): of bcfg2-admin pull''' raise PluginExecutionError - def CommitChanges(self): - '''Handle revctl commits, if needed''' - # not implemented yet - pass - -class StructurePlugin(Plugin): +class Structure(object): '''Structure Plugins contribute to abstract client configurations''' def BuildStructures(self, metadata): '''return a list of abstract goal structures for client''' raise PluginExecutionError -class MetadataPlugin(Plugin): +class Metadata(object): '''Signal metadata capabilities for this plugin''' def add_client(self, client_name, attribs): '''add client''' @@ -95,13 +90,13 @@ class MetadataPlugin(Plugin): def merge_additional_metadata(self, imd, source, groups, data): raise PluginExecutionError -class MetadataConnectorPlugin(Plugin): +class Connector(object): '''MetadataConnectorPlugins augment client metadata instances''' def get_additional_metadata(self, metadata): '''determine additional ([groups], {k:v}) for metadata''' return (list(), dict()) -class ProbingPlugin(Plugin): +class Probing(object): '''Signal probe capability for this plugin''' def GetProbes(self, _): '''Return a set of probes for execution on client''' @@ -111,7 +106,7 @@ class ProbingPlugin(Plugin): '''Receive probe results pertaining to client''' pass -class StatisticsPlugin(Plugin): +class Statistics(object): '''Signal statistics handling capability''' def StoreStatistics(self, client, xdata): pass @@ -119,13 +114,15 @@ class StatisticsPlugin(Plugin): def WriteBack(self): pass + +class PullSource(object): def GetExtra(self, client): return [] def GetCurrentEntry(self, client, e_type, e_name): raise PluginExecutionError -class DecisionPlugin(Plugin): +class Decision(object): '''Signal decision handling capability''' def GetDecisions(self, metadata, mode): return [] @@ -381,17 +378,18 @@ class XMLDirectoryBacked(DirectoryBacked): '''Directorybacked for *.xml''' patterns = re.compile('.*\.xml') -class PrioDir(GeneratorPlugin, XMLDirectoryBacked): +class PrioDir(Plugin, Generator, XMLDirectoryBacked): '''This is a generator that handles package assignments''' - __name__ = 'PrioDir' + name = 'PrioDir' __child__ = XMLSrc def __init__(self, core, datastore): Plugin.__init__(self, core, datastore) + Generator.__init__(self) try: XMLDirectoryBacked.__init__(self, self.data, self.core.fam) except OSError: - self.logger.error("Failed to load %s indices" % (self.__name__)) + self.logger.error("Failed to load %s indices" % (self.name)) raise PluginInitError def HandleEvent(self, event): @@ -653,9 +651,9 @@ class FakeProperties: def __init__(self): self.properties = lxml.etree.Element("Properties") -class GroupSpool(GeneratorPlugin): +class GroupSpool(Plugin, Generator): '''The TGenshi generator implements a templating mechanism for configuration files''' - __name__ = 'GroupSpool' + name = 'GroupSpool' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' use_props = False @@ -665,6 +663,7 @@ class GroupSpool(GeneratorPlugin): def __init__(self, core, datastore): Plugin.__init__(self, core, datastore) + Generator.__init__(self) if self.data[-1] == '/': self.data = self.data[:-1] self.Entries['ConfigFile'] = {} @@ -678,7 +677,7 @@ class GroupSpool(GeneratorPlugin): '%s/../etc/properties.xml' % (self.data), self.core.fam) except: self.properties = FakeProperties() - self.logger.info("%s properties disabled" % self.__name__) + self.logger.info("%s properties disabled" % self.name) else: self.properties = FakeProperties() diff --git a/src/lib/Server/Plugins/Account.py b/src/lib/Server/Plugins/Account.py index dd44390e1..86892dcaf 100644 --- a/src/lib/Server/Plugins/Account.py +++ b/src/lib/Server/Plugins/Account.py @@ -3,7 +3,8 @@ __revision__ = '$Revision$' import Bcfg2.Server.Plugin -class Account(Bcfg2.Server.Plugin.GeneratorPlugin): +class Account(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Generator): '''This module generates account config files, based on an internal data repo: static.(passwd|group|limits.conf) -> static entries @@ -12,12 +13,13 @@ class Account(Bcfg2.Server.Plugin.GeneratorPlugin): superusers -> users to be granted root privs on all hosts rootlike -> users to be granted root privs on some hosts ''' - __name__ = 'Account' + name = 'Account' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Generator.__init__(self) self.Entries = {'ConfigFile':{'/etc/passwd':self.from_yp_cb, '/etc/group':self.from_yp_cb, '/etc/security/limits.conf':self.gen_limits_cb, diff --git a/src/lib/Server/Plugins/BB.py b/src/lib/Server/Plugins/BB.py index 70b90016b..1e5166500 100644 --- a/src/lib/Server/Plugins/BB.py +++ b/src/lib/Server/Plugins/BB.py @@ -19,18 +19,16 @@ DOMAIN_SUFFIX = ".mcs.anl.gov" # default is .mcs.anl.gov PXE_CONFIG = "pxelinux.0" # default is pxelinux.0 -class BB(Bcfg2.Server.Plugin.GeneratorPlugin, - Bcfg2.Server.Plugin.StructurePlugin, - Bcfg2.Server.Plugins.Metadata.Metadata, +class BB(Bcfg2.Server.Plugins.Metadata.Metadata, Bcfg2.Server.Plugin.DirectoryBacked): '''BB Plugin handles bb node configuration''' - __name__ = 'BB' + name = 'BB' experimental = True write_to_disk = True def __init__(self, core, datastore): - Bcfg2.Server.Plugin.GeneratorPlugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) try: Bcfg2.Server.Plugin.DirectoryBacked.__init__(self, self.data, self.core.fam) except OSError, ioerr: @@ -43,8 +41,8 @@ class BB(Bcfg2.Server.Plugin.GeneratorPlugin, '/etc/sudoers':self.gen_sudoers, '/etc/dhcp3/dhcpd.conf':self.gen_dhcpd}} self.nodes = {} - self.dhcpd_loaded = False - self.need_update = False + self.dhcpd_loaded = False + self.need_update = False def viz(self, hosts, bundles, key, colors): '''admin mode viz support''' @@ -266,11 +264,11 @@ class BB(Bcfg2.Server.Plugin.GeneratorPlugin, '''Handle events''' Bcfg2.Server.Plugin.DirectoryBacked.HandleEvent(self, event) # static.dhcpd.conf hack - if 'static.dhcpd.conf' in self.entries: - self.dhcpd_loaded = True - if self.need_update and self.dhcpd_loaded: - self.update_dhcpd() - self.need_update = False + if 'static.dhcpd.conf' in self.entries: + self.dhcpd_loaded = True + if self.need_update and self.dhcpd_loaded: + self.update_dhcpd() + self.need_update = False # send events to groups.xml back to Metadata plugin if event and "groups.xml" == event.filename: Bcfg2.Server.Plugins.Metadata.Metadata.HandleEvent(self, event) @@ -331,6 +329,6 @@ class BB(Bcfg2.Server.Plugin.GeneratorPlugin, except OSError: self.logger.error("failed to find link for mac address %s" % mac) if self.dhcpd_loaded: - self.update_dhcpd() - else: - self.need_update = True + self.update_dhcpd() + else: + self.need_update = True diff --git a/src/lib/Server/Plugins/Base.py b/src/lib/Server/Plugins/Base.py index 8cd1e4fa8..223e4de43 100644 --- a/src/lib/Server/Plugins/Base.py +++ b/src/lib/Server/Plugins/Base.py @@ -5,10 +5,12 @@ import Bcfg2.Server.Plugin import copy import lxml.etree -class Base(Bcfg2.Server.Plugin.StructurePlugin, +class Base(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Structure, Bcfg2.Server.Plugin.XMLDirectoryBacked): - '''This Structure is good for the pile of independent configs needed for most actual systems''' - __name__ = 'Base' + '''This Structure is good for the pile of independent configs + needed for most actual systems''' + name = 'Base' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = Bcfg2.Server.Plugin.StructFile @@ -16,8 +18,11 @@ class Base(Bcfg2.Server.Plugin.StructurePlugin, '''base creates independent clauses based on client metadata''' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Structure.__init__(self) try: - Bcfg2.Server.Plugin.XMLDirectoryBacked.__init__(self, self.data, self.core.fam) + Bcfg2.Server.Plugin.XMLDirectoryBacked.__init__(self, + self.data, + self.core.fam) except OSError: self.logger.error("Failed to load Base repository") raise Bcfg2.Server.Plugin.PluginInitError @@ -26,6 +31,7 @@ class Base(Bcfg2.Server.Plugin.StructurePlugin, '''Build structures for client described by metadata''' ret = lxml.etree.Element("Independant", version='2.0') fragments = reduce(lambda x, y: x+y, - [base.Match(metadata) for base in self.entries.values()], []) + [base.Match(metadata) for base + in self.entries.values()], []) [ret.append(copy.deepcopy(frag)) for frag in fragments] return [ret] diff --git a/src/lib/Server/Plugins/Bundler.py b/src/lib/Server/Plugins/Bundler.py index 5cc881167..fe73ab453 100644 --- a/src/lib/Server/Plugins/Bundler.py +++ b/src/lib/Server/Plugins/Bundler.py @@ -3,16 +3,18 @@ __revision__ = '$Revision$' import copy, lxml.etree, Bcfg2.Server.Plugin -class Bundler(Bcfg2.Server.Plugin.StructurePlugin, +class Bundler(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Structure, Bcfg2.Server.Plugin.XMLDirectoryBacked): '''The bundler creates dependent clauses based on the bundle/translation scheme from bcfg1''' - __name__ = 'Bundler' + name = 'Bundler' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = Bcfg2.Server.Plugin.StructFile def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Structure.__init__(self) try: Bcfg2.Server.Plugin.XMLDirectoryBacked.__init__(self, self.data, self.core.fam) except OSError: diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Server/Plugins/Cfg.py index 864d4a8d4..02d912206 100644 --- a/src/lib/Server/Plugins/Cfg.py +++ b/src/lib/Server/Plugins/Cfg.py @@ -127,7 +127,7 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet): class Cfg(Bcfg2.Server.Plugin.GroupSpool): '''This generator in the configuration file repository for bcfg2''' - __name__ = 'Cfg' + name = 'Cfg' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' use_props = False diff --git a/src/lib/Server/Plugins/DBStats.py b/src/lib/Server/Plugins/DBStats.py index eb5e89282..24a030b64 100644 --- a/src/lib/Server/Plugins/DBStats.py +++ b/src/lib/Server/Plugins/DBStats.py @@ -1,19 +1,23 @@ import Bcfg2.Server.Plugin import Bcfg2.Server.Reports.importscript -from Bcfg2.Server.Reports.reports.models import Client, Entries -import difflib, lxml.etree, time, logging, datetime +from Bcfg2.Server.Reports.reports.models import Client +import difflib, lxml.etree, time, logging import Bcfg2.Server.Reports.settings from Bcfg2.Server.Reports.updatefix import update_database -import traceback # for debugging output only logger = logging.getLogger('Bcfg2.Plugins.DBStats') -class DBStats(Bcfg2.Server.Plugin.StatisticsPlugin): - __name__ = 'DBStats' +class DBStats(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Statistics, + Bcfg2.Server.Plugin.PullSource): + name = 'DBStats' __version__ = '$Id$' def __init__(self, core, datastore): + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Statistics.__init__(self) + Bcfg2.Server.Plugin.PullSource.__init__(self) self.cpath = "%s/Metadata/clients.xml" % datastore self.core = core logger.debug("Searching for new models to add to the statistics database") @@ -34,17 +38,19 @@ class DBStats(Bcfg2.Server.Plugin.StatisticsPlugin): # FIXME need to build a metadata interface to expose a list of clients # FIXME Server processing the request should be mentionned here start = time.time() - for i in [1,2,3]: + for i in [1, 2, 3]: try: Bcfg2.Server.Reports.importscript.load_stats( self.core.metadata.clientdata, container, 0, True) break except: - logger.error("DBStats: Failed to write data to database due to lock; retrying", exc_info=1) + logger.error("DBStats: Failed to write to db (lock); retrying", + exc_info=1) if i == 3: logger.error("DBStats: Retry limit failed; aborting operation") return - logger.info("Imported data in the reason fast path in %s second" % (time.time() - start)) + logger.info("Imported data in the reason fast path in %s second" \ + % (time.time() - start)) def GetExtra(self, client): c_inst = Client.objects.filter(name=client)[0] diff --git a/src/lib/Server/Plugins/Decisions.py b/src/lib/Server/Plugins/Decisions.py index 890101f24..db9754ee3 100644 --- a/src/lib/Server/Plugins/Decisions.py +++ b/src/lib/Server/Plugins/Decisions.py @@ -34,8 +34,10 @@ class DecisionSet(Bcfg2.Server.Plugin.EntrySet): ret += c.get_decisions() return ret -class Decisions(DecisionSet, Bcfg2.Server.Plugin.DecisionPlugin): - __name__ = 'Decisions' +class Decisions(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Decision, + DecisionSet): + name = 'Decisions' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' @@ -46,6 +48,7 @@ class Decisions(DecisionSet, Bcfg2.Server.Plugin.DecisionPlugin): - `core`: Bcfg2.Core instance - `datastore`: File repository location """ - Bcfg2.Server.Plugin.DecisionPlugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Decision.__init__(self) DecisionSet.__init__(self, self.data, core.fam, core.encoding) diff --git a/src/lib/Server/Plugins/Deps.py b/src/lib/Server/Plugins/Deps.py index 8749f2a31..cd9c4b79f 100644 --- a/src/lib/Server/Plugins/Deps.py +++ b/src/lib/Server/Plugins/Deps.py @@ -35,7 +35,7 @@ class DepXMLSrc(Bcfg2.Server.Plugin.XMLSrc): __node__ = DNode class Deps(Bcfg2.Server.Plugin.PrioDir): - __name__ = 'Deps' + name = 'Deps' __version__ = '$Id:$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = DepXMLSrc diff --git a/src/lib/Server/Plugins/Editor.py b/src/lib/Server/Plugins/Editor.py index ff89d90fd..6e2204e42 100644 --- a/src/lib/Server/Plugins/Editor.py +++ b/src/lib/Server/Plugins/Editor.py @@ -50,9 +50,10 @@ class EditEntrySet(Bcfg2.Server.Plugin.EntrySet): return self.inputs[client] -class Editor(Bcfg2.Server.Plugin.GroupSpool,Bcfg2.Server.Plugin.ProbingPlugin): - __name__ = 'Editor' - __version__ = '1' +class Editor(Bcfg2.Server.Plugin.GroupSpool, + Bcfg2.Server.Plugin.Probing): + name = 'Editor' + __version__ = '$Id: $' __author__ = 'bcfg2-dev@mcs.anl.gov' filename_pattern = 'edits' es_child_cls = EditDirectives diff --git a/src/lib/Server/Plugins/Hostbase.py b/src/lib/Server/Plugins/Hostbase.py index b08e847da..c61fdace3 100644 --- a/src/lib/Server/Plugins/Hostbase.py +++ b/src/lib/Server/Plugins/Hostbase.py @@ -1,11 +1,11 @@ '''This file provides the Hostbase plugin. It manages dns/dhcp/nis host information''' __revision__ = '$Revision$' -import sys, os +import os os.environ['DJANGO_SETTINGS_MODULE'] = 'Bcfg2.Server.Hostbase.settings' from lxml.etree import Element, SubElement -from syslog import syslog, LOG_INFO -from Bcfg2.Server.Plugin import StructurePlugin, PluginExecutionError, PluginInitError, DirectoryBacked, GeneratorPlugin +import Bcfg2.Server.Plugin +from Bcfg2.Server.Plugin import PluginExecutionError, PluginInitError from time import strftime from sets import Set from django.template import Context, loader @@ -13,49 +13,23 @@ from django.db import connection import re import cStringIO -## class DataNexus(DirectoryBacked): -## '''DataNexus is an object that watches multiple files and -## handles changes in an intelligent fashion.''' -## __name__ = 'DataNexus' - -## def __init__(self, path, filelist, fam): -## self.files = filelist -## DirectoryBacked.__init__(self, path, fam) - -## def HandleEvent(self, event): -## '''Trap adds and updates, else call baseclass HandleEvent''' -## action = event.code2str() -## if action in ['exists', 'created']: -## if (event.filename != self.name) and (event.filename not in self.files): -## syslog(LOG_INFO, "%s:Got event for unexpected file %s" % (self.__name__, event.filename)) -## return -## DirectoryBacked.HandleEvent(self, event) -## if action != 'endExist' and event.filename != self.name: -## self.rebuildState(event) - -## def rebuildState(self, event): -## '''This function is called when underlying data has changed''' -## pass - -class Hostbase(StructurePlugin,GeneratorPlugin): +class Hostbase(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Structure, + Bcfg2.Server.Plugin.Generator): '''The Hostbase plugin handles host/network info''' - __name__ = 'Hostbase' + name = 'Hostbase' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' filepath = '/my/adm/hostbase/files/bind' def __init__(self, core, datastore): - + self.ready = False - StructurePlugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Structure.__init__(self) + Bcfg2.Server.Plugin.Generator.__init__(self) files = ['zone.tmpl', 'reversesoa.tmpl', 'named.tmpl', 'reverseappend.tmpl', 'dhcpd.tmpl', 'hosts.tmpl', 'hostsappend.tmpl'] -## try: -## self.repository = DataNexus(self.data + '/templates/', -## files, self.core.fam) -## except: -## self.LogError("Failed to load data directory") -## raise PluginInitError self.filedata = {} self.dnsservers = [] self.dhcpservers = [] diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Server/Plugins/Metadata.py index bb5a34cca..355624ccc 100644 --- a/src/lib/Server/Plugins/Metadata.py +++ b/src/lib/Server/Plugins/Metadata.py @@ -49,16 +49,16 @@ class ClientMetadata(object): if value == profile] -class Metadata(Bcfg2.Server.Plugin.MetadataPlugin, - ): +class Metadata(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Metadata): '''This class contains data for bcfg2 server metadata''' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' - __name__ = "Metadata" + name = "Metadata" def __init__(self, core, datastore, watch_clients=True): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) - #self.__name__ = 'Metadata' + Bcfg2.Server.Plugin.Metadata.__init__(self) if watch_clients: try: core.fam.AddMonitor("%s/%s" % (self.data, "groups.xml"), self) diff --git a/src/lib/Server/Plugins/NagiosGen.py b/src/lib/Server/Plugins/NagiosGen.py index c3f03dc13..7dfaef125 100644 --- a/src/lib/Server/Plugins/NagiosGen.py +++ b/src/lib/Server/Plugins/NagiosGen.py @@ -14,15 +14,17 @@ alias %s address %s ''' -class NagiosGen(Bcfg2.Server.Plugin.GeneratorPlugin): +class NagiosGen(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Generator): '''NagiosGen is a Bcfg2 plugin that dynamically generates Nagios configuration file based on Bcfg2 data.''' - __name__ = 'NagiosGen' + name = 'NagiosGen' __version__ = '0.6' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Generator.__init__(self) self.Entries = {'ConfigFile': {'/etc/nagiosgen.status' : self.createhostconfig, '/etc/nagios/nagiosgen.cfg': self.createserverconfig}} diff --git a/src/lib/Server/Plugins/Pkgmgr.py b/src/lib/Server/Plugins/Pkgmgr.py index 61b153b2e..32a5bd400 100644 --- a/src/lib/Server/Plugins/Pkgmgr.py +++ b/src/lib/Server/Plugins/Pkgmgr.py @@ -124,7 +124,7 @@ class PkgSrc(Bcfg2.Server.Plugin.XMLSrc): class Pkgmgr(Bcfg2.Server.Plugin.PrioDir): '''This is a generator that handles package assignments''' - __name__ = 'Pkgmgr' + name = 'Pkgmgr' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = PkgSrc diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py index adc920257..c27f21def 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Server/Plugins/Probes.py @@ -46,19 +46,21 @@ class ProbeSet(Bcfg2.Server.Plugin.EntrySet): ret.append(probe) return ret -class Probes(Bcfg2.Server.Plugin.MetadataConnectorPlugin, - Bcfg2.Server.Plugin.ProbingPlugin): - __name__ = 'Probes' +class Probes(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Probing, + Bcfg2.Server.Plugin.Connector): + name = 'Probes' __version__ = '$Id: $' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): - Bcfg2.Server.Plugin.MetadataConnectorPlugin.__init__(self, core, - datastore) - self.__name__ = 'Probes' + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Connector.__init__(self) + Bcfg2.Server.Plugin.Probing.__init__(self) + try: self.probes = ProbeSet(self.data, core.fam, core.encoding, - self.__name__) + self.name) except: raise Bcfg2.Server.Plugin.PluginInitError diff --git a/src/lib/Server/Plugins/Rules.py b/src/lib/Server/Plugins/Rules.py index 8fc5bbd70..b23a52980 100644 --- a/src/lib/Server/Plugins/Rules.py +++ b/src/lib/Server/Plugins/Rules.py @@ -1,10 +1,10 @@ -'''This generator provides service mappings''' +'''This generator provides rule-based entry mappings''' __revision__ = '$Revision$' import Bcfg2.Server.Plugin class Rules(Bcfg2.Server.Plugin.PrioDir): '''This is a generator that handles service assignments''' - __name__ = 'Rules' + name = 'Rules' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' diff --git a/src/lib/Server/Plugins/SGenshi.py b/src/lib/Server/Plugins/SGenshi.py index 4fa95ff4e..7dd2f6865 100644 --- a/src/lib/Server/Plugins/SGenshi.py +++ b/src/lib/Server/Plugins/SGenshi.py @@ -44,14 +44,17 @@ class SGenshiEntrySet(Bcfg2.Server.Plugin.EntrySet): logger.error("SGenshi: Failed to template file %s" % entry.name) return ret -class SGenshi(SGenshiEntrySet, Bcfg2.Server.Plugin.StructurePlugin): +class SGenshi(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Structure, + SGenshiEntrySet): '''The SGenshi plugin provides templated structures''' - __name__ = 'SGenshi' + name = 'SGenshi' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Structure.__init__(self) try: SGenshiEntrySet.__init__(self, self.data, self.core.fam, core.encoding) except: diff --git a/src/lib/Server/Plugins/SSHbase.py b/src/lib/Server/Plugins/SSHbase.py index 4910cb6f4..e3e0f739b 100644 --- a/src/lib/Server/Plugins/SSHbase.py +++ b/src/lib/Server/Plugins/SSHbase.py @@ -4,7 +4,9 @@ __revision__ = '$Revision$' import binascii, os, socket, tempfile import Bcfg2.Server.Plugin -class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.DirectoryBacked): +class SSHbase(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Generator, + Bcfg2.Server.Plugin.DirectoryBacked): '''The sshbase generator manages ssh host keys (both v1 and v2) for hosts. It also manages the ssh_known_hosts file. It can integrate host keys from other management domains and similarly @@ -22,7 +24,7 @@ class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.Director ssh_known_hosts -> the current known hosts file. this is regenerated each time a new key is generated. ''' - __name__ = 'SSHbase' + name = 'SSHbase' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' @@ -31,14 +33,18 @@ class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.Director hostkeys = ["ssh_host_dsa_key.H_%s", "ssh_host_rsa_key.H_%s", "ssh_host_key.H_%s"] keypatterns = ['ssh_host_dsa_key', 'ssh_host_rsa_key', 'ssh_host_key', - 'ssh_host_dsa_key.pub', 'ssh_host_rsa_key.pub', 'ssh_host_key.pub'] + 'ssh_host_dsa_key.pub', 'ssh_host_rsa_key.pub', + 'ssh_host_key.pub'] def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Generator.__init__(self) try: - Bcfg2.Server.Plugin.DirectoryBacked.__init__(self, self.data, self.core.fam) + Bcfg2.Server.Plugin.DirectoryBacked.__init__(self, self.data, + self.core.fam) except OSError, ioerr: - self.logger.error("Failed to load SSHbase repository from %s" % (self.data)) + self.logger.error("Failed to load SSHbase repository from %s" \ + % (self.data)) self.logger.error(ioerr) raise Bcfg2.Server.Plugin.PluginInitError self.Entries = {'ConfigFile': @@ -90,7 +96,7 @@ class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.Director self.skn = False if not self.skn: if (len(self.entries.keys())) > (0.95 * len(os.listdir(self.data))): - a = self.skn + _ = self.skn def HandlesEntry(self, entry): '''Handle key entries dynamically''' @@ -120,7 +126,8 @@ class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.Director self.ipcache[client] = (ipaddr, client) return (ipaddr, client) except socket.gaierror: - ipaddr = os.popen("getent hosts %s" % client).read().strip().split() + cmd = "getent hosts %s" % client + ipaddr = os.popen(cmd).read().strip().split() if ipaddr: self.ipcache[client] = (ipaddr, client) return (ipaddr, client) @@ -175,7 +182,9 @@ class SSHbase(Bcfg2.Server.Plugin.GeneratorPlugin, Bcfg2.Server.Plugin.Director if hostkey not in self.entries.keys(): fileloc = "%s/%s" % (self.data, hostkey) - publoc = self.data + '/' + ".".join([hostkey.split('.')[0]]+['pub', "H_%s" % client]) + publoc = self.data + '/' + ".".join([hostkey.split('.')[0], + 'pub', + "H_%s" % client]) tempdir = tempfile.mkdtemp() temploc = "%s/%s" % (tempdir, hostkey) os.system('ssh-keygen -q -f %s -N "" -t %s -C root@%s < /dev/null' % diff --git a/src/lib/Server/Plugins/Statistics.py b/src/lib/Server/Plugins/Statistics.py index 7c5394a51..ca7a3c5b0 100644 --- a/src/lib/Server/Plugins/Statistics.py +++ b/src/lib/Server/Plugins/Statistics.py @@ -24,7 +24,6 @@ class StatisticsStore(object): '''Write statistics changes back to persistent store''' if (self.dirty and (self.lastwrite + self.__min_write_delay__ <= time()) ) \ or force: - #syslog(LOG_INFO, "Statistics: Updated statistics.xml") try: fout = open(self.filename + '.new', 'w') except IOError, ioerr: @@ -44,7 +43,6 @@ class StatisticsStore(object): fin.close() self.element = XML(data) self.dirty = 0 - #syslog(LOG_INFO, "Statistics: Read in statistics.xml") except (IOError, XMLSyntaxError): self.logger.error("Creating new statistics file %s"%(self.filename)) self.element = Element('ConfigStatistics') @@ -68,7 +66,8 @@ class StatisticsStore(object): # Find correct node entry in stats data # The following list comprehension should be guarenteed to return at # most one result - nodes = [elem for elem in self.element.findall('Node') if elem.get('name') == client] + nodes = [elem for elem in self.element.findall('Node') \ + if elem.get('name') == client] nummatch = len(nodes) if nummatch == 0: # Create an entry for this node @@ -76,11 +75,14 @@ class StatisticsStore(object): elif nummatch == 1 and not node_dirty: # Delete old instance node = nodes[0] - [node.remove(elem) for elem in node.findall('Statistics') if self.isOlderThan24h(elem.get('time'))] + [node.remove(elem) for elem in node.findall('Statistics') \ + if self.isOlderThan24h(elem.get('time'))] elif nummatch == 1 and node_dirty: # Delete old dirty statistics entry node = nodes[0] - [node.remove(elem) for elem in node.findall('Statistics') if (elem.get('state') == 'dirty' and self.isOlderThan24h(elem.get('time')))] + [node.remove(elem) for elem in node.findall('Statistics') \ + if (elem.get('state') == 'dirty' \ + and self.isOlderThan24h(elem.get('time')))] else: # Shouldn't be reached self.logger.error("Duplicate node entry for %s"%(client)) @@ -93,7 +95,7 @@ class StatisticsStore(object): # Set dirty self.dirty = 1 - self.WriteBack() + self.WriteBack(force=1) def isOlderThan24h(self, testTime): @@ -104,27 +106,35 @@ class StatisticsStore(object): return (now-utime) > secondsPerDay -class Statistics(Bcfg2.Server.Plugin.StatisticsPlugin): - __name__ = 'Statistics' +class Statistics(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Statistics, + Bcfg2.Server.Plugin.PullSource): + name = 'Statistics' __version__ = '$Id$' - def __init__(self, _, datastore): + def __init__(self, core, datastore): + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Statistics.__init__(self) + Bcfg2.Server.Plugin.PullSource.__init__(self) fpath = "%s/etc/statistics.xml" % datastore - self.data = StatisticsStore(fpath) + self.data_file = StatisticsStore(fpath) def StoreStatistics(self, client, xdata): - self.data.updateStats(xdata, client.hostname) + self.data_file.updateStats(xdata, client.hostname) def WriteBack(self): - self.data.WriteBack() + self.data_file.WriteBack() def FindCurrent(self, client): - rt = self.data.element.xpath('//Node[@name="%s"]' % client)[0] - maxtime = max([strptime(stat.get('time')) for stat in rt.findall('Statistics')]) - return [stat for stat in rt.findall('Statistics') if strptime(stat.get('time')) == maxtime][0] + rt = self.data_file.element.xpath('//Node[@name="%s"]' % client)[0] + maxtime = max([strptime(stat.get('time')) for stat \ + in rt.findall('Statistics')]) + return [stat for stat in rt.findall('Statistics') \ + if strptime(stat.get('time')) == maxtime][0] def GetExtra(self, client): - return [(entry.tag, entry.get('name')) for entry in self.FindCurrent(client).xpath('.//Extra/*')] + return [(entry.tag, entry.get('name')) for entry \ + in self.FindCurrent(client).xpath('.//Extra/*')] def GetCurrentEntry(self, client, e_type, e_name): curr = self.FindCurrent(client) diff --git a/src/lib/Server/Plugins/Svcmgr.py b/src/lib/Server/Plugins/Svcmgr.py index 23f06b627..770871c18 100644 --- a/src/lib/Server/Plugins/Svcmgr.py +++ b/src/lib/Server/Plugins/Svcmgr.py @@ -5,6 +5,6 @@ import Bcfg2.Server.Plugin class Svcmgr(Bcfg2.Server.Plugin.PrioDir): '''This is a generator that handles service assignments''' - __name__ = 'Svcmgr' + name = 'Svcmgr' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' diff --git a/src/lib/Server/Plugins/TCheetah.py b/src/lib/Server/Plugins/TCheetah.py index b9381268b..c2e632351 100644 --- a/src/lib/Server/Plugins/TCheetah.py +++ b/src/lib/Server/Plugins/TCheetah.py @@ -57,7 +57,7 @@ class TemplateFile: class TCheetah(Bcfg2.Server.Plugin.GroupSpool): '''The TCheetah generator implements a templating mechanism for configuration files''' - __name__ = 'TCheetah' + name = 'TCheetah' __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' filename_pattern = 'template' diff --git a/src/lib/Server/Plugins/TGenshi.py b/src/lib/Server/Plugins/TGenshi.py index f453b0450..1dfe2f3c5 100644 --- a/src/lib/Server/Plugins/TGenshi.py +++ b/src/lib/Server/Plugins/TGenshi.py @@ -96,7 +96,7 @@ class TGenshi(Bcfg2.Server.Plugin.GroupSpool): The TGenshi generator implements a templating mechanism for configuration files ''' - __name__ = 'TGenshi' + name = 'TGenshi' __version__ = '$Id$' __author__ = 'jeff@ocjtech.us' use_props = True diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index bf88b1bfe..5c689489b 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -260,7 +260,7 @@ Usage: [quit|exit]""" for etype, names in interested: for name in [name for name in names if name in \ generator.Entries.get(etype, {})]: - data.append((generator.__name__, etype, name)) + data.append((generator.name, etype, name)) printTabular(data) def do_event_debug(self, args): diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index b190a6e16..fed02bf6b 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -109,7 +109,7 @@ class Bcfg2Serv(Bcfg2.Component.Component): meta = self.Core.build_metadata(name) for plugin in [p for p in self.Core.plugins.values() \ - if isinstance(p, Bcfg2.Server.Plugin.ProbingPlugin)]: + if isinstance(p, Bcfg2.Server.Plugin.Probing)]: for probe in plugin.GetProbes(meta): resp.append(probe) return tostring(resp, encoding='UTF-8', xml_declaration=True) -- cgit v1.2.3-1-g7c22