Add support for multiple RPC workers under Metaplugin

Metaplugin needs a fix to support multiple RPC workers properly
because a plugin which supports multiple RPC workers cannot
initialize RPC connections at plugin initialization.

Closes-Bug: #1300570
Change-Id: I584f70abb8969054cd4edc8f914d00f6be930bab
This commit is contained in:
Itsuro Oda 2014-04-02 13:24:42 +09:00
parent 3b3313e73b
commit 22a7c75ee4
5 changed files with 47 additions and 9 deletions

View File

@ -335,3 +335,18 @@ class NeutronPluginBaseV2(object):
defined plugin API. defined plugin API.
""" """
raise NotImplementedError raise NotImplementedError
def rpc_workers_supported(self):
"""Return whether the plugin supports multiple RPC workers.
A plugin that supports multiple RPC workers should override the
start_rpc_listener method to ensure that this method returns True and
that start_rpc_listener is called at the appropriate time.
Alternately, a plugin can override this method to customize detection
of support for multiple rpc workers
.. note:: this method is optional, as it was not part of the originally
defined plugin API.
"""
return (self.__class__.start_rpc_listener !=
NeutronPluginBaseV2.start_rpc_listener)

View File

@ -95,7 +95,7 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
plugin_list = [plugin_set.split(':') plugin_list = [plugin_set.split(':')
for plugin_set for plugin_set
in cfg.CONF.META.plugin_list.split(',')] in cfg.CONF.META.plugin_list.split(',')]
rpc_flavor = cfg.CONF.META.rpc_flavor self.rpc_flavor = cfg.CONF.META.rpc_flavor
topic_save = topics.PLUGIN topic_save = topics.PLUGIN
topic_fake = topic_save + '-metaplugin' topic_fake = topic_save + '-metaplugin'
for flavor, plugin_provider in plugin_list: for flavor, plugin_provider in plugin_list:
@ -104,7 +104,7 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
# This enforces the plugin specified by rpc_flavor is only # This enforces the plugin specified by rpc_flavor is only
# consumer of 'q-plugin'. It is a bit tricky but there is no # consumer of 'q-plugin'. It is a bit tricky but there is no
# bad effect. # bad effect.
if rpc_flavor and rpc_flavor != flavor: if self.rpc_flavor and self.rpc_flavor != flavor:
topics.PLUGIN = topic_fake topics.PLUGIN = topic_fake
self.plugins[flavor] = self._load_plugin(plugin_provider) self.plugins[flavor] = self._load_plugin(plugin_provider)
topics.PLUGIN = topic_save topics.PLUGIN = topic_save
@ -135,9 +135,9 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
self.supported_extension_aliases += ['router', 'ext-gw-mode', self.supported_extension_aliases += ['router', 'ext-gw-mode',
'extraroute'] 'extraroute']
if rpc_flavor and rpc_flavor not in self.plugins: if self.rpc_flavor and self.rpc_flavor not in self.plugins:
raise exc.Invalid(_('rpc_flavor %s is not plugin list') % raise exc.Invalid(_('rpc_flavor %s is not plugin list') %
rpc_flavor) self.rpc_flavor)
self.extension_map = {} self.extension_map = {}
if not cfg.CONF.META.extension_map == '': if not cfg.CONF.META.extension_map == '':
@ -203,6 +203,15 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
flavor = self._get_flavor_by_network_id(context, network['id']) flavor = self._get_flavor_by_network_id(context, network['id'])
network[ext_flavor.FLAVOR_NETWORK] = flavor network[ext_flavor.FLAVOR_NETWORK] = flavor
def start_rpc_listener(self):
return self.plugins[self.rpc_flavor].start_rpc_listener()
def rpc_workers_supported(self):
#NOTE: If a plugin which supports multiple RPC workers is desired
# to handle RPC, rpc_flavor must be specified.
return (self.rpc_flavor and
self.plugins[self.rpc_flavor].rpc_workers_supported())
def create_network(self, context, network): def create_network(self, context, network):
n = network['network'] n = network['network']
flavor = n.get(ext_flavor.FLAVOR_NETWORK) flavor = n.get(ext_flavor.FLAVOR_NETWORK)

View File

@ -24,7 +24,6 @@ from oslo.config import cfg
from neutron.common import config from neutron.common import config
from neutron import context from neutron import context
from neutron import manager from neutron import manager
from neutron import neutron_plugin_base_v2
from neutron.openstack.common.db.sqlalchemy import session from neutron.openstack.common.db.sqlalchemy import session
from neutron.openstack.common import excutils from neutron.openstack.common import excutils
from neutron.openstack.common import importutils from neutron.openstack.common import importutils
@ -137,10 +136,9 @@ def serve_rpc():
# If 0 < rpc_workers then start_rpc_listener would be called in a # If 0 < rpc_workers then start_rpc_listener would be called in a
# subprocess and we cannot simply catch the NotImplementedError. It is # subprocess and we cannot simply catch the NotImplementedError. It is
# simpler to check this up front by testing whether the plugin overrides # simpler to check this up front by testing whether the plugin supports
# start_rpc_listener. # multiple RPC workers.
base = neutron_plugin_base_v2.NeutronPluginBaseV2 if not plugin.rpc_workers_supported():
if plugin.__class__.start_rpc_listener == base.start_rpc_listener:
LOG.debug(_("Active plugin doesn't implement start_rpc_listener")) LOG.debug(_("Active plugin doesn't implement start_rpc_listener"))
if 0 < cfg.CONF.rpc_workers: if 0 < cfg.CONF.rpc_workers:
msg = _("'rpc_workers = %d' ignored because start_rpc_listener " msg = _("'rpc_workers = %d' ignored because start_rpc_listener "

View File

@ -70,3 +70,7 @@ class Fake2(Fake1):
def fake_func2(self): def fake_func2(self):
return 'fake2' return 'fake2'
def start_rpc_listener(self):
# return value is only used to confirm this method was called.
return 'OK'

View File

@ -393,6 +393,8 @@ class MetaNeutronPluginV2TestRpcFlavor(base.BaseTestCase):
cfg.CONF.set_override('rpc_flavor', 'fake1', 'META') cfg.CONF.set_override('rpc_flavor', 'fake1', 'META')
self.plugin = MetaPluginV2() self.plugin = MetaPluginV2()
self.assertEqual(topics.PLUGIN, 'q-plugin') self.assertEqual(topics.PLUGIN, 'q-plugin')
ret = self.plugin.rpc_workers_supported()
self.assertFalse(ret)
def test_invalid_rpc_flavor(self): def test_invalid_rpc_flavor(self):
setup_metaplugin_conf() setup_metaplugin_conf()
@ -400,3 +402,13 @@ class MetaNeutronPluginV2TestRpcFlavor(base.BaseTestCase):
self.assertRaises(exc.Invalid, self.assertRaises(exc.Invalid,
MetaPluginV2) MetaPluginV2)
self.assertEqual(topics.PLUGIN, 'q-plugin') self.assertEqual(topics.PLUGIN, 'q-plugin')
def test_rpc_flavor_multiple_rpc_workers(self):
setup_metaplugin_conf()
cfg.CONF.set_override('rpc_flavor', 'fake2', 'META')
self.plugin = MetaPluginV2()
self.assertEqual(topics.PLUGIN, 'q-plugin')
ret = self.plugin.rpc_workers_supported()
self.assertTrue(ret)
ret = self.plugin.start_rpc_listener()
self.assertEqual('OK', ret)