예제 #1
0
class EventReceiverAmqp(threading.Thread):
    """EventReceiver part of the EventManagerAmqp

    This part of the EventManagerAmqp is responsible for receiving events
    from the message broker using the protocol AMQP. Only configured event
    types were processed (e.g. cmdb.core.objects.added)
    """
    def __init__(self,
                 receiver_callback,
                 flag_shutdown,
                 process_id=None,
                 event_types=["#"]):
        """Creates an instance of EventReceiverAmqp

        Args:
            receiver_callback(func): callback function for processing
                received events
            flag_shutdown(threading.Event): flag for handling shutdown
            process_id(str): process identifier (process name)
            event_types(list): list of event types, that will be processed
        """
        super(EventReceiverAmqp, self).__init__()
        self.__receiver_callback = receiver_callback
        self.__flag_shutdown = flag_shutdown
        self.__process_id = process_id
        self.__event_types = event_types

        # get configuration
        self.__config_mq = SystemConfigReader().get_all_values_from_section(
            'MessageQueueing')
        self.__config_host = self.__config_mq.get("host", "127.0.0.1")
        self.__config_port = self.__config_mq.get("port", "5672")
        self.__config_username = self.__config_mq.get("username", "guest")
        self.__config_password = self.__config_mq.get("password", "guest")
        self.__config_exchange = self.__config_mq.get("exchange",
                                                      "datagerry.eventbus")
        self.__config_retries = int(
            self.__config_mq.get("connection_attempts", "5"))
        self.__config_retrydelay = int(self.__config_mq.get(
            "retry_delay", "6"))
        self.__config_tls = False
        if self.__config_mq.get("use_tls",
                                "False") in ("true", "True", "1", "yes"):
            self.__config_tls = True

        # define variables
        self.__connection = None
        self.__channel = None

    def __process_event_cb(self, ch, method, properties, body):
        """event processing

        this callback function is executed, if an event was reveived.

        Args:
            ch: AMQP channel
            method: AMQP method
            properties: AMQP properties
            body: AMQP message body
        """
        event = Event.create_event(body)
        # allow None values, if event receiving should be ignored
        if self.__receiver_callback:
            self.__receiver_callback(event)

    def __check_shutdown_flag(self):
        """check, if the shutdown flag was set"""
        # reinstall shutdown check
        self.__connection.add_timeout(2, self.__check_shutdown_flag)
        # check shutdown flag
        if self.__flag_shutdown.is_set():
            self.__channel.stop_consuming()
            self.__connection.close()

    def __init_connection(self):
        """create a connection to message broker"""
        try:
            # init connection to broker
            credentials = pika.credentials.PlainCredentials(
                self.__config_username, self.__config_password)
            self.__connection = pika.BlockingConnection(
                pika.ConnectionParameters(
                    host=self.__config_host,
                    port=self.__config_port,
                    connection_attempts=self.__config_retries,
                    retry_delay=self.__config_retrydelay,
                    credentials=credentials,
                    ssl=self.__config_tls))
            self.__channel = self.__connection.channel()
            self.__channel.exchange_declare(exchange=self.__config_exchange,
                                            exchange_type="topic")
            queue_name = ""
            if self.__process_id:
                queue_name = "{}.{}".format(self.__config_exchange,
                                            self.__process_id)
            queue_declare_result = self.__channel.queue_declare(
                queue=queue_name, exclusive=True)
            queue_handler = queue_declare_result.method.queue
            for event_type in self.__event_types:
                self.__channel.queue_bind(exchange=self.__config_exchange,
                                          queue=queue_handler,
                                          routing_key=event_type)

            # register callback function for event handling
            self.__channel.basic_consume(self.__process_event_cb,
                                         queue=queue_handler,
                                         no_ack=True)
        except AMQPConnectionError:
            LOGGER.error("{}: EventReceiverAmqp connection error".format(
                self.__process_id))
            self.__flag_shutdown.set()

    def run(self):
        """run the event receiver"""
        # init connection to broker
        self.__init_connection()
        while not self.__flag_shutdown.is_set():
            try:
                # start handling events
                self.__connection.add_timeout(2, self.__check_shutdown_flag)
                self.__channel.start_consuming()
            # handle AMQP connection errors
            except AMQPConnectionError:
                LOGGER.warning(
                    "connection to broker lost, try to reconnect...")
                self.__init_connection()
예제 #2
0
class EventSenderAmqp(threading.Thread):
    """EventSender part of the EventManagerAmqp

    This part of the EventManagerAmqp is responsible for sending events
    to the message broker using the protocol AMQP.
    """
    def __init__(self, message_queue, flag_shutdown, process_id=None):
        """Creates an instance of EventSenderAmqp

        Args:
            message_queue(queue.Queue): handler of a queue for sending events
            flag_shutdown(threading.Event): flag for handling shutdown
            process_id(str): process identifier (process name)
        """
        super(EventSenderAmqp, self).__init__()
        self.__queue = message_queue
        self.__flag_shutdown = flag_shutdown
        self.__process_id = process_id

        # get configuration
        self.__config_mq = SystemConfigReader().get_all_values_from_section(
            'MessageQueueing')
        self.__config_host = self.__config_mq.get("host", "127.0.0.1")
        self.__config_port = self.__config_mq.get("port", "5672")
        self.__config_username = self.__config_mq.get("username", "guest")
        self.__config_password = self.__config_mq.get("password", "guest")
        self.__config_exchange = self.__config_mq.get("exchange",
                                                      "datagerry.eventbus")
        self.__config_retries = int(
            self.__config_mq.get("connection_attempts", "5"))
        self.__config_retrydelay = int(self.__config_mq.get(
            "retry_delay", "6"))
        self.__config_tls = False
        if self.__config_mq.get("use_tls",
                                "False") in ("true", "True", "1", "yes"):
            self.__config_tls = True

        # define variables
        self.__connection = None
        self.__channel = None

    def __init_connection(self):
        """create a connection to message broker"""
        try:
            credentials = pika.credentials.PlainCredentials(
                self.__config_username, self.__config_password)
            self.__connection = pika.BlockingConnection(
                pika.ConnectionParameters(
                    host=self.__config_host,
                    port=self.__config_port,
                    connection_attempts=self.__config_retries,
                    retry_delay=self.__config_retrydelay,
                    credentials=credentials,
                    ssl=self.__config_tls))
            self.__channel = self.__connection.channel()
            self.__channel.exchange_declare(exchange=self.__config_exchange,
                                            exchange_type="topic")
        except pika.exceptions.AMQPConnectionError:
            LOGGER.error("{}: EventSenderAmqp connection error".format(
                self.__process_id))
            self.__flag_shutdown.set()

    def run(self):
        """run the event sender"""
        # init connection to broker
        self.__init_connection()

        # check queue for new events
        while not self.__flag_shutdown.is_set():
            try:
                try:
                    event = self.__queue.get(block=True, timeout=2)
                    event_type = event.get_type()
                    event_serialized = event.json_repr()
                    self.__channel.basic_publish(
                        exchange=self.__config_exchange,
                        routing_key=event_type,
                        body=event_serialized)
                except queue.Empty:
                    self.__connection.process_data_events()
            # handle AMQP connection errors
            except pika.exceptions.AMQPConnectionError:
                LOGGER.warning(
                    "connection to broker lost, try to reconnect...")
                self.__init_connection()