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