Enable to select an RPC handling plugin under Metaplugin

Multiple plugins under metaplugin become 'q-plugin' topic
consumers and a request from an agent is handled by one of
them randomly. Fortunatly most of RPC callbacks are common
for plugins but a problem occurs if an RPC is not supported
by the received plugin.

This is one of risks when using metaplugin. Fundamental fix
of this problem (such as RPC delegation handling of metaplugin)
is difficult since each plugin needs to modify.
But when only one plugin has plugin specific RPCs and other
RPCs are independet of plugins, if the plugin can be selected
for RPC handling, the problem does not happen. Typical use
case of metaplugin such as combination of an agent-based
plugin and a controller-based plugin often applies to this
condition.

This patch adds 'rpc_flavor' configuration parameter to
select an RPC handling plugin. If 'rpc_flavor' is specified,
only the specified plugin becomes 'q-plugin' topic consumer.
If 'rpc_flavor' is not specified, the behavior is same as
previous one.

Change-Id: If133b054bba53829cebe63c1e0ebe6099eb1fd95
Closes-bug: #1267330
DocImpact
This commit is contained in:
Itsuro Oda 2013-12-17 10:16:51 +09:00
parent 0009e474e2
commit b98704e80b
4 changed files with 48 additions and 0 deletions

View File

@ -16,3 +16,6 @@ default_l3_flavor = 'openvswitch'
supported_extension_aliases = 'providernet'
# specific method map for each flavor to extensions
extension_map = 'get_port_stats:nvp'
# flavor of which plugin handles RPC
rpc_flavor =

View File

@ -31,6 +31,8 @@ meta_plugin_opts = [
help=_("Supported extension aliases")),
cfg.StrOpt('extension_map', default='',
help=_("A list of extensions, per plugin, to load.")),
cfg.StrOpt('rpc_flavor', default='',
help=_("Flavor of which plugin handles RPC")),
]
proxy_plugin_opts = [

View File

@ -18,6 +18,7 @@
from oslo.config import cfg
from neutron.common import exceptions as exc
from neutron.common import topics
from neutron import context as neutron_context
from neutron.db import api as db
from neutron.db import db_base_plugin_v2
@ -93,8 +94,19 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
plugin_list = [plugin_set.split(':')
for plugin_set
in cfg.CONF.META.plugin_list.split(',')]
rpc_flavor = cfg.CONF.META.rpc_flavor
topic_save = topics.PLUGIN
topic_fake = topic_save + '-metaplugin'
for flavor, plugin_provider in plugin_list:
# Rename topic used by a plugin other than rpc_flavor during
# loading the plugin instance if rpc_flavor is specified.
# This enforces the plugin specified by rpc_flavor is only
# consumer of 'q-plugin'. It is a bit tricky but there is no
# bad effect.
if rpc_flavor and rpc_flavor != flavor:
topics.PLUGIN = topic_fake
self.plugins[flavor] = self._load_plugin(plugin_provider)
topics.PLUGIN = topic_save
self.l3_plugins = {}
if cfg.CONF.META.l3_plugin_list:
@ -122,6 +134,10 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
self.supported_extension_aliases += ['router', 'ext-gw-mode',
'extraroute']
if rpc_flavor and rpc_flavor not in self.plugins:
raise exc.Invalid(_('rpc_flavor %s is not plugin list') %
rpc_flavor)
self.extension_map = {}
if not cfg.CONF.META.extension_map == '':
extension_list = [method_set.split(':')

View File

@ -21,6 +21,8 @@ import mock
from oslo.config import cfg
import testtools
from neutron.common import exceptions as exc
from neutron.common import topics
from neutron import context
from neutron.db import api as db
from neutron.db import db_base_plugin_v2
@ -372,3 +374,28 @@ class MetaNeutronPluginV2TestWithoutL3(MetaNeutronPluginV2Test):
def test_create_router_flavor_fail(self):
self.skipTest("Test case without router")
class MetaNeutronPluginV2TestRpcFlavor(base.BaseTestCase):
"""Tests for rpc_flavor."""
def setUp(self):
super(MetaNeutronPluginV2TestRpcFlavor, self).setUp()
db._ENGINE = None
db._MAKER = None
db.configure_db()
self.addCleanup(db.clear_db)
self.addCleanup(unregister_meta_hooks)
def test_rpc_flavor(self):
setup_metaplugin_conf()
cfg.CONF.set_override('rpc_flavor', 'fake1', 'META')
self.plugin = MetaPluginV2()
self.assertEqual(topics.PLUGIN, 'q-plugin')
def test_invalid_rpc_flavor(self):
setup_metaplugin_conf()
cfg.CONF.set_override('rpc_flavor', 'fake-fake', 'META')
self.assertRaises(exc.Invalid,
MetaPluginV2)
self.assertEqual(topics.PLUGIN, 'q-plugin')