]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Configure plugins by name
authorZang MingJie <zealot0630@gmail.com>
Fri, 10 Jan 2014 10:35:49 +0000 (18:35 +0800)
committerZang MingJie <zealot0630@gmail.com>
Wed, 15 Jan 2014 07:43:59 +0000 (15:43 +0800)
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

etc/neutron.conf
neutron/manager.py
neutron/tests/unit/test_neutron_manager.py
setup.cfg

index 6086d1a6591b694abb7b9c7d4c47092366986f7f..1e2226fc3e2c7891b915a6b774059713b6b13561 100644 (file)
@@ -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
index bc71464191248c67171339af64c3532705fd978d..eda835d3caedfeca69ca33c217b8e439d0bd8100 100644 (file)
@@ -25,6 +25,8 @@ from neutron.openstack.common import log as logging
 from neutron.openstack.common import periodic_task
 from neutron.plugins.common import constants
 
+from stevedore import driver
+
 
 LOG = logging.getLogger(__name__)
 
@@ -108,16 +110,10 @@ class NeutronManager(object):
         #                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:
@@ -131,6 +127,21 @@ class NeutronManager(object):
         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"))
@@ -159,13 +170,10 @@ class NeutronManager(object):
         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
index e8e5fde33f5918497d6f86f7029e057c8ff85f1e..86db9f94400bec06f248a5947f9e918cfcd133b1 100644 (file)
@@ -76,6 +76,17 @@ class NeutronManagerTestCase(base.BaseTestCase):
                        (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."
@@ -85,6 +96,18 @@ class NeutronManagerTestCase(base.BaseTestCase):
         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."
index 53063004202de08d0eb9d521448f851a0689cd7f..fc1eb6e05de657d9fdd57b2a075fe289c89db008 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -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