2017-11-07 14:41:38 +01:00

166 lines
3.8 KiB
Python

'''
Created on 02.02.2012
@author: kca
'''
from time import sleep
from abc import ABCMeta, abstractproperty, abstractmethod
from futile import Base
from futile.path import Path
from . import check_call, STDOUT
class DaemonController(Base):
__metaclass__ = ABCMeta
def __init__(self, sleep = 5, stop_sleep = 3, *args, **kw):
super(DaemonController, self).__init__(*args, **kw)
self.__sleep = int(sleep)
self.__stop_sleep = int(stop_sleep)
@abstractproperty
def is_running(self):
raise NotImplementedError()
def start(self):
self._start()
sleep(self.__sleep)
@abstractmethod
def _start(self):
raise NotImplementedError()
def stop(self):
self._stop()
sleep(self.__stop_sleep)
@abstractmethod
def _stop(self):
raise NotImplementedError()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.stop()
class DummyController(DaemonController):
def __init__(self, sleep = 0, stop_sleep = 0, *args, **kw):
super(DummyController).__init__(sleep = sleep, stop_sleep = stop_sleep, *args, **kw)
def _start(self):
pass
_stop = _start
@property
def is_running(self):
return False
import os
import errno
class CheckPIDFileController(DaemonController):
def __init__(self, pidfile, *args, **kw):
super(CheckPIDFileController, self).__init__(*args, **kw)
self.__pidfile = Path(pidfile)
@property
def pidfile(self):
return self.__pidfile
@property
def is_running(self):
if not self.pidfile.exists():
return False
if not self.pidfile.isfile():
raise Exception("pidfile '%s' is not a file" % (self.pidfile, ))
try:
pid = int(self.__pidfile.open().readline(16))
except:
self.logger.exception("Error reading pidfile %s" % (self.pidfile))
raise
try:
os.kill(pid, 0)
return True
except OSError, e:
if e.errno == errno.ESRCH:
return False
raise
class StartStopDaemonController(CheckPIDFileController):
def __init__(self, executable, fork = False, workingdir = None, pidfile = None, makepidfile = False, daemonargs = None, ssd = "/sbin/start-stop-daemon", ldpath = None, outfile = "/dev/null", *args, **kw):
if not pidfile:
pidfile = "/tmp/" + executable.replace("/", "_") + ".pid"
super(StartStopDaemonController, self).__init__(pidfile = pidfile, *args, **kw)
self.__executable = unicode(executable)
self.__workingdir = workingdir and unicode(workingdir) or None
if ldpath is not None:
if not isinstance(ldpath, (list, set, tuple, frozenset)):
ldpath = [ ldpath ]
ldpath = tuple(set(ldpath))
self.__ldpath = ldpath
self.__makepidfile = makepidfile
self.__daemonargs = daemonargs
self.__fork = fork
self.__ssd = ssd
self.__outfile = outfile
def get_daemonargs(self):
return self.__daemonargs
def set_daemonargs(self, da):
self.__daemonargs = da
daemonargs = property(get_daemonargs, set_daemonargs)
def __make_cmd(self, cmd, test):
cmd = [ self.__ssd, cmd, '-x', self.__executable, '-p', self.pidfile, '-o' ]
if self.__workingdir:
cmd += [ '-d', self.__workingdir ]
if test:
cmd.append('-t')
env = None
if self.__ldpath:
env = dict(LD_LIBRARY_PATH = ':'.join(self.__ldpath))
return cmd, env
def __check_cmd(self, cmd, env):
self.logger.debug("ssd env: " + str(env))
outfile = self.__outfile
if outfile:
outfile = Path(outfile).open("a")
try:
check_call(cmd, stdout = outfile, stderr = STDOUT, close_fds = True, cwd = self.__workingdir, env = env)
finally:
if outfile is not None:
outfile.close()
def _start(self):
cmd, env = self.__make_cmd("-S", False)
if self.__makepidfile:
cmd.append('-m')
if self.__fork:
cmd.append('-b')
if self.__daemonargs:
cmd += [ '--' ] + list(self.__daemonargs)
self.__check_cmd(cmd, env)
def _stop(self):
cmd, env = self.__make_cmd("-K", False)
self.__check_cmd(cmd, env)