Source code for backend.vm_manage.executor
# coding: utf-8
import threading
import time
from ..helpers import get_redis_logger
[docs]class Executor(object):
"""
Helper super-class to run background processes and clean up after them.
Child class should have method which spawns subprocess and add it handler to `self.child_processes` list.
Also don't forget to call recycle
"""
__name_for_log__ = "executor"
__who_for_log__ = "executor"
def __init__(self, opts):
self.opts = opts
self.child_processes = []
self.last_recycle = time.time()
self.recycle_period = 60
self.log = get_redis_logger(self.opts, "vmm.{}".format(self.__name_for_log__), self.__who_for_log__)
[docs] def run_detached(self, func, args):
"""
Abstaction to spawn Thread or Process
:return:
"""
# proc = Process(target=func, args=(args))
proc = threading.Thread(target=func, args=args)
self.child_processes.append(proc)
proc.start()
# self.log.debug("Spawn process started: {}".format(proc.pid))
return proc
[docs] def after_proc_finished(self, proc):
# hook for subclasses
pass
[docs] def recycle(self, force=False):
"""
Cleanup unused process, should be invoked periodically
:param force: do recycle now unconditionally
:type force: bool
"""
if not force and time.time() - self.last_recycle < self.recycle_period:
return
self.last_recycle = time.time()
self.log.debug("Running recycle {}")
still_alive = []
for proc in self.child_processes:
if proc.is_alive():
still_alive.append(proc)
else:
proc.join()
# self.log.debug("Child process finished: {}".format(proc.pid))
self.log.debug("Child process finished: {}".format(proc))
self.after_proc_finished(proc)
self.child_processes = still_alive
[docs] def terminate(self):
for proc in self.child_processes:
proc.terminate()
proc.join()
@property
def children_number(self):
self.recycle()
return len(self.child_processes)