Abandon de la philosophie un dossier par fichier.

On fait tout passer par l'environment du script, c'est plus pratique.

darcs-hash:20071218220729-af139-64bf7eda6339a5ecea06402607b5541362db243d.gz
This commit is contained in:
Jeremie Dimino 2007-12-18 23:07:29 +01:00
parent 3ec7919694
commit 4210b7c9ad

View file

@ -52,9 +52,6 @@ else:
def debug(msg, color=None): def debug(msg, color=None):
pass pass
# Les fichiers qui sont surveillés par le plugin dans les dossier /etc/../machin.cf/
_monitored_files = ["info.xml", "gen.py"]
# Dico nom de fichier -> code # Dico nom de fichier -> code
includes = {} includes = {}
@ -69,65 +66,11 @@ def include(env, incfile):
def load_file(filename): def load_file(filename):
'''Charge un script et affiche un message d'erreur en cas d'exception''' '''Charge un script et affiche un message d'erreur en cas d'exception'''
try: try:
return pygen.load(filename) return pygen.load(filename, os.path.dirname(filename) + "/." + os.path.basename(filename) + ".COMPILED")
except Exception, e: except Exception, e:
logger.error('Python compilation error: %s: %s' % (str(e.__class__).split('.', 2)[1], str(e))) logger.error('Python compilation error: %s: %s' % (str(e.__class__).split('.', 2)[1], str(e)))
return None return None
class PythonFile:
'''Template file creates Python template structures for the loaded file'''
def __init__(self, name, properties):
self.name = name
self.info = None
self.code = None
self.properties = properties
def Created(self, path, event):
'''Traitement des créations de fichier'''
if event.filename == "gen.py":
self.code = load_file(path)
else:
self.info = Bcfg2.Server.Plugin.XMLSrc(path, True)
self.info.HandleEvent(event)
def Changed(self, path, event):
'''Traitement des modifications de fichier'''
if event.filename == "gen.py":
self.code = load_file(path)
else:
self.info.HandleEvent(event)
def Deleted(self, path, event):
'''Traitement des suppressions de fichier'''
if event.filename == "gen.py":
self.code = None
else:
self.info = None
def BuildFile(self, entry, metadata):
'''Build literal file information'''
fname = entry.get('realname', entry.get('name'))
debug("building config file: %s" % fname, 'blue')
try:
env = pygen.Environment()
env["metadata"] = metadata
env["properties"] = self.properties
env["include"] = lambda incfile: include(env, incfile)
env["dump"] = lambda incfile: dump(env, incfile)
env.included = set([])
include(env, "common")
entry.text = pygen.generate(self.code, env)
debug(entry.text)
except Exception, e:
logger.error('Python exec error: %s: %s' % (str(e.__class__).split('.', 2)[1], str(e)))
raise Bcfg2.Server.Plugin.PluginExecutionError
if self.info:
mdata = {}
self.info.pnode.Match(metadata, mdata)
mdata = mdata['Info'][None]
[entry.attrib.__setitem__(key, value)
for (key, value) in mdata.iteritems()]
class PythonProperties(Bcfg2.Server.Plugin.SingleXMLFileBacked): class PythonProperties(Bcfg2.Server.Plugin.SingleXMLFileBacked):
'''Class for Python properties''' '''Class for Python properties'''
def Index(self): def Index(self):
@ -153,8 +96,8 @@ class Python(Bcfg2.Server.Plugin.Plugin):
Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
# Les entrées pour bcfg2 # Les entrées pour bcfg2
self.Entries['ConfigFile'] = {} self.Entries['ConfigFile'] = {}
# Nos entrées pour nous (dico de PythonFile) # Correspondance entrée ConfigFile -> code
self.entries = {} self.codes = {}
# Dico ID de requête GAM -> Dossier surveillé # Dico ID de requête GAM -> Dossier surveillé
self.handles = {} self.handles = {}
# Le dossier qui contient les fichiers à inclure # Le dossier qui contient les fichiers à inclure
@ -171,25 +114,48 @@ class Python(Bcfg2.Server.Plugin.Plugin):
self.logger.info("Failed to read properties file; Python properties disabled") self.logger.info("Failed to read properties file; Python properties disabled")
def BuildEntry(self, entry, metadata): def BuildEntry(self, entry, metadata):
'''Dispatch fetch calls to the correct object''' '''Construit le fichier'''
self.entries[entry.get('name')].BuildFile(entry, metadata) code = self.codes[entry.get('name')]
fname = entry.get('realname', entry.get('name'))
debug("building config file: %s" % fname, 'blue')
env = pygen.Environment()
env["metadata"] = metadata
env["properties"] = self.properties
env["include"] = lambda incfile: include(env, incfile)
env["dump"] = lambda incfile: dump(env, incfile)
env["info"] = { 'owner': 'root',
'group': 'root',
'perms': 0644 }
env.included = set([])
try:
include(env, "common")
entry.text = pygen.generate(code, env)
debug(entry.text)
except Exception, e:
logger.error('Python exec error: %s: %s' % (str(e.__class__).split('.', 2)[1], str(e)))
raise Bcfg2.Server.Plugin.PluginExecutionError
entry.attrib['owner'] = env["info"]['owner']
entry.attrib['group'] = env["info"]['group']
entry.attrib['perms'] = oct(env["info"]['perms'])
def HandleEvent(self, event): def HandleEvent(self, event):
'''Traitement des événements de FAM''' '''Traitement des événements de FAM'''
# On passe les fichiers ennuyeux
if event.filename[0] == '/' \
or event.filename.endswith(".COMPILED") \
or event.filename.endswith("~") \
or event.filename.startswith(".#"):
return
action = event.code2str() action = event.code2str()
debug("event received: action=%s filename=%s requestID=%s" % debug("event received: action=%s filename=%s requestID=%s" %
(action, event.filename, event.requestID), 'purple') (action, event.filename, event.requestID), 'purple')
if event.filename[0] == '/' or event.filename.endswith(".pyc"): path = self.handles[event.requestID] + "/" + event.filename
# Rien d'intéressant
return
hdle_path = self.handles[event.requestID]
path = hdle_path + "/" + event.filename
debug("absolute filename: %s" % path, 'yellow') debug("absolute filename: %s" % path, 'yellow')
if path.startswith(self.include): if path.startswith(self.include):
if posixpath.isfile(path) and path.endswith(".py"): if posixpath.isfile(path):
# Les fichiers d'includes... # Les fichiers d'includes...
identifier = path[len(self.include)+1:-3] identifier = path[len(self.include)+1:-3]
if action in ['exists', 'created', 'changed']: if action in ['exists', 'created', 'changed']:
@ -201,30 +167,19 @@ class Python(Bcfg2.Server.Plugin.Plugin):
elif posixpath.isdir(path) and action in ['exists', 'created']: elif posixpath.isdir(path) and action in ['exists', 'created']:
self.AddDirectoryMonitor(path) self.AddDirectoryMonitor(path)
elif posixpath.isfile(path) and event.filename in _monitored_files: elif posixpath.isfile(path):
# Le nom du dossier est le nom du fichier du fichier de # Le nom du dossier est le nom du fichier du fichier de
# configuration à générer # configuration à générer
identifier = hdle_path[len(self.data):] identifier = path[len(self.data):]
if action in ['exists', 'created']: if action in ['exists', 'created']:
if not self.entries.has_key(identifier):
entry = PythonFile(identifier, self.properties)
entry.file_count = 1
debug("adding config file: %s" % identifier, 'green') debug("adding config file: %s" % identifier, 'green')
self.entries[identifier] = entry self.codes[identifier] = load_file(path)
self.Entries['ConfigFile'][identifier] = self.BuildEntry self.Entries['ConfigFile'][identifier] = self.BuildEntry
else:
entry = self.entries[identifier]
entry.file_count += 1
entry.Created(path, event)
elif action == 'changed': elif action == 'changed':
self.entries[identifier].Changed(path, event) self.codes[identifier] = load_file(path)
elif action == 'deleted': elif action == 'deleted':
entry = self.entries[identifier]
entry.Deleted(path, event)
entry.file_count -= 1
if not entry.file_count:
debug("deleting config file: %s" % identifier, 'red') debug("deleting config file: %s" % identifier, 'red')
del self.entries[identifier] del self.codes[identifier]
del self.Entries['ConfigFile'][identifier] del self.Entries['ConfigFile'][identifier]
elif posixpath.isdir(path): elif posixpath.isdir(path):