|
@@ -15,7 +15,9 @@ import sys
|
15
|
15
|
import shutil
|
16
|
16
|
import argparse
|
17
|
17
|
import logging
|
|
18
|
+import re
|
18
|
19
|
import json
|
|
20
|
+import configparser
|
19
|
21
|
|
20
|
22
|
logging.basicConfig(level=logging.INFO)
|
21
|
23
|
|
|
@@ -48,6 +50,40 @@ def run_make(target, names):
|
48
|
50
|
os.chdir(cwd)
|
49
|
51
|
|
50
|
52
|
|
|
53
|
+##@brief Set configuration given args
|
|
54
|
+#@param args as returned by argparse
|
|
55
|
+def set_conf(name, args):
|
|
56
|
+ validate_names([name])
|
|
57
|
+ conffile = get_conffile(name)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+ config = configparser.ConfigParser(interpolation=None)
|
|
61
|
+ config.read(conffile)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+ if args.interface is not None:
|
|
65
|
+ if args.interface not in ('web', 'python'):
|
|
66
|
+ raise TypeError("Interface can only be on of : 'web', 'python'")
|
|
67
|
+ config['lodel2']['interface'] = args.interface
|
|
68
|
+ interface = config['lodel2']['interface']
|
|
69
|
+ if interface == 'web':
|
|
70
|
+ if 'lodel.webui' not in config:
|
|
71
|
+ config['lodel.webui'] = dict()
|
|
72
|
+ config['lodel.webui']['standalone'] = 'True'
|
|
73
|
+ if args.listen_port is not None:
|
|
74
|
+ config['lodel.webui']['listen_port'] = str(args.listen_port)
|
|
75
|
+ if args.listen_address is not None:
|
|
76
|
+ config['lodel.webui']['listen_address'] = str(args.listen_address)
|
|
77
|
+ else: #interface is python
|
|
78
|
+ if args.listen_port is not None or args.listen_address is not None:
|
|
79
|
+ logging.error("Listen port and listen address will not being set. \
|
|
80
|
+Selected interface is not the web iterface")
|
|
81
|
+ if 'lodel.webui' in config:
|
|
82
|
+ del(config['lodel.webui'])
|
|
83
|
+ #Now config should be OK to be written again in conffile
|
|
84
|
+ with open(conffile, 'w+') as cfp:
|
|
85
|
+ config.write(cfp)
|
|
86
|
+
|
51
|
87
|
##@brief If the name is not valid raise
|
52
|
88
|
def name_is_valid(name):
|
53
|
89
|
allowed_chars = [chr(i) for i in range(ord('a'), ord('z')+1)]
|
|
@@ -138,15 +174,29 @@ def get_conffile(name):
|
138
|
174
|
return os.path.join(store_datas[name]['path'], CONFFILE)
|
139
|
175
|
|
140
|
176
|
##@brief Print the list of instances and exit
|
141
|
|
-def list_instances(verbosity):
|
|
177
|
+#@param verbosity int
|
|
178
|
+#@param batch bool : if true make simple output
|
|
179
|
+def list_instances(verbosity, batch):
|
142
|
180
|
verbosity = 0 if verbosity is None else verbosity
|
143
|
181
|
if not os.path.isfile(STORE_FILE):
|
144
|
182
|
print("No store file, no instances are existing. Exiting...",
|
145
|
183
|
file=sys.stderr)
|
146
|
184
|
exit(0)
|
147
|
185
|
store_datas = get_store_datas()
|
148
|
|
- print('Instances list :')
|
|
186
|
+ if not batch:
|
|
187
|
+ print('Instances list :')
|
149
|
188
|
for name in store_datas:
|
|
189
|
+ details_instance(name, verbosity, batch)
|
|
190
|
+ exit(0)
|
|
191
|
+
|
|
192
|
+##@brief Print instance informations and return (None)
|
|
193
|
+#@param name str : instance name
|
|
194
|
+#@param verbosity int
|
|
195
|
+#@param batch bool : if true make simple output
|
|
196
|
+def details_instance(name, verbosity, batch):
|
|
197
|
+ validate_names([name])
|
|
198
|
+ store_datas = get_store_datas()
|
|
199
|
+ if not batch:
|
150
|
200
|
msg = "\t- '%s'" % name
|
151
|
201
|
if verbosity > 0:
|
152
|
202
|
msg += ' path = "%s"' % store_datas[name]['path']
|
|
@@ -159,19 +209,35 @@ def list_instances(verbosity):
|
159
|
209
|
msg += "\t\t=========================\n"
|
160
|
210
|
|
161
|
211
|
print(msg)
|
162
|
|
- exit(0)
|
163
|
|
-
|
|
212
|
+ else:
|
|
213
|
+ msg = name
|
|
214
|
+ if verbosity > 0:
|
|
215
|
+ msg += "\t"+'"%s"' % store_datas[name]['path']
|
|
216
|
+ if verbosity > 1:
|
|
217
|
+ conffile = get_conffile(name)
|
|
218
|
+ msg += "\n\t#####"+conffile+"#####\n"
|
|
219
|
+ with open(conffile, 'r') as cfp:
|
|
220
|
+ for line in cfp:
|
|
221
|
+ msg += "\t"+line
|
|
222
|
+ msg += "\n\t###########"
|
|
223
|
+ print(msg)
|
|
224
|
+
|
164
|
225
|
##@brief Returns instanciated parser
|
165
|
226
|
def get_parser():
|
166
|
227
|
parser = argparse.ArgumentParser(
|
167
|
228
|
description='SLIM (Simple Lodel Instance Manager.)')
|
168
|
229
|
selector = parser.add_argument_group('Instances selectors')
|
169
|
230
|
actions = parser.add_argument_group('Instances actions')
|
|
231
|
+ confs = parser.add_argument_group('Options (use with -c or -s)')
|
|
232
|
+
|
170
|
233
|
parser.add_argument('-l', '--list',
|
171
|
234
|
help='list existing instances and exit', action='store_const',
|
172
|
235
|
const=True, default=False)
|
173
|
236
|
parser.add_argument('-v', '--verbose', action='count')
|
174
|
|
-
|
|
237
|
+ parser.add_argument('-b', '--batch', action='store_const',
|
|
238
|
+ default=False, const=True,
|
|
239
|
+ help="Format output (when possible) making it usable by POSIX scripts \
|
|
240
|
+(only implemented for -l for the moment)")
|
175
|
241
|
selector.add_argument('-a', '--all', action='store_const',
|
176
|
242
|
default=False, const=True,
|
177
|
243
|
help='Select all instances')
|
|
@@ -184,6 +250,9 @@ def get_parser():
|
184
|
250
|
actions.add_argument('-d', '--delete', action='store_const',
|
185
|
251
|
default=False, const=True,
|
186
|
252
|
help="Delete an instance with given name (see -n --name)")
|
|
253
|
+ actions.add_argument('-s', '--set-option', action='store_const',
|
|
254
|
+ default=False, const=True,
|
|
255
|
+ help="Use this flag to set options on instance")
|
187
|
256
|
actions.add_argument('-e', '--edit-config', action='store_const',
|
188
|
257
|
default=False, const=True,
|
189
|
258
|
help='Edit configuration of specified instance')
|
|
@@ -197,14 +266,29 @@ def get_parser():
|
197
|
266
|
actions.add_argument('-m', '--make', metavar='TARGET', type=str,
|
198
|
267
|
nargs="?", default='not',
|
199
|
268
|
help='Run make for selected instances')
|
|
269
|
+
|
|
270
|
+ confs.add_argument('--interface', type=str,
|
|
271
|
+ help="Select wich interface to run. Possible values are \
|
|
272
|
+'python' and 'web'")
|
|
273
|
+ confs.add_argument('--listen-port', type=int,
|
|
274
|
+ help="Select the port on wich the web interface will listen to")
|
|
275
|
+ confs.add_argument('--listen-address', type=str,
|
|
276
|
+ help="Select the address on wich the web interface will bind to")
|
200
|
277
|
return parser
|
201
|
278
|
|
202
|
279
|
if __name__ == '__main__':
|
203
|
280
|
parser = get_parser()
|
204
|
281
|
args = parser.parse_args()
|
205
|
282
|
if args.list:
|
206
|
|
- list_instances(args.verbose)
|
|
283
|
+ # Instances list
|
|
284
|
+ if args.name is not None:
|
|
285
|
+ validate_names(args.name)
|
|
286
|
+ for name in args.name:
|
|
287
|
+ details_instance(name, args.verbose, args.batch)
|
|
288
|
+ else:
|
|
289
|
+ list_instances(args.verbose, args.batch)
|
207
|
290
|
elif args.create:
|
|
291
|
+ #Instance creation
|
208
|
292
|
if args.name is None:
|
209
|
293
|
parser.print_help()
|
210
|
294
|
print("\nAn instance name expected when creating an instance !",
|
|
@@ -213,6 +297,7 @@ if __name__ == '__main__':
|
213
|
297
|
for name in args.name:
|
214
|
298
|
new_instance(name)
|
215
|
299
|
elif args.delete:
|
|
300
|
+ #Instance deletion
|
216
|
301
|
if args.name is None:
|
217
|
302
|
parser.print_help()
|
218
|
303
|
print("\nAn instance name expected when creating an instance !",
|
|
@@ -222,6 +307,7 @@ if __name__ == '__main__':
|
222
|
307
|
for name in args.name:
|
223
|
308
|
delete_instance(name)
|
224
|
309
|
elif args.make != 'not':
|
|
310
|
+ #Running make in instances
|
225
|
311
|
if args.make is None:
|
226
|
312
|
target = 'all'
|
227
|
313
|
else:
|
|
@@ -234,6 +320,7 @@ instances, either by name using -n or all using -a")
|
234
|
320
|
exit(1)
|
235
|
321
|
run_make(target, names)
|
236
|
322
|
elif args.edit_config:
|
|
323
|
+ #Edit configuration
|
237
|
324
|
names = get_specified(args)
|
238
|
325
|
if len(names) > 1:
|
239
|
326
|
print("\n-e --edit-config option works only when 1 instance is \
|
|
@@ -245,10 +332,27 @@ specified")
|
245
|
332
|
os.system('editor "%s"' % conffile)
|
246
|
333
|
exit(0)
|
247
|
334
|
elif args.interactive:
|
|
335
|
+ #Run loader.py in foreground
|
248
|
336
|
if args.name is None or len(args.name) != 1:
|
249
|
337
|
print("\n-i option only allowed with ONE instance name")
|
|
338
|
+ parser.print_help()
|
|
339
|
+ exit(1)
|
250
|
340
|
validate_names(args.name)
|
251
|
341
|
name = args.name[0]
|
252
|
342
|
store_datas = get_store_datas()
|
253
|
343
|
os.chdir(store_datas[name]['path'])
|
254
|
344
|
os.execl('/usr/bin/env', '/usr/bin/env', 'python3', 'loader.py')
|
|
345
|
+ elif args.set_option:
|
|
346
|
+ names = None
|
|
347
|
+ if args.all:
|
|
348
|
+ names = list(get_store_datas().values())
|
|
349
|
+ elif args.name is not None:
|
|
350
|
+ names = args.name
|
|
351
|
+ if names is None:
|
|
352
|
+ print("\n-s option only allowed with instance specified (by name \
|
|
353
|
+or with -a)")
|
|
354
|
+ parser.print_help()
|
|
355
|
+ exit(1)
|
|
356
|
+ for name in names:
|
|
357
|
+ set_conf(name, args)
|
|
358
|
+
|