Merge "Add the ability to load a set of service plugins on startup"

This commit is contained in:
Jenkins 2016-02-11 02:07:01 +00:00 committed by Gerrit Code Review
commit 92dcc59aa4
8 changed files with 57 additions and 6 deletions

View File

@ -30,6 +30,7 @@ from neutron._i18n import _, _LE, _LI, _LW
from neutron.common import exceptions
import neutron.extensions
from neutron import manager
from neutron.plugins.common import constants as const
from neutron.services import provider_configuration
from neutron import wsgi
@ -440,11 +441,18 @@ class ExtensionManager(object):
# Exit loop as no progress was made
break
if exts_to_process:
LOG.error(_LE("It was impossible to process the following "
"extensions: %s because of missing requirements."),
','.join(exts_to_process.keys()))
raise exceptions.ExtensionsNotFound(
extensions=list(exts_to_process.keys()))
unloadable_extensions = set(exts_to_process.keys())
LOG.error(_LE("Unable to process extensions (%s) because "
"the configured plugins do not satisfy "
"their requirements. Some features will not "
"work as expected."),
', '.join(unloadable_extensions))
# Fail gracefully for default extensions, just in case some out
# of tree plugins are not entirely up to speed
default_extensions = set(const.DEFAULT_SERVICE_PLUGINS.values())
if not unloadable_extensions <= default_extensions:
raise exceptions.ExtensionsNotFound(
extensions=list(unloadable_extensions))
# Extending extensions' attributes map.
for ext in processed_exts.values():

View File

@ -161,6 +161,10 @@ class NeutronManager(object):
LOG.info(_LI("Service %s is supported by the core plugin"),
service_type)
def _get_default_service_plugins(self):
"""Get default service plugins to be loaded."""
return constants.DEFAULT_SERVICE_PLUGINS.keys()
def _load_service_plugins(self):
"""Loads service plugins.
@ -171,6 +175,7 @@ class NeutronManager(object):
self._load_services_from_core_plugin()
plugin_providers = cfg.CONF.service_plugins
plugin_providers.extend(self._get_default_service_plugins())
LOG.debug("Loading service plugins: %s", plugin_providers)
for provider in plugin_providers:
if provider == '':

View File

@ -38,6 +38,11 @@ EXT_TO_SERVICE_MAPPING = {
'qos': QOS,
}
# Maps default service plugins entry points to their extension aliases
DEFAULT_SERVICE_PLUGINS = {
'auto_allocate': 'auto-allocated-topology',
}
# Service operation status constants
ACTIVE = "ACTIVE"
DOWN = "DOWN"

View File

@ -350,6 +350,7 @@ class BaseTestCase(DietTestCase):
cp = PluginFixture(core_plugin)
self.useFixture(cp)
self.patched_dhcp_periodic = cp.patched_dhcp_periodic
self.patched_default_svc_plugins = cp.patched_default_svc_plugins
def setup_notification_driver(self, notification_driver=None):
self.addCleanup(fake_notifier.reset)
@ -365,6 +366,11 @@ class PluginFixture(fixtures.Fixture):
self.core_plugin = core_plugin
def _setUp(self):
# Do not load default service plugins in the testing framework
# as all the mocking involved can cause havoc.
self.default_svc_plugins_p = mock.patch(
'neutron.manager.NeutronManager._get_default_service_plugins')
self.patched_default_svc_plugins = self.default_svc_plugins_p.start()
self.dhcp_periodic_p = mock.patch(
'neutron.db.agentschedulers_db.DhcpAgentSchedulerDbMixin.'
'start_periodic_dhcp_agent_status_check')

View File

@ -502,13 +502,21 @@ class RequestExtensionTest(base.BaseTestCase):
class ExtensionManagerTest(base.BaseTestCase):
def test_missing_required_extensions(self):
def test_missing_required_extensions_raise_error(self):
ext_mgr = extensions.ExtensionManager('')
attr_map = {}
ext_mgr.add_extension(ext_stubs.StubExtensionWithReqs('foo_alias'))
self.assertRaises(exceptions.ExtensionsNotFound,
ext_mgr.extend_resources, "2.0", attr_map)
def test_missing_required_extensions_gracefully_error(self):
ext_mgr = extensions.ExtensionManager('')
attr_map = {}
default_ext = list(constants.DEFAULT_SERVICE_PLUGINS.values())[0]
ext_mgr.add_extension(ext_stubs.StubExtensionWithReqs(default_ext))
ext_mgr.extend_resources("2.0", attr_map)
self.assertIn(default_ext, ext_mgr.extensions)
def test_invalid_extensions_are_not_registered(self):
class InvalidExtension(object):

View File

@ -111,6 +111,15 @@ class NeutronManagerTestCase(base.BaseTestCase):
self.assertIn(constants.LOADBALANCER, svc_plugins.keys())
self.assertIn(constants.DUMMY, svc_plugins.keys())
def test_load_default_service_plugins(self):
self.patched_default_svc_plugins.return_value = {
'neutron.tests.unit.dummy_plugin.DummyServicePlugin': 'DUMMY'
}
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
mgr = manager.NeutronManager.get_instance()
svc_plugins = mgr.get_service_plugins()
self.assertIn('DUMMY', svc_plugins)
def test_post_plugin_validation(self):
cfg.CONF.import_opt('dhcp_agents_per_network',
'neutron.db.agentschedulers_db')

View File

@ -0,0 +1,9 @@
---
prelude: >
The "get-me-a-network" feature simplifies the process
for launching an instance with basic network connectivity
(via an externally connected private tenant network).
features:
- Once Nova takes advantage of this feature, a user can
launch an instance without explicitly provisioning
network resources.

View File

@ -76,6 +76,7 @@ neutron.service_plugins =
neutron.services.vpn.plugin.VPNDriverPlugin = neutron_vpnaas.services.vpn.plugin:VPNDriverPlugin
qos = neutron.services.qos.qos_plugin:QoSPlugin
flavors = neutron.services.flavors.flavors_plugin:FlavorsPlugin
auto_allocate = neutron.services.auto_allocate.plugin:Plugin
neutron.qos.notification_drivers =
message_queue = neutron.services.qos.notification_drivers.message_queue:RpcQosServiceNotificationDriver
neutron.ml2.type_drivers =