bunch of cleanups & fixes all over the place
[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   = ["SFA_REGISTRY_ROOT_AUTH",
28                    "SFA_REGISTRY_LEVEL1_AUTH",
29                    "SFA_REGISTRY_ENABLED",
30                    "SFA_REGISTRY_HOST", 
31                    "SFA_REGISTRY_PORT",
32                    "SFA_AGGREGATE_ENABLED",
33                    "SFA_AGGREGATE_HOST",
34                    "SFA_AGGREGATE_PORT",
35                    "SFA_SM_ENABLED",
36                    "SFA_SM_HOST",
37                    "SFA_SM_PORT",
38                    "SFA_PLC_USER",
39                    "SFA_PLC_PASSWORD",    
40                    "SFA_PLC_URL",
41                    "SFA_PLC_DB_NAME",
42                    "SFA_PLC_DB_HOST",
43                    "SFA_PLC_DB_PORT",
44                    "SFA_PLC_DB_USER",
45                    "SFA_PLC_DB_PASSWORD",
46                    ]
47 usual_variables = ["SFA_REGISTRY_ROOT_AUTH",
48                    "SFA_REGISTRY_LEVEL1_AUTH",
49                    "SFA_PLC_USER",
50                    "SFA_PLC_PASSWORD",
51                    "SFA_PLC_DB_HOST",
52                    "SFA_PLC_DB_USER",
53                    "SFA_PLC_DB_PASSWORD",
54                    ]
55
56
57 mainloop_usage= """Available commands:
58  u/U\t\t\tEdit usual variables
59  w/W\t\t\tWrite / Write & reload
60  q\t\t\tQuit (without saving)
61  h/?\t\t\tThis help
62 ---
63  l/L [<var>]\tShow Locally modified variables/values
64  s/S [<var>]\tShow all current variables/values 
65  e/E [<var>]\tEdit variables (all, in category, single)
66 ---
67 """ 
68
69 command_usage="%prog [options]"
70 command_usage += """
71   Unless you specify the -d option, meaning you want to configure
72   using defaults without interactive prompts""" 
73
74 variable_usage= """Edit Commands :
75 .\tStops prompting, return to mainloop
76 =\tShows default value
77 ?\tThis help    
78 """
79
80 def save_config(changes, config_file):
81     # always validate before saving
82     changes = validate(changes) 
83     
84     cfile = open(config_file, 'r')
85     lines = cfile.readlines()
86     cfile.close()
87     newlines = []
88     for line in lines:
89         added = False
90         for variable in changes:
91             if line.startswith(variable+'='):
92                 try:
93                     value = int(changes[variable])
94                     newline = '%s=%s\n' % (variable, value)
95                     newlines.append(newline)
96                 except:
97                     value = changes[variable]
98                     newline = '%s="%s"\n' % (variable, value)
99                     newlines.append(newline)
100                 added = True
101                 break
102         if not added:
103             newlines.append(line) 
104     
105     cfile = open(config_file, 'w')
106     cfile.writelines(newlines)
107     cfile.close()
108     print 'updated config file',config_file
109
110 def validate(changes):
111
112     if not changes:
113         return {}
114
115     defaults = get_defaults()
116     
117     # SFA_INTERFACE_HRN is SFA_REGISTRY_LEVEL1_AUTH, if thats blank it
118     # then defaults to SFA_REGISTRY_ROOT_AUTH 
119     # SFA_REGISTRY_LEVEL1_AUTH, so if either of these are present we must 
120     # update SFA_INTERFACE_HRN
121     if 'SFA_REGISTRY_ROOT_AUTH' in changes:
122         root_auth = changes['SFA_REGISTRY_ROOT_AUTH']
123     else:
124         root_auth = defaults['SFA_REGISTRY_ROOT_AUTH']
125              
126     if 'SFA_REGISTRY_LEVEL1_AUTH' in changes:
127         level1_auth = changes['SFA_REGISTRY_LEVEL1_AUTH']
128     else:
129         level1_auth = defaults['SFA_REGISTRY_LEVEL1_AUTH']
130                 
131     if level1_auth:
132         interface_hrn = level1_auth
133     else:
134         interface_hrn = root_auth
135     changes['SFA_INTERFACE_HRN'] = interface_hrn
136     return changes                            
137
138 def get_defaults():
139     sfa_config = Config()
140     
141     defaults = {}
142     for var in dir(sfa_config):
143         if var.startswith('SFA'):
144             value = eval("sfa_config.%s" % var)
145             defaults[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 Exception ('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             break
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                 for varname in all_variables:
212                     changes[varname] = prompt_variable(varname, default_config)
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(default_config)
230     result.update(changes)
231     return result
232     
233 def setup_server_key(config_dict):
234     hrn = config_dict.get('SFA_INTERFACE_HRN')
235     if not hrn: return
236    
237     # Get the path to the authorities directory hierarchy
238     hierarchy = Hierarchy()
239     path = hierarchy.basedir
240     auth_path = hrn.replace(".", os.sep)
241  
242     # define some useful variables   
243     key = 'server.key'
244     cert = 'server.cert'
245     hrn_leaf = get_leaf(hrn)
246     if not hrn_leaf:
247         hrn_leaf = hrn
248     new_server_key = os.sep.join([path, auth_path, hrn_leaf]) + ".pkey"
249     old_server_key = os.sep.join([path, key])
250     old_server_cert = os.sep.join([path, cert])
251
252     # remove old key/cert
253     for fd in [old_server_key, old_server_cert]:
254         if os.path.isfile(fd):
255             os.remove(fd)
256
257     # create new server.key
258     try:
259         distutils.file_util.copy_file(src=new_server_key, dst=old_server_key, verbose=1)
260         print "\t\t%(old_server_key)s\ncopied from\t%(new_server_key)s" % locals()
261     # this is expected when running this tool for the first time (before sfa-import-plc.py)
262     except:
263         print "Could not create %(old_server_key)s - ignore if you haven't run sfa-import-plc.py yet"%locals()
264     
265     
266
267 ####################
268 def main ():
269
270     command=sys.argv[0]
271     argv = sys.argv[1:]
272     save = True
273     parser = OptionParser(usage=command_usage, version="%prog 1.0")
274     parser.set_defaults(config_dir="/etc/sfa",
275                         usual_variables=[])
276     parser.add_option("","--configdir",dest="config_dir",action="append", help="specify configuration directory")
277     parser.add_option("","--usual_variable",dest="usual_variables",action="append", help="add a usual variable")
278     parser.add_option("-d", "--default", action="count", help="dont prompt for values, just use defaults")
279     (config,args) = parser.parse_args()
280     if len(args)>3:
281         parser.error("too many arguments")
282
283     config_dir = parser.values.config_dir
284     config_file = os.sep.join([config_dir, 'sfa_config'])
285     defaults = get_defaults()
286     # if -d is specified dont prompt, just configure with defaults
287     if '-d' in argv:
288         save_config(defaults, config_file)
289         results = defaults
290     else:        
291         results = mainloop (defaults, config_file)
292     setup_server_key(results)
293     return 0
294
295 if __name__ == '__main__':
296     main()