From c8ca57745a5ba5859ade9f36cd57b80210cc01f8 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:23:37 -0400 Subject: removed calls to built-in file()/io.FileIO() in favor of read() --- src/lib/Bcfg2/Server/Plugin.py | 7 ++----- src/lib/Bcfg2/Server/Plugins/Packages/Apt.py | 7 +++---- src/lib/Bcfg2/Server/Plugins/Packages/Pac.py | 7 ++++--- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 7fe98ea92..79350f800 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -22,9 +22,6 @@ except ImportError: # py3k compatibility if sys.hexversion >= 0x03000000: from functools import reduce - from io import FileIO as BUILTIN_FILE_TYPE -else: - BUILTIN_FILE_TYPE = file from Bcfg2.Bcfg2Py3k import Queue from Bcfg2.Bcfg2Py3k import Empty from Bcfg2.Bcfg2Py3k import Full @@ -434,7 +431,7 @@ class FileBacked(object): if event and event.code2str() not in ['exists', 'changed', 'created']: return try: - self.data = BUILTIN_FILE_TYPE(self.name).read() + self.data = open(self.name).read() self.Index() except IOError: err = sys.exc_info()[1] @@ -847,7 +844,7 @@ class XMLSrc(XMLFileBacked): def HandleEvent(self, _=None): """Read file upon update.""" try: - data = BUILTIN_FILE_TYPE(self.name).read() + data = open(self.name).read() except IOError: logger.error("Failed to read file %s" % (self.name)) return diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py index 83f7bbd10..685cd5c1d 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py @@ -2,8 +2,7 @@ import re import gzip from Bcfg2.Server.Plugins.Packages.Collection import Collection from Bcfg2.Server.Plugins.Packages.Source import Source -from Bcfg2.Bcfg2Py3k import cPickle, file - +from Bcfg2.Bcfg2Py3k import cPickle class AptCollection(Collection): def get_group(self, group): @@ -25,13 +24,13 @@ class AptSource(Source): 'components': self.components, 'arches': self.arches}] def save_state(self): - cache = file(self.cachefile, 'wb') + cache = open(self.cachefile, 'wb') cPickle.dump((self.pkgnames, self.deps, self.provides, self.essentialpkgs), cache, 2) cache.close() def load_state(self): - data = file(self.cachefile) + data = open(self.cachefile) (self.pkgnames, self.deps, self.provides, self.essentialpkgs) = cPickle.load(data) diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py b/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py index 99a090739..34c7b42c1 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py @@ -1,6 +1,6 @@ import gzip import tarfile -from Bcfg2.Bcfg2Py3k import cPickle, file +from Bcfg2.Bcfg2Py3k import cPickle from Bcfg2.Server.Plugins.Packages.Collection import Collection from Bcfg2.Server.Plugins.Packages.Source import Source @@ -9,6 +9,7 @@ class PacCollection(Collection): self.logger.warning("Packages: Package groups are not supported by Pacman") return [] + class PacSource(Source): basegroups = ['arch', 'parabola'] ptype = 'pacman' @@ -22,13 +23,13 @@ class PacSource(Source): 'components': self.components, 'arches': self.arches}] def save_state(self): - cache = file(self.cachefile, 'wb') + cache = open(self.cachefile, 'wb') cPickle.dump((self.pkgnames, self.deps, self.provides), cache, 2) cache.close() def load_state(self): - data = file(self.cachefile) + data = open(self.cachefile) self.pkgnames, self.deps, self.provides = cPickle.load(data) def filter_unknown(self, unknown): -- cgit v1.2.3-1-g7c22 From 1b6394708b267bcc9230fbb77e0fd4ad51f456b8 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:25:15 -0400 Subject: DatabaseBacked interface needs to be a Plugin object --- src/lib/Bcfg2/Server/Plugin.py | 44 +++++++++++++++----------------- src/lib/Bcfg2/Server/Plugins/Metadata.py | 6 ++--- src/lib/Bcfg2/Server/Plugins/Probes.py | 6 ++--- 3 files changed, 24 insertions(+), 32 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 79350f800..035de1465 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -99,30 +99,6 @@ class Debuggable(object): self.logger.error(message) -class DatabaseBacked(object): - def __init__(self): - pass - - @property - def _use_db(self): - use_db = self.core.setup.cfp.getboolean(self.name.lower(), - "use_database", - default=False) - if use_db and has_django: - return True - elif not use_db: - return False - else: - self.logger.error("use_database is true but django not found") - return False - - - -class PluginDatabaseModel(object): - class Meta: - app_label = "Server" - - class Plugin(Debuggable): """This is the base class for all Bcfg2 Server plugins. Several attributes must be defined in the subclass: @@ -169,6 +145,26 @@ class Plugin(Debuggable): return "%s Plugin" % self.__class__.__name__ +class DatabaseBacked(Plugin): + @property + def _use_db(self): + use_db = self.core.setup.cfp.getboolean(self.name.lower(), + "use_database", + default=False) + if use_db and has_django: + return True + elif not use_db: + return False + else: + self.logger.error("use_database is true but django not found") + return False + + +class PluginDatabaseModel(object): + class Meta: + app_label = "Server" + + class Generator(object): """Generator plugins contribute to literal client configurations.""" def HandlesEntry(self, entry, metadata): diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index e7be7c227..ef246ffd0 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -318,8 +318,7 @@ class MetadataGroup(tuple): def __hash__(self): return hash(self.name) -class Metadata(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.Metadata, +class Metadata(Bcfg2.Server.Plugin.Metadata, Bcfg2.Server.Plugin.Statistics, Bcfg2.Server.Plugin.DatabaseBacked): """This class contains data for bcfg2 server metadata.""" @@ -328,10 +327,9 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, sort_order = 500 def __init__(self, core, datastore, watch_clients=True): - Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Metadata.__init__(self) Bcfg2.Server.Plugin.Statistics.__init__(self) - Bcfg2.Server.Plugin.DatabaseBacked.__init__(self) + Bcfg2.Server.Plugin.DatabaseBacked.__init__(self, core, datastore) self.watch_clients = watch_clients self.states = dict() self.extra = dict() diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py index 114a9bbd8..53deefebd 100644 --- a/src/lib/Bcfg2/Server/Plugins/Probes.py +++ b/src/lib/Bcfg2/Server/Plugins/Probes.py @@ -152,8 +152,7 @@ class ProbeSet(Bcfg2.Server.Plugin.EntrySet): return ret -class Probes(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.Probing, +class Probes(Bcfg2.Server.Plugin.Probing, Bcfg2.Server.Plugin.Connector, Bcfg2.Server.Plugin.DatabaseBacked): """A plugin to gather information from a client machine.""" @@ -161,10 +160,9 @@ class Probes(Bcfg2.Server.Plugin.Plugin, __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): - Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Connector.__init__(self) Bcfg2.Server.Plugin.Probing.__init__(self) - Bcfg2.Server.Plugin.DatabaseBacked.__init__(self) + Bcfg2.Server.Plugin.DatabaseBacked.__init__(self, core, datastore) try: self.probes = ProbeSet(self.data, core.fam, core.encoding, -- cgit v1.2.3-1-g7c22 From bd4bf2d48fda146f9b31c0253e11aba6cabb69d4 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:26:26 -0400 Subject: ThreadedStatistics needs to be a Plugin object --- src/lib/Bcfg2/Server/Plugin.py | 24 +++++++++++------------- src/lib/Bcfg2/Server/Plugins/DBStats.py | 4 +--- src/lib/Bcfg2/Server/Plugins/Metadata.py | 2 +- src/lib/Bcfg2/Server/Plugins/Snapshots.py | 6 ++---- src/lib/Bcfg2/Server/Plugins/Statistics.py | 4 +--- 5 files changed, 16 insertions(+), 24 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 035de1465..b66371a80 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -229,22 +229,22 @@ class Probing(object): pass -class Statistics(object): +class Statistics(Plugin): """Signal statistics handling capability.""" def process_statistics(self, client, xdata): pass -class ThreadedStatistics(Statistics, - threading.Thread): +class ThreadedStatistics(Statistics, threading.Thread): """Threaded statistics handling capability.""" def __init__(self, core, datastore): - Statistics.__init__(self) + Statistics.__init__(self, core, datastore) threading.Thread.__init__(self) # Event from the core signaling an exit self.terminate = core.terminate self.work_queue = Queue(100000) - self.pending_file = "%s/etc/%s.pending" % (datastore, self.__class__.__name__) + self.pending_file = os.path.join(datastore, "etc", + "%s.pending" % self.name) self.daemon = False self.start() @@ -265,7 +265,7 @@ class ThreadedStatistics(Statistics, savefile = open(self.pending_file, 'w') pickle.dump(pending_data, savefile) savefile.close() - self.logger.info("Saved pending %s data" % self.__class__.__name__) + self.logger.info("Saved pending %s data" % self.name) except: self.logger.warning("Failed to save pending data") @@ -312,8 +312,9 @@ class ThreadedStatistics(Statistics, try: os.unlink(self.pending_file) except: - self.logger.error("Failed to unlink save file: %s" % self.pending_file) - self.logger.info("Loaded pending %s data" % self.__class__.__name__) + self.logger.error("Failed to unlink save file: %s" % + self.pending_file) + self.logger.info("Loaded pending %s data" % self.name) return True def run(self): @@ -333,14 +334,11 @@ class ThreadedStatistics(Statistics, self.save() def process_statistics(self, metadata, data): - warned = False try: self.work_queue.put_nowait((metadata, copy.copy(data))) - warned = False except Full: - if not warned: - self.logger.warning("%s: Queue is full. Dropping interactions." % self.__class__.__name__) - warned = True + self.logger.warning("%s: Queue is full. Dropping interactions." % + self.name) def handle_statistics(self, metadata, data): """Handle stats here.""" diff --git a/src/lib/Bcfg2/Server/Plugins/DBStats.py b/src/lib/Bcfg2/Server/Plugins/DBStats.py index 40ab11208..fa1f45a39 100644 --- a/src/lib/Bcfg2/Server/Plugins/DBStats.py +++ b/src/lib/Bcfg2/Server/Plugins/DBStats.py @@ -18,13 +18,11 @@ from Bcfg2.Server.Reports.reports.models import Client logger = logging.getLogger('Bcfg2.Plugins.DBStats') -class DBStats(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.ThreadedStatistics, +class DBStats(Bcfg2.Server.Plugin.ThreadedStatistics, Bcfg2.Server.Plugin.PullSource): name = 'DBStats' def __init__(self, core, datastore): - Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.ThreadedStatistics.__init__(self, core, datastore) Bcfg2.Server.Plugin.PullSource.__init__(self) self.cpath = "%s/Metadata/clients.xml" % datastore diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index ef246ffd0..79aaddbf6 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -328,7 +328,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, def __init__(self, core, datastore, watch_clients=True): Bcfg2.Server.Plugin.Metadata.__init__(self) - Bcfg2.Server.Plugin.Statistics.__init__(self) + Bcfg2.Server.Plugin.Statistics.__init__(self, core, datastore) Bcfg2.Server.Plugin.DatabaseBacked.__init__(self, core, datastore) self.watch_clients = watch_clients self.states = dict() diff --git a/src/lib/Bcfg2/Server/Plugins/Snapshots.py b/src/lib/Bcfg2/Server/Plugins/Snapshots.py index 232dbb0c3..666beef21 100644 --- a/src/lib/Bcfg2/Server/Plugins/Snapshots.py +++ b/src/lib/Bcfg2/Server/Plugins/Snapshots.py @@ -62,14 +62,12 @@ def build_snap_ent(entry): return [desired, state] -class Snapshots(Bcfg2.Server.Plugin.Statistics, - Bcfg2.Server.Plugin.Plugin): +class Snapshots(Bcfg2.Server.Plugin.Statistics): name = 'Snapshots' experimental = True def __init__(self, core, datastore): - Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) - Bcfg2.Server.Plugin.Statistics.__init__(self) + Bcfg2.Server.Plugin.Statistics.__init__(self, core, datastore) self.session = Bcfg2.Server.Snapshots.setup_session(core.cfile) self.work_queue = Queue() self.loader = threading.Thread(target=self.load_snapshot) diff --git a/src/lib/Bcfg2/Server/Plugins/Statistics.py b/src/lib/Bcfg2/Server/Plugins/Statistics.py index 9af7549ff..ce8d085cc 100644 --- a/src/lib/Bcfg2/Server/Plugins/Statistics.py +++ b/src/lib/Bcfg2/Server/Plugins/Statistics.py @@ -113,13 +113,11 @@ class StatisticsStore(object): return (now-utime) > secondsPerDay -class Statistics(Bcfg2.Server.Plugin.Plugin, - Bcfg2.Server.Plugin.ThreadedStatistics, +class Statistics(Bcfg2.Server.Plugin.ThreadedStatistics, Bcfg2.Server.Plugin.PullSource): name = 'Statistics' def __init__(self, core, datastore): - Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.ThreadedStatistics.__init__(self, core, datastore) Bcfg2.Server.Plugin.PullSource.__init__(self) fpath = "%s/etc/statistics.xml" % datastore -- cgit v1.2.3-1-g7c22 From 17d634011069564435df21d6bc1cd415f6e9f3e0 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:29:29 -0400 Subject: use cPickle instead of pickle in Statistics --- src/lib/Bcfg2/Server/Plugin.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index b66371a80..cc2fb96ba 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -4,7 +4,6 @@ import copy import logging import lxml.etree import os -import pickle import posixpath import re import sys @@ -22,9 +21,7 @@ except ImportError: # py3k compatibility if sys.hexversion >= 0x03000000: from functools import reduce -from Bcfg2.Bcfg2Py3k import Queue -from Bcfg2.Bcfg2Py3k import Empty -from Bcfg2.Bcfg2Py3k import Full +from Bcfg2.Bcfg2Py3k import Queue, Empty, Full, cPickle # grab default metadata info from bcfg2.conf opts = {'owner': Bcfg2.Options.MDATA_OWNER, @@ -263,7 +260,7 @@ class ThreadedStatistics(Statistics, threading.Thread): try: savefile = open(self.pending_file, 'w') - pickle.dump(pending_data, savefile) + cPickle.dump(pending_data, savefile) savefile.close() self.logger.info("Saved pending %s data" % self.name) except: @@ -276,7 +273,7 @@ class ThreadedStatistics(Statistics, threading.Thread): pending_data = [] try: savefile = open(self.pending_file, 'r') - pending_data = pickle.load(savefile) + pending_data = cPickle.load(savefile) savefile.close() except Exception: e = sys.exc_info()[1] -- cgit v1.2.3-1-g7c22 From faa5a73f5eea8622696a898c691cd5cade63e492 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:29:56 -0400 Subject: simplify default metadata loading --- src/lib/Bcfg2/Server/Plugin.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index cc2fb96ba..5c8913ef6 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -31,14 +31,12 @@ opts = {'owner': Bcfg2.Options.MDATA_OWNER, 'important': Bcfg2.Options.MDATA_IMPORTANT, 'paranoid': Bcfg2.Options.MDATA_PARANOID, 'sensitive': Bcfg2.Options.MDATA_SENSITIVE} -mdata_setup = Bcfg2.Options.OptionParser(opts) -mdata_setup.parse([]) -del mdata_setup['args'] +default_file_metadata = Bcfg2.Options.OptionParser(opts) +default_file_metadata.parse([]) +del default_file_metadata['args'] logger = logging.getLogger('Bcfg2.Server.Plugin') -default_file_metadata = mdata_setup - info_regex = re.compile( \ 'encoding:(\s)*(?P\w+)|' + 'group:(\s)*(?P\S+)|' + -- cgit v1.2.3-1-g7c22 From 909fa1494d036938da95cb3c93efac48592c04c0 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:30:35 -0400 Subject: raise NotImplementedError from unimplemented plugin interface methods --- src/lib/Bcfg2/Server/Plugin.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 5c8913ef6..c675dd60e 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -168,14 +168,14 @@ class Generator(object): def HandleEntry(self, entry, metadata): """This is the slow-path handler for configuration entry binding.""" - raise PluginExecutionError + raise NotImplementedError 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 + raise NotImplementedError class Metadata(object): @@ -196,7 +196,7 @@ class Metadata(object): pass def get_initial_metadata(self, client_name): - raise PluginExecutionError + raise NotImplementedError def merge_additional_data(self, imd, source, groups, data): raise PluginExecutionError @@ -345,17 +345,17 @@ class PullSource(object): return [] def GetCurrentEntry(self, client, e_type, e_name): - raise PluginExecutionError + raise NotImplementedError class PullTarget(object): def AcceptChoices(self, entry, metadata): - raise PluginExecutionError + raise NotImplementedError def AcceptPullData(self, specific, new_entry, verbose): """This is the null per-plugin implementation of bcfg2-admin pull.""" - raise PluginExecutionError + raise NotImplementedError class Decision(object): @@ -371,13 +371,13 @@ class ValidationError(Exception): class StructureValidator(object): """Validate/modify goal structures.""" def validate_structures(self, metadata, structures): - raise ValidationError("not implemented") + raise NotImplementedError class GoalValidator(object): """Validate/modify configuration goals.""" def validate_goals(self, metadata, goals): - raise ValidationError("not implemented") + raise NotImplementedError class Version(object): -- cgit v1.2.3-1-g7c22 From 8753aeb0f963abeb19db61c2f69ac4800001f354 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:30:58 -0400 Subject: fixed Metadata interface definition --- src/lib/Bcfg2/Server/Plugin.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index c675dd60e..d758f37ae 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -198,8 +198,11 @@ class Metadata(object): def get_initial_metadata(self, client_name): raise NotImplementedError - def merge_additional_data(self, imd, source, groups, data): - raise PluginExecutionError + def merge_additional_data(self, imd, source, data): + raise NotImplementedError + + def merge_additional_groups(self, imd, groups): + raise NotImplementedError class Connector(object): -- cgit v1.2.3-1-g7c22 From 10b49178cb83866f2cde363f73c8ad9f574a8590 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:31:12 -0400 Subject: fixed several Statistics bugs --- src/lib/Bcfg2/Server/Plugin.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index d758f37ae..31c62018a 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -253,9 +253,12 @@ class ThreadedStatistics(Statistics, threading.Thread): while not self.work_queue.empty(): (metadata, data) = self.work_queue.get_nowait() try: - pending_data.append((metadata.hostname, lxml.etree.tostring(data))) + pending_data.append((metadata.hostname, + lxml.etree.tostring(data))) except: - self.logger.warning("Dropping interaction for %s" % metadata.hostname) + err = sys.exc_info()[1] + self.logger.warning("Dropping interaction for %s: %s" % + (metadata.hostname, err)) except Empty: pass @@ -265,10 +268,11 @@ class ThreadedStatistics(Statistics, threading.Thread): savefile.close() self.logger.info("Saved pending %s data" % self.name) except: - self.logger.warning("Failed to save pending data") + err = sys.exc_info()[1] + self.logger.warning("Failed to save pending data: %s" % err) def load(self): - """Load any pending data to a file.""" + """Load any pending data from a file.""" if not os.path.exists(self.pending_file): return True pending_data = [] @@ -279,6 +283,7 @@ class ThreadedStatistics(Statistics, threading.Thread): except Exception: e = sys.exc_info()[1] self.logger.warning("Failed to load pending data: %s" % e) + return False for (pmetadata, pdata) in pending_data: # check that shutdown wasnt called early if self.terminate.isSet(): @@ -304,9 +309,11 @@ class ThreadedStatistics(Statistics, threading.Thread): break except lxml.etree.LxmlError: lxml_error = sys.exc_info()[1] - self.logger.error("Unable to load save interaction: %s" % lxml_error) + self.logger.error("Unable to load saved interaction: %s" % + lxml_error) except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: - self.logger.error("Unable to load metadata for save interaction: %s" % pmetadata) + self.logger.error("Unable to load metadata for save " + "interaction: %s" % pmetadata) try: os.unlink(self.pending_file) except: @@ -320,14 +327,14 @@ class ThreadedStatistics(Statistics, threading.Thread): return while not self.terminate.isSet() and self.work_queue != None: try: - (xdata, client) = self.work_queue.get(block=True, timeout=2) + (client, xdata) = self.work_queue.get(block=True, timeout=2) except Empty: continue except Exception: e = sys.exc_info()[1] self.logger.error("ThreadedStatistics: %s" % e) continue - self.handle_statistic(xdata, client) + self.handle_statistic(client, xdata) if self.work_queue != None and not self.work_queue.empty(): self.save() @@ -338,7 +345,7 @@ class ThreadedStatistics(Statistics, threading.Thread): self.logger.warning("%s: Queue is full. Dropping interactions." % self.name) - def handle_statistics(self, metadata, data): + def handle_statistic(self, metadata, data): """Handle stats here.""" pass -- cgit v1.2.3-1-g7c22 From 35bb03c45a057d1f0f313d129125cc0d1f7c1042 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 11:51:06 -0400 Subject: move MetadataConsistency/RuntimeError exceptions into Plugin.py so we don't depend on a particular Metadata plugin --- src/lib/Bcfg2/Server/Core.py | 25 ++++++-------- src/lib/Bcfg2/Server/Plugin.py | 16 +++++++-- src/lib/Bcfg2/Server/Plugins/Metadata.py | 59 ++++++++++++++------------------ 3 files changed, 50 insertions(+), 50 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py index 7e0e33024..5b84a334d 100644 --- a/src/lib/Bcfg2/Server/Core.py +++ b/src/lib/Bcfg2/Server/Core.py @@ -10,15 +10,10 @@ import time import inspect import lxml.etree from traceback import format_exc - -# this must be set before we import the Metadata plugin -os.environ['DJANGO_SETTINGS_MODULE'] = 'Bcfg2.settings' - import Bcfg2.settings import Bcfg2.Server import Bcfg2.Logger import Bcfg2.Server.FileMonitor -import Bcfg2.Server.Plugins.Metadata from Bcfg2.Bcfg2Py3k import xmlrpclib from Bcfg2.Server.Plugin import PluginInitError, PluginExecutionError @@ -31,6 +26,8 @@ try: except: pass +os.environ['DJANGO_SETTINGS_MODULE'] = 'Bcfg2.settings' + def exposed(func): func.exposed = True return func @@ -356,7 +353,7 @@ class BaseCore(object): revision=self.revision) try: meta = self.build_metadata(client) - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: + except Bcfg2.Server.Plugin.MetadataConsistencyError: self.logger.error("Metadata consistency error for client %s" % client) return lxml.etree.Element("error", type='metadata error') @@ -447,7 +444,7 @@ class BaseCore(object): """Build the metadata structure.""" if not hasattr(self, 'metadata'): # some threads start before metadata is even loaded - raise Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError + raise Bcfg2.Server.Plugin.MetadataRuntimeError imd = self.metadata.get_initial_metadata(client_name) for conn in self.connectors: grps = conn.get_additional_groups(imd) @@ -483,11 +480,11 @@ class BaseCore(object): meta = self.build_metadata(client) else: meta = None - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: + except Bcfg2.Server.Plugin.MetadataConsistencyError: err = sys.exc_info()[1] self.critical_error("Client metadata resolution error for %s: %s" % (address[0], err)) - except Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError: + except Bcfg2.Server.Plugin.MetadataRuntimeError: err = sys.exc_info()[1] self.critical_error('Metadata system runtime failure for %s: %s' % (address[0], err)) @@ -526,8 +523,8 @@ class BaseCore(object): client, metadata = self.resolve_client(address) try: self.metadata.set_version(client, version) - except (Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError, - Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError): + except (Bcfg2.Server.Plugin.MetadataConsistencyError, + Bcfg2.Server.Plugin.MetadataRuntimeError): err = sys.exc_info()[1] self.critical_error("Unable to set version for %s: %s" % (client, err)) @@ -584,8 +581,8 @@ class BaseCore(object): client = self.resolve_client(address, metadata=False)[0] try: self.metadata.set_profile(client, profile, address) - except (Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError, - Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError): + except (Bcfg2.Server.Plugin.MetadataConsistencyError, + Bcfg2.Server.Plugin.MetadataRuntimeError): err = sys.exc_info()[1] self.critical_error("Unable to assert profile for %s: %s" % (client, err)) @@ -599,7 +596,7 @@ class BaseCore(object): config = self.BuildConfiguration(client) return lxml.etree.tostring(config, encoding='UTF-8', xml_declaration=True) - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: + except Bcfg2.Server.Plugin.MetadataConsistencyError: self.critical_error("Metadata consistency failure for %s" % client) @exposed diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 31c62018a..e030ff1bd 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -72,6 +72,18 @@ class PluginExecutionError(Exception): pass +class MetadataConsistencyError(Exception): + """This error gets raised when metadata is internally inconsistent.""" + pass + + +class MetadataRuntimeError(Exception): + """This error is raised when the metadata engine + is called prior to reading enough data. + """ + pass + + class Debuggable(object): __rmi__ = ['toggle_debug'] @@ -294,7 +306,7 @@ class ThreadedStatistics(Statistics, threading.Thread): try: metadata = self.core.build_metadata(pmetadata) break - except Bcfg2.Server.Plugins.Metadata.MetadataRuntimeError: + except MetadataRuntimeError: pass self.terminate.wait(5) @@ -311,7 +323,7 @@ class ThreadedStatistics(Statistics, threading.Thread): lxml_error = sys.exc_info()[1] self.logger.error("Unable to load saved interaction: %s" % lxml_error) - except Bcfg2.Server.Plugins.Metadata.MetadataConsistencyError: + except MetadataConsistencyError: self.logger.error("Unable to load metadata for save " "interaction: %s" % pmetadata) try: diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index 79aaddbf6..fcef6ebb7 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -81,18 +81,6 @@ if has_django: return False -class MetadataConsistencyError(Exception): - """This error gets raised when metadata is internally inconsistent.""" - pass - - -class MetadataRuntimeError(Exception): - """This error is raised when the metadata engine - is called prior to reading enough data. - """ - pass - - class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): """Handles xml config files and all XInclude statements""" def __init__(self, metadata, watch_clients, basefile): @@ -117,13 +105,15 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): @property def xdata(self): if not self.data: - raise MetadataRuntimeError("%s has no data" % self.basefile) + raise Bcfg2.Server.Plugin.MetadataRuntimeError("%s has no data" % + self.basefile) return self.data @property def base_xdata(self): if not self.basedata: - raise MetadataRuntimeError("%s has no data" % self.basefile) + raise Bcfg2.Server.Plugin.MetadataRuntimeError("%s has no data" % + self.basefile) return self.basedata def load_xml(self): @@ -158,7 +148,7 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): except IOError: msg = "Failed to write %s: %s" % (tmpfile, sys.exc_info()[1]) self.logger.error(msg) - raise MetadataRuntimeError(msg) + raise Bcfg2.Server.Plugin.MetadataRuntimeError(msg) # prep data dataroot = xmltree.getroot() newcontents = lxml.etree.tostring(dataroot, pretty_print=True) @@ -174,7 +164,7 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): (tmpfile, sys.exc_info()[1]) self.logger.error(msg, exc_info=1) os.unlink(tmpfile) - raise MetadataRuntimeError(msg) + raise Bcfg2.Server.Plugin.MetadataRuntimeError(msg) datafile.close() # check if clients.xml is a symlink if os.path.islink(fname): @@ -187,7 +177,7 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): msg = "Metadata: Failed to rename %s: %s" % (tmpfile, sys.exc_info()[1]) self.logger.error(msg) - raise MetadataRuntimeError(msg) + raise Bcfg2.Server.Plugin.MetadataRuntimeError(msg) def find_xml_for_xpath(self, xpath): """Find and load xml file containing the xpath query""" @@ -434,7 +424,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, node = self._search_xdata(tag, name, config.xdata, alias=alias) if node != None: self.logger.error("%s \"%s\" already exists" % (tag, name)) - raise MetadataConsistencyError + raise Bcfg2.Server.Plugin.MetadataConsistencyError element = lxml.etree.SubElement(config.base_xdata.getroot(), tag, name=name) if attribs: @@ -478,13 +468,13 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, node = self._search_xdata(tag, name, config.xdata, alias=alias) if node == None: self.logger.error("%s \"%s\" does not exist" % (tag, name)) - raise MetadataConsistencyError + raise Bcfg2.Server.Plugin.MetadataConsistencyError xdict = config.find_xml_for_xpath('.//%s[@name="%s"]' % (tag, node.get('name'))) if not xdict: self.logger.error("Unexpected error finding %s \"%s\"" % (tag, name)) - raise MetadataConsistencyError + raise Bcfg2.Server.Plugin.MetadataConsistencyError for key, val in list(attribs.items()): xdict['xquery'][0].set(key, val) config.write_xml(xdict['filename'], xdict['xmltree']) @@ -520,13 +510,13 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, node = self._search_xdata(tag, name, config.xdata) if node == None: self.logger.error("%s \"%s\" does not exist" % (tag, name)) - raise MetadataConsistencyError + raise Bcfg2.Server.Plugin.MetadataConsistencyError xdict = config.find_xml_for_xpath('.//%s[@name="%s"]' % (tag, node.get('name'))) if not xdict: self.logger.error("Unexpected error finding %s \"%s\"" % (tag, name)) - raise MetadataConsistencyError + raise Bcfg2.Server.Plugin.MetadataConsistencyError xdict['xquery'][0].getparent().remove(xdict['xquery'][0]) config.write_xml(xdict['filename'], xdict['xmltree']) @@ -556,7 +546,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, except MetadataClientModel.DoesNotExist: msg = "Client %s does not exist" % client_name self.logger.warning(msg) - raise MetadataConsistencyError(msg) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(msg) client.delete() self.clients = self.list_clients() else: @@ -739,16 +729,16 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, self.logger.info("Asserting client %s profile to %s" % (client, profile)) if False in list(self.states.values()): - raise MetadataRuntimeError + raise Bcfg2.Server.Plugin.MetadataRuntimeError("Metadata has not been read yet") if not force and profile not in self.groups: msg = "Profile group %s does not exist" % profile self.logger.error(msg) - raise MetadataConsistencyError(msg) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(msg) group = self.groups[profile] if not force and not group.is_public: msg = "Cannot set client %s to private group %s" % (client, profile) self.logger.error(msg) - raise MetadataConsistencyError(msg) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(msg) if client in self.clients: if self._use_db: @@ -795,7 +785,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, else: msg = "Cannot set version on non-existent client %s" % client self.logger.error(msg) - raise MetadataConsistencyError(msg) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(msg) self.versions[client] = version self.clients_xml.write() @@ -829,7 +819,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, if len(self.addresses[address]) != 1: err = "Address %s has multiple reverse assignments; a uuid must be used" % address self.logger.error(err) - raise MetadataConsistencyError(err) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(err) return self.addresses[address][0] try: cname = socket.gethostbyaddr(address)[0].lower() @@ -839,7 +829,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, except socket.herror: warning = "address resolution error for %s" % address self.logger.warning(warning) - raise MetadataConsistencyError(warning) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(warning) def _merge_groups(self, client, groups, categories=None): """ set group membership based on the contents of groups.xml @@ -869,7 +859,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, def get_initial_metadata(self, client): """Return the metadata for a given client.""" if False in list(self.states.values()): - raise MetadataRuntimeError("Metadata has not been read yet") + raise Bcfg2.Server.Plugin.MetadataRuntimeError("Metadata has not been read yet") client = client.lower() if client in self.aliases: client = self.aliases[client] @@ -896,7 +886,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, else: msg = "Cannot add new client %s; no default group set" % client self.logger.error(msg) - raise MetadataConsistencyError(msg) + raise Bcfg2.Server.Plugin.MetadataConsistencyError(msg) if client in self.clientgroups: for cgroup in self.clientgroups[client]: @@ -1050,9 +1040,10 @@ class Metadata(Bcfg2.Server.Plugin.Metadata, id_method = 'address' try: client = self.resolve_client(address) - except MetadataConsistencyError: - self.logger.error("Client %s failed to resolve; metadata problem" - % address[0]) + except Bcfg2.Server.Plugin.MetadataConsistencyError: + err = sys.exc_info()[1] + self.logger.error("Client %s failed to resolve: %s" % + (address[0], err)) return False else: id_method = 'uuid' -- cgit v1.2.3-1-g7c22 From 4d7ba7032e33250adad09047906e1d22d8362a2b Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 13:56:02 -0400 Subject: use os.path instead of posixpath in Plugin.py --- src/lib/Bcfg2/Server/Plugin.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index e030ff1bd..78aaf0eb2 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -4,7 +4,6 @@ import copy import logging import lxml.etree import os -import posixpath import re import sys import threading @@ -506,8 +505,8 @@ class DirectoryBacked(object): """ dirpathname = os.path.join(self.data, relative) if relative not in self.handles.values(): - if not posixpath.isdir(dirpathname): - logger.error("Failed to open directory %s" % (dirpathname)) + if not os.path.isdir(dirpathname): + logger.error("%s is not a directory" % dirpathname) return reqid = self.fam.AddMonitor(dirpathname, self) self.handles[reqid] = relative @@ -567,7 +566,7 @@ class DirectoryBacked(object): # watching a directory just because it gets deleted. If it # is recreated, we will start getting notifications for it # again without having to add a new monitor. - elif posixpath.isdir(abspath): + elif os.path.isdir(abspath): # Deal with events for directories if action in ['exists', 'created']: self.add_directory_monitor(relpath) @@ -1214,9 +1213,9 @@ class GroupSpool(Plugin, Generator): def add_entry(self, event): epath = self.event_path(event) ident = self.event_id(event) - if posixpath.isdir(epath): + if os.path.isdir(epath): self.AddDirectoryMonitor(epath[len(self.data):]) - if ident not in self.entries and posixpath.isfile(epath): + if ident not in self.entries and os.path.isfile(epath): dirpath = "".join([self.data, ident]) self.entries[ident] = self.es_cls(self.filename_pattern, dirpath, @@ -1224,7 +1223,7 @@ class GroupSpool(Plugin, Generator): self.encoding) self.Entries[self.entry_type][ident] = \ self.entries[ident].bind_entry - if not posixpath.isdir(epath): + if not os.path.isdir(epath): # do not pass through directory events self.entries[ident].handle_event(event) @@ -1234,7 +1233,7 @@ class GroupSpool(Plugin, Generator): def event_id(self, event): epath = self.event_path(event) - if posixpath.isdir(epath): + if os.path.isdir(epath): return self.handles[event.requestID] + event.filename else: return self.handles[event.requestID][:-1] @@ -1282,7 +1281,7 @@ class GroupSpool(Plugin, Generator): relative += '/' name = self.data + relative if relative not in list(self.handles.values()): - if not posixpath.isdir(name): + if not os.path.isdir(name): self.logger.error("Failed to open directory %s" % name) return reqid = self.core.fam.AddMonitor(name, self) -- cgit v1.2.3-1-g7c22 From 3fba7f94f1567b91c417477212ea6eba4a456e0a Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 13:56:15 -0400 Subject: DirectoryBacked tests and fixes --- src/lib/Bcfg2/Server/Plugin.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 78aaf0eb2..6a0ebef0d 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -538,11 +538,6 @@ class DirectoryBacked(object): """ action = event.code2str() - # Clean up the absolute path names passed in - event.filename = os.path.normpath(event.filename) - if event.filename.startswith(self.data): - event.filename = event.filename[len(self.data)+1:] - # Exclude events for actions we don't care about if action == 'endExist': return @@ -552,10 +547,14 @@ class DirectoryBacked(object): (action, event.requestID, event.filename)) return + # Clean up path names + event.filename = os.path.normpath(event.filename.lstrip('/')) + # Calculate the absolute and relative paths this event refers to abspath = os.path.join(self.data, self.handles[event.requestID], event.filename) - relpath = os.path.join(self.handles[event.requestID], event.filename) + relpath = os.path.join(self.handles[event.requestID], + event.filename).lstrip('/') if action == 'deleted': for key in self.entries.keys(): -- cgit v1.2.3-1-g7c22 From baad4ec996c599874364025590d9149f578ef99d Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Thu, 9 Aug 2012 16:05:33 -0400 Subject: tests and fixes for XMLFileBacked --- src/lib/Bcfg2/Server/Plugin.py | 24 +++++++++++++--------- src/lib/Bcfg2/Server/Plugins/Metadata.py | 14 ++++++------- .../Server/Plugins/Packages/PackagesSources.py | 11 ++-------- 3 files changed, 22 insertions(+), 27 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 6a0ebef0d..e22eb508e 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -643,14 +643,18 @@ class XMLFileBacked(FileBacked): Bcfg2.Server.XI_NAMESPACE)] for el in included: name = el.get("href") - if name not in self.extras: - if name.startswith("/"): - fpath = name + if name.startswith("/"): + fpath = name + else: + if fname: + rel = fname else: - fpath = os.path.join(os.path.dirname(self.name), name) + rel = self.name + fpath = os.path.join(os.path.dirname(rel), name) + if fpath not in self.extras: if os.path.exists(fpath): self._follow_xincludes(fname=fpath) - self.add_monitor(fpath, name) + self.add_monitor(fpath) else: msg = "%s: %s does not exist, skipping" % (self.name, name) if el.findall('./%sfallback' % Bcfg2.Server.XI_NAMESPACE): @@ -664,9 +668,9 @@ class XMLFileBacked(FileBacked): self.xdata = lxml.etree.XML(self.data, base_url=self.name, parser=Bcfg2.Server.XMLParser) except lxml.etree.XMLSyntaxError: - err = sys.exc_info()[1] - logger.error("Failed to parse %s: %s" % (self.name, err)) - raise Bcfg2.Server.Plugin.PluginInitError + msg = "Failed to parse %s: %s" % (self.name, sys.exc_info()[1]) + logger.error(msg) + raise PluginInitError(msg) self._follow_xincludes() if self.extras: @@ -680,8 +684,8 @@ class XMLFileBacked(FileBacked): if self.__identifier__ is not None: self.label = self.xdata.attrib[self.__identifier__] - def add_monitor(self, fpath, fname): - self.extras.append(fname) + def add_monitor(self, fpath): + self.extras.append(fpath) if self.fam and self.should_monitor: self.fam.AddMonitor(fpath, self) diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index fcef6ebb7..3c2c3701a 100644 --- a/src/lib/Bcfg2/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -193,28 +193,26 @@ class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked): """Try to find the data in included files""" for included in self.extras: try: - xdata = lxml.etree.parse(os.path.join(self.basedir, - included), + xdata = lxml.etree.parse(included, parser=Bcfg2.Server.XMLParser) cli = xdata.xpath(xpath) if len(cli) > 0: - return {'filename': os.path.join(self.basedir, - included), + return {'filename': included, 'xmltree': xdata, 'xquery': cli} except lxml.etree.XMLSyntaxError: - self.logger.error('Failed to parse %s' % (included)) + self.logger.error('Failed to parse %s' % included) return {} - def add_monitor(self, fpath, fname): - self.extras.append(fname) + def add_monitor(self, fpath): + self.extras.append(fpath) if self.fam and self.should_monitor: self.fam.AddMonitor(fpath, self.metadata) def HandleEvent(self, event): """Handle fam events""" filename = os.path.basename(event.filename) - if filename in self.extras: + if event.filename in self.extras: if event.code2str() == 'exists': return False elif filename != self.basefile: diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py index 3ca96c0a4..0d565be31 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py @@ -41,16 +41,9 @@ class PackagesSources(Bcfg2.Server.Plugin.StructFile, def HandleEvent(self, event=None): Bcfg2.Server.Plugin.XMLFileBacked.HandleEvent(self, event=event) if event and event.filename != self.name: - for fname in self.extras: - fpath = None - if fname.startswith("/"): - fpath = os.path.abspath(fname) - else: - fpath = \ - os.path.abspath(os.path.join(os.path.dirname(self.name), - fname)) + for fpath in self.extras: if fpath == os.path.abspath(event.filename): - self.parsed.add(fname) + self.parsed.add(fpath) break if self.loaded: -- cgit v1.2.3-1-g7c22 From d5ed9b3fd3a7f291841fef12e5992706f5d317ca Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 10 Aug 2012 11:36:27 -0400 Subject: StructFile tests and fixes --- src/lib/Bcfg2/Server/Plugin.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index e22eb508e..8ba19632d 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -706,11 +706,9 @@ class StructFile(XMLFileBacked): return False negate = item.get('negate', 'false').lower() == 'true' if item.tag == 'Group': - return ((negate and item.get('name') not in metadata.groups) or - (not negate and item.get('name') in metadata.groups)) + return negate == (item.get('name') not in metadata.groups) elif item.tag == 'Client': - return ((negate and item.get('name') != metadata.hostname) or - (not negate and item.get('name') == metadata.hostname)) + return negate == (item.get('name') != metadata.hostname) else: return True @@ -724,7 +722,7 @@ class StructFile(XMLFileBacked): rv.extend(self._match(child, metadata)) return rv else: - rv = copy.copy(item) + rv = copy.deepcopy(item) for child in rv.iterchildren(): rv.remove(child) for child in item.iterchildren(): -- cgit v1.2.3-1-g7c22 From ffde9c4783902d6904e41c3d5aa620d3f47b1117 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 13 Aug 2012 14:27:27 -0400 Subject: added unit tests for INode, InfoNode --- src/lib/Bcfg2/Server/Plugin.py | 30 +++++++++++++++++------------- src/lib/Bcfg2/Server/Plugins/Deps.py | 21 ++------------------- 2 files changed, 19 insertions(+), 32 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 8ba19632d..cfde25035 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -762,26 +762,28 @@ class StructFile(XMLFileBacked): return rv -class INode: +class INode(object): """ LNodes provide lists of things available at a particular group intersection. """ - raw = {'Client': "lambda m, e:'%(name)s' == m.hostname and predicate(m, e)", - 'Group': "lambda m, e:'%(name)s' in m.groups and predicate(m, e)"} - nraw = {'Client': "lambda m, e:'%(name)s' != m.hostname and predicate(m, e)", - 'Group': "lambda m, e:'%(name)s' not in m.groups and predicate(m, e)"} + raw = dict( + Client="lambda m, e:'%(name)s' == m.hostname and predicate(m, e)", + Group="lambda m, e:'%(name)s' in m.groups and predicate(m, e)") + nraw = dict( + Client="lambda m, e:'%(name)s' != m.hostname and predicate(m, e)", + Group="lambda m, e:'%(name)s' not in m.groups and predicate(m, e)") containers = ['Group', 'Client'] ignore = [] def __init__(self, data, idict, parent=None): self.data = data self.contents = {} - if parent == None: - self.predicate = lambda m, d: True + if parent is None: + self.predicate = lambda m, e: True else: predicate = parent.predicate - if data.get('negate', 'false') in ['true', 'True']: + if data.get('negate', 'false').lower() == 'true': psrc = self.nraw else: psrc = self.raw @@ -790,20 +792,23 @@ class INode: {'name': data.get('name')}, {'predicate': predicate}) else: - raise Exception - mytype = self.__class__ + raise PluginExecutionError("Unknown tag: %s" % data.tag) self.children = [] + self._load_children(data, idict) + + def _load_children(self, data, idict): for item in data.getchildren(): if item.tag in self.ignore: continue elif item.tag in self.containers: - self.children.append(mytype(item, idict, self)) + self.children.append(self.__class__(item, idict, self)) else: try: self.contents[item.tag][item.get('name')] = \ dict(item.attrib) except KeyError: - self.contents[item.tag] = {item.get('name'): dict(item.attrib)} + self.contents[item.tag] = \ + {item.get('name'): dict(item.attrib)} if item.text: self.contents[item.tag][item.get('name')]['__text__'] = \ item.text @@ -984,7 +989,6 @@ class SpecificityError(Exception): class Specificity: - def __init__(self, all=False, group=False, hostname=False, prio=0, delta=False): self.hostname = hostname self.all = all diff --git a/src/lib/Bcfg2/Server/Plugins/Deps.py b/src/lib/Bcfg2/Server/Plugins/Deps.py index 9b848baae..d3a1ee871 100644 --- a/src/lib/Bcfg2/Server/Plugins/Deps.py +++ b/src/lib/Bcfg2/Server/Plugins/Deps.py @@ -7,27 +7,10 @@ import Bcfg2.Server.Plugin class DNode(Bcfg2.Server.Plugin.INode): """DNode provides supports for single predicate types for dependencies.""" - raw = {'Group': "lambda m, e:'%(name)s' in m.groups and predicate(m, e)"} - containers = ['Group'] - - def __init__(self, data, idict, parent=None): - self.data = data - self.contents = {} - if parent == None: - self.predicate = lambda x, d: True - else: - predicate = parent.predicate - if data.tag in list(self.raw.keys()): - self.predicate = eval(self.raw[data.tag] % - {'name': data.get('name')}, - {'predicate': predicate}) - else: - raise Exception - mytype = self.__class__ - self.children = [] + def _load_children(self, data, idict): for item in data.getchildren(): if item.tag in self.containers: - self.children.append(mytype(item, idict, self)) + self.children.append(self.__class__(item, idict, self)) else: data = [(child.tag, child.get('name')) for child in item.getchildren()] -- cgit v1.2.3-1-g7c22 From 9f27d18c1bc14a570f40a77b0c97373e6ab58431 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Mon, 13 Aug 2012 15:54:04 -0400 Subject: added tests for XMLSrc, InfoXML, XMLDirectoryBacked --- src/lib/Bcfg2/Server/Plugin.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index cfde25035..cb6d41fb3 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -862,29 +862,34 @@ class XMLSrc(XMLFileBacked): try: data = open(self.name).read() except IOError: - logger.error("Failed to read file %s" % (self.name)) - return + msg = "Failed to read file %s: %s" % (self.name, sys.exc_info()[1]) + logger.error(msg) + raise PluginExecutionError(msg) self.items = {} try: xdata = lxml.etree.XML(data, parser=Bcfg2.Server.XMLParser) except lxml.etree.XMLSyntaxError: - logger.error("Failed to parse file %s" % (self.name)) - return + msg = "Failed to parse file %s" % (self.name, sys.exc_info()[1]) + logger.error(msg) + raise PluginExecutionError(msg) self.pnode = self.__node__(xdata, self.items) self.cache = None try: self.priority = int(xdata.get('priority')) except (ValueError, TypeError): if not self.noprio: - logger.error("Got bogus priority %s for file %s" % - (xdata.get('priority'), self.name)) + msg = "Got bogus priority %s for file %s" % \ + (xdata.get('priority'), self.name) + logger.error(msg) + raise PluginExecutionError(msg) + del xdata, data def Cache(self, metadata): """Build a package dict for a given host.""" - if self.cache == None or self.cache[0] != metadata: + if self.cache is None or self.cache[0] != metadata: cache = (metadata, self.__cacheobj__()) - if self.pnode == None: + if self.pnode is None: logger.error("Cache method called early for %s; forcing data load" % (self.name)) self.HandleEvent() return @@ -988,8 +993,9 @@ class SpecificityError(Exception): pass -class Specificity: - def __init__(self, all=False, group=False, hostname=False, prio=0, delta=False): +class Specificity(object): + def __init__(self, all=False, group=False, hostname=False, prio=0, + delta=False): self.hostname = hostname self.all = all self.group = group -- cgit v1.2.3-1-g7c22 From f8f62180e36ccc846315e309b62d17e732a3148f Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 14 Aug 2012 07:53:43 -0400 Subject: fixed test inheritance --- src/lib/Bcfg2/Server/Plugin.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index cb6d41fb3..424594de8 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -654,6 +654,7 @@ class XMLFileBacked(FileBacked): if fpath not in self.extras: if os.path.exists(fpath): self._follow_xincludes(fname=fpath) + print "adding monitor to %s" % fpath self.add_monitor(fpath) else: msg = "%s: %s does not exist, skipping" % (self.name, name) @@ -918,11 +919,7 @@ class PrioDir(Plugin, Generator, XMLDirectoryBacked): 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)) - raise PluginInitError + XMLDirectoryBacked.__init__(self, self.data, self.core.fam) def HandleEvent(self, event): """Handle events and update dispatch table.""" @@ -1253,7 +1250,7 @@ class GroupSpool(Plugin, Generator): for entry in self.entries.values(): if hasattr(entry, "toggle_debug"): entry.toggle_debug() - return Plugin.toggle_debug() + return Plugin.toggle_debug(self) def HandleEvent(self, event): """Unified FAM event handler for GroupSpool.""" -- cgit v1.2.3-1-g7c22 From ed48c3c7cd7da8fac30a791ce2495706b6fa3876 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 14 Aug 2012 09:45:12 -0400 Subject: added tests for PrioDir --- src/lib/Bcfg2/Server/Plugin.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 424594de8..bb8973aec 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -958,13 +958,13 @@ class PrioDir(Plugin, Generator, XMLDirectoryBacked): else: prio = [int(src.priority) for src in matching] if prio.count(max(prio)) > 1: - self.logger.error("Found conflicting sources with " - "same priority for %s, %s %s" % - (metadata.hostname, - entry.tag.lower(), entry.get('name'))) + msg = "Found conflicting sources with same priority for " + \ + "%s:%s for %s" % (entry.tag, entry.get("name"), + metadata.hostname) + self.logger.error(msg) self.logger.error([item.name for item in matching]) self.logger.error("Priority was %s" % max(prio)) - raise PluginExecutionError + raise PluginExecutionError(msg) index = prio.index(max(prio)) for rname in list(matching[index].cache[1][entry.tag].keys()): -- cgit v1.2.3-1-g7c22 From 554022ae751777a6f853f54663dc5e9fab818dce Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 14 Aug 2012 11:02:50 -0400 Subject: added tests for Specificity/SpecificData --- src/lib/Bcfg2/Server/Plugin.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index bb8973aec..b630081d4 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -1002,6 +1002,12 @@ class Specificity(object): def __lt__(self, other): return self.__cmp__(other) < 0 + def __gt__(self, other): + return self.__cmp__(other) > 0 + + def __eq__(self, other): + return self.__cmp__(other) == 0 + def matches(self, metadata): return self.all or \ self.hostname == metadata.hostname or \ @@ -1010,26 +1016,36 @@ class Specificity(object): def __cmp__(self, other): """Sort most to least specific.""" if self.all: - return 1 - if self.group: + if other.all: + return 0 + else: + return 1 + elif other.all: + return -1 + elif self.group: if other.hostname: return 1 if other.group and other.prio > self.prio: return 1 if other.group and other.prio == self.prio: return 0 + elif other.group: + return -1 + elif self.hostname and other.hostname: + return 0 return -1 - def more_specific(self, other): - """Test if self is more specific than other.""" + def __str__(self): + rv = [self.__class__.__name__, ': '] if self.all: - True + rv.append("all") elif self.group: - if other.hostname: - return True - elif other.group and other.prio > self.prio: - return True - return False + rv.append("Group %s, priority %s" % (self.group, self.prio)) + elif self.hostname: + rv.append("Host %s" % self.hostname) + if self.delta: + rv.append(", delta=%s" % self.delta) + return "".join(rv) class SpecificData(object): -- cgit v1.2.3-1-g7c22 From be4f6ad065fa17ae34c810f2c09bc9f5fa4d9c23 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 14 Aug 2012 14:44:08 -0400 Subject: added unit tests for EntrySet --- src/lib/Bcfg2/Server/Plugin.py | 56 ++++++++++++-------------- src/lib/Bcfg2/Server/Plugins/Decisions.py | 6 +-- src/lib/Bcfg2/Server/Plugins/Probes.py | 5 +-- src/lib/Bcfg2/Server/Plugins/TemplateHelper.py | 7 ++-- 4 files changed, 35 insertions(+), 39 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index b630081d4..3fcf578d1 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -36,16 +36,15 @@ del default_file_metadata['args'] logger = logging.getLogger('Bcfg2.Server.Plugin') -info_regex = re.compile( \ - 'encoding:(\s)*(?P\w+)|' + - 'group:(\s)*(?P\S+)|' + - 'important:(\s)*(?P\S+)|' + - 'mtime:(\s)*(?P\w+)|' + - 'owner:(\s)*(?P\S+)|' + - 'paranoid:(\s)*(?P\S+)|' + - 'perms:(\s)*(?P\w+)|' + - 'secontext:(\s)*(?P\S+)|' + - 'sensitive:(\s)*(?P\S+)|') +info_regex = re.compile('owner:(\s)*(?P\S+)|' + + 'group:(\s)*(?P\S+)|' + + 'perms:(\s)*(?P\w+)|' + + 'secontext:(\s)*(?P\S+)|' + + 'paranoid:(\s)*(?P\S+)|' + + 'sensitive:(\s)*(?P\S+)|' + + 'encoding:(\s)*(?P\w+)|' + + 'important:(\s)*(?P\S+)|' + + 'mtime:(\s)*(?P\w+)|') def bind_info(entry, metadata, infoxml=None, default=default_file_metadata): for attr, val in list(default.items()): @@ -654,7 +653,6 @@ class XMLFileBacked(FileBacked): if fpath not in self.extras: if os.path.exists(fpath): self._follow_xincludes(fname=fpath) - print "adding monitor to %s" % fpath self.add_monitor(fpath) else: msg = "%s: %s does not exist, skipping" % (self.name, name) @@ -1068,7 +1066,7 @@ class EntrySet(Debuggable): """Entry sets deal with the host- and group-specific entries.""" ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\\.genshi_include)$") - def __init__(self, basename, path, entry_type, encoding): + def __init__(self, basename, path, entry_type, encoding, is_regex=False): Debuggable.__init__(self, name=basename) self.path = path self.entry_type = entry_type @@ -1076,7 +1074,12 @@ class EntrySet(Debuggable): self.metadata = default_file_metadata.copy() self.infoxml = None self.encoding = encoding - pattern = '(.*/)?%s(\.((H_(?P\S+))|' % basename + + if is_regex: + base_pat = basename + else: + base_pat = re.escape(basename) + pattern = '(.*/)?%s(\.((H_(?P\S+))|' % base_pat pattern += '(G(?P\d+)_(?P\S+))))?$' self.specific = re.compile(pattern) @@ -1093,20 +1096,13 @@ class EntrySet(Debuggable): if matching is None: matching = self.get_matching(metadata) - hspec = [ent for ent in matching if ent.specific.hostname] - if hspec: - return hspec[0] - - gspec = [ent for ent in matching if ent.specific.group] - if gspec: - gspec.sort() - return gspec[-1] - - aspec = [ent for ent in matching if ent.specific.all] - if aspec: - return aspec[0] - - raise PluginExecutionError + if matching: + matching.sort() + return matching[0] + else: + raise PluginExecutionError("No matching entries available for %s " + "for %s" % (self.path, + metadata.hostname)) def handle_event(self, event): """Handle FAM events for the TemplateSet.""" @@ -1195,8 +1191,7 @@ class EntrySet(Debuggable): if value: self.metadata[key] = value if len(self.metadata['perms']) == 3: - self.metadata['perms'] = "0%s" % \ - (self.metadata['perms']) + self.metadata['perms'] = "0%s" % self.metadata['perms'] def reset_metadata(self, event): """Reset metadata to defaults if info or info.xml removed.""" @@ -1209,7 +1204,8 @@ class EntrySet(Debuggable): bind_info(entry, metadata, infoxml=self.infoxml, default=self.metadata) def bind_entry(self, entry, metadata): - """Return the appropriate interpreted template from the set of available templates.""" + """Return the appropriate interpreted template from the set of + available templates.""" self.bind_info_to_entry(entry, metadata) return self.best_matching(metadata).bind_entry(entry, metadata) diff --git a/src/lib/Bcfg2/Server/Plugins/Decisions.py b/src/lib/Bcfg2/Server/Plugins/Decisions.py index b432474f2..78b549c2c 100644 --- a/src/lib/Bcfg2/Server/Plugins/Decisions.py +++ b/src/lib/Bcfg2/Server/Plugins/Decisions.py @@ -23,9 +23,9 @@ class DecisionSet(Bcfg2.Server.Plugin.EntrySet): - `encoding`: XML character encoding """ - pattern = '(white|black)list' - Bcfg2.Server.Plugin.EntrySet.__init__(self, pattern, path, \ - DecisionFile, encoding) + Bcfg2.Server.Plugin.EntrySet.__init__(self, '(white|black)list', path, + DecisionFile, encoding, + is_regex=True) try: fam.AddMonitor(path, self) except OSError: diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py index 53deefebd..e08f52a28 100644 --- a/src/lib/Bcfg2/Server/Plugins/Probes.py +++ b/src/lib/Bcfg2/Server/Plugins/Probes.py @@ -115,11 +115,10 @@ class ProbeSet(Bcfg2.Server.Plugin.EntrySet): bangline = re.compile('^#!\s*(?P.*)$') def __init__(self, path, fam, encoding, plugin_name): - fpattern = '[0-9A-Za-z_\-]+' self.plugin_name = plugin_name - Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, + Bcfg2.Server.Plugin.EntrySet.__init__(self, '[0-9A-Za-z_\-]+', path, Bcfg2.Server.Plugin.SpecificData, - encoding) + encoding, is_regex=True) fam.AddMonitor(path, self) def HandleEvent(self, event): diff --git a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py index 3712506d6..2b3aa6bc5 100644 --- a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py +++ b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py @@ -50,12 +50,13 @@ class HelperModule(Bcfg2.Server.Plugin.SpecificData): class HelperSet(Bcfg2.Server.Plugin.EntrySet): ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\.py[co])$") + fpattern = '[0-9A-Za-z_\-]+\.py' def __init__(self, path, fam, encoding, plugin_name): - fpattern = '[0-9A-Za-z_\-]+\.py' self.plugin_name = plugin_name - Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, - HelperModule, encoding) + Bcfg2.Server.Plugin.EntrySet.__init__(self, self.fpattern, path, + HelperModule, encoding, + is_regex=True) fam.AddMonitor(path, self) def HandleEvent(self, event): -- cgit v1.2.3-1-g7c22 From 8207c9c78a94d316bfbd582b2672796e488319b5 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 15 Aug 2012 08:17:35 -0400 Subject: added tests for GroupSpool --- src/lib/Bcfg2/Server/Plugin.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 3fcf578d1..7e7f7db18 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -178,7 +178,7 @@ class Generator(object): def HandleEntry(self, entry, metadata): """This is the slow-path handler for configuration entry binding.""" - raise NotImplementedError + return entry class Structure(object): @@ -1236,7 +1236,7 @@ class GroupSpool(Plugin, Generator): if os.path.isdir(epath): self.AddDirectoryMonitor(epath[len(self.data):]) if ident not in self.entries and os.path.isfile(epath): - dirpath = "".join([self.data, ident]) + dirpath = self.data + ident self.entries[ident] = self.es_cls(self.filename_pattern, dirpath, self.es_child_cls, @@ -1248,15 +1248,17 @@ class GroupSpool(Plugin, Generator): self.entries[ident].handle_event(event) def event_path(self, event): - return "".join([self.data, self.handles[event.requestID], - event.filename]) + return os.path.join(self.data, + self.handles[event.requestID].lstrip("/"), + event.filename) def event_id(self, event): epath = self.event_path(event) if os.path.isdir(epath): - return self.handles[event.requestID] + event.filename + return os.path.join(self.handles[event.requestID].lstrip("/"), + event.filename) else: - return self.handles[event.requestID][:-1] + return self.handles[event.requestID].rstrip("/") def toggle_debug(self): for entry in self.entries.values(): @@ -1273,7 +1275,7 @@ class GroupSpool(Plugin, Generator): if action in ['exists', 'created']: self.add_entry(event) - if action == 'changed': + elif action == 'changed': if ident in self.entries: self.entries[ident].handle_event(event) else: -- cgit v1.2.3-1-g7c22 From e911b57eb38dfa0fc06d19e70e02e121ae721e57 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Wed, 15 Aug 2012 08:21:19 -0400 Subject: print function fixes --- src/lib/Bcfg2/Server/Admin/Reports.py | 4 ++-- src/lib/Bcfg2/Server/Admin/Syncdb.py | 2 +- src/lib/Bcfg2/Server/Plugins/FileProbes.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Admin/Reports.py b/src/lib/Bcfg2/Server/Admin/Reports.py index 175b99d1d..335d6a1e7 100644 --- a/src/lib/Bcfg2/Server/Admin/Reports.py +++ b/src/lib/Bcfg2/Server/Admin/Reports.py @@ -109,7 +109,7 @@ class Reports(Bcfg2.Server.Admin.Mode): try: update_database() except UpdaterError: - print "Update failed" + print("Update failed") raise SystemExit(-1) elif args[0] == 'load_stats': quick = '-O3' in args @@ -121,7 +121,7 @@ class Reports(Bcfg2.Server.Admin.Mode): if stats_file[0] == '-': self.errExit("Invalid statistics file: %s" % stats_file) elif args[i] == '-c' or args[i] == '--clients-file': - print "DeprecationWarning: %s is no longer used" % args[i] + print("DeprecationWarning: %s is no longer used" % args[i]) i = i + 1 self.load_stats(stats_file, self.log.getEffectiveLevel() > logging.WARNING, quick) elif args[0] == 'purge': diff --git a/src/lib/Bcfg2/Server/Admin/Syncdb.py b/src/lib/Bcfg2/Server/Admin/Syncdb.py index c9bba0810..72d3d469e 100644 --- a/src/lib/Bcfg2/Server/Admin/Syncdb.py +++ b/src/lib/Bcfg2/Server/Admin/Syncdb.py @@ -35,5 +35,5 @@ class Syncdb(Bcfg2.Server.Admin.Mode): try: update_database() except UpdaterError: - print "Update failed" + print("Update failed") raise SystemExit(-1) diff --git a/src/lib/Bcfg2/Server/Plugins/FileProbes.py b/src/lib/Bcfg2/Server/Plugins/FileProbes.py index f95c05d42..a403c78d7 100644 --- a/src/lib/Bcfg2/Server/Plugins/FileProbes.py +++ b/src/lib/Bcfg2/Server/Plugins/FileProbes.py @@ -24,7 +24,7 @@ import lxml.etree path = "%s" if not os.path.exists(path): - print "%%s does not exist" %% path + print("%%s does not exist" %% path) raise SystemExit(1) stat = os.stat(path) @@ -34,7 +34,7 @@ data = lxml.etree.Element("ProbedFileData", group=grp.getgrgid(stat[5])[0], perms=oct(stat[0] & 07777)) data.text = binascii.b2a_base64(open(path).read()) -print lxml.etree.tostring(data) +print(lxml.etree.tostring(data)) """ class FileProbes(Bcfg2.Server.Plugin.Plugin, -- cgit v1.2.3-1-g7c22