- MyPLC 0.4 RC2
[myplc.git] / plc-config-tty
1 #!/usr/bin/python
2
3 # Interactively prompts for variable values
4 # expected arguments are
5 # command [default-xml [custom-xml]]
6 #
7 # Two-steps logic:
8 # (1) scans all variables (todo: pass categories as arguments)
9 #     and prompts for value
10 #     current value proposed as default
11 #     also allows to remove site-dependent setting
12 # (2) epilogue : allows to
13 #     list the site-dependent vars with values
14 #     and to locally (re-)edit a variable from its shell name
15 #     quit with or without saving
16
17 import sys
18 import os
19 import re
20 import readline
21
22 from plc_config import PLCConfiguration
23
24 ####################
25 release = "$Id"
26
27 def_main_config = "/etc/planetlab/default_config.xml"
28 def_site_config = "/etc/planetlab/configs/site.xml"
29 def_consolidated_config = "/etc/planetlab/plc_config.xml"
30
31 command_usage="""Usage: %s [default-xml [site-xml [consolidated-xml]]]
32 \t default-xml defaults to %s
33 \t site-xml defaults to %s
34 \t consolidated-xml defaults to %s
35 """ % (sys.argv[0],def_main_config,def_site_config, def_consolidated_config)
36
37 ####################
38 variable_usage= """Special answers :
39 #\tShow variable comments
40 .\tStops prompting, return to mainloop
41 /\tCleans any site-defined value, reverts to default
42 =\tShows default value
43 >\tSkips to next category
44 ?\tThis help
45 """
46
47 def usage ():
48     print(command_usage)
49     sys.exit(1)
50
51 ####################
52 def get_value (config,  category_id, variable_id):
53     (category, variable) = config.get (category_id, variable_id)
54     return variable['value']
55
56 # refrain from using plc_config's _sanitize 
57 def get_varname (config,  category_id, variable_id):
58     (category, variable) = config.get (category_id, variable_id)
59     return (category_id+"_"+variable['id']).upper()
60
61 def prompt_variable (cdef, cread, cwrite, category, variable):
62
63     assert category.has_key('id')
64     assert variable.has_key('id')
65
66     category_id = category ['id']
67     variable_id = variable['id']
68
69     while True:
70         default_value = get_value(cdef,category_id,variable_id)
71         current_value = get_value(cread,category_id, variable_id)
72         varname = get_varname (cread,category_id, variable_id)
73         
74         prompt = "== %s : [%s] " % (varname,current_value)
75         try:
76             answer = raw_input(prompt).strip()
77         except EOFError :
78             raise Exception ('BailOut')
79
80         # no change
81         if (answer == "") or (answer == current_value):
82             return None
83         elif (answer == "."):
84             raise Exception ('BailOut')
85         elif (answer == ">"):
86             raise Exception ('NextCategory')
87         elif (answer == "#"):
88             if friendly_name is not None:
89                 print ("### " + friendly_name)
90             if comments == None:
91                 print ("!!! No comment associated to %s" % varname)
92             else:
93                 for line in comments:
94                     print ("# " + line)
95         elif (answer == "?"):
96             print variable_usage.strip()
97         elif (answer == "="):
98             print ("%s defaults to %s" %(varname,default_value))
99         # revert to default : remove from cwrite (i.e. site-config)
100         elif (answer == "/"):
101             cwrite.delete(category_id,variable_id)
102             print ("%s reverted to %s" %(varname,default_value))
103             return
104         else:
105             variable['value'] = answer
106             cwrite.set(category,variable)
107             return
108
109 ####################
110 def prompt_all_variables (cdef, cread, cwrite):
111     try:
112         for (category_id, (category, variables)) in cread.variables().iteritems():
113             print ("========== Category = %s" % category_id)
114             for variable in variables.values():
115                 try:
116                     newvar = prompt_variable (cdef, cread, cwrite, category, variable)
117                 except Exception, inst:
118                     if (str(inst) == 'NextCategory'): break
119                     else: raise
120                     
121     except Exception, inst:
122         if (str(inst) == 'BailOut'): return
123         else: raise
124
125
126 ####################
127 def consolidate (main_config, site_config, consolidated_config):
128     try:
129         conso = PLCConfiguration (main_config)
130         conso.load (site_config)
131         conso.save (consolidated_config)
132     except Exception, inst:
133         print "Could not consolidate, %s" % (str(inst))
134         return
135     print ("Merged\n\t%s\nand\t%s\ninto\t%s"%(main_config,site_config,consolidated_config))
136         
137 ####################
138 def restart_plc ():
139     print ("==================== Stopping plc")
140     os.system("service plc stop")
141     print ("==================== Starting plc")
142     os.system("service plc start")
143
144 ####################
145 mainloop_usage= """Available commands
146 c\tEdits commonly tuned variables
147 e\tEdits all variables
148 p\tPrints all locally-customized vars and values
149 e <var>\tPrompts (edit) fro variable <var>
150 p <var>\tShows current setting for <var>
151 l\tlists all known variables
152 w\tsaves & consolidates
153 r\trestarts plc service
154 q\tQuits without saving
155 ---
156 Typical usage involves: c, [p,] w, r
157 """
158
159 re_mainloop_var="^(?P<command>[pe])[ \t]+(?P<varname>\w+)$"
160 matcher_mainloop_var=re.compile(re_mainloop_var)
161
162 common_variables=("PLC_NAME",
163                   "PLC_ROOT_USER",
164                   "PLC_ROOT_PASSWORD",
165                   "PLC_MAIL_SUPPORT_ADDRESS",
166                   "PLC_DB_HOST",
167                   "PLC_API_HOST",
168                   "PLC_WWW_HOST",
169                   "PLC_BOOT_HOST",
170                   "PLC_NET_DNS1",
171                   "PLC_NET_DNS2")
172
173 def mainloop (cdef, cread, cwrite,main_config, site_config, consolidated_config):
174     while True:
175         try:
176             answer = raw_input("Enter command (c for usual changes, w to save, ? for help) ").strip()
177         except EOFError:
178             answer =""
179         answer=answer.lower()
180         if (answer == "") or (answer == "?") or (answer == "h"):
181             print mainloop_usage
182         elif (answer == "q"):
183             # todo check confirmation
184             return
185         elif (answer == "e"):
186             prompt_all_variables(cdef, cread, cwrite)
187         elif (answer == "w"):
188             try:
189                 cwrite.save(site_config)
190             except:
191                 print ("Could not save -- fix write access on %s" % site_config)
192                 break
193             print ("Wrote %s" % site_config)
194             consolidate(main_config, site_config, consolidated_config)
195             print ("You might want to type 'r' (restart plc) or 'q' (quit)")
196         elif (answer == "l"):
197             print ("Config involves the following variables")
198             sys.stdout.write(cread.output_variables())
199         elif (answer == "p"):
200             print ("Current site config")
201             sys.stdout.write(cwrite.output_shell(False))
202         elif (answer == "c"):
203             try:
204                 for varname in common_variables:
205                     (category,variable) = cdef.locate_varname(varname)
206                     prompt_variable(cdef, cread, cwrite, category, variable)
207             except Exception, inst:
208                 if (str(inst) != 'BailOut'):
209                     raise
210         elif (answer == "r"):
211             restart_plc()
212         else:
213             groups_var = matcher_mainloop_var.match(answer)
214             if (groups_var):
215                 command = groups_var.group('command')
216                 varname = groups_var.group('varname')
217                 (category,variable) = cdef.locate_varname(varname)
218                 if not category:
219                     print "Unknown variable %s" % varname
220                 elif (command == 'p'):
221                     print ("%s = %s" % (varname,get_value(cwrite,
222                                                           category['id'],
223                                                           variable['id'])))
224                 else:
225                     try:
226                         prompt_variable(cdef, cread, cwrite, category,variable)
227                     except Exception, inst:
228                         if (str(inst) != 'BailOut'):
229                             raise
230             else:
231                 print ("Unknown command >%s<" % answer)
232
233 ####################
234 def main ():
235
236     save = True
237     command=sys.argv[0]
238     argv = sys.argv[1:]
239     if len(argv) == 0:
240         (main_config,site_config,consolidated_config) = (def_main_config, def_site_config, def_consolidated_config)
241     elif len(argv) == 1:
242         (main_config,site_config,consolidated_config) = (argv[1], def_site_config, def_consolidated_config)
243     elif len(argv) == 2:
244         (main_config, site_config,consolidated_config)  = (argv[1], argv[2], def_consolidated_config)
245     elif len(argv) == 3:
246         (main_config, site_config,consolidated_config)  = argv
247     else:
248         usage()
249
250     try:
251         # the default settings only - read only
252         cdef = PLCConfiguration(main_config)
253
254         # in effect : default settings + local settings - read only
255         cread = PLCConfiguration(main_config)
256
257     except:
258         print ("default config files not found, is myplc installed ?")
259         return 1
260
261     # local settings only, will be modified & saved
262     cwrite=PLCConfiguration()
263     
264     try:
265         cread.load(site_config)
266         cwrite.load(site_config)
267     except:
268         cwrite = PLCConfiguration()
269
270         print ("This is %s - %s -- Type ? at the prompt for help" %(command,release))
271     mainloop (cdef, cread, cwrite,main_config, site_config, consolidated_config)
272     return 0
273
274 if __name__ == '__main__':
275     main()