summaryrefslogtreecommitdiff
path: root/ironic/common/driver_factory.py
diff options
context:
space:
mode:
authorVasyl Saienko <vsaienko@mirantis.com>2016-05-17 13:59:39 +0300
committerVladyslav Drok <vdrok@mirantis.com>2016-07-12 19:08:07 +0300
commitcde11611d93946a1c79e406dc429aa5e742da729 (patch)
tree9eb33e34012373f15f5076c0562c7bc05fde79a4 /ironic/common/driver_factory.py
parent1825267b3a47ea9f82008a40dd90f0f4946bfd52 (diff)
downloadironic-cde11611d93946a1c79e406dc429aa5e742da729.tar.gz
Add network interface to base driver class
This change also introduces two network interfaces: * flat: Copies current neutron DHCP provider logic to work with cleaning ports; * noop: noop interface. The default value of the network_interface is None, meaning that the node will be using the default network interface. The default network interface is determined the following way: * if [DEFAULT]default_network_interface configuration option is set (the default for it is None), the specified interface becomes the default for all nodes; * if it is not set, 'flat' interface will be used if the deployment currently uses 'neutron' DHCP provider, otherwise 'noop' interface will be used. create_cleaning_ports and delete_cleaning_ports methods of the DHCP providers are still being called in case of out-of-tree DHCP providers, but this possibility will be removed completely in the next release. If the DHCP provider logic is rewritten into a custom network interface, please remove those methods from the provider, so that network interface is called instead. Partial-bug: #1526403 Co-Authored-By: Om Kumar <om.kumar@hp.com> Co-Authored-By: Vasyl Saienko <vsaienko@mirantis.com> Co-Authored-By: Sivaramakrishna Garimella <sivaramakrishna.garimella@hp.com> Co-Authored-By: Vladyslav Drok <vdrok@mirantis.com> Co-Authored-By: Zhenguo Niu <Niu.ZGlinux@gmail.com> Change-Id: I0c26582b6b6e9d32650ff3e2b9a3269c3c2d5454
Diffstat (limited to 'ironic/common/driver_factory.py')
-rw-r--r--ironic/common/driver_factory.py92
1 files changed, 77 insertions, 15 deletions
diff --git a/ironic/common/driver_factory.py b/ironic/common/driver_factory.py
index 6e834d4f7..bd4439f9e 100644
--- a/ironic/common/driver_factory.py
+++ b/ironic/common/driver_factory.py
@@ -41,6 +41,23 @@ driver_opts = [
'be found by enumerating the "ironic.drivers" '
'entrypoint. An example may be found in the '
'developer documentation online.')),
+ cfg.ListOpt('enabled_network_interfaces',
+ default=['flat', 'noop'],
+ help=_('Specify the list of network interfaces to load during '
+ 'service initialization. Missing network interfaces, '
+ 'or network interfaces which fail to initialize, will '
+ 'prevent the conductor service from starting. The '
+ 'option default is a recommended set of '
+ 'production-oriented network interfaces. A complete '
+ 'list of network interfaces present on your system may '
+ 'be found by enumerating the '
+ '"ironic.hardware.interfaces.network" entrypoint.')),
+ cfg.StrOpt('default_network_interface',
+ help=_('Default network interface to be used for nodes that '
+ 'do not have network_interface field set. A complete '
+ 'list of network interfaces present on your system may '
+ 'be found by enumerating the '
+ '"ironic.hardware.interfaces.network" entrypoint.'))
]
CONF = cfg.CONF
@@ -76,6 +93,20 @@ def _attach_interfaces_to_driver(driver, node, driver_name=None):
impl = getattr(driver_singleton, iface, None)
setattr(driver, iface, impl)
+ network_iface = node.network_interface
+ if network_iface is None:
+ network_iface = (CONF.default_network_interface or
+ ('flat' if CONF.dhcp.dhcp_provider == 'neutron'
+ else 'noop'))
+ network_factory = NetworkInterfaceFactory()
+ try:
+ net_driver = network_factory.get_driver(network_iface)
+ except KeyError:
+ raise exception.DriverNotFoundInEntrypoint(
+ driver_name=network_iface,
+ entrypoint=network_factory._entrypoint_name)
+ driver.network = net_driver
+
def get_driver(driver_name):
"""Simple method to get a ref to an instance of a driver.
@@ -93,7 +124,7 @@ def get_driver(driver_name):
try:
factory = DriverFactory()
- return factory[driver_name].obj
+ return factory.get_driver(driver_name)
except KeyError:
raise exception.DriverNotFound(driver_name=driver_name)
@@ -109,8 +140,11 @@ def drivers():
for name in factory.names)
-class DriverFactory(object):
- """Discover, load and manage the drivers available."""
+class BaseDriverFactory(object):
+ """Discover, load and manage the drivers available.
+
+ This is subclassed to load both main drivers and extra interfaces.
+ """
# NOTE(deva): loading the _extension_manager as a class member will break
# stevedore when it loads a driver, because the driver will
@@ -119,13 +153,25 @@ class DriverFactory(object):
# once, the first time DriverFactory.__init__ is called.
_extension_manager = None
+ # Entrypoint name containing the list of all available drivers/interfaces
+ _entrypoint_name = None
+ # Name of the [DEFAULT] section config option containing a list of enabled
+ # drivers/interfaces
+ _enabled_driver_list_config_option = ''
+ # This field will contain the list of the enabled drivers/interfaces names
+ # without duplicates
+ _enabled_driver_list = None
+
def __init__(self):
- if not DriverFactory._extension_manager:
- DriverFactory._init_extension_manager()
+ if not self.__class__._extension_manager:
+ self.__class__._init_extension_manager()
def __getitem__(self, name):
return self._extension_manager[name]
+ def get_driver(self, name):
+ return self[name].obj
+
# NOTE(deva): Use lockutils to avoid a potential race in eventlet
# that might try to create two driver factories.
@classmethod
@@ -136,19 +182,24 @@ class DriverFactory(object):
# creation of multiple NameDispatchExtensionManagers.
if cls._extension_manager:
return
+ enabled_drivers = getattr(CONF, cls._enabled_driver_list_config_option,
+ [])
# Check for duplicated driver entries and warn the operator
# about them
- counter = collections.Counter(CONF.enabled_drivers).items()
- duplicated_drivers = list(dup for (dup, i) in counter if i > 1)
+ counter = collections.Counter(enabled_drivers).items()
+ duplicated_drivers = []
+ cls._enabled_driver_list = []
+ for item, cnt in counter:
+ if cnt > 1:
+ duplicated_drivers.append(item)
+ cls._enabled_driver_list.append(item)
if duplicated_drivers:
LOG.warning(_LW('The driver(s) "%s" is/are duplicated in the '
'list of enabled_drivers. Please check your '
'configuration file.'),
', '.join(duplicated_drivers))
- enabled_drivers = set(CONF.enabled_drivers)
-
# NOTE(deva): Drivers raise "DriverLoadError" if they are unable to be
# loaded, eg. due to missing external dependencies.
# We capture that exception, and, only if it is for an
@@ -160,30 +211,31 @@ class DriverFactory(object):
def _catch_driver_not_found(mgr, ep, exc):
# NOTE(deva): stevedore loads plugins *before* evaluating
# _check_func, so we need to check here, too.
- if ep.name in enabled_drivers:
+ if ep.name in cls._enabled_driver_list:
if not isinstance(exc, exception.DriverLoadError):
raise exception.DriverLoadError(driver=ep.name, reason=exc)
raise exc
def _check_func(ext):
- return ext.name in enabled_drivers
+ return ext.name in cls._enabled_driver_list
cls._extension_manager = (
dispatch.NameDispatchExtensionManager(
- 'ironic.drivers',
+ cls._entrypoint_name,
_check_func,
invoke_on_load=True,
on_load_failure_callback=_catch_driver_not_found))
# NOTE(deva): if we were unable to load any configured driver, perhaps
# because it is not present on the system, raise an error.
- if (sorted(enabled_drivers) !=
+ if (sorted(cls._enabled_driver_list) !=
sorted(cls._extension_manager.names())):
found = cls._extension_manager.names()
- names = [n for n in enabled_drivers if n not in found]
+ names = [n for n in cls._enabled_driver_list if n not in found]
# just in case more than one could not be found ...
names = ', '.join(names)
- raise exception.DriverNotFound(driver_name=names)
+ raise exception.DriverNotFoundInEntrypoint(
+ driver_name=names, entrypoint=cls._entrypoint_name)
LOG.info(_LI("Loaded the following drivers: %s"),
cls._extension_manager.names())
@@ -192,3 +244,13 @@ class DriverFactory(object):
def names(self):
"""The list of driver names available."""
return self._extension_manager.names()
+
+
+class DriverFactory(BaseDriverFactory):
+ _entrypoint_name = 'ironic.drivers'
+ _enabled_driver_list_config_option = 'enabled_drivers'
+
+
+class NetworkInterfaceFactory(BaseDriverFactory):
+ _entrypoint_name = 'ironic.hardware.interfaces.network'
+ _enabled_driver_list_config_option = 'enabled_network_interfaces'