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