Ejemplo n.º 1
0
 def _system_started(self, startup, future=None):
     if future and not future.cancelled() and future.exception():
         self._system_coro_check(future)
         return
     info(self.version + ", ready.")
     if startup:
         future = self.activate(startup)
         future.add_done_callback(self._system_coro_check)
Ejemplo n.º 2
0
 def _system_started(self, startup, future=None):
     if future and not future.cancelled() and future.exception():
         self._system_coro_check(future)
         return
     info(self.version + ", ready.")
     if startup:
         future = self.activate(startup)
         future.add_done_callback(self._system_coro_check)
Ejemplo n.º 3
0
    def __exit__(self, a, b, c):
        with self._lock:
            self._forks -= 1

            if self._forks or not self._zombies:
                return

            collateral_victims = str(self._zombies)
            self._zombies.clear()

        info("Caught subprocesses termination from unknown pids: %s",
             collateral_victims)
Ejemplo n.º 4
0
    def __exit__(self, a, b, c):
        with self._lock:
            self._forks -= 1

            if self._forks or not self._zombies:
                return

            collateral_victims = str(self._zombies)
            self._zombies.clear()

        info(
            "Caught subprocesses termination from unknown pids: %s",
            collateral_victims)
Ejemplo n.º 5
0
    def _kill_system_co(self):

        self.notify.stopping()

        self._cancel_pending()

        # Tell the family it's been nice.  It's unlikely we won't have a process family, but
        # it's optional, so we should handle the situation.

        wait_done = False  # indicates if shutdown_timeout has expired

        if self._family:
            for f in self._family.values():
                yield from f.final_stop()
            # let normal shutdown happen
            if self._watcher.number_of_waiters > 0 and self._shutdown_timeout:
                debug(
                    "still have {0} waiting, sleeping for shutdown_timeout={1}"
                    .format(self._watcher.number_of_waiters,
                            self._shutdown_timeout))
                yield from asyncio.sleep(self._shutdown_timeout)
                wait_done = True

        try:
            os.kill(-1, signal.SIGTERM)  # first try a sig term
            if self.send_sighup:
                os.kill(-1, signal.SIGHUP)
        except ProcessLookupError:
            debug(
                "No processes remain when attempting to kill system, just stop."
            )
            self._no_processes(True)
            return

        if wait_done:  # give a short wait just so the signals fire
            yield from asyncio.sleep(1)  # these processes are unknowns
        else:
            yield from asyncio.sleep(self._shutdown_timeout)

        if self._all_killed:
            return

        info("Some processes remain after {0}secs.  Forcing kill".format(
            self._shutdown_timeout))

        try:
            os.kill(-1, signal.SIGKILL)
        except ProcessLookupError:
            debug("No processes when attempting to force quit")
            self._no_processes(True)
            return
Ejemplo n.º 6
0
def _process_logger(stream, kind, service):
    name = service.name.replace('.service', '')
    while True:
        data = yield from stream.readline()
        if not data:
            return
        line = data.decode('ascii', 'ignore').rstrip()
        if not line:
            continue            # ignore blank lines in stdout/stderr
        if kind == 'stderr':
            # we map to warning because stderr output is "to be considered" and not strictly
            # erroneous
            warn(line, program=name, pid=service.pid, facility=syslog_info.LOG_DAEMON)
        else:
            info(line, program=name, pid=service.pid, facility=syslog_info.LOG_DAEMON)
Ejemplo n.º 7
0
    def do_exec(self, opts, controller):
        delay = opts['<delay>']

        if delay is None or delay.lower() == "now":
            delay = 0.1
            message = "Shutting down now"
        else:
            try:
                delay = float(delay)
            except ValueError:
                return "Specified delay is not a valid decimal number: " + str(delay)
            message = "Shutting down in {0} seconds".format(delay)

        info("requested shutdown scheduled to occur in {0} seconds".format(delay))
        asyncio.get_event_loop().call_later(delay, controller.kill_system)

        return message
Ejemplo n.º 8
0
    def _kill_system_co(self):

        self.notify.stopping()

        self._cancel_pending()

        # Tell the family it's been nice.  It's unlikely we won't have a process family, but
        # it's optional, so we should handle the situation.

        wait_done = False       # indicates if shutdown_timeout has expired

        if self._family:
            for f in self._family.values():
                yield from f.final_stop()
            # let normal shutdown happen
            if self._watcher.number_of_waiters > 0 and self._shutdown_timeout:
                debug("still have {0} waiting, sleeping for shutdown_timeout={1}".format(self._watcher.number_of_waiters, self._shutdown_timeout))
                yield from asyncio.sleep(self._shutdown_timeout)
                wait_done = True

        try:
            os.kill(-1, signal.SIGTERM) # first try a sig term
            if self.send_sighup:
                os.kill(-1, signal.SIGHUP)
        except ProcessLookupError:
            debug("No processes remain when attempting to kill system, just stop.")
            self._no_processes(True)
            return

        if wait_done:                   # give a short wait just so the signals fire
            yield from asyncio.sleep(1) # these processes are unknowns
        else:
            yield from asyncio.sleep(self._shutdown_timeout)
            
        if self._all_killed:
            return

        info("Some processes remain after {0}secs.  Forcing kill".format(self._shutdown_timeout))

        try:
            os.kill(-1, signal.SIGKILL)
        except ProcessLookupError:
            debug("No processes when attempting to force quit")
            self._no_processes(True)
            return
Ejemplo n.º 9
0
    def do_exec(self, opts, controller):
        delay = opts['<delay>']

        if delay is None or delay.lower() == "now":
            delay = 0.1
            message = "Shutting down now"
        else:
            try:
                delay = float(delay)
            except ValueError:
                return "Specified delay is not a valid decimal number: " + str(
                    delay)
            message = "Shutting down in {0} seconds".format(delay)

        info("requested shutdown scheduled to occur in {0} seconds".format(
            delay))
        asyncio.get_event_loop().call_later(delay, controller.kill_system)

        return message
Ejemplo n.º 10
0
def _process_logger(stream, kind, service):
    name = service.name.replace('.service', '')
    while True:
        data = yield from stream.readline()
        if not data:
            return
        line = data.decode('ascii', 'ignore').rstrip()
        if not line:
            continue  # ignore blank lines in stdout/stderr
        if kind == 'stderr':
            # we map to warning because stderr output is "to be considered" and not strictly
            # erroneous
            warn(line,
                 program=name,
                 pid=service.pid,
                 facility=syslog_info.LOG_DAEMON)
        else:
            info(line,
                 program=name,
                 pid=service.pid,
                 facility=syslog_info.LOG_DAEMON)
Ejemplo n.º 11
0
    def _do_waitpid_all(self):
        # Because of signal coalescing, we must keep calling waitpid() as
        # long as we're able to reap a child.
        while True:
            try:
                pid, status = os.waitpid(-1, os.WNOHANG)
                debug("REAP pid={0},status={1}".format(pid,status))
            except ChildProcessError:
                # No more child processes exist.
                if self._had_children:
                    debug("no child processes present")
                    self.events.onNoProcesses()
                return
            else:
                self._had_children = True
                if pid == 0:
                    # A child process is still alive.
                    return

                returncode = ProcStatus(status)

            with self._lock:
                try:
                    callback, args = self._callbacks.pop(pid)
                except KeyError:
                    # unknown child
                    if self._forks:
                        # It may not be registered yet.
                        self._zombies[pid] = returncode
                        continue
                    callback = None

            if callback is None:
                info(
                    "Caught subprocess termination from unknown pid: "
                    "%d -> %d", pid, returncode)
            else:
                callback(pid, returncode, *args)
Ejemplo n.º 12
0
    def _do_waitpid_all(self):
        # Because of signal coalescing, we must keep calling waitpid() as
        # long as we're able to reap a child.
        while True:
            try:
                pid, status = os.waitpid(-1, os.WNOHANG)
                debug("REAP pid={0},status={1}".format(pid, status))
            except ChildProcessError:
                # No more child processes exist.
                if self._had_children:
                    debug("no child processes present")
                    self.events.onNoProcesses()
                return
            else:
                self._had_children = True
                if pid == 0:
                    # A child process is still alive.
                    return

                returncode = ProcStatus(status)

            with self._lock:
                try:
                    callback, args = self._callbacks.pop(pid)
                except KeyError:
                    # unknown child
                    if self._forks:
                        # It may not be registered yet.
                        self._zombies[pid] = returncode
                        continue
                    callback = None

            if callback is None:
                info(
                    "Caught subprocess termination from unknown pid: "
                    "%d -> %d", pid, returncode)
            else:
                callback(pid, returncode, *args)
Ejemplo n.º 13
0
    def _start_system_services(self):

        self._notify_enabled = yield from self.notify.connect()

        self._syslog = SyslogServer()
        self._syslog.configure(self._config, self._minimum_syslog_level)

        try:
            yield from self._syslog.run()
        except PermissionError as ex:
            self._syslog = None
            warn("syslog service cannot be started: {0}", ex)
        else:
            self._syslog.capture_python_logging()
            info("Switching all chaperone logging to /dev/log")

        self._command = CommandServer(self)

        try:
            yield from self._command.run()
        except PermissionError as ex:
            self._command = None
            warn("command service cannot be started: {0}", ex)
Ejemplo n.º 14
0
    def force_log_level(self, level=None):
        """
        Specifies the *minimum* logging level that will be applied to all syslog entries.
        This is primarily useful for debugging, where you want to override any limitations
        imposed on log file entries.

        As a (convenient) side-effect, if the level is DEBUG, then debug features of both
        asyncio as well as chaperone will be enabled.

        If level is not provided, then returns the current setting.
        """
        if level is None:
            return self._minimum_syslog_level

        levid = syslog_info.PRIORITY_DICT.get(level.lower(), None)
        if not levid:
            raise Exception("Not a valid log level: {0}".format(level))
        set_log_level(levid)
        self._minimum_syslog_level = levid
        self.debug = (levid == syslog_info.LOG_DEBUG)
        if self._syslog:
            self._syslog.reset_minimum_priority(levid)
        info("Forcing all log output to '{0}' or greater", level)
Ejemplo n.º 15
0
    def force_log_level(self, level = None):
        """
        Specifies the *minimum* logging level that will be applied to all syslog entries.
        This is primarily useful for debugging, where you want to override any limitations
        imposed on log file entries.

        As a (convenient) side-effect, if the level is DEBUG, then debug features of both
        asyncio as well as chaperone will be enabled.

        If level is not provided, then returns the current setting.
        """
        if level is None:
            return self._minimum_syslog_level

        levid = syslog_info.PRIORITY_DICT.get(level.lower(), None)
        if not levid:
            raise Exception("Not a valid log level: {0}".format(level))
        set_log_level(levid)
        self._minimum_syslog_level = levid
        self.debug = (levid == syslog_info.LOG_DEBUG)
        if self._syslog:
            self._syslog.reset_minimum_priority(levid)
        info("Forcing all log output to '{0}' or greater", level)
Ejemplo n.º 16
0
    def _start_system_services(self):

        self._notify_enabled = yield from self.notify.connect()

        self._syslog = SyslogServer()
        self._syslog.configure(self._config, self._minimum_syslog_level)

        try:
            yield from self._syslog.run()
        except PermissionError as ex:
            self._syslog = None
            warn("syslog service cannot be started: {0}", ex)
        else:
            self._syslog.capture_python_logging()
            info("Switching all chaperone logging to /dev/log")

        self._command = CommandServer(self)

        try:
            yield from self._command.run()
        except PermissionError as ex:
            self._command = None
            warn("command service cannot be started: {0}", ex)
Ejemplo n.º 17
0
 def loginfo(self, *args, **kwargs):
     info(*args, facility=self.syslog_facility, **kwargs)
Ejemplo n.º 18
0
 def loginfo(self, *args, **kwargs):
     info(*args, facility=self.syslog_facility, **kwargs)