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