doesn't crash so badly when run right after yum install
[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
106     if not changes:
107         return {}
108
109     defaults = get_defaults()
110     
111     # GENI_INTERFACE_HRN is GENI_REGISTRY_LEVEL1_AUTH, if thats blank it
112     # then defaults to GENI_REGISTRY_ROOT_AUTH 
113     # GENI_REGISTRY_LEVEL1_AUTH, so if either of these are present we must 
114     # update GENI_INTERFACE_HRN
115     if 'GENI_REGISTRY_ROOT_AUTH' in changes:
116         root_auth = changes['GENI_REGISTRY_ROOT_AUTH']
117     else:
118         root_auth = defaults['GENI_REGISTRY_ROOT_AUTH']
119              
120     if 'GENI_REGISTRY_LEVEL1_AUTH' in changes:
121         level1_auth = changes['GENI_REGISTRY_LEVEL1_AUTH']
122     else:
123         level1_auth = defaults['GENI_REGISTRY_LEVEL1_AUTH']
124                 
125     if level1_auth:
126         interface_hrn = level1_auth
127     else:
128         interface_hrn = root_auth
129     changes['GENI_INTERFACE_HRN'] = interface_hrn
130     return changes                            
131
132 def get_defaults():
133     geni_config = Config()
134     plc_vars = {'PLC_API_MAINTENANCE_PASSWORD': 'GENI_PLC_PASSWORD',
135                 'PLC_API_MAINTENANCE_USER': 'GENI_PLC_USER'
136                }
137     try:
138         from geni.util.config import plcConfig
139         plc_config = plcConfig
140     except:
141         plc_config = None
142     
143     defaults = {}
144     for var in dir(geni_config):
145         if var.startswith('GENI'):
146             value = eval("geni_config.%s" % var)
147             defaults[var] = value
148
149     # some defaults come from plc_config
150     for var in dir(plc_config):
151         if var in plc_vars:
152             value = eval("plc_config.%s" % var)
153             defaults[plc_vars[var]] = value
154
155     return defaults       
156
157 def prompt_variable(variable, default_config):
158     if variable in default_config:
159         default_value = default_config[variable]
160     else:
161         default_value = ""  
162    
163     while True:
164         prompt = "%(variable)s : [%(default_value)s] " % locals()
165         try: 
166             answer = raw_input(prompt).strip()
167         except EOFError:
168             raise Exception ('BailOut')
169         except KeyboardInterrupt:
170             print "\n"
171             raise Exception ('BailOut')
172
173         if (answer == "") or (answer == default_value):
174             return default_value
175         elif answer in ['""', "''"]:
176             return ""
177         elif (answer == "."):
178             raise Exception ('BailOut')
179         elif (answer == "?"):
180             print variable_usage.strip()
181         elif (answer == "="):
182             print ("%s defaults to %s" %(variable,default_value))
183         else:
184             return answer
185
186 def show_variable(variable, value_dict):
187     print "%s=%s" % (variable, value_dict[variable])                    
188     
189 def mainloop (default_config, config_file):
190     changes = {}
191     while True:
192         try:
193             answer = raw_input("Enter command (u for usual changes, w to save, ? for help) ").strip()
194         except EOFError:
195             answer =""
196         except KeyboardInterrupt:
197             print "\nBye"
198             sys.exit()
199
200         if (answer == "") or (answer in "?hH"):
201             print mainloop_usage
202             continue
203         if answer in ['?']:
204             print "help"  
205
206         if (answer in ["q","Q"]):
207             break
208         elif (answer == "w"):
209             save_config(changes, config_file)
210         elif (answer == "u"):
211             try: 
212                 for varname in usual_variables:
213                     changes[varname] = prompt_variable(varname, default_config)
214             except Exception, inst:
215                 if (str(inst) != 'BailOut'):
216                     raise
217         elif (answer in ["e","E"]):
218             try:
219                 prompt_variable (cdef,cread,cwrite,category,variable,
220                                  show_comments,False)
221             except Exception, inst:
222                 if (str(inst) != 'BailOut'):
223                     raise
224         elif (answer in "sS"):
225             for varname in usual_variables:
226                 show_variable (varname, default_config)
227         elif (answer in "lL"):
228             if not changes:
229                 print "No changes to display"
230             else:
231                 for varname in changes:
232                     show_variable(varname, changes)
233         else:
234             print ("Unknown command >%s< -- use h for help" % answer)
235
236     result = {}
237     result.update(default_config)
238     result.update(changes)
239     return result
240     
241 def setup_server_key(config_dict):
242     hrn = config_dict.get('GENI_INTERFACE_HRN')
243     if not hrn: return
244    
245     # Get the path to the authorities directory hierarchy
246     hierarchy = Hierarchy()
247     path = hierarchy.basedir
248     auth_path = hrn.replace(".", os.sep)
249  
250     # define some useful variables   
251     key = 'server.key'
252     cert = 'server.cert'
253     hrn_leaf = get_leaf(hrn)
254     if not hrn_leaf:
255         hrn_leaf = hrn
256     new_server_key = os.sep.join([path, auth_path, hrn_leaf]) + ".pkey"
257     old_server_key = os.sep.join([path, key])
258     old_server_cert = os.sep.join([path, cert])
259
260     # remove old key/cert
261     for fd in [old_server_key, old_server_cert]:
262         if os.path.isfile(fd):
263             os.remove(fd)
264
265     # create new server.key
266     try:
267         distutils.file_util.copy_file(src=new_server_key, dst=old_server_key, verbose=1)
268         print "\t\t%(old_server_key)s\ncopied from\t%(new_server_key)s" % locals()
269     # this is expected when running geni-config-tty for the first time (before gimport.py)
270     except:
271         print "Could not create %(old_server_key)s - ignore if you haven't run gimport yet"%locals()
272     
273     
274
275 ####################
276 def main ():
277
278     command=sys.argv[0]
279     argv = sys.argv[1:]
280     save = True
281     parser = OptionParser(usage=command_usage, version="%prog 1.0")
282     parser.set_defaults(config_dir="/etc/geni",
283                         usual_variables=[])
284     parser.add_option("","--configdir",dest="config_dir",action="append", help="specify configuration directory")
285     parser.add_option("","--usual_variable",dest="usual_variables",action="append", help="add a usual variable")
286     parser.add_option("-d", "--default", action="count", help="dont prompt for values, just use defaults")
287     (config,args) = parser.parse_args()
288     if len(args)>3:
289         parser.error("too many arguments")
290
291     config_dir = parser.values.config_dir
292     config_file = os.sep.join([config_dir, 'geni_config'])
293     defaults = get_defaults()
294     # if -d is specified dont prompt, just configure with defaults
295     if '-d' in argv:
296         save_config(defaults, config_file)
297         results = defaults
298     else:        
299         results = mainloop (defaults, config_file)
300     setup_server_key(results)
301     return 0
302
303 if __name__ == '__main__':
304     main()