コード例 #1
0
ファイル: gate.py プロジェクト: tawanda/ajenti
class WorkerGate(object):
    def __init__(self, session, name=None, log_tag=None, restricted=False,
                 initial_identity=None):
        self.session = session
        self.process = None
        self.stream = None
        self.stream_reader = None
        self.worker = None
        self.name = name
        self.log_tag = log_tag
        self.restricted = restricted
        self.initial_identity = initial_identity
        self.q_http_replies = BroadcastQueue()
        self.q_socket_messages = BroadcastQueue()

    def start(self):
        pipe_parent, pipe_child = gipc.pipe(duplex=True)
        self.stream = GateStreamServerEndpoint(pipe_parent)
        stream_child = GateStreamWorkerEndpoint(pipe_child)

        self.process = gipc.start_process(
            target=self._target,
            kwargs={
                'stream': stream_child,
                '_pipe': pipe_child,
            }
        )

        logging.debug('Started child process %s', self.process.pid)

        self.stream_reader = gevent.spawn(self._stream_reader)

    def stop(self):
        logging.debug('Stopping child process %s', self.process.pid)

        try:
            os.killpg(self.process.pid, signal.SIGTERM)
        except OSError as e:
            logging.debug('Child process %s is already dead: %s', self.process.pid, e)
            return

        self.process.terminate()
        self.process.join(0.125)
        try:
            os.kill(self.process.pid, 0)
            logging.debug('Child process %s did not stop, killing', self.process.pid)
            os.kill(self.process.pid, signal.SIGKILL)
            os.killpg(self.process.pid, signal.SIGKILL)

            os.kill(self.process.pid, 0)
            logging.error('Child process %s did not stop after SIGKILL!', self.process.pid)
        except OSError:
            pass

        self.stream_reader.kill(block=False)

    def _stream_reader(self):
        try:
            while True:
                resp = self.stream.buffer_single_response(None)
                if not resp:
                    return
                self.stream.ack_response(resp.id)
                if resp.object['type'] == 'socket':
                    self.q_socket_messages.broadcast(resp)
                if resp.object['type'] == 'http':
                    self.q_http_replies.broadcast(resp)
                if resp.object['type'] == 'terminate':
                    self.session.deactivate()
                if resp.object['type'] == 'restart-master':
                    aj.restart()
                if resp.object['type'] == 'reload-config':
                    aj.config.load()
                    aj.config.ensure_structure()
                    self.stream.send({
                        'type': 'config-data',
                        'data': aj.config.data,
                    })
        except greenlet.GreenletExit:
            pass

    def _target(self, stream=None, _pipe=None):
        self.worker = Worker(stream, self)
        self.worker.run()
コード例 #2
0
class WorkerGate(object):
    def __init__(self,
                 session,
                 name=None,
                 log_tag=None,
                 restricted=False,
                 initial_identity=None):
        self.session = session
        self.process = None
        self.stream = None
        self.stream_reader = None
        self.worker = None
        self.name = name
        self.log_tag = log_tag
        self.restricted = restricted
        self.initial_identity = initial_identity
        self.q_http_replies = BroadcastQueue()
        self.q_socket_messages = BroadcastQueue()

    def start(self):
        pipe_parent, pipe_child = gipc.pipe(
            duplex=True,
            encoder=lambda x: pickle.dumps(x, 2),
        )
        self.stream = GateStreamServerEndpoint(pipe_parent)
        stream_child = GateStreamWorkerEndpoint(pipe_child)

        self.process = gipc.start_process(target=self._target,
                                          kwargs={
                                              'stream': stream_child,
                                              '_pipe': pipe_child,
                                          })

        logging.debug('Started child process %s', self.process.pid)

        self.stream_reader = gevent.spawn(self._stream_reader)

    def stop(self):
        logging.debug('Stopping child process %s', self.process.pid)

        try:
            os.killpg(self.process.pid, signal.SIGTERM)
        except OSError as e:
            logging.debug('Child process %s is already dead: %s',
                          self.process.pid, e)
            return

        self.process.terminate()
        self.process.join(0.125)
        try:
            os.kill(self.process.pid, 0)
            logging.debug('Child process %s did not stop, killing',
                          self.process.pid)
            os.kill(self.process.pid, signal.SIGKILL)
            os.killpg(self.process.pid, signal.SIGKILL)

            os.kill(self.process.pid, 0)
            logging.error('Child process %s did not stop after SIGKILL!',
                          self.process.pid)
        except OSError:
            pass

        self.stream_reader.kill(block=False)

    def _stream_reader(self):
        try:
            while True:
                resp = self.stream.buffer_single_response(None)
                if not resp:
                    return
                self.stream.ack_response(resp.id)
                if resp.object['type'] == 'socket':
                    self.q_socket_messages.broadcast(resp)
                if resp.object['type'] == 'http':
                    self.q_http_replies.broadcast(resp)
                if resp.object['type'] == 'terminate':
                    self.session.deactivate()
                if resp.object['type'] == 'restart-master':
                    aj.restart()
                if resp.object['type'] == 'reload-config':
                    aj.config.load()
                    aj.config.ensure_structure()
                    self.stream.send({
                        'type': 'config-data',
                        'data': aj.config.data,
                    })
                if resp.object['type'] == 'log':
                    method = {
                        'info': logging.info,
                        'warn': logging.warn,
                        'debug': logging.debug,
                        'error': logging.error,
                        'critical': logging.critical,
                    }.get(resp.object['method'], None)
                    if method:
                        method(resp.object['message'],
                               extra=resp.object['kwargs'])
        except greenlet.GreenletExit:
            pass

    def _target(self, stream=None, _pipe=None):
        self.worker = Worker(stream, self)
        self.worker.run()
コード例 #3
0
class WorkerGate():
    def __init__(self,
                 session,
                 gateway_middleware,
                 name=None,
                 log_tag=None,
                 restricted=False,
                 initial_identity=None):
        self.session = session
        self.process = None
        self.stream = None
        self.stream_reader = None
        self.worker = None
        self.name = name
        self.log_tag = log_tag
        self.restricted = restricted
        self.gateway_middleware = gateway_middleware
        self.initial_identity = initial_identity
        self.q_http_replies = BroadcastQueue()
        self.q_socket_messages = BroadcastQueue()

    def start(self):
        pipe_parent, pipe_child = gipc.pipe(
            duplex=True,
            encoder=lambda x: pickle.dumps(x, 2),
        )
        self.stream = GateStreamServerEndpoint(pipe_parent)
        stream_child = GateStreamWorkerEndpoint(pipe_child)

        self.process = gipc.start_process(target=self._target,
                                          kwargs={
                                              'stream': stream_child,
                                              '_pipe': pipe_child,
                                          })

        logging.debug(f'Started child process {self.process.pid}')

        self.stream_reader = gevent.spawn(self._stream_reader)

    def stop(self):
        logging.debug(f'Stopping child process {self.process.pid}')

        try:
            os.killpg(self.process.pid, signal.SIGTERM)
        except OSError as e:
            logging.debug(
                f'Child process {self.process.pid} is already dead: {e}')
            return

        self.process.terminate()
        self.process.join(0.125)
        try:
            os.kill(self.process.pid, 0)
            logging.debug(
                f'Child process {self.process.pid} did not stop, killing')
            os.kill(self.process.pid, signal.SIGKILL)
            os.killpg(self.process.pid, signal.SIGKILL)

            os.kill(self.process.pid, 0)
            logging.error(
                f'Child process {self.process.pid} did not stop after SIGKILL!'
            )
        except OSError:
            pass

        self.stream.destroy()
        self.stream_reader.kill(block=False)

    def send_config_data(self):
        logging.debug(f'Sending a config update to {self.name}')
        self.stream.send({
            'type': 'config-data',
            'data': {
                'config': aj.config.data,
                'users': aj.users.data
            }
        })

    def send_sessionlist(self):
        logging.debug(f'Sending a session list update to {self.name}')
        self.stream.send({
            'type': 'session-list',
            'data': {
                key: session.serialize()
                for key, session in self.gateway_middleware.sessions.items()
            },
        })

    def _stream_reader(self):
        try:
            while True:
                resp = self.stream.buffer_single_response(None)
                if not resp:
                    return
                self.stream.ack_response(resp.id)
                if resp.object['type'] == 'socket':
                    self.q_socket_messages.broadcast(resp)
                if resp.object['type'] == 'http':
                    self.q_http_replies.broadcast(resp)
                if resp.object['type'] == 'terminate':
                    if self.session != self.gateway_middleware:
                        # Not the restricted session, we can disable it
                        self.session.deactivate()
                if resp.object['type'] == 'restart-master':
                    aj.restart()
                if resp.object['type'] == 'update-sessionlist':
                    self.gateway_middleware.broadcast_sessionlist()
                if resp.object['type'] == 'reload-config':
                    aj.config.load()
                    aj.users.load()
                    aj.config.ensure_structure()
                    self.gateway_middleware.broadcast_config_data()
                if resp.object['type'] == 'log':
                    method = {
                        'info': logging.info,
                        'warn': logging.warning,
                        'warning': logging.warning,
                        'debug': logging.debug,
                        'error': logging.error,
                        'critical': logging.critical,
                    }.get(resp.object['method'], None)
                    if method:
                        method(f"{resp.object['message']}",
                               extra=resp.object['kwargs'])
        except greenlet.GreenletExit:
            pass

    def _target(self, stream=None, _pipe=None):
        self.worker = Worker(stream, self)
        self.worker.run()