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