Browse Source

SLIM bugfixes and enhancement

Bufixes in start & stop functions
Add a -f --foreground option allowing to run an instance in foreground
There is one problem left : the unix socket creation is not done in the instance directory...
Yann Weber 8 years ago
parent
commit
b17901e75c
3 changed files with 72 additions and 19 deletions
  1. 1
    1
      progs/slim/Makefile.am
  2. 71
    18
      progs/slim/slim.py
  3. 0
    0
      progs/slim/slim_instances_pid.json

+ 1
- 1
progs/slim/Makefile.am View File

@@ -15,7 +15,7 @@ slim_install_model__DATA = 	install_model/loader.py \
15 15
 slim_conf_model_dir = $(slim_install_model_dir)/conf.d/
16 16
 slim_conf_model__DATA = install_model/conf.d/lodel2.ini
17 17
 
18
-slim_var__DATA = slim_instances.json
18
+slim_var__DATA = slim_instances.json slim_instances_pid.json
19 19
 slim_var_dir = $(localstatedir)/lodel2/slim/
20 20
 
21 21
 

+ 71
- 18
progs/slim/slim.py View File

@@ -142,9 +142,11 @@ def new_instance(name):
142 142
 ##@brief Delete an instance
143 143
 #@param name str : the instance name
144 144
 def delete_instance(name):
145
-    if get_pid(name) is not None:
145
+    pids = get_pids()
146
+    if name in pids:
146 147
         logging.error("The instance '%s' is started. Stop it before deleting \
147 148
 it" % name)
149
+        return
148 150
     store_datas = get_store_datas()
149 151
     logging.warning("Deleting instance %s" % name)
150 152
     logging.info("Deleting instance folder %s" % store_datas[name]['path'])
@@ -175,7 +177,7 @@ def validate_names(names):
175 177
 ##@brief Returns the PID dict
176 178
 #@return a dict with instance name as key an PID as value
177 179
 def get_pids():
178
-    if not os.path.isfile(PID_FILE):
180
+    if not os.path.isfile(PID_FILE) or os.stat(PID_FILE).st_size == 0:
179 181
         return dict()
180 182
     with open(PID_FILE, 'r') as pfd:
181 183
         return json.load(pfd)
@@ -193,11 +195,14 @@ def get_pid(name):
193 195
     if name not in pid_datas:
194 196
         return False
195 197
     else:
196
-        return pid_datas[name]
198
+        pid = pid_datas[name]
199
+        if not is_running(name, pid):
200
+            return False
201
+        return pid
197 202
 
198 203
 ##@brief Start an instance
199 204
 #@param names list : instance name list
200
-def start_instances(names):
205
+def start_instances(names, foreground):
201 206
     pids = get_pids()
202 207
     store_datas = get_store_datas()
203 208
     
@@ -207,11 +212,21 @@ def start_instances(names):
207 212
             continue
208 213
         os.chdir(store_datas[name]['path'])
209 214
         args = [sys.executable, 'loader.py']
210
-        curexec = subprocess.Popen(args)
211
-        pids[name] = curexec.pid
212
-        logging.info("Instance '%s' started. PID %d" % (name, curexec.pid))
215
+        if foreground:
216
+            logging.info("Calling execl with : ", args)
217
+            os.execl(args[0], *args)
218
+            return #only usefull if execl call fails (not usefull)
219
+        else:
220
+            curexec = subprocess.Popen(args,
221
+                stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
222
+                stderr=subprocess.DEVNULL, preexec_fn=os.setsid,
223
+                cwd = store_datas[name]['path'])
224
+            pids[name] = curexec.pid
225
+            logging.info("Instance '%s' started. PID %d" % (name, curexec.pid))
213 226
     save_pids(pids)
214 227
 
228
+##@brief Stop an instance given its name
229
+#@param names list : names list
215 230
 def stop_instances(names):
216 231
     pids = get_pids()
217 232
     store_datas = get_store_datas()
@@ -220,7 +235,30 @@ def stop_instances(names):
220 235
             logging.warning("The instance %s is not running" % name)
221 236
             continue
222 237
         pid = pids[name]
223
-        os.kill(pid, signal.SIGINT)
238
+        try:
239
+            os.kill(pid, signal.SIGINT)
240
+        except ProcessLookupError:
241
+            logging.warning("The instance %s seems to be in error, no process \
242
+with pid %d found" % (pids[name], name))
243
+        del(pids[name])
244
+    save_pids(pids)
245
+
246
+##@brief Checks that a process is running
247
+#
248
+#If not running clean the pid list
249
+#@return bool
250
+def is_running(name, pid):
251
+    try:
252
+        os.kill(pid, 0)
253
+        return True
254
+    except (OSError,ProcessLookupError):
255
+        pid_datas = get_pids()
256
+        logging.warning("Instance '%s' was marked as running, but not \
257
+process with pid %d found. Cleaning pid list" % (name, pid))
258
+        del(pid_datas[name])
259
+        save_pids(pid_datas)
260
+    return False
261
+        
224 262
 
225 263
 ##@brief Check if instance are specified
226 264
 def get_specified(args):
@@ -269,7 +307,7 @@ def details_instance(name, verbosity, batch):
269 307
     pids = get_pids()
270 308
     if not batch:
271 309
         msg = "\t- '%s'" % name
272
-        if name in pids:
310
+        if name in pids and is_running(name, pids[name]):
273 311
             msg += ' [Run PID %d] ' % pids[name]
274 312
         if verbosity > 0:
275 313
             msg += ' path = "%s"' % store_datas[name]['path']
@@ -302,6 +340,7 @@ def get_parser():
302 340
     selector = parser.add_argument_group('Instances selectors')
303 341
     actions = parser.add_argument_group('Instances actions')
304 342
     confs = parser.add_argument_group('Options (use with -c or -s)')
343
+    startstop = parser.add_argument_group('Start/stop options')
305 344
 
306 345
     parser.add_argument('-l', '--list', 
307 346
         help='list existing instances and exit', action='store_const',
@@ -335,14 +374,18 @@ def get_parser():
335 374
     actions.add_argument('-i', '--interactive', action='store_const',
336 375
         default=False, const=True,
337 376
         help='Run a loader.py from ONE instance in foreground')
338
-    actions.add_argument('--stop', action='store_const', 
339
-        default=False, const=True, help="Stop instances")
340
-    actions.add_argument('--start', action='store_const', 
341
-        default=False, const=True, help="Start instances")
342 377
     actions.add_argument('-m', '--make', metavar='TARGET', type=str,
343 378
         nargs="?", default='not',
344 379
         help='Run make for selected instances')
345 380
 
381
+    startstop.add_argument('--stop', action='store_const', 
382
+        default=False, const=True, help="Stop instances")
383
+    startstop.add_argument('--start', action='store_const', 
384
+        default=False, const=True, help="Start instances")
385
+    startstop.add_argument('-f', '--foreground', action='store_const',
386
+        default=False, const=True, help="Start in foreground (limited \
387
+to 1 instance")
388
+
346 389
     confs.add_argument('--interface', type=str,
347 390
         help="Select wich interface to run. Possible values are \
348 391
 'python' and 'web'")
@@ -355,6 +398,8 @@ def get_parser():
355 398
 if __name__ == '__main__':
356 399
     parser = get_parser()
357 400
     args = parser.parse_args()
401
+    if args.verbose is None:
402
+        args.verbose = 0
358 403
     if args.list:
359 404
         # Instances list
360 405
         if args.name is not None:
@@ -373,9 +418,9 @@ if __name__ == '__main__':
373 418
         for name in args.name:
374 419
             new_instance(name)
375 420
     elif args.purge:
376
-        print("Are you sure ? Yes/no ",)
377
-        rep = sys.stdin.read()
378
-        if rep == 'Yes':
421
+        print("Do you really want to delete all the instances ? Yes/no ",)
422
+        rep = sys.stdin.readline()
423
+        if rep == "Yes\n":
379 424
             store = get_store_datas()
380 425
             for name in store:
381 426
                 delete_instance(name)
@@ -440,15 +485,23 @@ specified")
440 485
         elif args.name is not None:
441 486
             names = args.name
442 487
         if names is None:
488
+            parser.print_help()
443 489
             print("\n-s option only allowed with instance specified (by name \
444 490
 or with -a)")
445
-            parser.print_help()
446 491
             exit(1)
447 492
         for name in names:
448 493
             set_conf(name, args)
449 494
     elif args.start:
450 495
         names = get_specified(args)
451
-        start_instances(names)
496
+        if names is None:
497
+            parser.print_help()
498
+            print("\nPlease specify at least 1 instance with the --start \
499
+option", file=sys.stderr)
500
+        elif args.foreground and len(names) > 1:
501
+            parser.prin_help()
502
+            print("\nOnly 1 instance allowed with the use of the --forground \
503
+argument")
504
+        start_instances(names, args.foreground)
452 505
     elif args.stop:
453 506
         names = get_specified(args)
454 507
         stop_instances(names)

+ 0
- 0
progs/slim/slim_instances_pid.json View File


Loading…
Cancel
Save