Avoid loading same service plugin more than once
In patch [1] requirement that only each service plugin
can be loaded only once was removed.
Unfortunatelly it is not possible that same service plugin
will be instantiate more than once because it may reqister some
callbacks or other things which can't be duplicated.
So this patch adds mechanism which will ensure that each service
plugin class is instantiate only once and reused if necessary.
[1] https://review.openstack.org/#/c/626561/
Closes-Bug: #1816771
Change-Id: Ie6e6cc1bbbe50ff7cfad4e8033e48711569ea020
(cherry picked from commit d802fad8a9
)
This commit is contained in:
parent
2331e5fefc
commit
fb0c062899
|
@ -113,6 +113,9 @@ class NeutronManager(object):
|
|||
__trace_args__ = {"name": "rpc"}
|
||||
|
||||
def __init__(self, options=None, config_file=None):
|
||||
# Store instances of already loaded plugins to avoid instantiate same
|
||||
# plugin more than once
|
||||
self._loaded_plugins = {}
|
||||
# If no options have been provided, create an empty dict
|
||||
if not options:
|
||||
options = {}
|
||||
|
@ -166,7 +169,12 @@ class NeutronManager(object):
|
|||
return self.load_class_for_provider(namespace, plugin_provider)
|
||||
|
||||
def _get_plugin_instance(self, namespace, plugin_provider):
|
||||
return self._get_plugin_class(namespace, plugin_provider)()
|
||||
plugin_class = self._get_plugin_class(namespace, plugin_provider)
|
||||
plugin_inst = self._loaded_plugins.get(plugin_class)
|
||||
if not plugin_inst:
|
||||
plugin_inst = plugin_class()
|
||||
self._loaded_plugins[plugin_class] = plugin_inst
|
||||
return plugin_inst
|
||||
|
||||
def _load_services_from_core_plugin(self, plugin):
|
||||
"""Puts core plugin in service_plugins for supported services."""
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import weakref
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
from neutron_lib.plugins import constants as lib_const
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
|
@ -132,11 +133,22 @@ class NeutronManagerTestCase(base.BaseTestCase):
|
|||
["neutron.tests.unit.dummy_plugin."
|
||||
"DummyWithRequireServicePlugin"])
|
||||
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
|
||||
with mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin.DummyServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_init_mock, mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin."
|
||||
"DummyWithRequireServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_with_require_init_mock:
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
# DUMMY will also be initialized since DUMMY_REQIURE needs it.
|
||||
# CORE, DUMMY, DUMMY_REQIURE
|
||||
self.assertEqual(3, len(plugins))
|
||||
# ensure that DUMMY and DUMMY_REQIURE was instantiate only once:
|
||||
self.assertEqual(1, dummy_init_mock.call_count)
|
||||
self.assertEqual(1, dummy_with_require_init_mock.call_count)
|
||||
|
||||
def test_load_plugins_with_requirements_with_parent(self):
|
||||
cfg.CONF.set_override("service_plugins",
|
||||
|
@ -145,10 +157,21 @@ class NeutronManagerTestCase(base.BaseTestCase):
|
|||
"neutron.tests.unit.dummy_plugin."
|
||||
"DummyWithRequireServicePlugin"])
|
||||
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
|
||||
with mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin.DummyServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_init_mock, mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin."
|
||||
"DummyWithRequireServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_with_require_init_mock:
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
# CORE, DUMMY, DUMMY_REQIURE
|
||||
self.assertEqual(3, len(plugins))
|
||||
# ensure that DUMMY and DUMMY_REQIURE was instantiate only once:
|
||||
self.assertEqual(1, dummy_init_mock.call_count)
|
||||
self.assertEqual(1, dummy_with_require_init_mock.call_count)
|
||||
|
||||
def test_load_plugins_with_requirements_child_first(self):
|
||||
cfg.CONF.set_override("service_plugins",
|
||||
|
@ -157,10 +180,21 @@ class NeutronManagerTestCase(base.BaseTestCase):
|
|||
"neutron.tests.unit.dummy_plugin."
|
||||
"DummyServicePlugin"])
|
||||
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
|
||||
with mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin.DummyServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_init_mock, mock.patch(
|
||||
"neutron.tests.unit.dummy_plugin."
|
||||
"DummyWithRequireServicePlugin.__init__",
|
||||
return_value=None
|
||||
) as dummy_with_require_init_mock:
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
# CORE, DUMMY, DUMMY_REQIURE
|
||||
self.assertEqual(3, len(plugins))
|
||||
# ensure that DUMMY and DUMMY_REQIURE was instantiate only once:
|
||||
self.assertEqual(1, dummy_init_mock.call_count)
|
||||
self.assertEqual(1, dummy_with_require_init_mock.call_count)
|
||||
|
||||
def test_core_plugin_supports_services(self):
|
||||
cfg.CONF.set_override("core_plugin",
|
||||
|
|
Loading…
Reference in New Issue