예제 #1
0
    def _reload(self, graceful=True, sequential=False):
        """ reload
        """
        if not graceful and sequential:
            logger.warn("with graceful=False, sequential=True is ignored")
        if self.prereload_fn is not None:
            self.prereload_fn(self)

        if not graceful:
            yield self._restart()
            return

        if self.is_stopped():
            yield self._start()
        elif self.send_hup:
            for process in self.processes.values():
                logger.info("SENDING HUP to %s" % process.pid)
                process.send_signal(signal.SIGHUP)
        else:
            if sequential:
                active_processes = self.get_active_processes()
                for process in active_processes:
                    yield self.kill_process(process)
                    self.reap_process(process.pid)
                    self.spawn_process()
                    yield gen.sleep(self.warmup_delay)
            else:
                for i in range(self.numprocesses):
                    self.spawn_process()
                yield self.manage_processes()
        logger.info('%s reloaded', self.name)
예제 #2
0
    def stop(cls):
        logger.info('Stopping ant-agent service')

        returncode, output = _sc_run('stop', cls.name)
        if returncode != 0:
            raise CallError(output)
        _wait_util(cls, 'stopped')

        logger.info('ant-agent stopped')
예제 #3
0
    def start(cls, *args):
        logger.info('Starting ant-agent service')

        # CircleWinService.config(*args)
        returncode, output = _sc_run('start', cls.name)
        if returncode != 0:
            raise CallError(output)
        _wait_util(cls, 'running')

        logger.info('ant-agent started')
예제 #4
0
 def _stop(self):
     logger.info('Arbiter exiting')
     self._stopping = True
     yield self._stop_watchers(close_output_streams=True)
     if self._provided_loop:
         cb = self.stop_controller_and_close_sockets
         self.loop.add_callback(cb)
     else:
         # stop_controller_and_close_sockets will be
         # called in the end of start() method
         self.loop.add_callback(self.loop.stop)
예제 #5
0
    def _register(self):
        logger.info('Registering signals...')
        for sig in self.SIGNALS:
            self._old[sig] = signal.getsignal(sig)
            signal.signal(sig, self.signal)

        # Don't let SIGQUIT and SIGUSR1 disturb active requests
        # by interrupting system calls
        if hasattr(signal, 'siginterrupt'):  # python >= 2.6
            signal.siginterrupt(signal.SIGQUIT, False)
            signal.siginterrupt(signal.SIGUSR1, False)
예제 #6
0
    def install(cls, *args):
        logger.info('Installing ant-upgrade service')

        returncode, output = _nssm_run('install', cls.name, UPGRADE_START)
        if returncode == 0 and 'Administrator access' in output:
            raise CallError(output)
        elif returncode == 5:
            raise AlreadyExist(cls.exist_msg)
        elif returncode != 0:
            raise CallError(output)

        logger.info('ant-upgrade installed')
예제 #7
0
    def remove(cls):
        """If you want to remove the service, please make sure stop it first.
        Otherwise you will get error message: "Error deleting". """
        logger.info('Removing ant-upgrade service')

        returncode, output = _nssm_run('remove', cls.name, 'confirm')
        if returncode == 3:
            raise NotExistError(cls.not_exist_msg)
        elif returncode == 4:
            raise CallError(cls.remove_err_msg)
        elif returncode != 0:
            raise CallError(output)
        logger.info('ant-upgrade removed')
예제 #8
0
    def signal(self, sig, frame=None):
        signame = self.SIG_NAMES.get(sig)
        logger.info('Got signal SIG_{}'.format(signame.upper()))

        if signame is not None:
            try:
                handler = getattr(self, "handle_%s" % signame)
                handler()
            except AttributeError:
                pass
            except Exception as e:
                tb = traceback.format_exc()
                logger.error("error: %s [%s]" % (e, tb))
                sys.exit(1)
예제 #9
0
def win_daemonize():
    logger.info('Starting deamon mode. '
                'The AntCircled service will be started.')
    args = sys.argv[1:]
    if '--daemon' in args:
        args.remove('--daemon')
    try:
        if not CircleWinService.exists():
            CircleWinService.install(*args)
            CircleWinService.start(*args)
            sys.exit(0)
    except (AlreadyExist, NotExistError, CallError) as e:
        logger.error(e)
        sys.exit(1)
예제 #10
0
    def install(cls, *args):
        logger.info('Installing ant-agent service')

        if not os.path.exists(CIRCLED_PATH):
            raise CallError('{} not exists.'.format(CIRCLED_PATH))

        returncode, output = _nssm_run('install', cls.name, BIN_START)
        if returncode == 0 and 'Administrator access' in output:
            raise CallError(output)
        elif returncode == 5:
            raise AlreadyExist(cls.exist_msg)
        elif returncode != 0:
            raise CallError(output)

        logger.info('ant-agent installed')
예제 #11
0
    def kill_process(self, process, stop_signal=None, graceful_timeout=None):
        """Kill process (stop_signal, graceful_timeout then SIGKILL)
        """
        if stop_signal is None:
            stop_signal = self.stop_signal
        if graceful_timeout is None:
            graceful_timeout = self.graceful_timeout

        if process.stopping:
            raise gen.Return(False)
        try:
            logger.info('Kill process "{}" (pid {})'.format(
                self.name, process.pid))
            if self.stop_children:
                self.send_signal_process(process, stop_signal)
            else:
                self.send_signal(process.pid, stop_signal)
        except NoSuchProcess:
            raise gen.Return(False)

        process.stopping = True
        waited = 0
        while waited < graceful_timeout:
            if not process.is_alive():
                break
            yield gen.sleep(0.1)
            waited += 0.1
        if waited >= graceful_timeout:
            # On Windows we can't send a SIGKILL signal, but the
            # process.stop function will terminate the process
            # later anyway
            if hasattr(signal, 'SIGKILL'):
                # We are not smart anymore
                self.send_signal_process(process,
                                         signal.SIGKILL,
                                         recursive=True)
        if self.stream_redirector:
            self.stream_redirector.remove_redirections(process)
        process.stopping = False
        process.stop()
        raise gen.Return(True)
예제 #12
0
    def run_hooks(self, hook_name):
        hooks = self.config.get('hooks', None)
        if not hooks:
            raise gen.Return(True)

        hook = hooks.get(hook_name, None)

        if not hook:
            logger.info('Watcher: "{}" have no {} hooks'.format(
                self.name, hook_name))
            raise gen.Return(True)

        self.running_hook = True
        logger.info('Watcher: "{}" run {} hooks'.format(self.name, hook_name))
        status, output = yield async_get_status_output(hook,
                                                       cwd=self.working_dir)
        self.running_hook = False
        if status:
            logger.error(output)
            raise gen.Return(False)
        raise gen.Return(True)
예제 #13
0
    def _stop(self, close_output_streams=False):
        if self.is_stopped():
            return
        self._status = "stopping"

        logger.debug('Stopping the watcher: "{}"'.format(self.name))
        logger.debug('Gracefully stopping processes [{}] for {}s'.format(
            self.name, self.graceful_timeout))
        yield self.kill_processes()
        self.reap_processes()

        # stop redirectors
        if self.stream_redirector:
            self.stream_redirector.stop()
            self.stream_redirector = None
        if close_output_streams:
            if self.stdout_stream and hasattr(self.stdout_stream, 'close'):
                self.stdout_stream.close()
            if self.stderr_stream and hasattr(self.stderr_stream, 'close'):
                self.stderr_stream.close()

        self._status = "stopped"
        logger.info('Watcher: "{}" stopped'.format(self.name))
        yield self.run_hooks('post_stop')
예제 #14
0
    def start(self, callback=None):
        """Starts all the watchers.

        If the ioloop has been provided during __init__() call,
        starts all watchers as a standard coroutine

        If the ioloop hasn't been provided during __init__() call (default),
        starts all watchers and the eventloop (and blocks here). In this mode
        the method MUST NOT yield anything because it's called as a standard
        method.

        :param callback: Callback called after all the watchers have been
                   started, when the loop hasn't been provided.
        :type function:
        """
        logger.info('Starting circle arbiter on pid {}'.format(self.pid))
        self.initialize()

        # start controller
        self.ctrl.start()
        self._restarting = False
        try:
            # initialize processes
            logger.info('Starting watchers')
            if self._provided_loop:
                yield self.start_watchers()
            else:
                # start_watchers will be called just after the start_io_loop()
                if not callback:

                    def callback(x):
                        pass

                self.loop.add_future(self.start_watchers(), callback)
            logger.info('Arbiter now waiting for commands')
            self._running = True
            if not self._provided_loop:
                # If an event loop is not provided, block at this line
                self.start_io_loop()
        finally:
            if not self._provided_loop:
                # If an event loop is not provided, do some cleaning
                self.stop_controller_and_close_sockets()
        raise gen.Return(self._restarting)
예제 #15
0
    def _start(self):
        """Start."""
        logger.info('Starting watcher: "{}"'.format(self.name))
        if not self.is_stopped():
            if len(self.processes) < self.numprocesses:
                self.reap_processes()
                yield self.spawn_processes()
            return

        found_wids = bool(self._found_wids)

        self._status = "starting"

        if self.stdout_stream and hasattr(self.stdout_stream, 'open'):
            self.stdout_stream.open()
        if self.stderr_stream and hasattr(self.stderr_stream, 'open'):
            self.stderr_stream.open()

        self._create_redirectors()

        self.reap_processes()
        yield self.spawn_processes()

        # If not self.processes, the before_spawn or after_spawn hooks have
        # probably prevented startup so give up
        if not self.processes:
            logger.debug('Aborting startup')
            # stop streams too since we are bailing on this watcher completely
            yield self._stop()
            return

        self._status = "active"
        if found_wids:
            logger.info('Watcher "{}" already running'.format(self.name))
        else:
            logger.info('Watcher "{}" started'.format(self.name))

        hook_status = yield self.run_hooks('post_start')
        if not hook_status:
            yield self._stop()
예제 #16
0
    def spawn_process(self, recovery_wid=None):
        """Spawn process.

        Return True if ok, False if the watcher must be stopped
        """
        if self.is_stopped():
            return True

        cmd = util.replace_gnu_args(self.cmd, env=self.env)
        nb_tries = 0

        # start the redirector now so we can catch any startup errors
        if self.stream_redirector:
            self.stream_redirector.start()

        while nb_tries < self.max_retry or self.max_retry == -1:
            process = None
            pipe_stdout = self.stdout_stream is not None
            pipe_stderr = self.stderr_stream is not None

            # noinspection PyPep8Naming
            ProcessClass = self._process_class
            try:
                process = ProcessClass(
                    self.name,
                    recovery_wid or self._nextwid,
                    cmd,
                    args=self.args,
                    working_dir=self.working_dir,
                    shell=self.shell,
                    uid=self.uid,
                    gid=self.gid,
                    env=self.env,
                    rlimits=self.rlimits,
                    executable=self.executable,
                    # todo, watcher remove 'use_fds'
                    use_fds=False,
                    watcher=self,
                    pipe_stdout=pipe_stdout,
                    pipe_stderr=pipe_stderr,
                    close_child_stdin=self.close_child_stdin,
                    close_child_stdout=self.close_child_stdout,
                    close_child_stderr=self.close_child_stderr)

                # stream stderr/stdout if configured
                if self.stream_redirector:
                    self.stream_redirector.add_redirections(process)

                self.processes[process.pid] = process
                logger.info('Running process "{}" (pid {})'.format(
                    self.name, process.pid))

            # catch ValueError as well, as a misconfigured rlimit setting could
            # lead to bad infinite retries here
            except (OSError, ValueError) as e:
                logger.warn('Error in %s: %s', self.name, str(e))

            if process is None:
                nb_tries += 1
                continue
            else:
                return process.started
        return False