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