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