Allow multiple binding drivers

In before, only one binding driver is allowed. This patch introduces
a new config to support multiple binding drivers. The first use case
is to allow SR-IOV binding to be co-existed with other binding.

* Rename the config 'driver' to 'default_driver' in 'binding' group.
  This is for making it clear that it is allowed to have more than
  one type of bindings.
* Introduce a new config called 'enabled_drivers'.
* Allow client to pass a driver name to port_bind and port_unbind.
  If this parameter is None, kuryr will load the default driver.

Partial-Implements: blueprint sriov-binding
Change-Id: I14b23379de9f2459ba97d5d82dfdb51553370cb1
This commit is contained in:
Hongbin Lu 2017-10-01 17:53:50 +00:00 committed by Hongbin Lu
parent 4188f679d8
commit da736d115b
8 changed files with 81 additions and 9 deletions

View File

@ -12,9 +12,17 @@
from oslo_config import cfg
from oslo_utils import importutils
from kuryr.lib import exceptions
def _verify_driver(driver):
if driver.__name__ not in cfg.CONF.binding.enabled_drivers:
raise exceptions.DriverNotEnabledException(
'Driver %s is not enabled' % driver.__name__)
def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
segmentation_id=None, **kwargs):
segmentation_id=None, driver=None, **kwargs):
"""Binds the Neutron port to the network interface on the host.
:param endpoint_id: the ID of the endpoint as string
@ -29,30 +37,39 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
port of a container which is running inside this Nova
instance (either ipvlan/macvlan or a subport).
:param segmentation_id: ID of the segment for container traffic isolation)
:param driver: the binding driver name
:param kwargs: Additional driver-specific arguments
:returns: the tuple of the names of the veth pair and the tuple of stdout
and stderr returned by processutils.execute invoked with the
executable script for binding
:raises: kuryr.common.exceptions.VethCreationFailure,
kuryr.common.exceptions.DriverNotEnabledException,
processutils.ProcessExecutionError
"""
driver = importutils.import_module(cfg.CONF.binding.driver)
driver = importutils.import_module(
driver or cfg.CONF.binding.default_driver)
_verify_driver(driver)
return driver.port_bind(endpoint_id, port, subnets, network=network,
vm_port=vm_port,
segmentation_id=segmentation_id,
**kwargs)
def port_unbind(endpoint_id, neutron_port, **kwargs):
def port_unbind(endpoint_id, neutron_port, driver=None, **kwargs):
"""Unbinds the Neutron port from the network interface on the host.
:param endpoint_id: the ID of the Docker container as string
:param neutron_port: a port dictionary returned from python-neutronclient
:param driver: the binding driver name
:param kwargs: Additional driver-specific arguments
:returns: the tuple of stdout and stderr returned by processutils.execute
invoked with the executable script for unbinding
:raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
:raises: processutils.ProcessExecutionError, pyroute2.NetlinkError,
kuryr.common.exceptions.DriverNotEnabledException,
"""
driver = importutils.import_module(cfg.CONF.binding.driver)
driver = importutils.import_module(
driver or cfg.CONF.binding.default_driver)
_verify_driver(driver)
return driver.port_unbind(endpoint_id, neutron_port, **kwargs)

View File

@ -68,9 +68,13 @@ binding_opts = [
default='eth',
help=_('The name prefix of the veth endpoint put inside the '
'container.')),
cfg.StrOpt('driver',
cfg.StrOpt('default_driver',
default='kuryr.lib.binding.drivers.veth',
deprecated_name='driver',
help=_('Driver to use for binding and unbinding ports.')),
cfg.ListOpt('enabled_drivers',
default=['kuryr.lib.binding.drivers.veth'],
help=_('Drivers to use for binding and unbinding ports.')),
cfg.StrOpt('link_iface',
default='',
help=_('Specifies the name of the Nova instance interface to '

View File

@ -118,3 +118,11 @@ class AddressInUseException(KuryrException):
This exception is thrown when a specific address is requested and the
requested ip address already exists and is used.
"""
class DriverNotEnabledException(KuryrException):
"""Exception represents the binding driver is not enabled.
This exception is thrown when kuryr tries to load a specific binding driver
but the driver is not enabled.
"""

View File

@ -22,7 +22,7 @@ _driver = ""
def _get_driver():
global _driver
if not _driver:
driver_name = cfg.CONF.binding.driver.rsplit('.', 1)[1]
driver_name = cfg.CONF.binding.default_driver.rsplit('.', 1)[1]
# REVISIT(vikasc): Need to remove this if check
if driver_name == 'vlan':

View File

@ -0,0 +1,32 @@
# 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 oslo_config import cfg
from oslo_utils import importutils
from kuryr.lib import binding
from kuryr.lib import exceptions
from kuryr.tests.unit import base
class TestBinding(base.TestCase):
"""Unit tests for binding module"""
def test__verify_driver(self):
cfg.CONF.set_override('enabled_drivers',
['kuryr.lib.binding.drivers.veth'],
group='binding')
driver = importutils.import_module('kuryr.lib.binding.drivers.veth')
binding._verify_driver(driver) # assert no exception raise
driver = importutils.import_module('kuryr.lib.binding.drivers.vlan')
self.assertRaises(exceptions.DriverNotEnabledException,
binding._verify_driver, driver)

View File

@ -29,7 +29,7 @@ class VlanSegmentationDriverTest(base.TestCase):
def setUp(self):
super(VlanSegmentationDriverTest, self).setUp()
cfg.CONF.binding.driver = 'kuryr.lib.binding.drivers.vlan'
cfg.CONF.binding.default_driver = 'kuryr.lib.binding.drivers.vlan'
def test_allocate_segmentation_id(self):
vlan_seg_driver = vlan.SegmentationDriver()

View File

@ -30,4 +30,4 @@ class ConfigurationTest(base.TestCase):
self.assertEqual('baremetal',
cfg.CONF.deployment_type)
self.assertEqual('kuryr.lib.binding.drivers.veth',
cfg.CONF.binding.driver)
cfg.CONF.binding.default_driver)

View File

@ -0,0 +1,11 @@
---
features:
- |
Add support for multiple binding drivers. Introduce a new config
called 'enabled_drivers' which specifies a list of binding drivers
allowed to use.
deprecations:
- |
Rename the config 'driver' to 'default_driver' in 'binding' group.
This is for making it clear that it is allowed to have more than
one type of bindings.