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:
parent
3b3313e73b
commit
22a7c75ee4
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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 "
|
||||||
|
@ -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'
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user