X-Git-Url: http://git.onelab.eu/?p=myplc.git;a=blobdiff_plain;f=plc_config.py;h=5d6ef40c7b065581b5588bac3b6a579ea9fed210;hp=89d8f263712267c260e603fc64ea2b87f9fb1fec;hb=HEAD;hpb=b0e953495da2f5eac88c93acf1be7511439f0c38 diff --git a/plc_config.py b/plc_config.py index 89d8f26..5d6ef40 100644 --- a/plc_config.py +++ b/plc_config.py @@ -1,4 +1,4 @@ ->#!/usr/bin/python +#!/usr/bin/python # # Merge PlanetLab Central (PLC) configuration files into a variety of # output formats. These files represent the global configuration for a @@ -7,8 +7,6 @@ # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # -# $Id$ -# import codecs import os @@ -42,7 +40,7 @@ class PLCConfiguration: You may also save() the configuration. If a file path or object is not specified, the configuration will be written to the file path or object that was first loaded. - + plc.save() plc.save("/etc/planetlab/plc_config.xml") """ @@ -251,7 +249,7 @@ class PLCConfiguration: It looks for filled-in values in the order of, local object (self), followed by cread (read values), and finally default values. - Arguments: + Arguments: default configuration site configuration @@ -360,7 +358,7 @@ class PLCConfiguration: if not category.has_key('id') or type(category['id']) not in types.StringTypes: return - + category_id = category['id'].lower() if self._variables.has_key(category_id): @@ -422,7 +420,7 @@ class PLCConfiguration: for tag in ['name', 'value', 'description']: if variable.has_key(tag): self._set_text_of_child(variable_element, tag, variable[tag]) - + if category_element.getElementsByTagName('variablelist'): variablelist_element = category_element.getElementsByTagName('variablelist')[0] else: @@ -443,7 +441,7 @@ class PLCConfiguration: (variable, category) when found (None, None) otherwise """ - + for (category_id, (category, variables)) in self._variables.iteritems(): for variable in variables.values(): (id, name, value, comments) = self._sanitize_variable(category_id, variable) @@ -577,7 +575,7 @@ class PLCConfiguration: for attribute in ['type']: if package.has_key(attribute): packagereq_element.setAttribute(attribute, package[attribute]) - + if group_element.getElementsByTagName('packagelist'): packagelist_element = group_element.getElementsByTagName('packagelist')[0] else: @@ -828,6 +826,35 @@ DO NOT EDIT. This file was automatically generated at return buf.getvalue() + def validate_type(self, variable_type, value): + + # ideally we should use the "validate_*" methods in PLCAPI or + # even declare some checks along with the default + # configuration (using RELAX NG?) but this shall work for now. + def ip_validator(val): + import socket + try: + socket.inet_aton(val) + return True + except: return False + + def email_validator(val): + return re.match('\A[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]+\Z', val) + + def boolean_validator (val): + return val in ['true', 'false'] + + validators = { + 'email' : email_validator, + 'ip': ip_validator, + 'boolean': boolean_validator, + } + + # validate it if not a know type. + validator = validators.get(variable_type, lambda x: True) + return validator(value) + + # xml.dom.minidom.Text.writexml adds surrounding whitespace to textual # data when pretty-printing. Override this behavior. @@ -846,10 +873,6 @@ class TrimTextElement(xml.dom.minidom.Element): #################### # GLOBAL VARIABLES # -release_id = "$Id$" -release_rev = "$Revision:$" -release_url = "$URL:$" - g_configuration=None usual_variables=None config_dir=None @@ -877,8 +900,9 @@ def init_configuration (): mainloop_usage= """Available commands: Uppercase versions give variables comments, when available u/U\t\t\tEdit usual variables - w/W\t\t\tWrite / Write & reload - r\t\t\tRestart %s service + w\t\t\tWrite + r\t\t\tRestart %(service)s service + R\t\t\tReload %(service)s service (rebuild config files for sh, python....) q\t\t\tQuit (without saving) h/?\t\t\tThis help --- @@ -887,10 +911,10 @@ def init_configuration (): e/E [|]\tEdit variables (all, in category, single) --- c\t\t\tList categories - v/V [|]List Variables (all, in category, single) + v/V [|]\tList Variables (all, in category, single) --- Typical usage involves: u, [l,] w, r, q -""" % service +""" % globals() def usage (): command_usage="%prog [options] [default-xml [site-xml [consolidated-xml]]]" @@ -916,6 +940,10 @@ def get_value (config, category_id, variable_id): (category, variable) = config.get (category_id, variable_id) return variable['value'] +def get_type (config, category_id, variable_id): + (category, variable) = config.get (category_id, variable_id) + return variable['type'] + def get_current_value (cread, cwrite, category_id, variable_id): # the value stored in cwrite, if present, is the one we want try: @@ -924,7 +952,7 @@ def get_current_value (cread, cwrite, category_id, variable_id): result=get_value (cread,category_id,variable_id) return result -# refrain from using plc_config's _sanitize +# refrain from using plc_config's _sanitize def get_varname (config, category_id, variable_id): (category, variable) = config.get (category_id, variable_id) return (category_id+"_"+variable['id']).upper() @@ -968,7 +996,7 @@ def list_category (config, cid): for variable in variables.values(): result += ["%s_%s" %(cid,variable['id'])] return result - + def print_category (config, cid, show_comments=True): cid=cid.lower() CID=cid.upper() @@ -995,15 +1023,15 @@ def consolidate (default_config, site_config, consolidated_config): def reload_service (): global service - os.system("set -x ; service %s reload" % service) - + os.system("set -x ; systemctl reload %s" % service) + #################### def restart_service (): global service print ("==================== Stopping %s" % service) - os.system("service %s stop" % service) + os.system("systemctl stop %s" % service) print ("==================== Starting %s" % service) - os.system("service %s start" % service) + os.system("systemctl start %s" % service) #################### def prompt_variable (cdef, cread, cwrite, category, variable, @@ -1017,9 +1045,10 @@ def prompt_variable (cdef, cread, cwrite, category, variable, while True: default_value = get_value(cdef,category_id,variable_id) + variable_type = get_type(cdef,category_id,variable_id) current_value = get_current_value(cread,cwrite,category_id, variable_id) varname = get_varname (cread,category_id, variable_id) - + if show_comments : print_name_comments (cdef, category_id, variable_id) prompt = "== %s : [%s] " % (varname,current_value) @@ -1053,9 +1082,12 @@ def prompt_variable (cdef, cread, cwrite, category, variable, else: print "No support for next category" else: - variable['value'] = answer - cwrite.set(category,variable) - return + if cdef.validate_type(variable_type, answer): + variable['value'] = answer + cwrite.set(category,variable) + return + else: + print "Not a valid value" def prompt_variables_all (cdef, cread, cwrite, show_comments): try: @@ -1068,7 +1100,7 @@ def prompt_variables_all (cdef, cread, cwrite, show_comments): except Exception, inst: if (str(inst) == 'NextCategory'): break else: raise - + except Exception, inst: if (str(inst) == 'BailOut'): return else: raise @@ -1156,7 +1188,6 @@ def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_con continue show_comments=command.isupper() - command=command.lower() mode='ALL' if arg: @@ -1177,10 +1208,10 @@ def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_con print "%s: no such category or variable" % arg continue - if (command in "qQ"): + if command in "qQ": # todo check confirmation return - elif (command == "w"): + elif command == "w": try: # Confirm that various constraints are met before saving file. validate_variables = g_configuration.get('validate_variables',{}) @@ -1198,8 +1229,8 @@ def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_con print ("Wrote %s" % site_config) consolidate(default_config, site_config, consolidated_config) print ("You might want to type 'r' (restart %s), 'R' (reload %s) or 'q' (quit)" % \ - (service,service)) - elif (command == "u"): + (service, service)) + elif command in "uU": global usual_variables try: for varname in usual_variables: @@ -1209,13 +1240,13 @@ def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_con except Exception, inst: if (str(inst) != 'BailOut'): raise - elif (command == "r"): + elif command == "r": restart_service() - elif (command == "R"): + elif command == "R": reload_service() - elif (command == "c"): + elif command == "c": print_categories(cread) - elif (command in "eE"): + elif command in "eE": if mode == 'ALL': prompt_variables_all(cdef, cread, cwrite,show_comments) elif mode == 'CATEGORY': @@ -1225,12 +1256,12 @@ def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_con prompt_variable (cdef,cread,cwrite,category,variable, show_comments,False) except Exception, inst: - if (str(inst) != 'BailOut'): + if str(inst) != 'BailOut': raise - elif (command in "vVsSlL"): + elif command in "vVsSlL": show_value=(command in "sSlL") (c1,c2,c3) = (cdef, cread, cwrite) - if (command in "lL"): + if command in "lL": (c1,c2,c3) = (cwrite,cwrite,cwrite) if mode == 'ALL': show_variables_all(c1,c2,c3,show_value,show_comments) @@ -1251,16 +1282,16 @@ def check_dir (config_file): except OSError, e: print "Cannot create dir %s due to %s - exiting" % (dirname,e) sys.exit(1) - + if (not os.path.exists (dirname)): print "Cannot create dir %s - exiting" % dirname sys.exit(1) else: print "Created directory %s" % dirname - + #################### def optParserSetup(configuration): - parser = OptionParser(usage=usage(), version="%prog " + release_rev + release_url ) + parser = OptionParser(usage=usage()) parser.set_defaults(config_dir=configuration['config_dir'], service=configuration['service'], usual_variables=configuration['usual_variables']) @@ -1318,7 +1349,7 @@ def main(command,argv,configuration): # local settings only, will be modified & saved cwrite=PLCConfiguration() - + try: cread.load(site_config) cwrite.load(site_config)