class Dispatcher: debug = False def __init__(self, debug=False): self.debug = debug self._init() def wait(self): log.info("Waiting for messages..") timeout = 600 while True: try: # Close the Django DB connection before processing # every incoming message. This plays nicely with # DB connection pooling, if enabled and allows # the dispatcher to recover from broken connections # gracefully. close_connection() msg = self.client.basic_wait(timeout=timeout) if not msg: log.warning( "Idle connection for %d seconds. Will connect" " to a different host. Verify that" " snf-ganeti-eventd is running!!", timeout) self.client.reconnect() except SystemExit: break except Exception as e: log.exception("Caught unexpected exception: %s", e) self.client.basic_cancel() self.client.close() def _init(self): log.info("Initializing") self.client = AMQPClient(logger=log_amqp) # Connect to AMQP host self.client.connect() # Declare queues and exchanges exchange = settings.EXCHANGE_GANETI exchange_dl = queues.convert_exchange_to_dead(exchange) self.client.exchange_declare(exchange=exchange, type="topic") self.client.exchange_declare(exchange=exchange_dl, type="topic") for queue in queues.QUEUES: # Queues are mirrored to all RabbitMQ brokers self.client.queue_declare(queue=queue, mirrored=True, dead_letter_exchange=exchange_dl) # Declare the corresponding dead-letter queue queue_dl = queues.convert_queue_to_dead(queue) self.client.queue_declare(queue=queue_dl, mirrored=True) # Bind queues to handler methods for binding in queues.BINDINGS: try: callback = getattr(callbacks, binding[3]) except AttributeError: log.error("Cannot find callback %s", binding[3]) raise SystemExit(1) queue = binding[0] exchange = binding[1] routing_key = binding[2] self.client.queue_bind(queue=queue, exchange=exchange, routing_key=routing_key) self.client.basic_consume(queue=binding[0], callback=callback, prefetch_count=5) queue_dl = queues.convert_queue_to_dead(queue) exchange_dl = queues.convert_exchange_to_dead(exchange) # Bind the corresponding dead-letter queue self.client.queue_bind(queue=queue_dl, exchange=exchange_dl, routing_key=routing_key) log.debug("Binding %s(%s) to queue %s with handler %s", exchange, routing_key, queue, binding[3])
class Dispatcher: debug = False def __init__(self, debug=False): self.debug = debug self._init() def wait(self): log.info("Waiting for messages..") timeout = DISPATCHER_RECONNECT_TIMEOUT while True: try: # Close the Django DB connection before processing # every incoming message. This plays nicely with # DB connection pooling, if enabled and allows # the dispatcher to recover from broken connections # gracefully. close_connection() msg = self.client.basic_wait(timeout=timeout) if not msg: log.warning( "Idle connection for %d seconds. Will connect" " to a different host. Verify that" " snf-ganeti-eventd is running!!", timeout) self.client.reconnect(timeout=1) except AMQPConnectionError as e: log.error("AMQP connection failed: %s" % e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) except select.error as e: if e[0] != errno.EINTR: log.exception("Caught unexpected exception: %s", e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) else: break except (SystemExit, KeyboardInterrupt): break except Exception as e: log.exception("Caught unexpected exception: %s", e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) log.info("Clean up AMQP connection before exit") self.client.basic_cancel(timeout=1) self.client.close(timeout=1) def _init(self): log.info("Initializing") # Set confirm buffer to 1 for heartbeat messages self.client = AMQPClient(logger=log_amqp, confirm_buffer=1) # Connect to AMQP host self.client.connect() # Declare queues and exchanges exchange = settings.EXCHANGE_GANETI exchange_dl = queues.convert_exchange_to_dead(exchange) self.client.exchange_declare(exchange=exchange, type="topic") self.client.exchange_declare(exchange=exchange_dl, type="topic") for queue in queues.QUEUES: # Queues are mirrored to all RabbitMQ brokers self.client.queue_declare(queue=queue, mirrored=True, dead_letter_exchange=exchange_dl) # Declare the corresponding dead-letter queue queue_dl = queues.convert_queue_to_dead(queue) self.client.queue_declare(queue=queue_dl, mirrored=True) # Bind queues to handler methods for binding in queues.BINDINGS: try: callback = getattr(callbacks, binding[3]) except AttributeError: log.error("Cannot find callback %s", binding[3]) raise SystemExit(1) queue = binding[0] exchange = binding[1] routing_key = binding[2] self.client.queue_bind(queue=queue, exchange=exchange, routing_key=routing_key) self.client.basic_consume(queue=binding[0], callback=callback, prefetch_count=5) queue_dl = queues.convert_queue_to_dead(queue) exchange_dl = queues.convert_exchange_to_dead(exchange) # Bind the corresponding dead-letter queue self.client.queue_bind(queue=queue_dl, exchange=exchange_dl, routing_key=routing_key) log.debug("Binding %s(%s) to queue %s with handler %s", exchange, routing_key, queue, binding[3]) # Declare the queue that will be used for receiving requests, e.g. a # status check request hostname, pid = get_hostname(), os.getpid() queue = queues.get_dispatcher_request_queue(hostname, pid) self.client.queue_declare(queue=queue, mirrored=True, ttl=REQUEST_QUEUE_TTL) self.client.basic_consume(queue=queue, callback=handle_request) log.debug("Binding %s(%s) to queue %s with handler 'hadle_request'", exchange, routing_key, queue)
class Dispatcher: debug = False def __init__(self, debug=False): self.debug = debug self._init() def wait(self): log.info("Waiting for messages..") timeout = 600 while True: try: # Close the Django DB connection before processing # every incoming message. This plays nicely with # DB connection pooling, if enabled and allows # the dispatcher to recover from broken connections # gracefully. close_connection() msg = self.client.basic_wait(timeout=timeout) if not msg: log.warning( "Idle connection for %d seconds. Will connect" " to a different host. Verify that" " snf-ganeti-eventd is running!!", timeout, ) self.client.reconnect() except SystemExit: break except Exception as e: log.exception("Caught unexpected exception: %s", e) self.client.basic_cancel() self.client.close() def _init(self): log.info("Initializing") self.client = AMQPClient(logger=log_amqp) # Connect to AMQP host self.client.connect() # Declare queues and exchanges exchange = settings.EXCHANGE_GANETI exchange_dl = queues.convert_exchange_to_dead(exchange) self.client.exchange_declare(exchange=exchange, type="topic") self.client.exchange_declare(exchange=exchange_dl, type="topic") for queue in queues.QUEUES: # Queues are mirrored to all RabbitMQ brokers self.client.queue_declare(queue=queue, mirrored=True, dead_letter_exchange=exchange_dl) # Declare the corresponding dead-letter queue queue_dl = queues.convert_queue_to_dead(queue) self.client.queue_declare(queue=queue_dl, mirrored=True) # Bind queues to handler methods for binding in queues.BINDINGS: try: callback = getattr(callbacks, binding[3]) except AttributeError: log.error("Cannot find callback %s", binding[3]) raise SystemExit(1) queue = binding[0] exchange = binding[1] routing_key = binding[2] self.client.queue_bind(queue=queue, exchange=exchange, routing_key=routing_key) self.client.basic_consume(queue=binding[0], callback=callback, prefetch_count=5) queue_dl = queues.convert_queue_to_dead(queue) exchange_dl = queues.convert_exchange_to_dead(exchange) # Bind the corresponding dead-letter queue self.client.queue_bind(queue=queue_dl, exchange=exchange_dl, routing_key=routing_key) log.debug("Binding %s(%s) to queue %s with handler %s", exchange, routing_key, queue, binding[3])
def main(): parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', default=False, dest='verbose', help='Enable verbose logging') parser.add_option('--host', default=BROKER_HOST, dest='host', help='RabbitMQ host (default: %s)' % BROKER_HOST) parser.add_option('--port', default=BROKER_PORT, dest='port', help='RabbitMQ port (default: %s)' % BROKER_PORT, type='int') parser.add_option('--user', default=BROKER_USER, dest='user', help='RabbitMQ user (default: %s)' % BROKER_USER) parser.add_option('--password', default=BROKER_PASSWORD, dest='password', help='RabbitMQ password (default: %s)' % BROKER_PASSWORD) parser.add_option('--vhost', default=BROKER_VHOST, dest='vhost', help='RabbitMQ vhost (default: %s)' % BROKER_VHOST) parser.add_option('--queue', default=CONSUMER_QUEUE, dest='queue', help='RabbitMQ queue (default: %s)' % CONSUMER_QUEUE) parser.add_option('--exchange', default=CONSUMER_EXCHANGE, dest='exchange', help='RabbitMQ exchange (default: %s)' % CONSUMER_EXCHANGE) parser.add_option('--key', default=CONSUMER_KEY, dest='key', help='RabbitMQ key (default: %s)' % CONSUMER_KEY) parser.add_option('--callback', default=None, dest='callback', help='Callback function to consume messages') parser.add_option('--test', action='store_true', default=False, dest='test', help='Produce a dummy message for testing') opts, args = parser.parse_args() DEBUG = False if opts.verbose: DEBUG = True logging.basicConfig( format='%(asctime)s [%(levelname)s] %(name)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.DEBUG if DEBUG else logging.INFO) logger = logging.getLogger('dispatcher') host = 'amqp://%s:%s@%s:%s' % (opts.user, opts.password, opts.host, opts.port) queue = opts.queue key = opts.key exchange = opts.exchange client = AMQPClient(hosts=[host]) client.connect() if opts.test: client.exchange_declare(exchange=exchange, type='topic') client.basic_publish(exchange=exchange, routing_key=key, body= json.dumps({"test": "0123456789"})) client.close() sys.exit() callback = None if opts.callback: cb = opts.callback.rsplit('.', 1) if len(cb) == 2: __import__(cb[0]) cb_module = sys.modules[cb[0]] callback = getattr(cb_module, cb[1]) def handle_message(client, msg): logger.debug('%s', msg) if callback: callback(msg) client.basic_ack(msg) client.queue_declare(queue=queue) client.queue_bind(queue=queue, exchange=exchange, routing_key=key) client.basic_consume(queue=queue, callback=handle_message) try: while True: client.basic_wait() except KeyboardInterrupt: pass finally: client.close()
def main(): parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', default=False, dest='verbose', help='Enable verbose logging') parser.add_option('--host', default=BROKER_HOST, dest='host', help='RabbitMQ host (default: %s)' % BROKER_HOST) parser.add_option('--port', default=BROKER_PORT, dest='port', help='RabbitMQ port (default: %s)' % BROKER_PORT, type='int') parser.add_option('--user', default=BROKER_USER, dest='user', help='RabbitMQ user (default: %s)' % BROKER_USER) parser.add_option('--password', default=BROKER_PASSWORD, dest='password', help='RabbitMQ password (default: %s)' % BROKER_PASSWORD) parser.add_option('--vhost', default=BROKER_VHOST, dest='vhost', help='RabbitMQ vhost (default: %s)' % BROKER_VHOST) parser.add_option('--queue', default=CONSUMER_QUEUE, dest='queue', help='RabbitMQ queue (default: %s)' % CONSUMER_QUEUE) parser.add_option('--exchange', default=CONSUMER_EXCHANGE, dest='exchange', help='RabbitMQ exchange (default: %s)' % CONSUMER_EXCHANGE) parser.add_option('--key', default=CONSUMER_KEY, dest='key', help='RabbitMQ key (default: %s)' % CONSUMER_KEY) parser.add_option('--callback', default=None, dest='callback', help='Callback function to consume messages') parser.add_option('--test', action='store_true', default=False, dest='test', help='Produce a dummy message for testing') opts, args = parser.parse_args() DEBUG = False if opts.verbose: DEBUG = True logging.basicConfig( format='%(asctime)s [%(levelname)s] %(name)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.DEBUG if DEBUG else logging.INFO) logger = logging.getLogger('dispatcher') host = 'amqp://%s:%s@%s:%s' % (opts.user, opts.password, opts.host, opts.port) queue = opts.queue key = opts.key exchange = opts.exchange client = AMQPClient(hosts=[host]) client.connect() if opts.test: client.exchange_declare(exchange=exchange, type='topic') client.basic_publish(exchange=exchange, routing_key=key, body=json.dumps({"test": "0123456789"})) client.close() sys.exit() callback = None if opts.callback: cb = opts.callback.rsplit('.', 1) if len(cb) == 2: __import__(cb[0]) cb_module = sys.modules[cb[0]] callback = getattr(cb_module, cb[1]) def handle_message(client, msg): logger.debug('%s', msg) if callback: callback(msg) client.basic_ack(msg) client.queue_declare(queue=queue) client.queue_bind(queue=queue, exchange=exchange, routing_key=key) client.basic_consume(queue=queue, callback=handle_message) try: while True: client.basic_wait() except KeyboardInterrupt: pass finally: client.close()
class Dispatcher: debug = False def __init__(self, debug=False): self.debug = debug self._init() def wait(self): log.info("Waiting for messages..") timeout = DISPATCHER_RECONNECT_TIMEOUT while True: try: # Close the Django DB connection before processing # every incoming message. This plays nicely with # DB connection pooling, if enabled and allows # the dispatcher to recover from broken connections # gracefully. close_connection() msg = self.client.basic_wait(timeout=timeout) if not msg: log.warning("Idle connection for %d seconds. Will connect" " to a different host. Verify that" " snf-ganeti-eventd is running!!", timeout) self.client.reconnect(timeout=1) except AMQPConnectionError as e: log.error("AMQP connection failed: %s" % e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) except select.error as e: if e[0] != errno.EINTR: log.exception("Caught unexpected exception: %s", e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) else: break except (SystemExit, KeyboardInterrupt): break except Exception as e: log.exception("Caught unexpected exception: %s", e) log.warning("Sleeping for %d seconds before retrying to " "connect to an AMQP broker" % DISPATCHER_FAILED_CONNECTION_WAIT) time.sleep(DISPATCHER_FAILED_CONNECTION_WAIT) log.info("Clean up AMQP connection before exit") self.client.basic_cancel(timeout=1) self.client.close(timeout=1) def _init(self): log.info("Initializing") # Set confirm buffer to 1 for heartbeat messages self.client = AMQPClient(logger=log_amqp, confirm_buffer=1) # Connect to AMQP host self.client.connect() # Declare queues and exchanges exchange = settings.EXCHANGE_GANETI exchange_dl = queues.convert_exchange_to_dead(exchange) self.client.exchange_declare(exchange=exchange, type="topic") self.client.exchange_declare(exchange=exchange_dl, type="topic") for queue in queues.QUEUES: # Queues are mirrored to all RabbitMQ brokers self.client.queue_declare(queue=queue, mirrored=True, dead_letter_exchange=exchange_dl) # Declare the corresponding dead-letter queue queue_dl = queues.convert_queue_to_dead(queue) self.client.queue_declare(queue=queue_dl, mirrored=True) # Bind queues to handler methods for binding in queues.BINDINGS: try: callback = getattr(callbacks, binding[3]) except AttributeError: log.error("Cannot find callback %s", binding[3]) raise SystemExit(1) queue = binding[0] exchange = binding[1] routing_key = binding[2] self.client.queue_bind(queue=queue, exchange=exchange, routing_key=routing_key) self.client.basic_consume(queue=binding[0], callback=callback, prefetch_count=5) queue_dl = queues.convert_queue_to_dead(queue) exchange_dl = queues.convert_exchange_to_dead(exchange) # Bind the corresponding dead-letter queue self.client.queue_bind(queue=queue_dl, exchange=exchange_dl, routing_key=routing_key) log.debug("Binding %s(%s) to queue %s with handler %s", exchange, routing_key, queue, binding[3]) # Declare the queue that will be used for receiving requests, e.g. a # status check request hostname, pid = get_hostname(), os.getpid() queue = queues.get_dispatcher_request_queue(hostname, pid) self.client.queue_declare(queue=queue, mirrored=True, ttl=REQUEST_QUEUE_TTL) self.client.basic_consume(queue=queue, callback=handle_request) log.debug("Binding %s(%s) to queue %s with handler 'hadle_request'", exchange, routing_key, queue)