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)
def test_get_dispatcher_request_queue(self): expected = "snf:dispatcher:{0}:{1}".format(self.hostname, self.pid) converted = queues.get_dispatcher_request_queue( self.hostname, self.pid ) self.assertEqual(expected, converted)
def check_dispatcher_status(pid_file): """Check the status of a running snf-dispatcher process. Check the status of a running snf-dispatcher process, the PID of which is contained in the 'pid_file'. This function will send a 'status-check' message to the running snf-dispatcher, wait for dispatcher's response and pretty-print the results. """ dispatcher_pid = pidlockfile.read_pid_from_pidfile(pid_file) if dispatcher_pid is None: sys.stdout.write("snf-dispatcher with PID file '%s' is not running." " PID file does not exist\n" % pid_file) sys.exit(1) sys.stdout.write("snf-dispatcher (PID: %s): running\n" % dispatcher_pid) hostname = get_hostname() local_queue = "snf:check_tool:%s:%s" % (hostname, os.getpid()) dispatcher_queue = queues.get_dispatcher_request_queue( hostname, dispatcher_pid) log_amqp.setLevel(logging.WARNING) try: client = AMQPClient(logger=log_amqp) client.connect() client.queue_declare(queue=local_queue, mirrored=False, exclusive=True) client.basic_consume(queue=local_queue, callback=lambda x, y: 0, no_ack=True) msg = json.dumps({"action": "status-check", "reply_to": local_queue}) client.basic_publish("", dispatcher_queue, msg) except: sys.stdout.write("Error while connecting with AMQP\nError:\n") traceback.print_exc() sys.exit(1) sys.stdout.write("AMQP -> snf-dispatcher: ") msg = client.basic_wait(timeout=CHECK_TOOL_ACK_TIMEOUT) if msg is None: sys.stdout.write("fail\n") sys.stdout.write("ERROR: No reply from snf-dipatcher after '%s'" " seconds.\n" % CHECK_TOOL_ACK_TIMEOUT) sys.exit(1) else: try: body = json.loads(msg["body"]) assert (body["action"] == "status-check"), "Invalid action" assert (body["status"] == "started"), "Invalid status" sys.stdout.write("ok\n") except Exception as e: sys.stdout.write("Received invalid msg from snf-dispatcher:" " msg: %s error: %s\n" % (msg, e)) sys.exit(1) msg = client.basic_wait(timeout=CHECK_TOOL_REPORT_TIMEOUT) if msg is None: sys.stdout.write("fail\n") sys.stdout.write("ERROR: No status repot after '%s' seconds.\n" % CHECK_TOOL_REPORT_TIMEOUT) sys.exit(1) sys.stdout.write("Backends:\n") status = json.loads(msg["body"])["status"] for backend, bstatus in sorted(status.items()): sys.stdout.write(" * %s: \n" % backend) sys.stdout.write(" snf-dispatcher -> ganeti: %s\n" % bstatus["RAPI"]) sys.stdout.write(" snf-ganeti-eventd -> AMQP: %s\n" % bstatus["eventd"]) sys.exit(0)
def check_dispatcher_status(pid_file): """Check the status of a running snf-dispatcher process. Check the status of a running snf-dispatcher process, the PID of which is contained in the 'pid_file'. This function will send a 'status-check' message to the running snf-dispatcher, wait for dispatcher's response and pretty-print the results. """ dispatcher_pid = pidlockfile.read_pid_from_pidfile(pid_file) if dispatcher_pid is None: sys.stdout.write("snf-dispatcher with PID file '%s' is not running." " PID file does not exist\n" % pid_file) sys.exit(1) sys.stdout.write("snf-dispatcher (PID: %s): running\n" % dispatcher_pid) hostname = get_hostname() local_queue = "snf:check_tool:%s:%s" % (hostname, os.getpid()) dispatcher_queue = queues.get_dispatcher_request_queue(hostname, dispatcher_pid) log_amqp.setLevel(logging.WARNING) try: client = AMQPClient(logger=log_amqp) client.connect() client.queue_declare(queue=local_queue, mirrored=False, exclusive=True) client.basic_consume(queue=local_queue, callback=lambda x, y: 0, no_ack=True) msg = json.dumps({"action": "status-check", "reply_to": local_queue}) client.basic_publish("", dispatcher_queue, msg) except: sys.stdout.write("Error while connecting with AMQP\nError:\n") traceback.print_exc() sys.exit(1) sys.stdout.write("AMQP -> snf-dispatcher: ") msg = client.basic_wait(timeout=CHECK_TOOL_ACK_TIMEOUT) if msg is None: sys.stdout.write("fail\n") sys.stdout.write("ERROR: No reply from snf-dipatcher after '%s'" " seconds.\n" % CHECK_TOOL_ACK_TIMEOUT) sys.exit(1) else: try: body = json.loads(msg["body"]) assert(body["action"] == "status-check"), "Invalid action" assert(body["status"] == "started"), "Invalid status" sys.stdout.write("ok\n") except Exception as e: sys.stdout.write("Received invalid msg from snf-dispatcher:" " msg: %s error: %s\n" % (msg, e)) sys.exit(1) msg = client.basic_wait(timeout=CHECK_TOOL_REPORT_TIMEOUT) if msg is None: sys.stdout.write("fail\n") sys.stdout.write("ERROR: No status repot after '%s' seconds.\n" % CHECK_TOOL_REPORT_TIMEOUT) sys.exit(1) sys.stdout.write("Backends:\n") status = json.loads(msg["body"])["status"] for backend, bstatus in sorted(status.items()): sys.stdout.write(" * %s: \n" % backend) sys.stdout.write(" snf-dispatcher -> ganeti: %s\n" % bstatus["RAPI"]) sys.stdout.write(" snf-ganeti-eventd -> AMQP: %s\n" % bstatus["eventd"]) sys.exit(0)
def test_get_dispatcher_request_queue(self): expected = "snf:dispatcher:{0}:{1}".format(self.hostname, self.pid) converted = queues.get_dispatcher_request_queue( self.hostname, self.pid) self.assertEqual(expected, converted)