rename as this is a different document than the original sfa
[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     cfile.close()
76     newlines = []
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     print 'updated config file',config_file
98
99 def validate(changes):
100     defaults = get_defaults()
101     
102     if not changes:
103         return {}
104
105     # GENI_INTERFACE_HRN is GENI_REGISTRY_LEVEL1_AUTH, if thats blank it
106     # then defaults to GENI_REGISTRY_ROOT_AUTH 
107     # GENI_REGISTRY_LEVEL1_AUTH, so if either of these are present we must 
108     # update GENI_INTERFACE_HRN
109     if 'GENI_REGISTRY_ROOT_AUTH' in changes:
110         root_auth = changes['GENI_REGISTRY_ROOT_AUTH']
111     else:
112         root_auth = defaults['GENI_REGISTRY_ROOT_AUTH']
113              
114     if 'GENI_REGISTRY_LEVEL1_AUTH' in changes:
115         level1_auth = changes['GENI_REGISTRY_LEVEL1_AUTH']
116     else:
117         level1_auth = defaults['GENI_REGISTRY_LEVEL1_AUTH']
118                 
119     if level1_auth:
120         interface_hrn = level1_auth
121     else:
122         interface_hrn = root_auth
123     changes['GENI_INTERFACE_HRN'] = interface_hrn
124     return changes                            
125
126 def get_defaults():
127     geni_config = Config()
128     plc_vars = {'PLC_API_MAINTENANCE_PASSWORD': 'GENI_PLC_PASSWORD',
129                 'PLC_API_MAINTENANCE_USER': 'GENI_PLC_USER'
130                }
131     try:
132         from geni.util.config import plcConfig
133         plc_config = plcConfig
134     except:
135         plc_config = None
136     
137     defaults = {}
138     for var in dir(geni_config):
139         if var.startswith('GENI'):
140             value = eval("geni_config.%s" % var)
141             defaults[var] = value
142
143     # some defaults come from plc_config
144     for var in dir(plc_config):
145         if var in plc_vars:
146             value = eval("plc_config.%s" % var)
147             defaults[plc_vars[var]] = value
148
149     return defaults       
150
151 def prompt_variable(variable, default_config):
152     if variable in default_config:
153         default_value = default_config[variable]
154     else:
155         default_value = ""  
156    
157     while True:
158         prompt = "%(variable)s : [%(default_value)s] " % locals()
159         try: 
160             answer = raw_input(prompt).strip()
161         except EOFError:
162             raise Exception ('BailOut')
163         except KeyboardInterrupt:
164             print "\n"
165             raise Excception ('BailOut')
166
167         if (answer == "") or (answer == default_value):
168             return default_value
169         elif answer in ['""', "''"]:
170             return ""
171         elif (answer == "."):
172             raise Exception ('BailOut')
173         elif (answer == "?"):
174             print variable_usage.strip()
175         elif (answer == "="):
176             print ("%s defaults to %s" %(variable,default_value))
177         else:
178             return answer
179
180 def show_variable(variable, value_dict):
181     print "%s=%s" % (variable, value_dict[variable])                    
182     
183 def mainloop (default_config, config_file):
184     changes = {}
185     while True:
186         try:
187             answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip()
188         except EOFError:
189             answer =""
190         except KeyboardInterrupt:
191             print "\nBye"
192             sys.exit()
193
194         if (answer == "") or (answer in "?hH"):
195             print mainloop_usage
196             continue
197         if answer in ['?']:
198             print "help"  
199
200         if (answer in ["q","Q"]):
201             break
202         elif (answer == "w"):
203             save_config(changes, config_file)
204         elif (answer == "u"):
205             try: 
206                 for varname in usual_variables:
207                     changes[varname] = prompt_variable(varname, default_config)
208             except Exception, inst:
209                 if (str(inst) != 'BailOut'):
210                     raise
211         elif (answer in ["e","E"]):
212             try:
213                 prompt_variable (cdef,cread,cwrite,category,variable,
214                                  show_comments,False)
215             except Exception, inst:
216                 if (str(inst) != 'BailOut'):
217                     raise
218         elif (answer in "sS"):
219             for varname in usual_variables:
220                 show_variable (varname, default_config)
221         elif (answer in "lL"):
222             if not changes:
223                 print "No changes to display"
224             else:
225                 for varname in changes:
226                     show_variable(varname, changes)
227         else:
228             print ("Unknown command >%s< -- use h for help" % answer)
229
230     result = {}
231     result.update(default_config)
232     result.update(changes)
233     return result
234     
235 def setup_server_key(config_dict):
236     hrn = config_dict.get('GENI_INTERFACE_HRN')
237     if not hrn: return
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 "\t\t%(old_server_key)s\ncopied from\t%(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()