Refactor configuration of message queue to be generic

Registered by Jay Pipes

In order to make the message queue generic and adaptable, I'm proposing we refactor the way that the message queue configuration variables are structured.

Currently, the message queue configuration variables are tied to RabbitMQ:

from nova/flags.py:

DEFINE_boolean('fake_rabbit', False, 'use a fake rabbit')
...
DEFINE_string('rabbit_host', 'localhost', 'rabbit host')
DEFINE_integer('rabbit_port', 5672, 'rabbit port')
DEFINE_string('rabbit_userid', 'guest', 'rabbit userid')
DEFINE_string('rabbit_password', 'guest', 'rabbit password')
DEFINE_string('rabbit_virtual_host', '/', 'rabbit virtual host')

A more future-proof and generic way to structure configuration might be to do something like the following:

DEFINE_string('mq_adapter', 'rabbitmq', 'What message queue to use? Default: RabbitMQ)
DEFINE_string('mq_rabbit_host', 'localhost', 'rabbit host')
DEFINE_integer('mq_rabbit_port', 5672, 'rabbit port')
DEFINE_string('mq_rabbit_userid', 'guest', 'rabbit userid')
DEFINE_string('mq_rabbit_password', 'guest', 'rabbit password')
DEFINE_string('mq_rabbit_virtual_host', '/', 'rabbit virtual host')

Since we are using gflags instead of something like Cement (which has support for namespaced configuration variables), I've prefixed the configuration variables that describe message queue functionality with "mq_".

I removed the fake_rabbit boolean flag and replaced it, instead, with a string flag called 'mq_adapter' which defaults to 'rabbitmq'.

In the test suites, we could add the following:

self.flags(mq_adapter="fake_rabbitmq")

or just:

self.flags(mq_adapter="fake")

which would simply fill the test case's message queue implementation with an instance of the fake MQ.

This would make a lot of code like this (from nova/rpc.py) more adaptable:

class Connection(connection.BrokerConnection):
    @classmethod
    def instance(cls):
        if not hasattr(cls, '_instance'):
            params = dict(hostname=FLAGS.rabbit_host,
                          port=FLAGS.rabbit_port,
                          userid=FLAGS.rabbit_userid,
                          password=FLAGS.rabbit_password,
                          virtual_host=FLAGS.rabbit_virtual_host)

            if FLAGS.fake_rabbit:
                params['backend_cls'] = fakerabbit.Backend

            cls._instance = cls(**params)
        return cls._instance

to something more like this:

class Connection(connection.BrokerConnection):
    @classmethod
    def instance(cls):
        if not hasattr(cls, '_instance'):
            mq = self._get_mq_adapter(FLAGS.mq_adapter)
            mq.configure(FLAGS)
            cls._instance = mq
        return cls._instance

        def _find_mq_adapter(self, adapter):
            if adapter == 'rabbitmq':
                from nova.mq.rabbit import RabbitMessageQueue as mq_adapter
            elif adapter == 'fake':
                from nova.mq.fake import FakeMessageQueue as mq_adapter
            return mq_adapter()

Blueprint information

Status:
Complete
Approver:
None
Priority:
Undefined
Drafter:
Jay Pipes
Direction:
Needs approval
Assignee:
None
Definition:
Obsolete
Series goal:
None
Implementation:
Unknown
Milestone target:
None
Completed by
Jay Pipes

Related branches

Sprints

Whiteboard

After lots of research into this, I've decided that using the existing Celery distributed task queue manager is probably the best solution to this. There is a blueprint and wiki spec for it here:

https://blueprints.launchpad.net/nova/+spec/bexar-message-queue-celery
http://wiki.openstack.org/UseCeleryAsQueueManager

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.