IPAM Driver is loaded based on value of 'ipam_driver'.
Added new variable 'ipam_driver' in config.
DocImpact
Partially-Implements: blueprint neutron-ipam
Change-Id: Ia52ad70ef4f0b02cf82cfefcf50b9f1e30b05b79
# core_plugin =
# Example: core_plugin = ml2
+# (StrOpt) Neutron IPAM (IP address management) driver to be loaded from the
+# neutron.ipam_drivers namespace. See setup.cfg for the entry point names.
+# If ipam_driver is not set (default behavior), no ipam driver is used.
+# Example: ipam_driver =
+# In order to use the reference implementation of neutron ipam driver, use
+# 'internal'.
+# Example: ipam_driver = internal
+
# (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
help=_('If True, effort is made to advertise MTU settings '
'to VMs via network methods (DHCP and RA MTU options) '
'when the network\'s preferred MTU is known.')),
+ cfg.StrOpt('ipam_driver', default=None,
+ help=_('IPAM driver to use.')),
cfg.BoolOpt('vlan_transparent', default=False,
help=_('If True, then allow plugins that support it to '
'create VLAN transparent networks.')),
import abc
+from oslo_config import cfg
+from oslo_log import log
import six
-from oslo_log import log
+from neutron import manager
LOG = log.getLogger(__name__)
:type subnet_pool: dict
:returns: An instance of Driver for the given subnet pool
"""
- raise NotImplementedError
+ ipam_driver_name = cfg.CONF.ipam_driver
+ mgr = manager.NeutronManager
+ LOG.debug("Loading ipam driver: %s", ipam_driver_name)
+ driver_class = mgr.load_class_for_provider('neutron.ipam_drivers',
+ ipam_driver_name)
+ return driver_class(subnet_pool, context)
@abc.abstractmethod
def allocate_subnet(self, request):
self.service_plugins = {constants.CORE: self.plugin}
self._load_service_plugins()
- def _get_plugin_instance(self, namespace, plugin_provider):
+ @staticmethod
+ def load_class_for_provider(namespace, plugin_provider):
+ if not plugin_provider:
+ LOG.exception(_LE("Error, plugin is not set"))
+ raise ImportError(_("Plugin not found."))
try:
# Try to resolve plugin by name
mgr = driver.DriverManager(namespace, plugin_provider)
LOG.exception(_LE("Error loading plugin by name, %s"), e1)
LOG.exception(_LE("Error loading plugin by class, %s"), e2)
raise ImportError(_("Plugin not found."))
+ return plugin_class
+
+ def _get_plugin_instance(self, namespace, plugin_provider):
+ plugin_class = self.load_class_for_provider(namespace, plugin_provider)
return plugin_class()
def _load_services_from_core_plugin(self):
--- /dev/null
+# Copyright (c) 2015 Infoblox Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from neutron.ipam import driver
+
+
+class FakeDriver(driver.Pool):
+ """Fake IPAM driver for tests only
+
+ Just implement IPAM Driver interface without any functionality inside
+ """
+
+ def allocate_subnet(self, subnet):
+ return driver.Subnet()
+
+ def get_subnet(self, cidr):
+ return driver.Subnet()
+
+ def update_subnet(self, request):
+ return driver.Subnet()
+
+ def remove_subnet(self, cidr):
+ pass
# License for the specific language governing permissions and limitations
# under the License.
+import types
+
+import mock
import netaddr
+from oslo_config import cfg
from neutron.common import constants
from neutron.common import ipv6_utils
+from neutron import context
from neutron import ipam
+from neutron.ipam import driver
from neutron.ipam import exceptions as ipam_exc
+from neutron import manager
from neutron.openstack.common import uuidutils
from neutron.tests import base
+from neutron.tests.unit.ipam import fake_driver
+
+FAKE_IPAM_CLASS = 'neutron.tests.unit.ipam.fake_driver.FakeDriver'
class IpamSubnetRequestTestCase(base.BaseTestCase):
mac='meh',
alien='et',
prefix='meh')
+
+
+class TestIpamDriverLoader(base.BaseTestCase):
+
+ def setUp(self):
+ super(TestIpamDriverLoader, self).setUp()
+ self.ctx = context.get_admin_context()
+
+ def _verify_fake_ipam_driver_is_loaded(self, driver_name):
+ mgr = manager.NeutronManager
+ ipam_driver = mgr.load_class_for_provider('neutron.ipam_drivers',
+ driver_name)
+
+ self.assertEqual(
+ fake_driver.FakeDriver, ipam_driver,
+ "loaded ipam driver should be FakeDriver")
+
+ def _verify_import_error_is_generated(self, driver_name):
+ mgr = manager.NeutronManager
+ self.assertRaises(ImportError, mgr.load_class_for_provider,
+ 'neutron.ipam_drivers',
+ driver_name)
+
+ def test_ipam_driver_is_loaded_by_class(self):
+ self._verify_fake_ipam_driver_is_loaded(FAKE_IPAM_CLASS)
+
+ def test_ipam_driver_is_loaded_by_name(self):
+ self._verify_fake_ipam_driver_is_loaded('fake')
+
+ def test_ipam_driver_raises_import_error(self):
+ self._verify_import_error_is_generated(
+ 'neutron.tests.unit.ipam.SomeNonExistentClass')
+
+ def test_ipam_driver_raises_import_error_for_none(self):
+ self._verify_import_error_is_generated(None)
+
+ def _load_ipam_driver(self, driver_name, subnet_pool_id):
+ cfg.CONF.set_override("ipam_driver", driver_name)
+ return driver.Pool.get_instance(subnet_pool_id, self.ctx)
+
+ def test_ipam_driver_is_loaded_from_ipam_driver_config_value(self):
+ ipam_driver = self._load_ipam_driver('fake', None)
+ self.assertIsInstance(
+ ipam_driver, (fake_driver.FakeDriver, types.ClassType),
+ "loaded ipam driver should be of type FakeDriver")
+
+ @mock.patch(FAKE_IPAM_CLASS)
+ def test_ipam_driver_is_loaded_with_subnet_pool_id(self, ipam_mock):
+ subnet_pool_id = 'SomePoolID'
+ self._load_ipam_driver('fake', subnet_pool_id)
+ ipam_mock.assert_called_once_with(subnet_pool_id, self.ctx)
cisco_n1kv_ext = neutron.plugins.ml2.drivers.cisco.n1kv.n1kv_ext_driver:CiscoN1kvExtensionDriver
neutron.openstack.common.cache.backends =
memory = neutron.openstack.common.cache._backends.memory:MemoryBackend
+neutron.ipam_drivers =
+ fake = neutron.tests.unit.ipam.fake_driver:FakeDriver
+ internal = neutron.ipam.drivers.neutrondb_ipam.driver:NeutronDbPool
# These are for backwards compat with Icehouse notification_driver configuration values
oslo.messaging.notify.drivers =
neutron.openstack.common.notifier.log_notifier = oslo_messaging.notify._impl_log:LogDriver