示例#1
0
    def send_hello_msg_to_node(self, nodeId):
        self.log.debug("Controller sends HelloMsg to agent")
        dest = nodeId
        cmdDesc = msgs.CmdDesc()
        cmdDesc.type = msgs.get_msg_type(msgs.HelloMsg)
        cmdDesc.func_name = msgs.get_msg_type(msgs.HelloMsg)
        cmdDesc.serialization_type = msgs.CmdDesc.PROTOBUF

        msg = msgs.HelloMsg()
        msg.uuid = str(self.controller.uuid)
        msg.timeout = self.helloTimeout
        msgContainer = [dest, cmdDesc, msg]
        self.controller.transport.send_downlink_msg(msgContainer)
    def send_upstream(self, msg):
        dest = "controller"
        cmdDesc = msgs.CmdDesc()
        cmdDesc.type = "hierarchical_control"
        cmdDesc.func_name = "hierarchical_control"
        cmdDesc.call_id = str(0)
        cmdDesc.serialization_type = msgs.CmdDesc.PICKLE

        encapsulatedMsg = {
            "node_uuid": self.agent.uuid,
            "control_program_id": self.id,
            "msg": msg
        }
        msgContainer = [dest, cmdDesc, encapsulatedMsg]
        self.agent.send_upstream(msgContainer)
示例#3
0
    def process_cmd(self, msgContainer, localControllerId=None):
        dest = msgContainer[0]
        cmdDesc = msgContainer[1]
        msg = msgContainer[2]

        self.log.debug("Agent serves command: {}:{} from controller".format(
            cmdDesc.type, cmdDesc.func_name))
        if not cmdDesc.exec_time or cmdDesc.exec_time == 0:
            self.log.debug("Agent sends message: {}:{} to module".format(
                cmdDesc.type, cmdDesc.func_name))
            self.moduleManager.send_cmd_to_module(msgContainer,
                                                  localControllerId)
        else:
            execTime = datetime.datetime.strptime(cmdDesc.exec_time,
                                                  "%Y-%m-%d %H:%M:%S.%f")
            if execTime < datetime.datetime.now():
                e = Exception(
                    "Node: {} tried to schedule function: {}:{} call in past, consider time synchronization"
                    .format(self.name, upi_type, fname))

                dest = "controller"
                respDesc = msgs.CmdDesc()
                respDesc.type = cmdDesc.type
                respDesc.func_name = cmdDesc.func_name
                respDesc.call_id = cmdDesc.call_id
                #TODO: define new protobuf message for return values; currently using repeat_number in CmdDesc
                #0-executed correctly, 1-exception
                respDesc.repeat_number = 1
                #Serialize return value
                respDesc.serialization_type = msgs.CmdDesc.PICKLE
                retVal = e
                response = [dest, respDesc, retVal]
                self.send_upstream(response)
                return

            self.log.debug(
                "Agent schedule task for message: {}:{} at {}".format(
                    cmdDesc.type, cmdDesc.func_name, execTime))
            self.jobScheduler.add_job(self.moduleManager.send_cmd_to_module,
                                      'date',
                                      run_date=execTime,
                                      kwargs={
                                          'msgContainer': msgContainer,
                                          'localControllerId':
                                          localControllerId
                                      })
示例#4
0
    def start(self):
        # Work on requests from controller
        while True:
            socks = dict(self.poller.poll())
            if self.dl_socket in socks and socks[self.dl_socket] == zmq.POLLIN:
                msgContainer = self.dl_socket.recv_multipart()

                assert len(msgContainer) == 3, msgContainer
                dest = msgContainer[0]
                cmdDesc = msgs.CmdDesc()
                cmdDesc.ParseFromString(msgContainer[1])
                msg = msgContainer[2]

                if cmdDesc.serialization_type == msgs.CmdDesc.PICKLE:
                    msg = pickle.loads(msg)

                msgContainer[0] = dest.decode('utf-8')
                msgContainer[1] = cmdDesc
                msgContainer[2] = msg
                self.recv_callback(msgContainer)
    def exec_cmd(self, upi_type, fname, *args, **kwargs):
        self.log.debug(
            "Controller executes cmd: {}.{} with args:{}, kwargs:{}".format(
                upi_type, fname, args, kwargs))

        #get function call context
        iface = self._iface
        exec_time = self._exec_time
        delay = self._delay
        timeout = self._timeout
        blocking = self._blocking
        callback = self._callback
        self._clear_call_context()

        #TODO: support timeout, on controller and agent sides?
        callId = str(self.generate_call_id())

        #build cmd desc message
        cmdDesc = msgs.CmdDesc()
        cmdDesc.type = upi_type
        cmdDesc.func_name = fname
        cmdDesc.call_id = callId

        if iface:
            cmdDesc.interface = iface

        if delay:
            exec_time = datetime.datetime.now() + datetime.timedelta(
                seconds=delay)
            blocking = False

        if exec_time:
            cmdDesc.exec_time = str(exec_time)
            blocking = False

        #call check
        if exec_time and exec_time < datetime.datetime.now():
            raise Exception("Scheduling function: {}:{} call in past".format(
                upi_type, fname))

        if not self.agent.is_upi_supported(
                iface=iface, upi_type=upi_type, fname=fname):
            raise Exception(
                "UPI Function: {}:{} not supported for iface: {}, please install proper modules"
                .format(upi_type, fname, iface))

        #set callback for this function call
        if callback:
            self.callbacks[callId] = callback
            blocking = False

        msgContainer = ["agent", cmdDesc, kwargs]

        #if blocking call, return response
        if blocking:
            #send command to execution engine
            response = self.agent.moduleManager.send_cmd_to_module_blocking(
                msgContainer)
            cmdDesc = response[1]
            retVal = response[2]
            return retVal

        #send command to execution engine (non-blocking)
        self.agent.process_cmd(msgContainer=msgContainer,
                               localControllerId=self.id)

        return None
    def exec_cmd(self, upi_type, fname, *args, **kwargs):
        self.log.debug(
            "Controller builds cmd message: {}.{} with args:{}, kwargs:{}".
            format(upi_type, fname, args, kwargs))

        #get function call context
        scope = local_func_call_context._scope
        iface = local_func_call_context._iface
        exec_time = local_func_call_context._exec_time
        delay = local_func_call_context._delay
        timeout = local_func_call_context._timeout
        blocking = local_func_call_context._blocking
        callback = local_func_call_context._callback

        self._clear_call_context()

        nodeNum = None
        callId = str(self.generate_call_id())

        #build cmd desc message
        cmdDesc = msgs.CmdDesc()
        cmdDesc.type = upi_type
        cmdDesc.func_name = fname
        cmdDesc.call_id = callId

        if iface:
            cmdDesc.interface = iface

        if delay:
            exec_time = datetime.datetime.now() + datetime.timedelta(
                seconds=delay)
            blocking = False

        if exec_time:
            cmdDesc.exec_time = exec_time.strftime("%Y-%m-%d %H:%M:%S.%f")
            blocking = False

        #call check
        if exec_time and exec_time < datetime.datetime.now():
            raise Exception("Scheduling function: {}:{} call in past".format(
                upi_type, fname))

        #count nodes if list passed
        if hasattr(scope, '__iter__') and not isinstance(scope, str):
            nodeNum = len(scope)
        else:
            nodeNum = 1

        #set callback for this function call
        if callback:
            self.callbacks[callId] = CallIdCallback(callback, nodeNum)
            blocking = False

        #if blocking call, wait for response
        if blocking:
            asyncResultCollector = AsyncResultCollector(nodeNum)
            self._asyncResults[callId] = asyncResultCollector

        #Serialize kwargs (they contrain args)
        cmdDesc.serialization_type = msgs.CmdDesc.PICKLE
        msgContainer = [cmdDesc, kwargs]

        #TODO: currently sending cmd msg to each node separately;
        #it would be more efficient to exploit PUB/SUB zmq mechanism
        #create group with uuid and tell nodes to subscribe to this uuid
        #then send msg to group
        if hasattr(scope, '__iter__') and not isinstance(scope, str):
            for node in scope:
                self.send_cmd_to_node(node, callId, msgContainer)
        else:
            node = scope
            self.send_cmd_to_node(node, callId, msgContainer)

        #if blocking call, wait for response
        if blocking:
            response = asyncResultCollector.get(timeout=timeout)
            del self._asyncResults[callId]
            return response

        return None