Example #1
0
    def _read_from_file(self):
        buf = self._reader.readline().strip()
        if not buf:
            return

        _g_logger.debug("read message " + buf)
        ba = buf.split()
        command = ba.pop(0)
        arguments = ba

        message_id = utils.new_message_id()
        request_id = utils.new_message_id()
        request_doc = {
            'type': message_types.MessageTypes.REQUEST,
            'request_id': request_id,
            'message_id': message_id,
            'payload': {
                'command': command,
                'arguments': arguments
            }
        }

        # check for any retrans requests of this message
        if len(self._retrans) > self._request_number:
            rt = self._retrans[self._request_number]
            self._retrans_map[request_id] = rt
            rt.set_request_doc(request_doc)
        self._request_number += 1

        self._check_retrans(request_id, message_types.MessageTypes.REQUEST)
        dcm_events.register_callback(self.recv_obj.incoming_parent_q_message,
                                     args=[request_doc])
Example #2
0
    def _read_from_file(self):
        buf = self._reader.readline().strip()
        if not buf:
            return

        _g_logger.debug("read message " + buf)
        ba = buf.split()
        command = ba.pop(0)
        arguments = ba

        message_id = utils.new_message_id()
        request_id = utils.new_message_id()
        request_doc = {
            'type': message_types.MessageTypes.REQUEST,
            'request_id': request_id,
            'message_id': message_id,
            'payload': {'command': command, 'arguments': arguments}
        }

        # check for any retrans requests of this message
        if len(self._retrans) > self._request_number:
            rt = self._retrans[self._request_number]
            self._retrans_map[request_id] = rt
            rt.set_request_doc(request_doc)
        self._request_number += 1

        self._check_retrans(request_id, message_types.MessageTypes.REQUEST)
        dcm_events.register_callback(
            self.recv_obj.incoming_parent_q_message, args=[request_doc])
Example #3
0
 def _sm_send_status(self):
     status_doc = {'type': message_types.MessageTypes.STATUS,
                   'message_id': utils.new_message_id(),
                   'request_id': self._request_id,
                   'entity': "status send",
                   'agent_id': self._agent_id,
                   'state': self._sm._current_state,
                   'reply': self._response_doc}
     self._conn.send(status_doc)
Example #4
0
 def _sm_send_cancel(self, **kwargs):
     """
     This occurs when a user has asked to cancel a message.  If the session
     is not close, or will not imminently close, we simply send a cancel
     message (meaning put a cancel message next in the queue).
     """
     message_id = utils.new_message_id()
     cancel_doc = {'request_id': self._request_id,
                   'message_id': message_id,
                   'type': types.MessageTypes.CANCEL}
     self.send_doc(cancel_doc)
Example #5
0
 def _sm_acked_request_received(self, **kwargs):
     """
     In this case a retransmission of the request comes in after the user
     acknowledged the message.  Here we resend the ack.
     """
     # reply using the latest message id
     ack_doc = {'type': message_types.MessageTypes.ACK,
                'message_id': utils.new_message_id(),
                'request_id': self._request_id,
                'entity': "request_received",
                'agent_id': self._agent_id}
     self._conn.send(ack_doc)
Example #6
0
 def _sm_nacked_request_received(self, **kwargs):
     """
     This happens when a request is received after it has been nacked.
     This will occur if the first nack is lost or delayed.  We retransmit
     the nack
     """
     nack_doc = {'type': message_types.MessageTypes.NACK,
                 'message_id': utils.new_message_id(),
                 'request_id': self._request_id,
                 'entity': "request_received",
                 'error_message': "The agent already rejected this request",
                 'agent_id': self._agent_id}
     self._conn.send(nack_doc)
Example #7
0
 def _sm_send_cancel(self, **kwargs):
     """
     This occurs when a user has asked to cancel a message.  If the session
     is not close, or will not imminently close, we simply send a cancel
     message (meaning put a cancel message next in the queue).
     """
     message_id = utils.new_message_id()
     cancel_doc = {
         'request_id': self._request_id,
         'message_id': message_id,
         'type': types.MessageTypes.CANCEL
     }
     self.send_doc(cancel_doc)
Example #8
0
 def _sm_send_request(self, **kwargs):
     """
     Send a request. This event handler occurs when ever a RPC request is
     sent for the first time.
     """
     _g_logger.info("This initial request has been made.")
     send_doc = {'request_id': self._request_id,
                 'message_id': utils.new_message_id(),
                 'type': types.MessageTypes.REQUEST,
                 'payload': self._doc}
     message_timer = utils.MessageTimer(self._timeout,
                                        self.request_timeout,
                                        send_doc)
     self._send_request_message(message_timer)
Example #9
0
 def _sm_send_request(self, **kwargs):
     """
     Send a request. This event handler occurs when ever a RPC request is
     sent for the first time.
     """
     _g_logger.info("This initial request has been made.")
     send_doc = {
         'request_id': self._request_id,
         'message_id': utils.new_message_id(),
         'type': types.MessageTypes.REQUEST,
         'payload': self._doc
     }
     message_timer = utils.MessageTimer(self._timeout, self.request_timeout,
                                        send_doc)
     self._send_request_message(message_timer)
Example #10
0
    def _sm_acked_re_reply(self, **kwargs):
        self._db.update_record(self._request_id,
                               states.ReplyStates.REPLY,
                               reply_doc=self._response_doc)

        reply_doc = {'type': message_types.MessageTypes.REPLY,
                     'message_id': utils.new_message_id(),
                     'request_id': self._request_id,
                     'payload': self._response_doc,
                     'entity': "acked_reply",
                     'agent_id': self._agent_id}

        message_timer = utils.MessageTimer(self._timeout,
                                           self.reply_timeout,
                                           reply_doc)
        self._send_reply_message(message_timer)
Example #11
0
    def _sm_requesting_user_accepts(self, **kwargs):
        """
        The user decided to accept the message.  Here we will send the ack
        """
        self._db.new_record(self._request_id,
                            self._request_document,
                            None,
                            states.ReplyStates.ACKED,
                            self._agent_id)

        ack_doc = {'type': message_types.MessageTypes.ACK,
                   'message_id': utils.new_message_id(),
                   'request_id': self._request_id,
                   'entity': "user_accepts",
                   'agent_id': self._agent_id}
        self._conn.send(ack_doc)
Example #12
0
    def _send_bad_message_reply(self, incoming_doc, message):
        _g_logger.debug("Sending the bad message %s" % message)
        # we want to send a NACK to the message however it may be an error
        # because it was not formed with message_id or request_id.  In this
        # case we will send values in that place indicating that *a* message
        # was bad.  There will be almost no way for the sender to know which
        # one
        try:
            request_id = incoming_doc['request_id']
        except KeyError:
            request_id = ReplyRPC.MISSING_VALUE_STRING

        nack_doc = {'type': message_types.MessageTypes.NACK,
                    'message_id': utils.new_message_id(),
                    'request_id': request_id,
                    'error_message': message,
                    'agent_id': self._conf.agent_id}
        self._conn.send(nack_doc)
Example #13
0
    def _sm_reply_request_retrans(self, **kwargs):
        """
        After replying to a message we receive a retransmission of the
        original request.  This can happen if the remote end never receives
        an ack and the reply message is either lost or delayed.  Here we
        retransmit the reply.
        """
        reply_doc = {'type': message_types.MessageTypes.REPLY,
                     'message_id': utils.new_message_id(),
                     'request_id': self._request_id,
                     'payload': self._response_doc,
                     'entity': "request_retrans",
                     'agent_id': self._agent_id}

        message_timer = utils.MessageTimer(self._timeout,
                                           self.reply_timeout,
                                           reply_doc)
        self._send_reply_message(message_timer)
Example #14
0
    def _sm_requesting_user_rejects(self, **kwargs):
        """
        The user decides to reject the incoming request so we must send
        a nack to the remote side.
        """
        self._db.new_record(self._request_id,
                            self._request_document,
                            None,
                            states.ReplyStates.ACKED,
                            self._agent_id)

        nack_doc = {'type': message_types.MessageTypes.NACK,
                    'message_id': utils.new_message_id(),
                    'request_id': self._request_id,
                    'entity': "user_rejects",
                    'error_message': "The agent rejected the request.",
                    'agent_id': self._agent_id}
        self._conn.send(nack_doc)
Example #15
0
    def _sm_acked_reply(self, **kwargs):
        """
        This is the standard case.  A user has accepted the message and is
        now replying to it.  We send the reply.
        """
        self._response_doc = kwargs['message']

        self._db.update_record(self._request_id,
                               states.ReplyStates.REPLY,
                               reply_doc=self._response_doc)

        reply_doc = {'type': message_types.MessageTypes.REPLY,
                     'message_id': utils.new_message_id(),
                     'request_id': self._request_id,
                     'payload': self._response_doc,
                     'entity': "acked_reply",
                     'agent_id': self._agent_id}

        message_timer = utils.MessageTimer(self._timeout,
                                           self.reply_timeout,
                                           reply_doc)
        self._send_reply_message(message_timer)
Example #16
0
    def _sm_requesting_user_replies(self, **kwargs):
        """
        The user decides to reply before acknowledging the message.  Therefore
        we just send the reply and it acts as the ack and the reply
        """
        self._response_doc = kwargs['message']

        self._db.update_record(self._request_id,
                               states.ReplyStates.REPLY,
                               reply_doc=self._response_doc)

        reply_doc = {'type': message_types.MessageTypes.REPLY,
                     'message_id': utils.new_message_id(),
                     'request_id': self._request_id,
                     'payload': self._response_doc,
                     'entity': "user_replies",
                     'agent_id': self._agent_id}

        message_timer = utils.MessageTimer(self._timeout,
                                           self.reply_timeout,
                                           reply_doc)
        self._send_reply_message(message_timer)
Example #17
0
    def _process_doc(self, incoming_doc):
        if incoming_doc is None:
            return

        with tracer.RequestTracer(incoming_doc['request_id']):
            self._call_reply_observers("incoming_message", incoming_doc)
            _g_logger.debug("New message type %s" % incoming_doc['type'])

            # if the agent is misbehaving the AM might tell it to kill itself.
            # cold.
            if incoming_doc["type"] == message_types.MessageTypes.HEMLOCK:
                _g_logger.error("HEMLOCK: DCM told me to kill myself.")
                os.killpg(0, signal.SIGKILL)
                sys.exit(10)

            # if it is a alert message short circuit
            if incoming_doc["type"] == message_types.MessageTypes.ALERT_ACK:
                if self._id_system:
                    self._id_system.incoming_message(incoming_doc)
                return

            request_id = incoming_doc["request_id"]

            # is this request already in memory?
            if request_id in self._requests:
                _g_logger.debug("The message was found in the requests.")

                # send it through, state machine will deal with it
                req = self._requests[request_id]
                req.incoming_message(incoming_doc)
                return
            # if the request id has already been seen by the database
            db_record = self._db.lookup_req(request_id)
            if db_record:
                _g_logger.info("Inflating the record from the DB."
                               + request_id)
                req = ReplyRPC(
                    self,
                    self._conf.agent_id,
                    self._conn,
                    request_id,
                    incoming_doc,
                    self._db,
                    timeout=self._timeout,
                    reply_doc=db_record.reply_doc,
                    start_state=db_record.state)

                # this will probably be used in the near future so get it
                # on the memory list
                self._requests[request_id] = req
                req.incoming_message(incoming_doc)
                return

            if incoming_doc["type"] == message_types.MessageTypes.REQUEST:
                if len(list(self._requests.keys())) >=\
                        self._conf.messaging_max_at_once > -1:

                    # short circuit the case where the agent is too busy
                    dcm_logger.log_to_dcm_console_overloaded(
                        msg="The new request was rejected because the agent has too many outstanding requests.")
                    nack_doc = {
                        'type': message_types.MessageTypes.NACK,
                        'message_id': utils.new_message_id(),
                        'request_id': request_id,
                        'agent_id': self._conf.agent_id,
                        'error_message': ("The agent can only handle %d "
                                          "commands at once"
                                          % self._conf.messaging_max_at_once)}
                    self._conn.send(nack_doc)
                    return

                _g_logger.debug("A new request has come in.")

                req = ReplyRPC(
                    self,
                    self._conf.agent_id,
                    self._conn,
                    request_id,
                    incoming_doc,
                    self._db,
                    timeout=self._timeout)
                self._call_reply_observers("new_message", req)

                # only add the message if processing was successful
                self._requests[request_id] = req
                try:
                    self._dispatcher.incoming_request(req)
                except Exception:
                    _g_logger.exception("The dispatcher could not handle a "
                                        "message.")
                    del self._requests[request_id]
                    dcm_logger.log_to_dcm_console_messaging_error(
                        msg="The dispatcher could not handle the message.")
                    raise
            else:
                # if we have never heard of the ID and this is not a new
                # request we return a courtesy error
                _g_logger.debug("Unknown message ID sending a NACK")

                nack_doc = {'type': message_types.MessageTypes.NACK,
                            'message_id': utils.new_message_id(),
                            'request_id': request_id,
                            'agent_id': self._conf.agent_id,
                            'error_message':
                            "%s is an unknown ID" % request_id}
                self._conn.send(nack_doc)