summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/Server/Generators/Cfg.py105
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':