Beispiel #1
0
    def wait(self):
        """Waits for a client to ask something

        :returns: a triple (run inputs, run config, done status)
        """

        while True:
            if self.__dirty_socket:
                raise NoResultError()
            msg = Message(data=self.__socket.recv())
            reply = Message(name='ack')
            self.__log('received {}...'.format(msg.name))

            # route our reply
            if msg.name == 'execute':
                # first check if the request is valid
                if msg.payload is not None and 'parameters' in msg.payload and 'inputs' in msg.payload:
                    # this is an execution, pass control back to the main loop (but needing closure)
                    self.__log('passing execution back...')
                    self.__dirty_socket = True
                    return (packing.unpack_io_object(
                        msg.payload['inputs'], defs=self.cruxfile['inputs']),
                            self.__defaultify(msg.payload['parameters']),
                            False)
                else:
                    reply.name = 'malformed'
                    reply.success = False
                    self.__log.error('received malformed execution request')
            elif msg.name == 'get_cruxfile':
                reply.payload = self.cruxfile
            elif msg.name == 'shutdown':
                break
            else:
                # method called has not yet been implemented/is unknown
                reply.name = 'nyi'
                reply.success = False

            # skipped if there was a shutdown or execute instruction
            self.__socket.send(reply.pack())
            self.__dirty_socket = False

        # if we've broken out this side of the loop, assume we're shutting down
        self.__log('shutting down loop...')
        self.__socket.send(reply.pack())
        self.__dirty_socket = False
        return (None, None, True)
Beispiel #2
0
    def output(self, output):
        """Returns data to the client

        :param output: the data to send back
        """

        # create the return message
        reply = Message(name='return', payload=output, success=True)

        # pack & send off
        self.__socket.send(reply.pack(defs=self.cruxfile['outputs']))
        self.__dirty_socket = False
        self.__log('returned output')
Beispiel #3
0
    def fail(self, msg=None):
        """Fail the current operation

        :param msg: An optional message to tell the client what's up
        """

        # create the return message
        reply = Message(name='return', payload=msg, success=False)

        # pack & send off
        self.__socket.send(reply.pack())
        self.__dirty_socket = False
        self.__log('returned error message')
Beispiel #4
0
    def listen(self):
        self.__log.info('daemon listening on {}'.format(self.__apisock_addr))

        # loop until we stop
        while not self.__should_stop:
            message = Message(data=self.__apisock.recv())
            try:
                reply = self.__route(message)
            except Exception as e:
                reply = Message(name='failure',
                                payload='internal error',
                                success=False)
                if self.__debug:
                    self.__log.error(e)
            self.__apisock.send(reply.pack())
        self.__log.warn('stopping daemon!')
        self.__pool.terminate_all()
Beispiel #5
0
class CruxREPL(cmd.Cmd):
    # zmq crap
    __context = None
    __socket = None
    __addr = None

    # message saving and stuff
    last_msg = None
    current_msg = None
    saved_msgs = {}

    # logging
    __log = None

    def __init__(self, script=None):
        super().__init__()

        self.__log = Logger(logging=True, name='dispatch')
        # set up zmq stuff
        self.__context = zmq.Context()
        self.__socket = self.__context.socket(zmq.REQ)

        self.current_msg = Message()
        self.__set_prompt()

        if script is not None:
            with open(script, 'r') as cmds:
                self.load(cmds.read().splitlines())

    def __set_prompt(self):
        if self.__addr is None:
            state = colored('disconnected', 'red')
        else:
            state = colored(self.__addr, 'green')
        self.prompt = '({})> '.format(state)

    def exit(self):
        if self.__addr is not None:
            self.do_disconnect(None)

    def load(self, cmds):
        stripped = []
        for c in cmds:
            c = c.strip()
            if c != '':
                stripped.append(c)

        self.__log('preloading {}'.format(stripped))

        self.cmdqueue.extend(stripped)

    def message_show(self, msg):
        if msg is None:
            print(colored('no message', 'yellow'))
            return
        print('{}: {}'.format(
            colored('name', 'blue'),
            json.dumps(msg.name) if msg.name is not None else colored(
                'None', 'red')))
        print('{}: {}'.format(
            colored('payload', 'blue'),
            json.dumps(msg.payload) if msg.payload is not None else colored(
                'None', 'red')))
        print('{}: {}'.format(
            colored('success', 'blue'),
            json.dumps(msg.success) if msg.success is not None else colored(
                'None', 'red')))

    def do_EOF(self, arg):
        """End the program"""
        self.exit()
        print("")
        return True

    def do_exit(self, arg):
        """End the program"""
        self.exit()
        return True

    def do_connect(self, addr):
        """Connect to an address"""
        if self.__addr is not None:
            self.__log.warn(
                'socket was connected to {}, disconnecting...'.format(
                    self.__addr))
            self.__socket.disconnect(self.__addr)
        self.__addr = addr
        self.__socket.connect(self.__addr)
        self.__log.info('connected to {}'.format(self.__addr))
        self.__set_prompt()

    def do_disconnect(self, args):
        """Disconnect"""
        if self.__addr is not None:
            self.__socket.disconnect(self.__addr)
            self.__log.info('disconnected from {}'.format(self.__addr))
        else:
            self.__log.warn('socket was not connected, ignoring...')
        self.__addr = None
        self.__set_prompt()

    def do_cset(self, args):
        """set the (payload/name/success) currently edited message. cset [field] [value]"""
        try:
            field, data = args.split(' ', 1)
        except:
            self.__log.error('error parsing arguments')
            return
        if not field in ['name', 'payload', 'success']:
            self.__log.error('invalid field \'{}\''.format(field))
            return
        try:
            setattr(self.current_msg, field, json.loads(data))
        except json.decoder.JSONDecodeError as jde:
            self.__log.error('invalid data \'{}\''.format(data))
        else:
            self.__log.info('set field {} to {}'.format(field, data))

    def do_cshow(self, _):
        """Show the currently edited message"""
        self.message_show(self.current_msg)

    def do_creset(self, _):
        """Reset the current message"""
        self.current_msg = Message()

    def do_lshow(self, _):
        """Show the last received message"""
        self.message_show(self.last_msg)

    def do_lreset(self, _):
        """Reset the last received message"""
        self.last_msg = None

    def do_echo(self, txt):
        """Echo some text"""
        print('[{}]: {}'.format(colored('echo ', 'magenta'), txt))

    def do_send(self, _):
        """Send the currently edited message to the connected server"""
        if self.__addr is None:
            self.__log.error('not connected!')
            return
        try:
            packed = self.current_msg.pack()
        except MessageException as me:
            self.__log.error(me.msg)
        else:
            self.__socket.send(packed)
            self.last_msg = Message(data=self.__socket.recv())
            self.__log('sending...')

    def do_assert(self, args):
        """Make an assertion that the args are equal. assert [field] [value]"""
        try:
            field, data = args.split(' ', 1)
            data = json.loads(data)
        except:
            self.__log.error('error parsing arguments')
            return

        # resolve the path
        def resolve_path(obj, fieldpath):
            if type(obj) is list:
                fieldpath[0] = int(fieldpath[0])
            if len(fieldpath) == 0:
                return obj
            if len(fieldpath) == 1:
                return obj[fieldpath[0]]
            else:
                return resolve_path(obj[fieldpath[0]], fieldpath[1:])

        try:
            field = field.split('.')
            compare = resolve_path(getattr(self.last_msg, field[0]), field[1:])
        except:
            self.__log.warn(
                'assertion warning: field path expansion failed for {}'.format(
                    field))
            compare = None

        if compare == data:
            self.__log.info('assertion passed: {}'.format(data))
        else:
            self.__log.error('assertion failed!: {} != {}'.format(
                json.dumps(data), json.dumps(compare)))