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