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
This commit is contained in:
parent
98fdc53c80
commit
d802fad8a9
@ -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)
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
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)
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
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)
|
||||
manager.NeutronManager.get_instance()
|
||||
plugins = directory.get_plugins()
|
||||
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
Block a user