#!/usr/bin/python # -*- coding: utf-8 -*- """Classes and functions for configuration file handling """ import sys import re import resource import directive import random RESOURCE_TYPES = ('dird', 'console', 'filed', 'stored') rxp_item = re.compile('^\\s*(\\w[\\w ]*\\w+)\\s*\\=(.*)') # xxx = xxx matchen rxp_item2 = re.compile('^\\s*(\\w[\\w ]*\\w+)\\s*\\=\\s*{(.*)}\\s*') # match type = { a = 1; b= 2} rxp_openbrace = re.compile('^\\s*(\\w[\\w ]*\\w+)\\s*\\=?\\s*\\{\\s*') # match xxx { rxp_open = re.compile('^\\s*(\\w[\\w ]*\\w+)\\s*$') # match xxx rxp_closebrace = re.compile('[^{]*}.*') # match } rxp_comment = re.compile('^\s*#.*') #'dird', 'console', 'filed' or 'stored' class Config(object): """Class for bacula configuration access""" def __init__(self, resource_type, filename=""): self.resource_type = resource_type self.filename = filename self.resources = resource.Root(level=0) self.resources.type="" def read(self): self.parse(self.resources,open(self.filename,"r"),0) #print self.resources def write(self, filename=None): if(filename==None): filename=self.filename f=open(filename,"w") f.write(str(self.getRoot())) f.close() def getRoot(self): return self.resources def addResource(self,resname,level,curRes): try: resClass = getattr(resource,resname); except: resClass = resource.Resource newRes=resClass(level+1) newRes.type=resname curRes.add_item(newRes); return newRes def parse(self,curRes,f,level): #print "START",curRes.type while True: line=f.readline() if not line: break inlinecomment=None commentStart=line.find("#") if commentStart!=-1: inlinecomment=line[commentStart:] line=line[:commentStart].strip() #curRes.add_comment(inlinecomment) include=line.strip() if include.startswith("@"): includepath=include[1:].strip() print "include " +includepath self.parse(curRes,open(includepath,"r"),level) if rxp_closebrace.match(line): #print "closebraceline" break item2 = rxp_item2.match(line) if item2: #print "item2" name = item2.group(1) value = item2.group(2) #print "item:",name,value newRes=resource.Resource(level+1) newRes.type=name newRes.value="{"+value+"}" curRes.add_item(newRes) continue openbraceline = rxp_openbrace.match(line) if openbraceline: #print "openbraceline" resname = openbraceline.group(1) newRes=self.addResource(resname,level,curRes) self.parse(newRes,f,level+1); continue open = rxp_open.match(line) if open: resname = open.group(1) newRes=self.addResource(resname,level,curRes) self.parse(newRes,f,level+1); continue item = rxp_item.match(line) if item: name = item.group(1) value = item.group(2).strip() #print "item:",name,value newRes=resource.Resource(level+1) newRes.type=name newRes.value=value curRes.add_item(newRes) continue #print "END",curRes.name class DirdConfig(Config): def __init__(self, filename=""): Config.__init__(self, 'dird', filename) class ConsoleConfig(Config): pass class FiledConfig(Config): def __init__(self, filename=""): Config.__init__(self, 'fd', filename) def setDefaults(self,directorName,directorPassword,myName): director=resource.Director(1,"Director") director.add("Name",directorName) director.add("Password",'"'+directorPassword+'"') self.getRoot().add_item(director) fileDaemon=resource.FileDaemon(1,"FileDaemon") fileDaemon.add("Name",myName) #fileDaemon.add("FDport","9102") fileDaemon.add("WorkingDirectory","/var/lib/bacula") fileDaemon.add("Pid Directory","/var/run") fileDaemon.add("Maximum Concurrent Jobs","20") self.getRoot().add_item(fileDaemon) messages=resource.Messages(1,"Messages") messages.add("Name","Standard") messages.add("director",directorName+" = all, !skipped, !restored") self.getRoot().add_item(messages) class StoredConfig(Config): pass def genpasswd(len=32): charset="01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!/%()=?@" password="" for a in xrange(0,len): password += random.choice(charset) return password def createClientConfig(dirdcfg,clientName,clientPassword=genpasswd()): director=dirdcfg.getRoot().getByType("Director")[0] dirdName=director.getName() r=dirdcfg.getRoot().getByName(clientName) if len(r)==1: client=r[0] else: return filename=clientName+".conf" fdcfg=FiledConfig(filename) fdcfg.setDefaults(dirdName,clientPassword,clientName) fdcfg.write() def createAllClientConfigs(dirdcfg): clients=dirdcfg.getRoot().getByType("Client",1) director=dirdcfg.getRoot().getByType("Director")[0] dirdName=director.getName() for c in clients: print c clientName=c.getName() if clientName!=None: r=c.getByType("Password") if len(r)>0: clientPassword=r[0].value clientPassword=clientPassword.replace('"','') else: clientPassword="" filename=clientName+".conf" fdcfg=FiledConfig(filename) fdcfg.setDefaults(dirdName,clientPassword,clientName) fdcfg.write() if __name__ == "__main__": if len(sys.argv) < 2: filename="test.conf" else: filename=sys.argv[1] dirdcfg = DirdConfig(filename) dirdcfg.read() root=dirdcfg.getRoot() job=resource.Job(1,"Job") job.setDefaults("test2-job","test2","testdefs","Full Set") root.add_item(job) pwd=genpasswd() newclient=resource.Client(1,"Client") newclient.setDefaults("test-fd","testclient","MyCatalog",pwd) root.add_item(newclient) dirdcfg.write("test.conf.out") fdcfg=FiledConfig("test-fd.conf") fdcfg.setDefaults("bacula-dird",pwd,"test-fd") fdcfg.write() createClientConfig(dirdcfg,"gaffel-fd") createClientConfig(dirdcfg,"test-fd") createAllClientConfigs(dirdcfg) sys.exit(0)