Пример #1
0
    def recv_ctl(self, msg):
        """receive control message with actions to perform"""
        if msg.type == ControlMessage.ident:
            self.logger.debug('GatewayChannel._state_ctl')
            if msg.action == 'shell':
                data = msg.data_decode()
                cmd = data['cmd']

                stderr = data['stderr']
                timeout = data['timeout']
                remote = data['remote']

                #self.propagation.invoke_gateway = data['invoke_gateway']
                self.logger.debug('decoded gw invoke (%s)',
                                  data['invoke_gateway'])

                taskinfo = data['taskinfo']
                self.logger.debug('assigning task infos (%s)', data['taskinfo'])

                task = task_self()
                task._info.update(taskinfo)
                task.set_info('print_debug', _gw_print_debug)

                if task.info('debug'):
                    self.logger.setLevel(logging.DEBUG)

                self.logger.debug('inherited fanout value=%d',
                                  task.info("fanout"))

                self.logger.debug('launching execution/enter gathering state')

                responder = TreeWorkerResponder(task, self, msg.srcid)

                self.propagation = TreeWorker(msg.target, responder, timeout,
                                              command=cmd,
                                              topology=self.topology,
                                              newroot=self.nodename,
                                              stderr=stderr,
                                              remote=remote)
                # FIXME ev_start-not-called workaround
                responder.worker = self.propagation
                self.propagation.upchannel = self
                task.schedule(self.propagation)
                self.logger.debug("TreeWorker scheduled")
                self._ack(msg)
            elif msg.action == 'write':
                data = msg.data_decode()
                self.logger.debug('GatewayChannel write: %d bytes',
                                  len(data['buf']))
                self.propagation.write(data['buf'])
                self._ack(msg)
            elif msg.action == 'eof':
                self.logger.debug('GatewayChannel eof')
                self.propagation.set_write_eof()
                self._ack(msg)
            else:
                self.logger.error('unexpected CTL action: %s', msg.action)
        else:
            self.logger.error('unexpected message: %s', str(msg))
Пример #2
0
    def _check_channel_ctl_shell(self,
                                 command,
                                 target,
                                 stderr,
                                 remote,
                                 reply_msg_class,
                                 reply_pattern,
                                 write_buf=None,
                                 timeout=-1,
                                 replycnt=1,
                                 reply_rc=0):
        """helper to check channel shell action"""
        self.channel_send_start()
        msg = self.recvxml(StartMessage)
        self.channel_send_cfg('n1')
        msg = self.recvxml(ACKMessage)

        # prepare a remote shell command request...
        workertree = TreeWorker(nodes=target,
                                handler=None,
                                timeout=timeout,
                                command=command)
        # code snippet from PropagationChannel.shell()
        ctl = ControlMessage(id(workertree))
        ctl.action = 'shell'
        ctl.target = NodeSet(target)

        info = task_self()._info.copy()
        info['debug'] = False

        ctl_data = {
            'cmd': command,
            'invoke_gateway': workertree.invoke_gateway,
            'taskinfo': info,
            'stderr': stderr,
            'timeout': timeout,
            'remote': remote
        }
        ctl.data_encode(ctl_data)
        self.gateway.send(ctl.xml())

        self.recvxml(ACKMessage)

        if write_buf:
            ctl = ControlMessage(id(workertree))
            ctl.action = 'write'
            ctl.target = NodeSet(target)
            ctl_data = {
                'buf': write_buf,
            }
            # Send write message
            ctl.data_encode(ctl_data)
            self.gateway.send(ctl.xml())
            self.recvxml(ACKMessage)

            # Send EOF message
            ctl = ControlMessage(id(workertree))
            ctl.action = 'eof'
            ctl.target = NodeSet(target)
            self.gateway.send(ctl.xml())
            self.recvxml(ACKMessage)

        while replycnt > 0:
            msg = self.recvxml(reply_msg_class)
            replycnt -= len(NodeSet(msg.nodes))
            self.assertTrue(msg.nodes in ctl.target)
            if msg.has_payload or reply_pattern:
                msg_data = msg.data_decode()
                try:
                    if not reply_pattern.search(msg_data):
                        self.assertEqual(
                            msg.data, reply_pattern,
                            'Pattern "%s" not found in data="%s"' %
                            (reply_pattern.pattern, msg_data))
                except AttributeError:
                    # not a regexp
                    self.assertEqual(msg_data, reply_pattern)

        if timeout <= 0:
            msg = self.recvxml(RetcodeMessage)
            self.assertEqual(msg.retcode, reply_rc)

        self.channel_send_stop()
        self.gateway.wait()
        self.gateway.close()
Пример #3
0
    def recv_ctl(self, msg):
        """receive control message with actions to perform"""
        if msg.type == ControlMessage.ident:
            self.logger.debug('GatewayChannel._state_ctl')
            if msg.action == 'shell':
                data = msg.data_decode()
                cmd = data['cmd']

                stderr = data['stderr']
                timeout = data['timeout']
                remote = data['remote']

                #self.propagation.invoke_gateway = data['invoke_gateway']
                self.logger.debug('decoded gw invoke (%s)',
                                  data['invoke_gateway'])

                taskinfo = data['taskinfo']
                self.logger.debug('assigning task infos (%s)',
                                  data['taskinfo'])

                task = task_self()
                task._info.update(taskinfo)
                task.set_info('print_debug', _gw_print_debug)

                if task.info('debug'):
                    self.logger.setLevel(logging.DEBUG)

                self.logger.debug('inherited fanout value=%d',
                                  task.info("fanout"))

                self.logger.debug('launching execution/enter gathering state')

                responder = TreeWorkerResponder(task, self, msg.srcid)

                self.propagation = TreeWorker(msg.target,
                                              responder,
                                              timeout,
                                              command=cmd,
                                              topology=self.topology,
                                              newroot=self.nodename,
                                              stderr=stderr,
                                              remote=remote)
                # FIXME ev_start-not-called workaround
                responder.worker = self.propagation
                self.propagation.upchannel = self
                task.schedule(self.propagation)
                self.logger.debug("TreeWorker scheduled")
                self._ack(msg)
            elif msg.action == 'write':
                data = msg.data_decode()
                self.logger.debug('GatewayChannel write: %d bytes',
                                  len(data['buf']))
                self.propagation.write(data['buf'])
                self._ack(msg)
            elif msg.action == 'eof':
                self.logger.debug('GatewayChannel eof')
                self.propagation.set_write_eof()
                self._ack(msg)
            else:
                self.logger.error('unexpected CTL action: %s', msg.action)
        else:
            self.logger.error('unexpected message: %s', str(msg))
Пример #4
0
class GatewayChannel(Channel):
    """high level logic for gateways"""
    def __init__(self, task):
        Channel.__init__(self, error_response=True)
        self.task = task
        self.nodename = None
        self.topology = None
        self.propagation = None
        self.logger = logging.getLogger(__name__)

    def start(self):
        """initialization"""
        # prepare communication
        self._init()
        self.logger.debug('ready to accept channel communication')

    def close(self):
        """close gw channel"""
        self.logger.debug('closing gateway channel')
        self._close()

    def recv(self, msg):
        """handle incoming message"""
        try:
            self.logger.debug('handling incoming message: %s', str(msg))
            if msg.type == EndMessage.ident:
                self.logger.debug('recv: got EndMessage')
                self._close()
            elif self.setup:
                self.recv_ctl(msg)
            elif self.opened:
                self.recv_cfg(msg)
            elif msg.type == StartMessage.ident:
                self.logger.debug('got start message %s', msg)
                self.opened = True
                self._open()
                self.logger.debug('channel started (version %s on remote end)',
                                  self._xml_reader.version)
            else:
                self.logger.error('unexpected message: %s', str(msg))
                raise MessageProcessingError('unexpected message: %s' % msg)
        except MessageProcessingError as ex:
            self.logger.error('on recv(): %s', str(ex))
            self.send(ErrorMessage(str(ex)))
            self._close()

        except EngineAbortException:
            # gateway task abort: don't handle like other exceptions
            raise

        except Exception as ex:
            self.logger.exception('on recv(): %s', str(ex))
            self.send(ErrorMessage(str(ex)))
            self._close()

    def recv_cfg(self, msg):
        """receive cfg/topology configuration"""
        if msg.type != ConfigurationMessage.ident:
            raise MessageProcessingError('unexpected message: %s' % msg)

        self.logger.debug('got channel configuration')

        # gw node name
        hostname = _getshorthostname()
        if not msg.gateway:
            self.nodename = hostname
            self.logger.warn('gw name not provided, using system hostname %s',
                             self.nodename)
        else:
            self.nodename = msg.gateway

        self.logger.debug('using gateway node name %s', self.nodename)
        if self.nodename.lower() != hostname.lower():
            self.logger.debug('gw name %s does not match system hostname %s',
                              self.nodename, hostname)

        # topology
        task_self().topology = self.topology = msg.data_decode()
        self.logger.debug('decoded propagation tree')
        self.logger.debug('\n%s', self.topology)
        self.setup = True
        self._ack(msg)

    def recv_ctl(self, msg):
        """receive control message with actions to perform"""
        if msg.type == ControlMessage.ident:
            self.logger.debug('GatewayChannel._state_ctl')
            if msg.action == 'shell':
                data = msg.data_decode()
                cmd = data['cmd']

                stderr = data['stderr']
                timeout = data['timeout']
                remote = data['remote']

                #self.propagation.invoke_gateway = data['invoke_gateway']
                self.logger.debug('decoded gw invoke (%s)',
                                  data['invoke_gateway'])

                taskinfo = data['taskinfo']
                self.logger.debug('assigning task infos (%s)', data['taskinfo'])

                task = task_self()
                task._info.update(taskinfo)
                task.set_info('print_debug', _gw_print_debug)

                if task.info('debug'):
                    self.logger.setLevel(logging.DEBUG)

                self.logger.debug('inherited fanout value=%d',
                                  task.info("fanout"))

                self.logger.debug('launching execution/enter gathering state')

                responder = TreeWorkerResponder(task, self, msg.srcid)

                self.propagation = TreeWorker(msg.target, responder, timeout,
                                              command=cmd,
                                              topology=self.topology,
                                              newroot=self.nodename,
                                              stderr=stderr,
                                              remote=remote)
                # FIXME ev_start-not-called workaround
                responder.worker = self.propagation
                self.propagation.upchannel = self
                task.schedule(self.propagation)
                self.logger.debug("TreeWorker scheduled")
                self._ack(msg)
            elif msg.action == 'write':
                data = msg.data_decode()
                self.logger.debug('GatewayChannel write: %d bytes',
                                  len(data['buf']))
                self.propagation.write(data['buf'])
                self._ack(msg)
            elif msg.action == 'eof':
                self.logger.debug('GatewayChannel eof')
                self.propagation.set_write_eof()
                self._ack(msg)
            else:
                self.logger.error('unexpected CTL action: %s', msg.action)
        else:
            self.logger.error('unexpected message: %s', str(msg))

    def _ack(self, msg):
        """acknowledge a received message"""
        self.send(ACKMessage(msg.msgid))

    def ev_close(self, worker, timedout):
        """Gateway (parent) channel is closing.

        We abort the whole gateway task to stop other running workers.
        This avoids any unwanted remaining processes on gateways.
        """
        self.logger.debug('GatewayChannel: ev_close')
        self.worker.task.abort()
Пример #5
0
class GatewayChannel(Channel):
    """high level logic for gateways"""
    def __init__(self, task):
        Channel.__init__(self)
        self.task = task
        self.nodename = None
        self.topology = None
        self.propagation = None
        self.logger = logging.getLogger(__name__)

    def start(self):
        """initialization"""
        # prepare communication
        self._init()
        self.logger.debug('ready to accept channel communication')

    def close(self):
        """close gw channel"""
        self.logger.debug('closing gateway channel')
        self._close()

    def recv(self, msg):
        """handle incoming message"""
        try:
            self.logger.debug('handling incoming message: %s', str(msg))
            if msg.type == EndMessage.ident:
                self.logger.debug('recv: got EndMessage')
                self._close()
            elif self.setup:
                self.recv_ctl(msg)
            elif self.opened:
                self.recv_cfg(msg)
            elif msg.type == StartMessage.ident:
                self.logger.debug('got start message %s', msg)
                self.opened = True
                self._open()
                self.logger.debug('channel started (version %s on remote end)',
                                  self._xml_reader.version)
            else:
                self.logger.error('unexpected message: %s', str(msg))
                raise MessageProcessingError('unexpected message: %s' % msg)
        except MessageProcessingError as ex:
            self.logger.error('on recv(): %s', str(ex))
            self.send(ErrorMessage(str(ex)))
            self._close()

        except EngineAbortException:
            # gateway task abort: don't handle like other exceptions
            raise

        except Exception as ex:
            self.logger.exception('on recv(): %s', str(ex))
            self.send(ErrorMessage(str(ex)))
            self._close()

    def recv_cfg(self, msg):
        """receive cfg/topology configuration"""
        if msg.type != ConfigurationMessage.ident:
            raise MessageProcessingError('unexpected message: %s' % msg)

        self.logger.debug('got channel configuration')

        # gw node name
        hostname = _getshorthostname()
        if not msg.gateway:
            self.nodename = hostname
            self.logger.warn('gw name not provided, using system hostname %s',
                             self.nodename)
        else:
            self.nodename = msg.gateway

        self.logger.debug('using gateway node name %s', self.nodename)
        if self.nodename.lower() != hostname.lower():
            self.logger.debug('gw name %s does not match system hostname %s',
                              self.nodename, hostname)

        # topology
        task_self().topology = self.topology = msg.data_decode()
        self.logger.debug('decoded propagation tree')
        self.logger.debug('\n%s', self.topology)
        self.setup = True
        self._ack(msg)

    def recv_ctl(self, msg):
        """receive control message with actions to perform"""
        if msg.type == ControlMessage.ident:
            self.logger.debug('GatewayChannel._state_ctl')
            if msg.action == 'shell':
                data = msg.data_decode()
                cmd = data['cmd']

                stderr = data['stderr']
                timeout = data['timeout']
                remote = data['remote']

                #self.propagation.invoke_gateway = data['invoke_gateway']
                self.logger.debug('decoded gw invoke (%s)',
                                  data['invoke_gateway'])

                taskinfo = data['taskinfo']
                self.logger.debug('assigning task infos (%s)',
                                  data['taskinfo'])

                task = task_self()
                task._info.update(taskinfo)
                task.set_info('print_debug', _gw_print_debug)

                if task.info('debug'):
                    self.logger.setLevel(logging.DEBUG)

                self.logger.debug('inherited fanout value=%d',
                                  task.info("fanout"))

                self.logger.debug('launching execution/enter gathering state')

                responder = TreeWorkerResponder(task, self, msg.srcid)

                self.propagation = TreeWorker(msg.target,
                                              responder,
                                              timeout,
                                              command=cmd,
                                              topology=self.topology,
                                              newroot=self.nodename,
                                              stderr=stderr,
                                              remote=remote)
                # FIXME ev_start-not-called workaround
                responder.worker = self.propagation
                self.propagation.upchannel = self
                task.schedule(self.propagation)
                self.logger.debug("TreeWorker scheduled")
                self._ack(msg)
            elif msg.action == 'write':
                data = msg.data_decode()
                self.logger.debug('GatewayChannel write: %d bytes',
                                  len(data['buf']))
                self.propagation.write(data['buf'])
                self._ack(msg)
            elif msg.action == 'eof':
                self.logger.debug('GatewayChannel eof')
                self.propagation.set_write_eof()
                self._ack(msg)
            else:
                self.logger.error('unexpected CTL action: %s', msg.action)
        else:
            self.logger.error('unexpected message: %s', str(msg))

    def _ack(self, msg):
        """acknowledge a received message"""
        self.send(ACKMessage(msg.msgid))

    def ev_close(self, worker, timedout):
        """Gateway (parent) channel is closing.

        We abort the whole gateway task to stop other running workers.
        This avoids any unwanted remaining processes on gateways.
        """
        self.logger.debug('GatewayChannel: ev_close')
        self.worker.task.abort()