add more usual settings
[sfa.git] / geni-config-tty
1 #!/usr/bin/python
2
3 # Interactively prompts for variable values
4 # expected arguments are
5 # command -d [default-xml [custom-xml [ consolidated-xml ]]]
6 #
7 # -d is for the myplc-devel package
8
9 # we use 3 instances of PLCConfiguration throughout:
10 # cdef : models the defaults, from plc_default.xml
11 # cread : merged from plc_default & configs/site.xml
12 # cwrite : site.xml + pending changes
13
14 import sys
15 import os
16 import re
17 import readline
18 import traceback
19 import distutils.file_util
20 from optparse import OptionParser
21
22 from geni.util.config import Config
23 from geni.util.hierarchy import *
24 from geni.util.misc import *
25
26
27 all_variables   = ["GENI_REGISTRY_ROOT_AUTH",
28                    "GENI_REGISTRY_LEVEL1_AUTH",
29                    "GENI_REGISTRY_ENABLED",
30                    "GENI_REGISTRY_HOST", 
31                    "GENI_REGISTRY_PORT",
32                    "GENI_AGGREGATE_ENABLED",
33                    "GENI_AGGREGATE_HOST",
34                    "GENI_AGGREGATE_PORT",
35                    "GENI_SM_ENABLED",
36                    "GENI_SM_HOST",
37                    "GENI_SM_PORT",
38                    "GENI_PLC_USER",
39                    "GENI_PLC_PASSWORD",    
40                    "GENI_PLC_HOST",
41                    "GENI_PLC_PORT",
42                    "GENI_PLC_API_PATH"
43                    ]
44 usual_variables = ["GENI_REGISTRY_ROOT_AUTH",
45                    "GENI_REGISTRY_LEVEL1_AUTH",
46                    "GENI_PLC_USER",
47                    "GENI_PLC_PASSWORD",    
48                    ]
49
50
51 mainloop_usage= """Available commands:
52  u/U\t\t\tEdit usual variables
53  w/W\t\t\tWrite / Write & reload
54  q\t\t\tQuit (without saving)
55  h/?\t\t\tThis help
56 ---
57  l/L [<var>]\tShow Locally modified variables/values
58  s/S [<var>]\tShow all current variables/values 
59  e/E [<var>]\tEdit variables (all, in category, single)
60 ---
61 """ 
62
63 command_usage="%prog [options]"
64 command_usage += """
65   Unless you specify the -d option, meaning you want to configure
66   using defaults without interactive prompts""" 
67
68 variable_usage= """Edit Commands :
69 .\tStops prompting, return to mainloop
70 =\tShows default value
71 ?\tThis help    
72 """
73
74 def save_config(changes, config_file):
75     # always validate before saving
76     changes = validate(changes) 
77     
78     cfile = open(config_file, 'r')
79     lines = cfile.readlines()
80     cfile.close()
81     newlines = []
82     for line in lines:
83         added = False
84         for variable in changes:
85             if line.startswith(variable+'='):
86                 try:
87                     value = int(changes[variable])
88                     newline = '%s=%s\n' % (variable, value)
89                     newlines.append(newline)
90                 except:
91                     value = changes[variable]
92                     newline = '%s="%s"\n' % (variable, value)
93                     newlines.append(newline)
94                 added = True
95                 break
96         if not added:
97             newlines.append(line) 
98     
99     cfile = open(config_file, 'w')
100     cfile.writelines(newlines)
101     cfile.close()
102     print 'updated config file',config_file
103
104 def validate(changes):
105     defaults = get_defaults()
106     
107     if not changes:
108         return {}
109
110     # GENI_INTERFACE_HRN is GENI_REGISTRY_LEVEL1_AUTH, if thats blank it
111     # then defaults to GENI_REGISTRY_ROOT_AUTH 
112     # GENI_REGISTRY_LEVEL1_AUTH, so if either of these are present we must 
113     # update GENI_INTERFACE_HRN
114     if 'GENI_REGISTRY_ROOT_AUTH' in changes:
115         root_auth = changes['GENI_REGISTRY_ROOT_AUTH']
116     else:
117         root_auth = defaults['GENI_REGISTRY_ROOT_AUTH']
118              
119     if 'GENI_REGISTRY_LEVEL1_AUTH' in changes:
120         level1_auth = changes['GENI_REGISTRY_LEVEL1_AUTH']
121     else:
122         level1_auth = defaults['GENI_REGISTRY_LEVEL1_AUTH']
123                 
124     if level1_auth:
125         interface_hrn = level1_auth
126     else:
127         interface_hrn = root_auth
128     changes['GENI_INTERFACE_HRN'] = interface_hrn
129     return changes                            
130
131 def get_defaults():
132     geni_config = Config()
133     plc_vars = {'PLC_API_MAINTENANCE_PASSWORD': 'GENI_PLC_PASSWORD',
134                 'PLC_API_MAINTENANCE_USER': 'GENI_PLC_USER'
135                }
136     try:
137         from geni.util.config import plcConfig
138         plc_config = plcConfig
139     except:
140         plc_config = None
141     
142     defaults = {}
143     for var in dir(geni_config):
144         if var.startswith('GENI'):
145             value = eval("geni_config.%s" % var)
146             defaults[var] = value
147
148     # some defaults come from plc_config
149     for var in dir(plc_config):
150         if var in plc_vars:
151             value = eval("plc_config.%s" % var)
152             defaults[plc_vars[var]] = value
153
154     return defaults       
155
156 def prompt_variable(variable, default_config):
157     if variable in default_config:
158         default_value = default_config[variable]
159     else:
160         default_value = ""  
161    
162     while True:
163         prompt = "%(variable)s : [%(default_value)s] " % locals()
164         try: 
165             answer = raw_input(prompt).strip()
166         except EOFError:
167             raise Exception ('BailOut')
168         except KeyboardInterrupt:
169             print "\n"
170             raise Excception ('BailOut')
171
172         if (answer == "") or (answer == default_value):
173             return default_value
174         elif answer in ['""', "''"]:
175             return ""
176         elif (answer == "."):
177             raise Exception ('BailOut')
178         elif (answer == "?"):
179             print variable_usage.strip()
180         elif (answer == "="):
181             print ("%s defaults to %s" %(variable,default_value))
182         else:
183             return answer
184
185 def show_variable(variable, value_dict):
186     print "%s=%s" % (variable, value_dict[variable])                    
187     
188 def mainloop (default_config, config_file):
189     changes = {}
190     while True:
191         try:
192             answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip()
193         except EOFError:
194             answer =""
195         except KeyboardInterrupt:
196             print "\nBye"
197             sys.exit()
198
199         if (answer == "") or (answer in "?hH"):
200             print mainloop_usage
201             continue
202         if answer in ['?']:
203             print "help"  
204
205         if (answer in ["q","Q"]):
206             break
207         elif (answer == "w"):
208             save_config(changes, config_file)
209         elif (answer == "u"):
210             try: 
211                 for varname in usual_variables:
212                     changes[varname] = prompt_variable(varname, default_config)
213             except Exception, inst:
214                 if (str(inst) != 'BailOut'):
215                     raise
216         elif (answer in ["e","E"]):
217             try:
218                 prompt_variable (cdef,cread,cwrite,category,variable,
219                                  show_comments,False)
220             except Exception, inst:
221                 if (str(inst) != 'BailOut'):
222                     raise
223         elif (answer in "sS"):
224             for varname in usual_variables:
225                 show_variable (varname, default_config)
226         elif (answer in "lL"):
227             if not changes:
228                 print "No changes to display"
229             else:
230                 for varname in changes:
231                     show_variable(varname, changes)
232         else:
233             print ("Unknown command >%s< -- use h for help" % answer)
234
235     result = {}
236     result.update(default_config)
237     result.update(changes)
238     return result
239     
240 def setup_server_key(config_dict):
241     hrn = config_dict.get('GENI_INTERFACE_HRN')
242     if not hrn: return
243    
244     # Get the path to the authorities directory hierarchy
245     hierarchy = Hierarchy()
246     path = hierarchy.basedir
247     auth_path = hrn.replace(".", os.sep)
248  
249     # define some useful variables   
250     key = 'server.key'
251     cert = 'server.cert'
252     hrn_leaf = get_leaf(hrn)
253     if not hrn_leaf:
254         hrn_leaf = hrn
255     new_server_key = os.sep.join([path, auth_path, hrn_leaf]) + ".pkey"
256     old_server_key = os.sep.join([path, key])
257     old_server_cert = os.sep.join([path, cert])
258
259     # remove old key/cert
260     for fd in [old_server_key, old_server_cert]:
261         if os.path.isfile(fd):
262             os.remove(fd)
263
264     # create new server.key
265     distutils.file_util.copy_file(src=new_server_key, dst=old_server_key, verbose=1)
266     print "\t\t%(old_server_key)s\ncopied from\t%(new_server_key)s" % locals()
267     
268     
269
270 ####################
271 def main ():
272
273     command=sys.argv[0]
274     argv = sys.argv[1:]
275     save = True
276     parser = OptionParser(usage=command_usage, version="%prog 1.0")
277     parser.set_defaults(config_dir="/etc/geni",
278                         usual_variables=[])
279     parser.add_option("","--configdir",dest="config_dir",action="append", help="specify configuration directory")
280     parser.add_option("","--usual_variable",dest="usual_variables",action="append", help="add a usual variable")
281     parser.add_option("-d", "--default", action="count", help="dont prompt for values, just use defaults")
282     (config,args) = parser.parse_args()
283     if len(args)>3:
284         parser.error("too many arguments")
285
286     config_dir = parser.values.config_dir
287     config_file = os.sep.join([config_dir, 'geni_config'])
288     defaults = get_defaults()
289     # if -d is specified dont prompt, just configure with defaults
290     if '-d' in argv:
291         save_config(defaults, config_file)
292         results = defaults
293     else:        
294         results = mainloop (defaults, config_file)
295     setup_server_key(results)
296     return 0
297
298 if __name__ == '__main__':
299     main()