# Interactively prompts for variable values
# expected arguments are
-# command [default-xml [custom-xml]]
+# command -d [default-xml [custom-xml [ consolidated-xml ]]]
#
-# Two-steps logic:
-# (1) scans all variables (todo: pass categories as arguments)
-# and prompts for value
-# current value proposed as default
-# also allows to remove site-dependent setting
-# (2) epilogue : allows to
-# list the site-dependent vars with values
-# and to locally (re-)edit a variable from its shell name
-# quit with or without saving
+# -d is for the myplc-devel package
+
+# 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 getopt
from plc_config import PLCConfiguration
+from plc_config import ConfigurationException
####################
-release = "$Id"
+release_id = "$Id$"
+release_rev = "$Revision$"
+
+def init_flavour (flavour):
+ global service
+ global usual_variables
+ if (flavour == "devel"):
+ service="plc-devel"
+ usual_variables=("PLC_DEVEL_FEDORA_URL",
+ "PLC_DEVEL_CVSROOT")
+ config_dir = "/plc/devel/data/etc/planetlab"
+ else:
+ service="plc"
+ usual_variables=("PLC_NAME",
+ "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"
+ global def_default_config
+ def_default_config= "%s/default_config.xml" % config_dir
+ global def_site_config
+ def_site_config = "%s/configs/site.xml" % config_dir
+ global def_consolidated_config
+ def_consolidated_config = "%s/plc_config.xml" % config_dir
-def_main_config = "/etc/planetlab/default_config.xml"
-def_site_config = "/etc/planetlab/configs/site.xml"
-def_consolidated_config = "/etc/planetlab/plc_config.xml"
+ global mainloop_usage
+ mainloop_usage= """Available commands:
+ Uppercase versions give variables comments, when available
+ u/U\t\t\tEdit usual variables
+ w\t\t\tWrite & consolidate
+ r\t\t\tRestart %s service
+ q\t\t\tQuit (without saving)
+ h/?\t\t\tThis help
+---
+ l/L [<cat>|<var>]\tShow Locally modified variables/values
+ s/S [<cat>|<var>]\tShow variables/values (all, in category, single)
+ e/E [<cat>|<var>]\tEdit variables (all, in category, single)
+---
+ c\t\t\tList categories
+ v/V [<cat>|<var>]List Variables (all, in category, single)
+---
+Typical usage involves: u, [l,] w, r, q
+""" % service
-command_usage="""Usage: %s [default-xml [site-xml [consolidated-xml]]]
+def usage ():
+ command_usage="Usage: %s [-d] [-v] [default-xml [site-xml [consolidated-xml]]]"% sys.argv[0]
+ init_flavour ("boot")
+ command_usage +="""
+ -v shows version and exits
+\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)
+ command_usage += """
+ Unless you specify the -d option, meaning you want to configure
+ myplc-devel instead of regular myplc, in which case"""
+ init_flavour ("devel")
+ command_usage +="""
\t default-xml defaults to %s
\t site-xml defaults to %s
-\t consolidated-xml defaults to %s
-""" % (sys.argv[0],def_main_config,def_site_config, def_consolidated_config)
+\t consolidated-xml defaults to %s""" % (def_default_config,def_site_config, def_consolidated_config)
+ print(command_usage)
+ sys.exit(1)
####################
-variable_usage= """Special answers :
+variable_usage= """Edit Commands :
#\tShow variable comments
.\tStops prompting, return to mainloop
/\tCleans any site-defined value, reverts to default
?\tThis help
"""
-def usage ():
- print(command_usage)
- sys.exit(1)
-
####################
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()
-def prompt_variable (cdef, cread, cwrite, category, variable):
+# 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):
+ 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))
+ os.system("set -x ; service plc reload")
+
+####################
+def restart_plc ():
+ 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')
while True:
default_value = get_value(cdef,category_id,variable_id)
- current_value = get_value(cread,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()
return None
elif (answer == "."):
raise Exception ('BailOut')
- elif (answer == ">"):
- raise Exception ('NextCategory')
elif (answer == "#"):
- if friendly_name is not None:
- print ("### " + friendly_name)
- if comments == None:
- print ("!!! No comment associated to %s" % varname)
- else:
- for line in comments:
- print ("# " + line)
+ print_name_comments(cread,category_id,variable_id)
elif (answer == "?"):
print variable_usage.strip()
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_all_variables (cdef, cread, cwrite):
+def prompt_variables_all (cdef, cread, cwrite, show_comments):
try:
for (category_id, (category, variables)) in cread.variables().iteritems():
- print ("========== Category = %s" % category_id)
+ print ("========== Category = %s" % category_id.upper())
for variable in variables.values():
try:
- newvar = prompt_variable (cdef, cread, cwrite, category, variable)
+ newvar = prompt_variable (cdef, cread, cwrite, category, variable,
+ show_comments, True)
except Exception, inst:
if (str(inst) == 'NextCategory'): break
else: raise
if (str(inst) == 'BailOut'): return
else: raise
-
-####################
-def consolidate (main_config, site_config, consolidated_config):
+def prompt_variables_category (cdef, cread, cwrite, cid, show_comments):
+ cid=cid.lower()
+ CID=cid.upper()
try:
- conso = PLCConfiguration (main_config)
- conso.load (site_config)
- conso.save (consolidated_config)
+ 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:
- print "Could not consolidate, %s" % (str(inst))
- return
- print ("Overwote %s\n\tfrom %s\n\tand %s"%(consolidated_config,main_config,site_config))
-
+ if (str(inst) == 'BailOut'): return
+ else: raise
+
####################
-def restart_plc ():
- print ("==================== Stopping plc")
- os.system("service plc stop")
- print ("==================== Starting plc")
- os.system("service plc start")
+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)
####################
-mainloop_usage= """Available commands
-c\tEdits commonly tuned variables
-e\tEdits all variables
-p\tPrints all locally-customized vars and values
-e <var>\tPrompts (edit) fro variable <var>
-p <var>\tShows current setting for <var>
-l\tlists all known variables
-w\tSaves and quit
-W\tsaves, consolidates and quit
-r\trestarts plc service
-q\tQuits without saving
-"""
+re_mainloop_0arg="^(?P<command>[uUwrqlLsSeEcvVhH\?])[ \t]*$"
+re_mainloop_1arg="^(?P<command>[sSeEvV])[ \t]+(?P<arg>\w+)$"
+matcher_mainloop_0arg=re.compile(re_mainloop_0arg)
+matcher_mainloop_1arg=re.compile(re_mainloop_1arg)
-re_mainloop_var="^(?P<command>[pe])[ \t]+(?P<varname>\w+)$"
-matcher_mainloop_var=re.compile(re_mainloop_var)
-
-common_variables=("PLC_NAME",
- "PLC_ROOT_USER",
- "PLC_ROOT_PASSWORD",
- "PLC_MAIL_SUPPORT_ADDRESS",
- "PLC_DB_HOST",
- "PLC_API_HOST",
- "PLC_WWW_HOST",
- "PLC_BOOT_HOST",
- "PLC_NET_DNS1",
- "PLC_NET_DNS2")
-
-def mainloop (cdef, cread, cwrite,main_config, site_config, consolidated_config):
+def mainloop (cdef, cread, cwrite, default_config, site_config, consolidated_config):
while True:
try:
- answer = raw_input("Enter command (c for usual changes, w to save, ? for help) ").strip()
+ answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip()
except EOFError:
answer =""
- if (answer == "") or (answer == "?") or (answer == "h"):
+ if (answer == "") or (answer in "?hH"):
print mainloop_usage
- elif (answer == "q"):
+ 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 (answer == "e"):
- prompt_all_variables(cdef, cread, cwrite)
- elif (answer.lower() == "w"):
+ elif (command in "wW"):
try:
+ # Confirm that various constraints are met before saving file.
+ cwrite.verify(cdef, cread)
cwrite.save(site_config)
+ except ConfigurationException, e:
+ print "Save failed due to a configuration exception: %s" % e
+ break;
except:
+ import traceback; print traceback.print_exc()
print ("Could not save -- fix write access on %s" % site_config)
break
print ("Wrote %s" % site_config)
- if (answer == "W"):
- consolidate(main_config, site_config, consolidated_config)
- return
- elif (answer == "l"):
- print ("Config involves the following variables")
- sys.stdout.write(cread.output_variables())
- elif (answer == "p"):
- print ("Current site config")
- sys.stdout.write(cwrite.output_shell(False))
- elif (answer == "c"):
+ consolidate(default_config, site_config, consolidated_config)
+ print ("You might want to type 'r' (restart plc) or 'q' (quit)")
+ elif (command == "u"):
try:
- for varname in common_variables:
+ for varname in usual_variables:
(category,variable) = cdef.locate_varname(varname)
- prompt_variable(cdef, cread, cwrite, category, variable)
+ prompt_variable(cdef, cread, cwrite, category, variable, False)
except Exception, inst:
if (str(inst) != 'BailOut'):
raise
- elif (answer == "r"):
+ elif (command == "r"):
restart_plc()
+ 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:
- groups_var = matcher_mainloop_var.match(answer)
- if (groups_var):
- command = groups_var.group('command')
- varname = groups_var.group('varname')
- (category,variable) = cdef.locate_varname(varname)
- if not category:
- print "Unknown variable %s" % varname
- elif (command == 'p'):
- print ("%s = %s" % (varname,get_value(cwrite,
- category['id'],
- variable['id'])))
- else:
- try:
- prompt_variable(cdef, cread, cwrite, category,variable)
- except Exception, inst:
- if (str(inst) != 'BailOut'):
- raise
- else:
- print ("Unknown command >%s<" % answer)
+ 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)):
+ os.makedirs(dirname,0755)
+ if (not os.path.exists (dirname)):
+ print "Cannot create dir %s - exiting" % dirname
+ sys.exit(1)
+ else:
+ print "Created directory %s" % dirname
+
####################
def main ():
- save = True
command=sys.argv[0]
argv = sys.argv[1:]
+
+ save = True
+ # default is myplc (non -devel) unless -d is specified
+ init_flavour("boot")
+ optlist,list = getopt.getopt(argv,":dhv")
+ for opt in optlist:
+ if opt[0] == "-h":
+ usage()
+ if opt[0] == "-v":
+ print ("This is %s - %s" %(command,release_rev))
+ sys.exit(1)
+ if opt[0] == "-d":
+ init_flavour("devel")
+ argv=argv[1:]
+
if len(argv) == 0:
- (main_config,site_config,consolidated_config) = (def_main_config, def_site_config, def_consolidated_config)
+ (default_config,site_config,consolidated_config) = (def_default_config, def_site_config, def_consolidated_config)
elif len(argv) == 1:
- (main_config,site_config,consolidated_config) = (argv[1], def_site_config, def_consolidated_config)
+ (default_config,site_config,consolidated_config) = (argv[0], def_site_config, def_consolidated_config)
elif len(argv) == 2:
- (main_config, site_config,consolidated_config) = (argv[1], argv[2], def_consolidated_config)
+ (default_config, site_config,consolidated_config) = (argv[0], argv[1], def_consolidated_config)
elif len(argv) == 3:
- (main_config, site_config,consolidated_config) = argv
+ (default_config, site_config,consolidated_config) = argv
else:
usage()
+ for c in (default_config,site_config,consolidated_config):
+ check_dir (c)
+
try:
# the default settings only - read only
- cdef = PLCConfiguration(main_config)
+ cdef = PLCConfiguration(default_config)
# in effect : default settings + local settings - read only
- cread = PLCConfiguration(main_config)
+ cread = PLCConfiguration(default_config)
except:
print ("default config files not found, is myplc installed ?")
except:
cwrite = PLCConfiguration()
- print ("This is %s - %s -- Type ? at the prompt for help" %(command,release))
- mainloop (cdef, cread, cwrite,main_config, site_config, consolidated_config)
+ mainloop (cdef, cread, cwrite,default_config, site_config, consolidated_config)
return 0
if __name__ == '__main__':