Skip to content

Commit

Permalink
Configure plugins by name
Browse files Browse the repository at this point in the history
To configure core plugin or service plugins, instead of using class names,
simpler names can also be used, ex:

service_plugins = router, firewall, lbaas

For compatibility with previous versions, the class name of a plugin can be
specified instead of its entrypoint name, ex:

service_plugins = router, neutron.services.firewall.fwaas_plugin.FirewallPlugin, lbaas

DocImpact

Implements: blueprint config-plugin-by-name
Change-Id: Ia4aaa1d305b160a4d6dab9e227c744727a4c78c2
  • Loading branch information
kghost committed Jan 15, 2014
1 parent ab1f474 commit 9fbb6aa
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 19 deletions.
18 changes: 15 additions & 3 deletions etc/neutron.conf
Expand Up @@ -44,11 +44,23 @@ lock_path = $state_path/lock
# extensions are in there you don't need to specify them here
# api_extensions_path =

# Neutron plugin provider module
# (StrOpt) Neutron core plugin entrypoint to be loaded from the
# neutron.core_plugins namespace. See setup.cfg for the entrypoint names of the
# plugins included in the neutron source distribution. For compatibility with
# previous versions, the class name of a plugin can be specified instead of its
# entrypoint name.
#
# core_plugin =

# Advanced service modules
# Example: core_plugin = ml2

# (ListOpt) List of service plugin entrypoints to be loaded from the
# neutron.service_plugins namespace. See setup.cfg for the entrypoint names of
# the plugins included in the neutron source distribution. For compatibility
# with previous versions, the class name of a plugin can be specified instead
# of its entrypoint name.
#
# service_plugins =
# Example: service_plugins = router,firewall,lbaas,vpnaas,metering

# Paste configuration file
# api_paste_config = api-paste.ini
Expand Down
40 changes: 24 additions & 16 deletions neutron/manager.py
Expand Up @@ -25,6 +25,8 @@
from neutron.openstack.common import periodic_task
from neutron.plugins.common import constants

from stevedore import driver


LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -108,16 +110,10 @@ def __init__(self, options=None, config_file=None):
# intentianally to allow v2 plugins to be monitored
# for performance metrics.
plugin_provider = cfg.CONF.core_plugin
LOG.debug(_("Plugin location: %s"), plugin_provider)
# If the plugin can't be found let them know gracefully
try:
LOG.info(_("Loading Plugin: %s"), plugin_provider)
plugin_klass = importutils.import_class(plugin_provider)
except ImportError:
LOG.exception(_("Error loading plugin"))
raise Exception(_("Plugin not found. "))
LOG.info(_("Loading core plugin: %s"), plugin_provider)
self.plugin = self._get_plugin_instance('neutron.core_plugins',
plugin_provider)
legacy.modernize_quantum_config(cfg.CONF)
self.plugin = plugin_klass()

msg = validate_post_plugin_load()
if msg:
Expand All @@ -131,6 +127,21 @@ def __init__(self, options=None, config_file=None):
self.service_plugins = {constants.CORE: self.plugin}
self._load_service_plugins()

def _get_plugin_instance(self, namespace, plugin_provider):
try:
# Try to resolve plugin by name
mgr = driver.DriverManager(namespace, plugin_provider)
plugin_class = mgr.driver
except RuntimeError as e1:
# fallback to class name
try:
plugin_class = importutils.import_class(plugin_provider)
except ImportError as e2:
LOG.exception(_("Error loading plugin by name, %s"), e1)
LOG.exception(_("Error loading plugin by class, %s"), e2)
raise ImportError(_("Plugin not found."))
return plugin_class()

def _load_services_from_core_plugin(self):
"""Puts core plugin in service_plugins for supported services."""
LOG.debug(_("Loading services supported by the core plugin"))
Expand Down Expand Up @@ -159,13 +170,10 @@ def _load_service_plugins(self):
for provider in plugin_providers:
if provider == '':
continue
try:
LOG.info(_("Loading Plugin: %s"), provider)
plugin_class = importutils.import_class(provider)
except ImportError:
LOG.exception(_("Error loading plugin"))
raise ImportError(_("Plugin not found."))
plugin_inst = plugin_class()

LOG.info(_("Loading Plugin: %s"), provider)
plugin_inst = self._get_plugin_instance('neutron.service_plugins',
provider)

# only one implementation of svc_type allowed
# specifying more than one plugin
Expand Down
23 changes: 23 additions & 0 deletions neutron/tests/unit/test_neutron_manager.py
Expand Up @@ -76,6 +76,17 @@ def test_service_plugin_is_loaded(self):
(dummy_plugin.DummyServicePlugin, types.ClassType)),
"loaded plugin should be of type neutronDummyPlugin")

def test_service_plugin_by_name_is_loaded(self):
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
cfg.CONF.set_override("service_plugins", ["dummy"])
mgr = NeutronManager.get_instance()
plugin = mgr.get_service_plugins()[constants.DUMMY]

self.assertTrue(
isinstance(plugin,
(dummy_plugin.DummyServicePlugin, types.ClassType)),
"loaded plugin should be of type neutronDummyPlugin")

def test_multiple_plugins_specified_for_service_type(self):
cfg.CONF.set_override("service_plugins",
["neutron.tests.unit.dummy_plugin."
Expand All @@ -85,6 +96,18 @@ def test_multiple_plugins_specified_for_service_type(self):
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
self.assertRaises(ValueError, NeutronManager.get_instance)

def test_multiple_plugins_by_name_specified_for_service_type(self):
cfg.CONF.set_override("service_plugins", ["dummy", "dummy"])
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
self.assertRaises(ValueError, NeutronManager.get_instance)

def test_multiple_plugins_mixed_specified_for_service_type(self):
cfg.CONF.set_override("service_plugins",
["neutron.tests.unit.dummy_plugin."
"DummyServicePlugin", "dummy"])
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
self.assertRaises(ValueError, NeutronManager.get_instance)

def test_service_plugin_conflicts_with_core_plugin(self):
cfg.CONF.set_override("service_plugins",
["neutron.tests.unit.dummy_plugin."
Expand Down
22 changes: 22 additions & 0 deletions setup.cfg
Expand Up @@ -119,6 +119,28 @@ console_scripts =
quantum-rootwrap = neutron.openstack.common.rootwrap.cmd:main
quantum-usage-audit = neutron.cmd.usage_audit:main
neutron-metering-agent = neutron.services.metering.agents.metering_agent:main
neutron.core_plugins =
bigswitch = neutron.plugins.bigswitch.plugin:NeutronRestProxyV2
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2
cisco = neutron.plugins.cisco.network_plugin:PluginV2
embrane = neutron.plugins.embrane.plugins.embrane_ovs_plugin:EmbraneOvsPlugin
hyperv = neutron.plugins.hyperv.hyperv_neutron_plugin:HyperVNeutronPlugin
linuxbridge = neutron.plugins.linuxbridge.lb_neutron_plugin:LinuxBridgePluginV2
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
mlnx = neutron.plugins.mlnx.mlnx_plugin:MellanoxEswitchPlugin
nec = neutron.plugins.nec.nec_plugin:NECPluginV2
nicira = neutron.plugins.nicira.NeutronPlugin:NvpPluginV2
openvswitch = neutron.plugins.openvswitch.ovs_neutron_plugin:OVSNeutronPluginV2
plumgrid = neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin:NeutronPluginPLUMgridV2
ryu = neutron.plugins.ryu.ryu_neutron_plugin:RyuNeutronPluginV2
neutron.service_plugins =
dummy = neutron.tests.unit.dummy_plugin:DummyServicePlugin
router = neutron.services.l3_router.l3_router_plugin:L3RouterPlugin
firewall = neutron.services.firewall.fwaas_plugin:FirewallPlugin
lbaas = neutron.services.loadbalancer.plugin:LoadBalancerPlugin
vpnaas = neutron.services.vpn.plugin:VPNDriverPlugin
metering = neutron.services.metering.metering_plugin:MeteringPlugin
neutron.ml2.type_drivers =
flat = neutron.plugins.ml2.drivers.type_flat:FlatTypeDriver
local = neutron.plugins.ml2.drivers.type_local:LocalTypeDriver
Expand Down

0 comments on commit 9fbb6aa

Please sign in to comment.