From 8749484b9bdde8930ad5b64f60d53ddae9ff35de Mon Sep 17 00:00:00 2001 From: Marc Fiuczynski Date: Sat, 20 Jun 2009 18:17:54 +0000 Subject: [PATCH] refactored the bulk of plc-config-tty into plc_config.py --- plc-config-tty | 573 +++---------------------------------------------- plc_config.py | 502 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 526 insertions(+), 549 deletions(-) diff --git a/plc-config-tty b/plc-config-tty index 6b0fe60..9e8ec4e 100755 --- a/plc-config-tty +++ b/plc-config-tty @@ -1,552 +1,41 @@ #!/bin/env python -# Interactively prompts for variable values -# expected arguments are -# command -d [default-xml [custom-xml [ consolidated-xml ]]] - -# we use 3 instances of PLCConfiguration throughout: -# cdef : models the defaults, from plc_default.xml -# cread : merged from plc_default & configs/site.xml -# cwrite : site.xml + pending changes - import sys -import os -import re -import readline -import traceback -from optparse import OptionParser - -from plc_config import PLCConfiguration -from plc_config import ConfigurationException - -#################### -release_id = "$Id$" -release_rev = "$Revision$" -release_url = "$URL$" +import plc_config -flavours={} - -def noop_validator(v): - pass - -def plc_validator(validated_variables): +def validator(validated_variables): maint_user = validated_variables["PLC_API_MAINTENANCE_USER"] root_user = validated_variables["PLC_ROOT_USER"] if maint_user == root_user: - raise ConfigurationException("PLC_API_MAINTENANCE_USER=%s cannot be the same as PLC_ROOT_USER=%s"%(maint_user,root_user)) - -flavours["plc"]={'service':"plc", - 'usual_variables':["PLC_NAME", - "PLC_SHORTNAME", - "PLC_SLICE_PREFIX", - "PLC_ROOT_USER", - "PLC_ROOT_PASSWORD", - "PLC_MAIL_ENABLED", - "PLC_MAIL_SUPPORT_ADDRESS", - "PLC_DB_HOST", - "PLC_API_HOST", - "PLC_WWW_HOST", - "PLC_BOOT_HOST", - "PLC_NET_DNS1", - "PLC_NET_DNS2", - ], - 'config_dir':"/etc/planetlab", - 'validate_variables':{"PLC_API":"MAINTENANCE_USER","PLC":"ROOT_USER"}, - 'validator':plc_validator, - } - -defined_flavour = "plc" - -# historically we could also configure the devel pkg.... -def init_flavour (flavour): - global service, usual_variables - - global defined_flavour - if flavours.has_key(flavour): - defined_flavour = flavour - else: - defined_flavour = "plc" - - flav=flavours.get(flavour,flavours["plc"]) - service=flav["service"] - usual_variables=flav["usual_variables"] - config_dir=flav["config_dir"] - - global def_default_config, def_site_config, def_consolidated_config - def_default_config= "%s/default_config.xml" % config_dir - def_site_config = "%s/configs/site.xml" % config_dir - def_consolidated_config = "%s/%s_config.xml" % (config_dir, service) - - global mainloop_usage - 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 - q\t\t\tQuit (without saving) - h/?\t\t\tThis help ---- - l/L [|]\tShow Locally modified variables/values - s/S [|]\tShow variables/values (all, in category, single) - e/E [|]\tEdit variables (all, in category, single) ---- - c\t\t\tList categories - v/V [|]List Variables (all, in category, single) ---- -Typical usage involves: u, [l,] w, r, q -""" % service - -def usage (): - command_usage="%prog [options] [default-xml [site-xml [consolidated-xml]]]" - init_flavour ("plc") - command_usage +=""" -\t default-xml defaults to %s -\t site-xml defaults to %s -\t consolidated-xml defaults to %s""" % (def_default_config,def_site_config, def_consolidated_config) - return command_usage - -#################### -variable_usage= """Edit Commands : -#\tShow variable comments -.\tStops prompting, return to mainloop -/\tCleans any site-defined value, reverts to default -=\tShows default value ->\tSkips to next category -?\tThis help -""" - -#################### -def get_value (config, category_id, variable_id): - (category, variable) = config.get (category_id, variable_id) - return variable['value'] - -def get_current_value (cread, cwrite, category_id, variable_id): - # the value stored in cwrite, if present, is the one we want - try: - result=get_value (cwrite,category_id,variable_id) - except: - result=get_value (cread,category_id,variable_id) - return result - -# 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() - -# could not avoid using _sanitize here.. -def get_name_comments (config, cid, vid): - try: - (category, variable) = config.get (cid, vid) - (id, name, value, comments) = config._sanitize_variable (cid,variable) - return (name,comments) - except: - return (None,[]) - -def print_name_comments (config, cid, vid): - (name,comments)=get_name_comments(config,cid,vid) - if name: - print "### %s" % name - if comments: - for line in comments: - print "# %s" % line - else: - print "!!! No comment associated to %s_%s" % (cid,vid) - -#################### -def list_categories (config): - result=[] - for (category_id, (category, variables)) in config.variables().iteritems(): - result += [category_id] - return result - -def print_categories (config): - print "Known categories" - for cid in list_categories(config): - print "%s" % (cid.upper()) - -#################### -def list_category (config, cid): - result=[] - for (category_id, (category, variables)) in config.variables().iteritems(): - if (cid == category_id): - 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() - vids=list_category(config,cid) - if (len(vids) == 0): - print "%s : no such category"%CID - else: - print "Category %s contains" %(CID) - for vid in vids: - print vid.upper() - -#################### -def consolidate (default_config, site_config, consolidated_config): - global service - try: - conso = PLCConfiguration (default_config) - conso.load (site_config) - conso.save (consolidated_config) - except Exception, inst: - print "Could not consolidate, %s" % (str(inst)) - return - print ("Merged\n\t%s\nand\t%s\ninto\t%s"%(default_config,site_config, - consolidated_config)) - -def reload_service (): - global service - os.system("set -x ; service %s reload" % service) - -#################### -def restart_service (): - global service - print ("==================== Stopping %s" % service) - os.system("service %s stop" % service) - print ("==================== Starting %s" % service) - os.system("service %s start" % service) - -#################### -def prompt_variable (cdef, cread, cwrite, category, variable, - show_comments, support_next=False): - - assert category.has_key('id') - assert variable.has_key('id') - - category_id = category ['id'] - variable_id = variable['id'] - - while True: - default_value = get_value(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) - try: - answer = raw_input(prompt).strip() - except EOFError : - raise Exception ('BailOut') - except KeyboardInterrupt: - print "\n" - raise Exception ('BailOut') - - # no change - if (answer == "") or (answer == current_value): - return None - elif (answer == "."): - raise Exception ('BailOut') - elif (answer == "#"): - print_name_comments(cread,category_id,variable_id) - elif (answer == "?"): - print variable_usage.strip() - elif (answer == "="): - print ("%s defaults to %s" %(varname,default_value)) - # revert to default : remove from cwrite (i.e. site-config) - elif (answer == "/"): - cwrite.delete(category_id,variable_id) - print ("%s reverted to %s" %(varname,default_value)) - return - elif (answer == ">"): - if support_next: - raise Exception ('NextCategory') - else: - print "No support for next category" - else: - variable['value'] = answer - cwrite.set(category,variable) - return - -def prompt_variables_all (cdef, cread, cwrite, show_comments): - try: - for (category_id, (category, variables)) in cread.variables().iteritems(): - print ("========== Category = %s" % category_id.upper()) - for variable in variables.values(): - try: - newvar = prompt_variable (cdef, cread, cwrite, category, variable, - show_comments, True) - except Exception, inst: - if (str(inst) == 'NextCategory'): break - else: raise - - except Exception, inst: - if (str(inst) == 'BailOut'): return - else: raise - -def prompt_variables_category (cdef, cread, cwrite, cid, show_comments): - cid=cid.lower() - CID=cid.upper() - try: - print ("========== Category = %s" % CID) - for vid in list_category(cdef,cid): - (category,variable) = cdef.locate_varname(vid.upper()) - newvar = prompt_variable (cdef, cread, cwrite, category, variable, - show_comments, False) - except Exception, inst: - if (str(inst) == 'BailOut'): return - else: raise - -#################### -def show_variable (cdef, cread, cwrite, - category, variable,show_value,show_comments): - assert category.has_key('id') - assert variable.has_key('id') - - category_id = category ['id'] - variable_id = variable['id'] - - default_value = get_value(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) - if show_value: - print "%s = %s" % (varname,current_value) - else: - print "%s" % (varname) - -def show_variables_all (cdef, cread, cwrite, show_value, show_comments): - for (category_id, (category, variables)) in cread.variables().iteritems(): - print ("========== Category = %s" % category_id.upper()) - for variable in variables.values(): - show_variable (cdef, cread, cwrite, - category, variable,show_value,show_comments) - -def show_variables_category (cdef, cread, cwrite, cid, show_value,show_comments): - cid=cid.lower() - CID=cid.upper() - print ("========== Category = %s" % CID) - for vid in list_category(cdef,cid): - (category,variable) = cdef.locate_varname(vid.upper()) - show_variable (cdef, cread, cwrite, category, variable, - show_value,show_comments) - -#################### -re_mainloop_0arg="^(?P[uUwrRqlLsSeEcvVhH\?])[ \t]*$" -re_mainloop_1arg="^(?P[sSeEvV])[ \t]+(?P\w+)$" -matcher_mainloop_0arg=re.compile(re_mainloop_0arg) -matcher_mainloop_1arg=re.compile(re_mainloop_1arg) - -def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_config): - global service - while True: - try: - answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip() - except EOFError: - answer ="" - except KeyboardInterrupt: - print "\nBye" - sys.exit() - - if (answer == "") or (answer in "?hH"): - print mainloop_usage - continue - groups_parse = matcher_mainloop_0arg.match(answer) - command=None - if (groups_parse): - command = groups_parse.group('command') - arg=None - else: - groups_parse = matcher_mainloop_1arg.match(answer) - if (groups_parse): - command = groups_parse.group('command') - arg=groups_parse.group('arg') - if not command: - print ("Unknown command >%s< -- use h for help" % answer) - continue - - show_comments=command.isupper() - command=command.lower() - - mode='ALL' - if arg: - mode=None - arg=arg.lower() - variables=list_category (cdef,arg) - if len(variables): - # category_id as the category name - # variables as the list of variable names - mode='CATEGORY' - category_id=arg - arg=arg.upper() - (category,variable)=cdef.locate_varname(arg) - if variable: - # category/variable as output by locate_varname - mode='VARIABLE' - if not mode: - print "%s: no such category or variable" % arg - continue - - if (command in "qQ"): - # todo check confirmation - return - elif (command == "w"): - global defined_flavour - try: - # Confirm that various constraints are met before saving file. - validate_variables = flavours[defined_flavour].get('validate_variables',{}) - validated_variables = cwrite.verify(cdef, cread, validate_variables) - validator = flavours[defined_flavour].get('validator',noop_validator) - validator(validated_variables) - cwrite.save(site_config) - except ConfigurationException, e: - print "Save failed due to a configuration exception: %s" % e - break; - except: - print traceback.print_exc() - print ("Could not save -- fix write access on %s" % site_config) - break - 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"): - try: - for varname in usual_variables: - (category,variable) = cdef.locate_varname(varname) - prompt_variable(cdef, cread, cwrite, category, variable, False) - except Exception, inst: - if (str(inst) != 'BailOut'): - raise - elif (command == "r"): - restart_service() - elif (command == "R"): - reload_service() - elif (command == "c"): - print_categories(cread) - elif (command in "eE"): - if mode == 'ALL': - prompt_variables_all(cdef, cread, cwrite,show_comments) - elif mode == 'CATEGORY': - prompt_variables_category(cdef,cread,cwrite,category_id,show_comments) - elif mode == 'VARIABLE': - try: - prompt_variable (cdef,cread,cwrite,category,variable, - show_comments,False) - except Exception, inst: - if (str(inst) != 'BailOut'): - raise - elif (command in "vVsSlL"): - show_value=(command in "sSlL") - (c1,c2,c3) = (cdef, cread, cwrite) - if (command in "lL"): - (c1,c2,c3) = (cwrite,cwrite,cwrite) - if mode == 'ALL': - show_variables_all(c1,c2,c3,show_value,show_comments) - elif mode == 'CATEGORY': - show_variables_category(c1,c2,c3,category_id,show_value,show_comments) - elif mode == 'VARIABLE': - show_variable (c1,c2,c3,category,variable,show_value,show_comments) - else: - print ("Unknown command >%s< -- use h for help" % answer) - -#################### -# creates directory for file if not yet existing -def check_dir (config_file): - dirname = os.path.dirname (config_file) - if (not os.path.exists (dirname)): - try: - os.makedirs(dirname,0755) - 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 main (): + errStr="PLC_API_MAINTENANCE_USER=%s cannot be the same as PLC_ROOT_USER=%s"%(maint_user,root_user) + raise plc_config.ConfigurationException(errStr) + +usual_variables = [ \ + "PLC_NAME", + "PLC_SHORTNAME", + "PLC_SLICE_PREFIX", + "PLC_ROOT_USER", + "PLC_ROOT_PASSWORD", + "PLC_MAIL_ENABLED", + "PLC_MAIL_SUPPORT_ADDRESS", + "PLC_DB_HOST", + "PLC_API_HOST", + "PLC_WWW_HOST", + "PLC_BOOT_HOST", + "PLC_NET_DNS1", + "PLC_NET_DNS2", + ] + +configuration={ \ + 'name':'plc', + 'service':"plc", + 'usual_variables':usual_variables, + 'config_dir':"/etc/planetlab", + 'validate_variables':{"PLC_API":"MAINTENANCE_USER","PLC":"ROOT_USER"}, + 'validator':validator, + } +if __name__ == '__main__': command=sys.argv[0] argv = sys.argv[1:] - save = True - parser = OptionParser(usage=usage(), version="%prog 1.0" + release_rev + release_url ) - parser.set_defaults(flavour="plc", - config="flavour.config", - config_dir=None, - service=None, - usual_variables=[]) - parser.add_option("","--configdir",dest="config_dir",help="specify configuration directory") - parser.add_option("","--service",dest="service",help="specify /etc/init.d style service name") - parser.add_option("","--usual_variable",dest="usual_variables",action="append", help="add a usual variable") - parser.add_option("","--flavour",dest="flavour", help="Sets the configuration flavour") - - (config,args) = parser.parse_args() - if len(args)>3: - parser.error("too many arguments") - - if config.flavour not in flavours: - if config.service==None: - parser.error("unknown flavour '%s'" % config.flavour) - else: - flavours[config.flavour]={} - flavour=flavours[config.flavour] - flavour['service']=config.service - flavour['usual_variables']=config.usual_variables - if config.config_dir==None: - flavour['config_dir']="/etc/%s"%config.service - else: - flavour['config_dir']=config.config_dir - else: - flavour=flavours[config.flavour] - - # in case the config dir should be something other than /etc/planetlab - if config.config_dir <> None: - flavour['config_dir']=config.config_dir - - # add in new usual_variables defined on the command line - for usual_variable in config.usual_variables: - if usual_variable not in flavour['usual_variables']: - flavour['usual_variables'].append(usual_variable) - - # intialize flavour - init_flavour(config.flavour) - - (default_config,site_config,consolidated_config) = (def_default_config, def_site_config, def_consolidated_config) - if len(args) >= 1: - default_config=args[0] - if len(args) >= 2: - site_config=args[1] - if len(args) == 3: - consolidated_config=args[2] - - for c in (default_config,site_config,consolidated_config): - check_dir (c) - - try: - # the default settings only - read only - cdef = PLCConfiguration(default_config) - - # in effect : default settings + local settings - read only - cread = PLCConfiguration(default_config) - - except ConfigurationException, e: - print ("Error %s in default config file %s" %(e,default_config)) - return 1 - except: - print traceback.print_exc() - print ("default config files %s not found, is myplc installed ?" % default_config) - return 1 - - - # local settings only, will be modified & saved - cwrite=PLCConfiguration() - - try: - cread.load(site_config) - cwrite.load(site_config) - except: - cwrite = PLCConfiguration() - - mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_config) - return 0 - -if __name__ == '__main__': - main() + plc_config.main(command,argv,configuration) diff --git a/plc_config.py b/plc_config.py index 45805b9..cedd66c 100644 --- a/plc_config.py +++ b/plc_config.py @@ -10,16 +10,19 @@ # $Id$ # -import xml.dom.minidom -from xml.parsers.expat import ExpatError -from StringIO import StringIO -import time -import re -import textwrap import codecs import os +import re +import readline +import sys +import textwrap +import time +import traceback import types - +import xml.dom.minidom +from xml.parsers.expat import ExpatError +from StringIO import StringIO +from optparse import OptionParser class ConfigurationException(Exception): pass @@ -841,6 +844,491 @@ class TrimTextElement(xml.dom.minidom.Element): writer.write(newl) +#################### +# GLOBAL VARIABLES +# +release_id = "$Id:$" +release_rev = "$Revision:$" +release_url = "$URL:$" + +g_configuration=None +usual_variables=None +config_dir=None +service=None + +def noop_validator(validated_variables): + pass + + +# historically we could also configure the devel pkg.... +def init_configuration (): + global g_configuration + global usual_variables, config_dir, service + + usual_variables=g_configuration["usual_variables"] + config_dir=g_configuration["config_dir"] + service=g_configuration["service"] + + global def_default_config, def_site_config, def_consolidated_config + def_default_config= "%s/default_config.xml" % config_dir + def_site_config = "%s/configs/site.xml" % config_dir + def_consolidated_config = "%s/%s_config.xml" % (config_dir, service) + + global mainloop_usage + 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 + q\t\t\tQuit (without saving) + h/?\t\t\tThis help +--- + l/L [|]\tShow Locally modified variables/values + s/S [|]\tShow variables/values (all, in category, single) + e/E [|]\tEdit variables (all, in category, single) +--- + c\t\t\tList categories + v/V [|]List Variables (all, in category, single) +--- +Typical usage involves: u, [l,] w, r, q +""" % service + +def usage (): + command_usage="%prog [options] [default-xml [site-xml [consolidated-xml]]]" + init_configuration () + command_usage +=""" +\t default-xml defaults to %s +\t site-xml defaults to %s +\t consolidated-xml defaults to %s""" % (def_default_config,def_site_config, def_consolidated_config) + return command_usage + +#################### +variable_usage= """Edit Commands : +#\tShow variable comments +.\tStops prompting, return to mainloop +/\tCleans any site-defined value, reverts to default +=\tShows default value +>\tSkips to next category +?\tThis help +""" + +#################### +def get_value (config, category_id, variable_id): + (category, variable) = config.get (category_id, variable_id) + return variable['value'] + +def get_current_value (cread, cwrite, category_id, variable_id): + # the value stored in cwrite, if present, is the one we want + try: + result=get_value (cwrite,category_id,variable_id) + except: + result=get_value (cread,category_id,variable_id) + return result + +# 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() + +# could not avoid using _sanitize here.. +def get_name_comments (config, cid, vid): + try: + (category, variable) = config.get (cid, vid) + (id, name, value, comments) = config._sanitize_variable (cid,variable) + return (name,comments) + except: + return (None,[]) + +def print_name_comments (config, cid, vid): + (name,comments)=get_name_comments(config,cid,vid) + if name: + print "### %s" % name + if comments: + for line in comments: + print "# %s" % line + else: + print "!!! No comment associated to %s_%s" % (cid,vid) + +#################### +def list_categories (config): + result=[] + for (category_id, (category, variables)) in config.variables().iteritems(): + result += [category_id] + return result + +def print_categories (config): + print "Known categories" + for cid in list_categories(config): + print "%s" % (cid.upper()) + +#################### +def list_category (config, cid): + result=[] + for (category_id, (category, variables)) in config.variables().iteritems(): + if (cid == category_id): + 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() + vids=list_category(config,cid) + if (len(vids) == 0): + print "%s : no such category"%CID + else: + print "Category %s contains" %(CID) + for vid in vids: + print vid.upper() + +#################### +def consolidate (default_config, site_config, consolidated_config): + global service + try: + conso = PLCConfiguration (default_config) + conso.load (site_config) + conso.save (consolidated_config) + except Exception, inst: + print "Could not consolidate, %s" % (str(inst)) + return + print ("Merged\n\t%s\nand\t%s\ninto\t%s"%(default_config,site_config, + consolidated_config)) + +def reload_service (): + global service + os.system("set -x ; service %s reload" % service) + +#################### +def restart_service (): + global service + print ("==================== Stopping %s" % service) + os.system("service %s stop" % service) + print ("==================== Starting %s" % service) + os.system("service %s start" % service) + +#################### +def prompt_variable (cdef, cread, cwrite, category, variable, + show_comments, support_next=False): + + assert category.has_key('id') + assert variable.has_key('id') + + category_id = category ['id'] + variable_id = variable['id'] + + while True: + default_value = get_value(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) + try: + answer = raw_input(prompt).strip() + except EOFError : + raise Exception ('BailOut') + except KeyboardInterrupt: + print "\n" + raise Exception ('BailOut') + + # no change + if (answer == "") or (answer == current_value): + return None + elif (answer == "."): + raise Exception ('BailOut') + elif (answer == "#"): + print_name_comments(cread,category_id,variable_id) + elif (answer == "?"): + print variable_usage.strip() + elif (answer == "="): + print ("%s defaults to %s" %(varname,default_value)) + # revert to default : remove from cwrite (i.e. site-config) + elif (answer == "/"): + cwrite.delete(category_id,variable_id) + print ("%s reverted to %s" %(varname,default_value)) + return + elif (answer == ">"): + if support_next: + raise Exception ('NextCategory') + else: + print "No support for next category" + else: + variable['value'] = answer + cwrite.set(category,variable) + return + +def prompt_variables_all (cdef, cread, cwrite, show_comments): + try: + for (category_id, (category, variables)) in cread.variables().iteritems(): + print ("========== Category = %s" % category_id.upper()) + for variable in variables.values(): + try: + newvar = prompt_variable (cdef, cread, cwrite, category, variable, + show_comments, True) + except Exception, inst: + if (str(inst) == 'NextCategory'): break + else: raise + + except Exception, inst: + if (str(inst) == 'BailOut'): return + else: raise + +def prompt_variables_category (cdef, cread, cwrite, cid, show_comments): + cid=cid.lower() + CID=cid.upper() + try: + print ("========== Category = %s" % CID) + for vid in list_category(cdef,cid): + (category,variable) = cdef.locate_varname(vid.upper()) + newvar = prompt_variable (cdef, cread, cwrite, category, variable, + show_comments, False) + except Exception, inst: + if (str(inst) == 'BailOut'): return + else: raise + +#################### +def show_variable (cdef, cread, cwrite, + category, variable,show_value,show_comments): + assert category.has_key('id') + assert variable.has_key('id') + + category_id = category ['id'] + variable_id = variable['id'] + + default_value = get_value(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) + if show_value: + print "%s = %s" % (varname,current_value) + else: + print "%s" % (varname) + +def show_variables_all (cdef, cread, cwrite, show_value, show_comments): + for (category_id, (category, variables)) in cread.variables().iteritems(): + print ("========== Category = %s" % category_id.upper()) + for variable in variables.values(): + show_variable (cdef, cread, cwrite, + category, variable,show_value,show_comments) + +def show_variables_category (cdef, cread, cwrite, cid, show_value,show_comments): + cid=cid.lower() + CID=cid.upper() + print ("========== Category = %s" % CID) + for vid in list_category(cdef,cid): + (category,variable) = cdef.locate_varname(vid.upper()) + show_variable (cdef, cread, cwrite, category, variable, + show_value,show_comments) + +#################### +re_mainloop_0arg="^(?P[uUwrRqlLsSeEcvVhH\?])[ \t]*$" +re_mainloop_1arg="^(?P[sSeEvV])[ \t]+(?P\w+)$" +matcher_mainloop_0arg=re.compile(re_mainloop_0arg) +matcher_mainloop_1arg=re.compile(re_mainloop_1arg) + +def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_config): + global service + while True: + try: + answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip() + except EOFError: + answer ="" + except KeyboardInterrupt: + print "\nBye" + sys.exit() + + if (answer == "") or (answer in "?hH"): + print mainloop_usage + continue + groups_parse = matcher_mainloop_0arg.match(answer) + command=None + if (groups_parse): + command = groups_parse.group('command') + arg=None + else: + groups_parse = matcher_mainloop_1arg.match(answer) + if (groups_parse): + command = groups_parse.group('command') + arg=groups_parse.group('arg') + if not command: + print ("Unknown command >%s< -- use h for help" % answer) + continue + + show_comments=command.isupper() + command=command.lower() + + mode='ALL' + if arg: + mode=None + arg=arg.lower() + variables=list_category (cdef,arg) + if len(variables): + # category_id as the category name + # variables as the list of variable names + mode='CATEGORY' + category_id=arg + arg=arg.upper() + (category,variable)=cdef.locate_varname(arg) + if variable: + # category/variable as output by locate_varname + mode='VARIABLE' + if not mode: + print "%s: no such category or variable" % arg + continue + + if (command in "qQ"): + # todo check confirmation + return + elif (command == "w"): + try: + # Confirm that various constraints are met before saving file. + validate_variables = g_configuration.get('validate_variables',{}) + validated_variables = cwrite.verify(cdef, cread, validate_variables) + validator = g_configuration.get('validator',noop_validator) + validator(validated_variables) + cwrite.save(site_config) + except ConfigurationException, e: + print "Save failed due to a configuration exception: %s" % e + break; + except: + print traceback.print_exc() + print ("Could not save -- fix write access on %s" % site_config) + break + 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"): + global usual_variables + try: + for varname in usual_variables: + (category,variable) = cdef.locate_varname(varname) + if not (category is None and variable is None): + prompt_variable(cdef, cread, cwrite, category, variable, False) + except Exception, inst: + if (str(inst) != 'BailOut'): + raise + elif (command == "r"): + restart_service() + elif (command == "R"): + reload_service() + elif (command == "c"): + print_categories(cread) + elif (command in "eE"): + if mode == 'ALL': + prompt_variables_all(cdef, cread, cwrite,show_comments) + elif mode == 'CATEGORY': + prompt_variables_category(cdef,cread,cwrite,category_id,show_comments) + elif mode == 'VARIABLE': + try: + prompt_variable (cdef,cread,cwrite,category,variable, + show_comments,False) + except Exception, inst: + if (str(inst) != 'BailOut'): + raise + elif (command in "vVsSlL"): + show_value=(command in "sSlL") + (c1,c2,c3) = (cdef, cread, cwrite) + if (command in "lL"): + (c1,c2,c3) = (cwrite,cwrite,cwrite) + if mode == 'ALL': + show_variables_all(c1,c2,c3,show_value,show_comments) + elif mode == 'CATEGORY': + show_variables_category(c1,c2,c3,category_id,show_value,show_comments) + elif mode == 'VARIABLE': + show_variable (c1,c2,c3,category,variable,show_value,show_comments) + else: + print ("Unknown command >%s< -- use h for help" % answer) + +#################### +# creates directory for file if not yet existing +def check_dir (config_file): + dirname = os.path.dirname (config_file) + if (not os.path.exists (dirname)): + try: + os.makedirs(dirname,0755) + 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 1.0" + release_rev + release_url ) + parser.set_defaults(config_dir=configuration['config_dir'], + service=configuration['service'], + usual_variables=configuration['usual_variables']) + parser.add_option("","--configdir",dest="config_dir",help="specify configuration directory") + parser.add_option("","--service",dest="service",help="specify /etc/init.d style service name") + parser.add_option("","--usual_variable",dest="usual_variables",action="append", help="add a usual variable") + return parser + +def main(command,argv,configuration): + global g_configuration + g_configuration=configuration + + parser = optParserSetup(configuration) + (config,args) = parser.parse_args() + if len(args)>3: + parser.error("too many arguments") + + configuration['service']=config.service + configuration['usual_variables']=config.usual_variables + configuration['config_dir']=config.config_dir + # add in new usual_variables defined on the command line + for usual_variable in config.usual_variables: + if usual_variable not in configuration['usual_variables']: + configuration['usual_variables'].append(usual_variable) + + # intialize configuration + init_configuration() + + (default_config,site_config,consolidated_config) = (def_default_config, def_site_config, def_consolidated_config) + if len(args) >= 1: + default_config=args[0] + if len(args) >= 2: + site_config=args[1] + if len(args) == 3: + consolidated_config=args[2] + + for c in (default_config,site_config,consolidated_config): + check_dir (c) + + try: + # the default settings only - read only + cdef = PLCConfiguration(default_config) + + # in effect : default settings + local settings - read only + cread = PLCConfiguration(default_config) + + except ConfigurationException, e: + print ("Error %s in default config file %s" %(e,default_config)) + return 1 + except: + print traceback.print_exc() + print ("default config files %s not found, is myplc installed ?" % default_config) + return 1 + + + # local settings only, will be modified & saved + cwrite=PLCConfiguration() + + try: + cread.load(site_config) + cwrite.load(site_config) + except: + cwrite = PLCConfiguration() + + mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_config) + return 0 + if __name__ == '__main__': import sys if len(sys.argv) > 1 and sys.argv[1] in ['build', 'install', 'uninstall']: -- 2.43.0