Commit 8e107684 authored by Ad Schellevis's avatar Ad Schellevis

style fixes configd

parent cba10171
...@@ -29,3 +29,4 @@ ...@@ -29,3 +29,4 @@
-------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------
package : configd package : configd
""" """
...@@ -30,8 +30,9 @@ ...@@ -30,8 +30,9 @@
package : configd package : configd
""" """
class Helpers(object): class Helpers(object):
def __init__(self,template_in_data): def __init__(self, template_in_data):
""" initialize template helpers """ initialize template helpers
:param template_in_data: :param template_in_data:
...@@ -39,22 +40,22 @@ class Helpers(object): ...@@ -39,22 +40,22 @@ class Helpers(object):
""" """
self._template_in_data = template_in_data self._template_in_data = template_in_data
def getNodeByTag(self,tag): def getNodeByTag(self, tag):
""" get tree node by tag """ get tree node by tag
:param tag: tag in dot notation (section.item) :param tag: tag in dot notation (section.item)
:return: dict or None if not found :return: dict or None if not found
""" """
node = self._template_in_data node = self._template_in_data
for item in tag.split('.'): for item in tag.split('.'):
if node.has_key(item): if item in node:
node=node[item] node = node[item]
else: else:
# not found # not found
return None return None
# path found, return # path found, return
return node return node
def exists(self,tag): def exists(self, tag):
""" """
check if node exists in dictionary structure check if node exists in dictionary structure
:param tag: tag in dot notation (section.item) :param tag: tag in dot notation (section.item)
...@@ -64,3 +65,4 @@ class Helpers(object): ...@@ -64,3 +65,4 @@ class Helpers(object):
return True return True
else: else:
return False return False
...@@ -43,7 +43,7 @@ import xml.etree.cElementTree as ElementTree ...@@ -43,7 +43,7 @@ import xml.etree.cElementTree as ElementTree
class Config(object): class Config(object):
def __init__(self,filename): def __init__(self, filename):
self._filename = filename self._filename = filename
self._config_data = {} self._config_data = {}
self._file_mod = 0 self._file_mod = 0
...@@ -62,25 +62,25 @@ class Config(object): ...@@ -62,25 +62,25 @@ class Config(object):
self._config_data = self._traverse(root) self._config_data = self._traverse(root)
self._file_mod = mod_time self._file_mod = mod_time
def _traverse(self,xmlNode): def _traverse(self, xmlNode):
""" traverse xml node and return ordered dictionary structure """ traverse xml node and return ordered dictionary structure
:param xmlNode: ElementTree node :param xmlNode: ElementTree node
:return: collections.OrderedDict :return: collections.OrderedDict
""" """
this_item = collections.OrderedDict() this_item = collections.OrderedDict()
if len(list(xmlNode)) > 0 : if len(list(xmlNode)) > 0:
for item in list(xmlNode): for item in list(xmlNode):
item_content = self._traverse(item) item_content = self._traverse(item)
if this_item.has_key(item.tag): if item.tag in this_item:
if type(this_item[item.tag]) != list: if type(this_item[item.tag]) != list:
tmp_item = copy.deepcopy(this_item[item.tag]) tmp_item = copy.deepcopy(this_item[item.tag])
this_item[item.tag] = [] this_item[item.tag] = []
this_item[item.tag].append(tmp_item) this_item[item.tag].append(tmp_item)
if item_content != None: if item_content is not None:
# skip empty fields # skip empty fields
this_item[item.tag].append(item_content) this_item[item.tag].append(item_content)
elif item_content != None: elif item_content is not None:
# create a new named item # create a new named item
this_item[item.tag] = self._traverse(item) this_item[item.tag] = self._traverse(item)
else: else:
...@@ -89,8 +89,7 @@ class Config(object): ...@@ -89,8 +89,7 @@ class Config(object):
return this_item return this_item
def indent(self, elem, level=0):
def indent(self,elem, level=0):
""" indent cElementTree (prettyprint fix) """ indent cElementTree (prettyprint fix)
used from : http://infix.se/2007/02/06/gentlemen-indent-your-xml used from : http://infix.se/2007/02/06/gentlemen-indent-your-xml
@param elem: cElementTree @param elem: cElementTree
...@@ -110,7 +109,6 @@ class Config(object): ...@@ -110,7 +109,6 @@ class Config(object):
if level and (not elem.tail or not elem.tail.strip()): if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i elem.tail = i
def get(self): def get(self):
""" get active config data, load from disc if file in memory is different """ get active config data, load from disc if file in memory is different
......
...@@ -37,7 +37,7 @@ __author__ = 'Ad Schellevis' ...@@ -37,7 +37,7 @@ __author__ = 'Ad Schellevis'
import syslog import syslog
def execute(action,parameters): def execute(action, parameters):
""" wrapper for inline functions """ wrapper for inline functions
:param action: action object ( processhandler.Action type ) :param action: action object ( processhandler.Action type )
...@@ -54,7 +54,7 @@ def execute(action,parameters): ...@@ -54,7 +54,7 @@ def execute(action,parameters):
# send generated filenames to syslog # send generated filenames to syslog
for filename in filenames: for filename in filenames:
syslog.syslog(syslog.LOG_DEBUG,' %s generated %s' % ( parameters, filename ) ) syslog.syslog(syslog.LOG_DEBUG, ' %s generated %s' % (parameters, filename))
del conf del conf
del tmpl del tmpl
......
...@@ -47,6 +47,7 @@ import uuid ...@@ -47,6 +47,7 @@ import uuid
import shlex import shlex
import ph_inline_actions import ph_inline_actions
class Handler(object): class Handler(object):
""" Main handler class, opens unix domain socket and starts listening """ Main handler class, opens unix domain socket and starts listening
- New connections are handed over to a HandlerClient type object in a new thread - New connections are handed over to a HandlerClient type object in a new thread
...@@ -58,12 +59,12 @@ class Handler(object): ...@@ -58,12 +59,12 @@ class Handler(object):
-> execute ActionHandler command using Action objects -> execute ActionHandler command using Action objects
<- send back result string <- send back result string
""" """
def __init__(self,socket_filename,config_path,simulation_mode=False): def __init__(self, socket_filename, config_path, simulation_mode=False):
""" Constructor """ Constructor
:param socket_filename: filename of unix domain socket to use :param socket_filename: filename of unix domain socket to use
:param config_path: location of configuration files :param config_path: location of configuration files
:param emulate: emulation mode, do not start actual (script) commands :param simulation_mode: emulation mode, do not start actual (script) commands
:return: object :return: object
""" """
self.socket_filename = socket_filename self.socket_filename = socket_filename
...@@ -90,7 +91,7 @@ class Handler(object): ...@@ -90,7 +91,7 @@ class Handler(object):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(self.socket_filename) sock.bind(self.socket_filename)
os.chmod(self.socket_filename,0o666) os.chmod(self.socket_filename, 0o666)
sock.listen(30) sock.listen(30)
while True: while True:
# wait for a connection to arrive # wait for a connection to arrive
...@@ -100,7 +101,7 @@ class Handler(object): ...@@ -100,7 +101,7 @@ class Handler(object):
client_address=client_address, client_address=client_address,
action_handler=actHandler, action_handler=actHandler,
simulation_mode=self.simulation_mode) simulation_mode=self.simulation_mode)
if self.single_threaded : if self.single_threaded:
# run single threaded # run single threaded
cmd_thread.run() cmd_thread.run()
else: else:
...@@ -116,20 +117,20 @@ class Handler(object): ...@@ -116,20 +117,20 @@ class Handler(object):
except: except:
# something went wrong... send traceback to syslog, restart listener (wait for a short time) # something went wrong... send traceback to syslog, restart listener (wait for a short time)
print (traceback.format_exc()) print (traceback.format_exc())
syslog.syslog(syslog.LOG_ERR, 'Handler died on %s'%traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, 'Handler died on %s' % traceback.format_exc())
time.sleep(1) time.sleep(1)
class HandlerClient(threading.Thread): class HandlerClient(threading.Thread):
""" Handle commands via specified socket connection """ Handle commands via specified socket connection
""" """
def __init__ (self,connection,client_address,action_handler,simulation_mode=False): def __init__(self, connection, client_address, action_handler, simulation_mode=False):
""" """
:param connection: socket connection object :param connection: socket connection object
:param client_address: client address ( from socket accept ) :param client_address: client address ( from socket accept )
:param action_handler: action handler object :param action_handler: action handler object
:param emulate: Emulation mode, do not start actual (script) commands :param simulation_mode: Emulation mode, do not start actual (script) commands
:return: None :return: None
""" """
threading.Thread.__init__(self) threading.Thread.__init__(self)
...@@ -180,10 +181,10 @@ class HandlerClient(threading.Thread): ...@@ -180,10 +181,10 @@ class HandlerClient(threading.Thread):
# execute requested action # execute requested action
if self.simulation_mode: if self.simulation_mode:
self.action_handler.showAction(exec_command,exec_action,exec_params) self.action_handler.showAction(exec_command, exec_action, exec_params)
result = 'OK' result = 'OK'
else: else:
result = self.action_handler.execute(exec_command,exec_action,exec_params) result = self.action_handler.execute(exec_command, exec_action, exec_params)
if not exec_in_background: if not exec_in_background:
# send response back to client( including trailing enter ) # send response back to client( including trailing enter )
...@@ -197,7 +198,7 @@ class HandlerClient(threading.Thread): ...@@ -197,7 +198,7 @@ class HandlerClient(threading.Thread):
# send end of stream characters # send end of stream characters
if not exec_in_background: if not exec_in_background:
self.connection.sendall("%c%c%c"%(chr(0),chr(0),chr(0))) self.connection.sendall("%c%c%c" % (chr(0), chr(0), chr(0)))
except SystemExit: except SystemExit:
# ignore system exit related errors # ignore system exit related errors
pass pass
...@@ -214,10 +215,11 @@ class HandlerClient(threading.Thread): ...@@ -214,10 +215,11 @@ class HandlerClient(threading.Thread):
if not exec_in_background: if not exec_in_background:
self.connection.close() self.connection.close()
class ActionHandler(object): class ActionHandler(object):
""" Start/stop services and functions using configuration data defined in conf/actions_<topic>.conf """ Start/stop services and functions using configuration data defined in conf/actions_<topic>.conf
""" """
def __init__(self,config_path): def __init__(self, config_path):
""" Initialize action handler to start system functions """ Initialize action handler to start system functions
:param config_path: full path of configuration data :param config_path: full path of configuration data
...@@ -234,11 +236,12 @@ class ActionHandler(object): ...@@ -234,11 +236,12 @@ class ActionHandler(object):
""" """
self.action_map = {} self.action_map = {}
for config_filename in glob.glob('%s/actions_*.conf'%(self.config_path)) + glob.glob('%s/actions.d/actions_*.conf'%(self.config_path)): for config_filename in glob.glob('%s/actions_*.conf' % self.config_path) \
+ glob.glob('%s/actions.d/actions_*.conf' % self.config_path):
# this topic's name (service, filter, template, etc) # this topic's name (service, filter, template, etc)
# make sure there's an action map index for this topic # make sure there's an action map index for this topic
topic_name = config_filename.split('actions_')[-1].split('.')[0] topic_name = config_filename.split('actions_')[-1].split('.')[0]
if self.action_map.has_key(topic_name) == False: if topic_name not in self.action_map:
self.action_map[topic_name] = {} self.action_map[topic_name] = {}
# traverse config directory and open all filenames starting with actions_ # traverse config directory and open all filenames starting with actions_
...@@ -248,12 +251,12 @@ class ActionHandler(object): ...@@ -248,12 +251,12 @@ class ActionHandler(object):
# map configuration data on object # map configuration data on object
action_obj = Action() action_obj = Action()
for act_prop in cnf.items(section): for act_prop in cnf.items(section):
setattr(action_obj,act_prop[0],act_prop[1]) setattr(action_obj, act_prop[0], act_prop[1])
if section.find('.') > -1: if section.find('.') > -1:
# at this moment we only support 2 levels of actions ( 3 if you count topic as well ) # at this moment we only support 2 levels of actions ( 3 if you count topic as well )
for alias in section.split('.')[0].split('|'): for alias in section.split('.')[0].split('|'):
if self.action_map[topic_name].has_key(alias) == False: if alias not in self.action_map[topic_name]:
self.action_map[topic_name][alias] = {} self.action_map[topic_name][alias] = {}
self.action_map[topic_name][alias][section.split('.')[1]] = action_obj self.action_map[topic_name][alias][section.split('.')[1]] = action_obj
else: else:
...@@ -269,20 +272,20 @@ class ActionHandler(object): ...@@ -269,20 +272,20 @@ class ActionHandler(object):
:return: action object or None if not found :return: action object or None if not found
""" """
action_obj = None action_obj = None
if self.action_map.has_key(command): if command in self.action_map:
if self.action_map[command].has_key(action): if action in self.action_map[command]:
if type(self.action_map[command][action]) == dict: if type(self.action_map[command][action]) == dict:
if len(parameters) > 0 and self.action_map[command][action].has_key(parameters[0]) == True: if len(parameters) > 0 and parameters[0] in self.action_map[command][action]:
# 3 level action ( "interface linkup start" for example ) # 3 level action ( "interface linkup start" for example )
if isinstance(self.action_map[command][action][parameters[0]],Action): if isinstance(self.action_map[command][action][parameters[0]], Action):
action_obj = self.action_map[command][action][parameters[0]] action_obj = self.action_map[command][action][parameters[0]]
action_obj.setParameterStartPos(1) action_obj.setParameterStartPos(1)
elif isinstance(self.action_map[command][action],Action): elif isinstance(self.action_map[command][action], Action):
action_obj = self.action_map[command][action] action_obj = self.action_map[command][action]
return action_obj return action_obj
def execute(self,command,action,parameters): def execute(self, command, action, parameters):
""" execute configuration defined action """ execute configuration defined action
:param command: command/topic for example interface :param command: command/topic for example interface
...@@ -291,27 +294,27 @@ class ActionHandler(object): ...@@ -291,27 +294,27 @@ class ActionHandler(object):
:return: OK on success, else error code :return: OK on success, else error code
""" """
action_params = [] action_params = []
action_obj = self.findAction(command,action,parameters) action_obj = self.findAction(command, action, parameters)
if action_obj is not None: if action_obj is not None:
if parameters is not None and len(parameters) > action_obj.getParameterStartPos(): if parameters is not None and len(parameters) > action_obj.getParameterStartPos():
action_params = parameters[action_obj.getParameterStartPos():] action_params = parameters[action_obj.getParameterStartPos():]
return '%s\n'%action_obj.execute(action_params) return '%s\n' % action_obj.execute(action_params)
return 'Action not found\n' return 'Action not found\n'
def showAction(self, command, action, parameters):
def showAction(self,command,action,parameters):
""" debug/simulation mode: show action information """ debug/simulation mode: show action information
:return: :return:
""" """
action_obj = self.findAction(command,action,parameters) action_obj = self.findAction(command, action, parameters)
print ('---------------------------------------------------------------------') print ('---------------------------------------------------------------------')
print ('execute %s.%s with parameters : %s '%(command,action,parameters) ) print ('execute %s.%s with parameters : %s ' % (command, action, parameters))
print ('action object %s (%s)' % (action_obj,action_obj.command) ) print ('action object %s (%s)' % (action_obj, action_obj.command))
print ('---------------------------------------------------------------------') print ('---------------------------------------------------------------------')
class Action(object): class Action(object):
""" Action class, handles actual (system) calls. """ Action class, handles actual (system) calls.
set command, parameters (template) type and log message set command, parameters (template) type and log message
...@@ -327,7 +330,7 @@ class Action(object): ...@@ -327,7 +330,7 @@ class Action(object):
self.message = None self.message = None
self._parameter_start_pos = 0 self._parameter_start_pos = 0
def setParameterStartPos(self,pos): def setParameterStartPos(self, pos):
""" """
:param pos: start position of parameter list :param pos: start position of parameter list
...@@ -341,7 +344,7 @@ class Action(object): ...@@ -341,7 +344,7 @@ class Action(object):
""" """
return self._parameter_start_pos return self._parameter_start_pos
def execute(self,parameters): def execute(self, parameters):
""" execute an action """ execute an action
:param parameters: list of parameters :param parameters: list of parameters
...@@ -350,15 +353,15 @@ class Action(object): ...@@ -350,15 +353,15 @@ class Action(object):
# send-out syslog message # send-out syslog message
if self.message is not None: if self.message is not None:
if self.message.count('%s') > 0 and parameters is not None and len(parameters) > 0: if self.message.count('%s') > 0 and parameters is not None and len(parameters) > 0:
syslog.syslog(syslog.LOG_NOTICE,self.message % tuple(parameters[0:self.message.count('%s')]) ) syslog.syslog(syslog.LOG_NOTICE, self.message % tuple(parameters[0:self.message.count('%s')]))
else: else:
syslog.syslog(syslog.LOG_NOTICE,self.message) syslog.syslog(syslog.LOG_NOTICE, self.message)
# validate input # validate input
if self.type is None: if self.type is None:
# no action type, nothing to do here # no action type, nothing to do here
return 'No action type' return 'No action type'
elif self.type.lower() in ('script','script_output'): elif self.type.lower() in ('script', 'script_output'):
# script type commands, basic script type only uses exit statuses, script_output sends back stdout data. # script type commands, basic script type only uses exit statuses, script_output sends back stdout data.
if self.command is None: if self.command is None:
# no command supplied, exit # no command supplied, exit
...@@ -367,11 +370,11 @@ class Action(object): ...@@ -367,11 +370,11 @@ class Action(object):
# build script command to execute, shared for both types # build script command to execute, shared for both types
script_command = self.command script_command = self.command
if self.parameters is not None and type(self.parameters) == str: if self.parameters is not None and type(self.parameters) == str:
script_command = '%s %s'%(script_command,self.parameters) script_command = '%s %s' % (script_command, self.parameters)
if script_command.find('%s') > -1 and len(parameters) > 0: if script_command.find('%s') > -1 and len(parameters) > 0:
# use command execution parameters in action parameter template # use command execution parameters in action parameter template
# use quotes on parameters to prevent code injection # use quotes on parameters to prevent code injection
script_command = script_command % tuple(map(lambda x:'"'+x.replace('"','\\"')+'"', script_command = script_command % tuple(map(lambda x: '"'+x.replace('"', '\\"')+'"',
parameters[0:script_command.count('%s')])) parameters[0:script_command.count('%s')]))
if self.type.lower() == 'script': if self.type.lower() == 'script':
...@@ -382,16 +385,16 @@ class Action(object): ...@@ -382,16 +385,16 @@ class Action(object):
if exit_status == 0: if exit_status == 0:
return 'OK' return 'OK'
else: else:
return 'Error (%d)'%exit_status return 'Error (%d)' % exit_status
except: except:
syslog.syslog(syslog.LOG_ERR, 'Script action failed at %s'%traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, 'Script action failed at %s' % traceback.format_exc())
return 'Execute error' return 'Execute error'
elif self.type.lower() == 'script_output': elif self.type.lower() == 'script_output':
try: try:
script_output = subprocess.check_output(script_command, shell=True) script_output = subprocess.check_output(script_command, shell=True)
return script_output return script_output
except: except:
syslog.syslog(syslog.LOG_ERR, 'Script action failed at %s'%traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, 'Script action failed at %s' % traceback.format_exc())
return 'Execute error' return 'Execute error'
# fallback should never get here # fallback should never get here
...@@ -405,13 +408,10 @@ class Action(object): ...@@ -405,13 +408,10 @@ class Action(object):
else: else:
inline_act_parameters = '' inline_act_parameters = ''
return ph_inline_actions.execute(self, inline_act_parameters)
return ph_inline_actions.execute(self,inline_act_parameters)
except: except:
syslog.syslog(syslog.LOG_ERR, 'Inline action failed at %s'%traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, 'Inline action failed at %s' % traceback.format_exc())
return 'Execute error' return 'Execute error'
return 'Unknown action type' return 'Unknown action type'
...@@ -41,9 +41,10 @@ import copy ...@@ -41,9 +41,10 @@ import copy
import jinja2 import jinja2
import addons.template_helpers import addons.template_helpers
class Template(object): class Template(object):
def __init__(self,target_root_directory="/"): def __init__(self, target_root_directory="/"):
""" constructor """ constructor
:return: :return:
""" """
...@@ -55,82 +56,80 @@ class Template(object): ...@@ -55,82 +56,80 @@ class Template(object):
# setup jinja2 environment # setup jinja2 environment
self._template_dir = os.path.dirname(os.path.abspath(__file__))+'/../templates/' self._template_dir = os.path.dirname(os.path.abspath(__file__))+'/../templates/'
self._j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(self._template_dir),trim_blocks=True) self._j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(self._template_dir), trim_blocks=True)
def _readManifest(self,filename): def _readManifest(self, filename):
""" """
:param filename: manifest filename (path/+MANIFEST) :param filename: manifest filename (path/+MANIFEST)
:return: dictionary containing manifest items :return: dictionary containing manifest items
""" """
result = {} result = {}
for line in open(filename,'r').read().split('\n'): for line in open(filename, 'r').read().split('\n'):
parts = line.split(':') parts = line.split(':')
if len(parts) > 1: if len(parts) > 1:
result[parts[0]] = ':'.join(parts[1:]) result[parts[0]] = ':'.join(parts[1:])
return result return result
def _readTargets(self,filename): def _readTargets(self, filename):
""" read raw target filename masks """ read raw target filename masks
:param filename: targets filename (path/+TARGETS) :param filename: targets filename (path/+TARGETS)
:return: dictionary containing +TARGETS filename sets :return: dictionary containing +TARGETS filename sets
""" """
result = {} result = {}
for line in open(filename,'r').read().split('\n'): for line in open(filename, 'r').read().split('\n'):
parts = line.split(':') parts = line.split(':')
if len(parts) > 1 and parts[0].strip()[0] != '#': if len(parts) > 1 and parts[0].strip()[0] != '#':
result[parts[0]] = ':'.join(parts[1:]).strip() result[parts[0]] = ':'.join(parts[1:]).strip()
return result return result
def list_module(self,module_name,read_manifest=False): def list_module(self, module_name, read_manifest=False):
""" list single module content """ list single module content
:param module_name: module name in dot notation ( company.module ) :param module_name: module name in dot notation ( company.module )
:param read_manifest: boolean, read manifest file if it exists :param read_manifest: boolean, read manifest file if it exists
:return: dictionary with module data :return: dictionary with module data
""" """
result = {} result = {}
file_path = '%s/%s'%(self._template_dir,module_name.replace('.','/')) file_path = '%s/%s' % (self._template_dir, module_name.replace('.', '/'))
if os.path.exists('%s/+MANIFEST'%file_path ) and read_manifest: if os.path.exists('%s/+MANIFEST' % file_path) and read_manifest:
result['+MANIFEST'] = self._readManifest('%s/+MANIFEST'%file_path) result['+MANIFEST'] = self._readManifest('%s/+MANIFEST' % file_path)
if os.path.exists('%s/+TARGETS'%file_path ) : if os.path.exists('%s/+TARGETS' % file_path):
result['+TARGETS'] = self._readTargets('%s/+TARGETS'%file_path) result['+TARGETS'] = self._readTargets('%s/+TARGETS' % file_path)
else: else:
result['+TARGETS'] = {} result['+TARGETS'] = {}
return result return result
def list_modules(self,read_manifest=False): def list_modules(self):
""" traverse template directory and list all modules """ traverse template directory and list all modules
the template directory is structured like Manufacturer/Module/config_files the template directory is structured like Manufacturer/Module/config_files
:param read_manifest: boolean, read manifest file if it exists
:return: list (dict) of registered modules :return: list (dict) of registered modules
""" """
result = {} result = {}
for root, dirs, files in os.walk(self._template_dir): for root, dirs, files in os.walk(self._template_dir):
if len(root) > len(self._template_dir): if len(root) > len(self._template_dir):
module_name = '.'.join(root.replace(self._template_dir,'').split('/')[:2]) module_name = '.'.join(root.replace(self._template_dir, '').split('/')[:2])
if result.has_key(module_name) == False: if module_name not in result:
result[module_name] = self.list_module(module_name) result[module_name] = self.list_module(module_name)
return result return result
def setConfig(self, config_data):
def setConfig(self,config_data):
""" set config data """ set config data
:param config_data: config data as dictionary/list structure :param config_data: config data as dictionary/list structure
:return: None :return: None
""" """
if type(config_data) in( dict, collections.OrderedDict): if type(config_data) in(dict, collections.OrderedDict):
self._config = config_data self._config = config_data
else: else:
# no data given, reset # no data given, reset
self._config = {} self._config = {}
def __findStringTags(self,instr): def __findStringTags(self, instr):
""" """
:param instr: string with optional tags [field.$$] :param instr: string with optional tags [field.$$]
:return: :return:
...@@ -142,7 +141,7 @@ class Template(object): ...@@ -142,7 +141,7 @@ class Template(object):
return retval return retval
def __findFilters(self,tags): def __findFilters(self, tags):
""" match tags to config and construct a dictionary which we can use to construct the output filenames """ match tags to config and construct a dictionary which we can use to construct the output filenames
:param tags: list of tags [xmlnode.xmlnode.%.xmlnode,xmlnode] :param tags: list of tags [xmlnode.xmlnode.%.xmlnode,xmlnode]
:return: dictionary containing key (tagname) value {existing node key, value} :return: dictionary containing key (tagname) value {existing node key, value}
...@@ -155,25 +154,25 @@ class Template(object): ...@@ -155,25 +154,25 @@ class Template(object):
config_ptr = self._config config_ptr = self._config
target_keys = [] target_keys = []
for xmlNodeName in tag.split('.'): for xmlNodeName in tag.split('.'):
if config_ptr.has_key(xmlNodeName): if xmlNodeName in config_ptr:
config_ptr = config_ptr[xmlNodeName] config_ptr = config_ptr[xmlNodeName]
elif xmlNodeName == '%': elif xmlNodeName == '%':
target_keys = config_ptr.keys() target_keys = config_ptr.keys()
else: else:
break break
if len(target_keys) == 0 : if len(target_keys) == 0:
# single node, only used for string replacement in output name. # single node, only used for string replacement in output name.
result[tag] = {tag:config_ptr} result[tag] = {tag: config_ptr}
else: else:
# multiple node's, find all nodes # multiple node's, find all nodes
for target_node in target_keys: for target_node in target_keys:
config_ptr = self._config config_ptr = self._config
str_wildcard_loc = len(tag.split('%')[0].split('.')) str_wildcard_loc = len(tag.split('%')[0].split('.'))
filter_target= [] filter_target = []
for xmlNodeName in tag.replace('%',target_node).split('.'): for xmlNodeName in tag.replace('%', target_node).split('.'):
if config_ptr.has_key(xmlNodeName): if xmlNodeName in config_ptr:
if type (config_ptr[xmlNodeName]) in (collections.OrderedDict,dict): if type(config_ptr[xmlNodeName]) in (collections.OrderedDict, dict):
if str_wildcard_loc >= len(filter_target): if str_wildcard_loc >= len(filter_target):
filter_target.append(xmlNodeName) filter_target.append(xmlNodeName)
if str_wildcard_loc == len(filter_target): if str_wildcard_loc == len(filter_target):
...@@ -186,47 +185,44 @@ class Template(object): ...@@ -186,47 +185,44 @@ class Template(object):
return result return result
def _create_directory(self,filename): def _create_directory(self, filename):
""" create directory """ create directory
:param filename: create path for filename ( if not existing ) :param filename: create path for filename ( if not existing )
:return: None :return: None
""" """
fparts=[] fparts = []
for fpart in filename.strip().split('/')[:-1]: for fpart in filename.strip().split('/')[:-1]:
fparts.append(fpart) fparts.append(fpart)
if len(fpart) >1: if len(fpart) > 1:
if os.path.exists('/'.join(fparts)) == False: if not os.path.exists('/'.join(fparts)):
os.mkdir('/'.join(fparts)) os.mkdir('/'.join(fparts))
def generate(self, module_name, create_directory=True):
def generate(self,module_name,create_directory=True):
""" generate configuration files using bound config and template data """ generate configuration files using bound config and template data
:param module_name: module name in dot notation ( company.module ) :param module_name: module name in dot notation ( company.module )
:param create_directory: automatically create directories to place template output in ( if not existing ) :param create_directory: automatically create directories to place template output in ( if not existing )
:return: list of generated output files :return: list of generated output files
""" """
result=[] result = []
module_data = self.list_module(module_name) module_data = self.list_module(module_name)
for src_template in module_data['+TARGETS'].keys(): for src_template in module_data['+TARGETS'].keys():
target = module_data['+TARGETS'][src_template] target = module_data['+TARGETS'][src_template]
target_filename_tags = self.__findStringTags(target) target_filename_tags = self.__findStringTags(target)
target_filters = self.__findFilters(target_filename_tags) target_filters = self.__findFilters(target_filename_tags)
result_filenames = {target:{}} result_filenames = {target: {}}
for target_filter in target_filters.keys(): for target_filter in target_filters.keys():
for key in target_filters[target_filter].keys(): for key in target_filters[target_filter].keys():
for filename in result_filenames.keys(): for filename in result_filenames.keys():
if filename.find('[%s]'%target_filter) > -1: if filename.find('[%s]' % target_filter) > -1:
new_filename = filename.replace('[%s]'%target_filter,target_filters[target_filter][key]) new_filename = filename.replace('[%s]' % target_filter, target_filters[target_filter][key])
result_filenames[new_filename] = copy.deepcopy(result_filenames[filename]) result_filenames[new_filename] = copy.deepcopy(result_filenames[filename])
result_filenames[new_filename][key] = target_filters[target_filter][key] result_filenames[new_filename][key] = target_filters[target_filter][key]
j2_page = self._j2_env.get_template('%s/%s'%( module_name.replace('.','/'), src_template)) j2_page = self._j2_env.get_template('%s/%s' % (module_name.replace('.', '/'), src_template))
for filename in result_filenames.keys(): for filename in result_filenames.keys():
if not ( filename.find('[') != -1 and filename.find(']') != -1 ) : if not (filename.find('[') != -1 and filename.find(']') != -1):
# copy config data # copy config data
cnf_data = copy.deepcopy(self._config) cnf_data = copy.deepcopy(self._config)
cnf_data['TARGET_FILTERS'] = result_filenames[filename] cnf_data['TARGET_FILTERS'] = result_filenames[filename]
...@@ -240,16 +236,15 @@ class Template(object): ...@@ -240,16 +236,15 @@ class Template(object):
content = j2_page.render(cnf_data) content = j2_page.render(cnf_data)
# prefix filename with defined root directory # prefix filename with defined root directory
filename = ('%s/%s'%(self._target_root_directory, filename)).replace('//','/') filename = ('%s/%s' % (self._target_root_directory, filename)).replace('//', '/')
if create_directory: if create_directory:
# make sure the target directory exists # make sure the target directory exists
self._create_directory(filename) self._create_directory(filename)
f_out = open(filename,'wb') f_out = open(filename, 'wb')
f_out.write(content) f_out.write(content)
f_out.close() f_out.close()
result.append(filename) result.append(filename)
return result return result
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment