diff options
-rw-r--r-- | src/lib/Server/Generators/Cfg.py | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/src/lib/Server/Generators/Cfg.py b/src/lib/Server/Generators/Cfg.py index 43446af1d..ff3677270 100644 --- a/src/lib/Server/Generators/Cfg.py +++ b/src/lib/Server/Generators/Cfg.py @@ -5,10 +5,9 @@ from binascii import b2a_base64 from os import stat from re import compile as regcompile from stat import S_ISDIR, ST_MODE -from syslog import syslog, LOG_INFO +from syslog import syslog, LOG_INFO, LOG_ERR -from Bcfg2.Server.Generator import Generator, DirectoryBacked, FileBacked -from Bcfg2.Server.Metadata import Metadata +from Bcfg2.Server.Generator import Generator, FileBacked class CfgFileException(Exception): '''Raised for repository errors''' @@ -18,22 +17,31 @@ class FileEntry(FileBacked): '''The File Entry class pertains to the config files contained in a particular directory. This includes :info, all base files and deltas''' - def __init__(self, name, metadata): + def __init__(self, name, all, image, classes, bundles, attribs, hostname): FileBacked.__init__(self, name) - self.metadata = metadata - - def Applies(self, other): - '''redirect to metadata.Applies''' - return self.metadata.Applies(other) + self.all = all + self.image = image + self.bundles = bundles + self.classes = classes + self.attributes = attribs + self.hostname = hostname def __cmp__(self, other): - '''figure out if self is more or less specific than other''' - return self.metadata.__cmp__(other.metadata) + fields = ['all', 'image', 'classes', 'bundles', 'attributes', 'hostname'] + try: + most1 = [index for index in range(len(fields)) if getattr(self, fields[index])][0] + except IndexError: + most1 = 0 + try: + most2 = [index for index in range(len(fields)) if getattr(other, fields[index])][0] + except IndexError: + most2 = 0 + return most1 - most2 class ConfigFileEntry(object): '''ConfigFileEntry is a repository entry for a single file, containing all data for all clients.''' - mx = regcompile("(^(?P<filename>.*)(\.((B(?P<bprio>\d+)_(?P<bundle>\S+))|(A(?P<aprio>\d+)_(?P<attr>\S+))|(I(?P<iprio>\d+)_(?P<image>\S+))|(I(?P<cprio>\d+)_(?P<class>\S+))|(H_(?P<hostname>\S+)))(\.(?P<op>cat|udiff))?)?$)") + specific = regcompile('(.*/)(?P<filename>[\w.]+)\.((H_(?P<hostname>\w+))|(B(?P<bprio>\d+)_(?P<bundle>\w+))|(A(?P<aprio>\d+)_(?P<attr>\w+))|(I(?P<iprio>\d+)_(?P<image>\w+))|(C(?P<cprio>\d+)_(?P<class>\w+)))(\.(?P<op>cat|udiff))?') info = regcompile('^owner:(\s)*(?P<owner>\w+)|group:(\s)*(?P<group>\w+)|perms:(\s)*(?P<perms>\w+)|encoding:(\s)*(?P<encoding>\w+)|(?P<paranoid>paranoid(\s)*)$') def __init__(self, path): @@ -73,46 +81,45 @@ class ConfigFileEntry(object): if name[-5:] == ':info': return self.read_info(name) - g = self.mx.match(name) - if g == None: + if name.split('/')[-1] == self.path.split('/')[-1]: + self.basefiles.append(FileEntry(name, True, None, [], [], [], None)) + return + + specmatch = self.specific.match(name) + if specmatch == None: + syslog(LOG_ERR, "Failed to match file %s" % (name)) print "match failed for file name %s" % (name) return data = {} - for attr in ['bundle', 'attr', 'hostname', 'class']: - if g.group(attr) != None: - data[attr] = g.group(attr) - if data == {}: - all = True - else: - all = False - # metadata args (global, image, classes, bundles, attributes, hostname) - arg = (all, data.get('image', None)) - for mtype in ['class', 'bundle', 'attr']: - arg = arg + (data.get(mtype, []),) - arg = arg + (data.get('hostname', None),) - m = apply(Metadata, arg) - if g.group("op") != None: - self.deltas.append(FileEntry(name, m)) - # need to sort here + for item, value in specmatch.groupdict().iteritems(): + if value != None: + data[item] = value + + cfile = FileEntry(name, False, data.get('image', None), data.get('class', []), + data.get('bundle', []), data.get('attr', []), data.get('hostname', None)) + + if specmatch.group("op") != None: + self.deltas.append(cfile) + self.deltas.sort() else: - self.basefiles.append(FileEntry(name, m)) - # need to sort here + self.basefiles.append(cfile) + self.basefiles.sort() def HandleEvent(self, event): '''Handle FAM updates''' action = event.code2str() if event.filename[-5:] == ':info': return self.read_info(event.filename) - for l in [self.basefiles, self.deltas]: - for entry in l: - if entry.name.split('/')[-1] == event.filename: - if action == 'changed': - entry.HandleEvent(event) - elif action == 'deleted': - l.remove(entry) - else: - print "unhandled action %s" % (action) + for entry in self.basefiles + self.deltas: + if entry.name.split('/')[-1] == event.filename: + if action == 'changed': + syslog(LOG_INFO, "File %s changed" % event.filename) + entry.HandleEvent(event) + elif action == 'deleted': + [flist.remove(entry) for flist in [self.basefiles, self.deltas] if entry in flist] + else: + print "unhandled action %s" % (action) def GetConfigFile(self, entry, metadata): '''Fetch config file from repository''' @@ -120,16 +127,16 @@ class ConfigFileEntry(object): filedata = "" # first find basefile try: - basefile = [x for x in self.basefiles if x.Applies(metadata)][0] + basefile = [bfile for bfile in self.basefiles if metadata.Applies(bfile)][-1] except IndexError: raise CfgFileException, ('basefile', name) filedata += basefile.data # find applicable deltas - deltas = [x for x in self.deltas if x.Applies(metadata)] + #deltas = [x for x in self.deltas if x.Applies(metadata)] # filter for more specific - for delta in deltas: - pass + #for delta in deltas: + # pass # apply diffs, etc entry.attrib.update({'owner':self.owner, 'group':self.group, 'perms':self.perms, 'encoding':self.encoding}) @@ -140,7 +147,7 @@ class ConfigFileEntry(object): else: entry.text = filedata -class ConfigFileRepository(DirectoryBacked): +class ConfigFileRepository(object): '''This class implements repos and all change handling''' def __init__(self, name, fam): @@ -191,9 +198,9 @@ class ConfigFileRepository(DirectoryBacked): filename = "%s/%s" % (self.famID[event.requestID], event.filename) else: filename = event.filename - if action == 'exists': - if filename != self.name: - self.AddEntry(filename) + + if ((action == 'exists') and (filename != self.name)): + self.AddEntry(filename) elif action == 'created': self.AddEntry(filename) elif action == 'changed': |