supported_vnic_type configurable for ovs

Now supported_vnic_types is hardcoded to the mechanism drivers, but that
can depend on several factors, like type of the NIC, admin decision,
etc.
With this patch we put the right to decide which vnic types are
supported for ovs agent into the hands of the admin, by allowing
blacklisting items from the mechanism driver specific list.
Background: http://eavesdrop.openstack.org/meetings/neutron_qos/2018/
neutron_qos.2018-07-31-15.00.log.html#l-58

Change-Id: I63e562e2eccc5b02c1c767d6a2c28cb803131e99
Partial-Bug: #1578989
See-Also: https://review.openstack.org/502306 (nova spec)
See-Also: https://review.openstack.org/508149 (neutron spec)
This commit is contained in:
Lajos Katona 2018-09-28 09:32:37 +02:00
parent c4b16aa492
commit a85c5ed3fb
9 changed files with 210 additions and 3 deletions

View File

@ -260,6 +260,31 @@ For more details, see the
Configuration of those drivers is not part of this document.
Supported VNIC types
^^^^^^^^^^^^^^^^^^^^
The ``vnic_type_blacklist`` option is used to remove values from the mechanism driver's
``supported_vnic_types`` list.
.. list-table:: Mechanism drivers and supported VNIC types
:header-rows: 1
* - mech driver / supported_vnic_types
- supported VNIC types
- blacklisting available
* - Linux bridge
- normal
- no
* - MacVTap
- macvtap
- no
* - Open vSwitch
- normal, direct
- yes (ovs_driver vnic_type_blacklist, see: `Configuration Reference <../configuration/ml2-conf.html#ovs_driver>`__)
* - SRIOV
- direct, macvtap, direct_physical
- no
Extension Drivers
-----------------

View File

@ -0,0 +1,40 @@
# Copyright (c) 2018 Ericsson
#
# 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 neutron._i18n import _
ovs_driver_opts = [
cfg.ListOpt('vnic_type_blacklist',
default=[],
help=_("Comma-separated list of VNIC types for which support "
"is administratively prohibited by the mechanism "
"driver. Please note that the supported vnic_types "
"depend on your network interface card, on the kernel "
"version of your operating system, and on other "
"factors, like OVS version. In case of ovs mechanism "
"driver the valid vnic types are normal and direct. "
"Note that direct is supported only from kernel 4.8, "
"and from ovs 2.8.0. Bind DIRECT (SR-IOV) port allows "
"to offload the OVS flows using tc to the SR-IOV NIC. "
"This allows to support hardware offload via tc and "
"that allows us to manage the VF by OpenFlow control "
"plane using representor net-device.")),
]
def register_ovs_mech_driver_opts(cfg=cfg.CONF):
cfg.register_opts(ovs_driver_opts, "OVS_DRIVER")

View File

@ -47,6 +47,7 @@ import neutron.conf.plugins.ml2.drivers.l2pop
import neutron.conf.plugins.ml2.drivers.linuxbridge
import neutron.conf.plugins.ml2.drivers.macvtap
import neutron.conf.plugins.ml2.drivers.mech_sriov.agent_common
import neutron.conf.plugins.ml2.drivers.openvswitch.mech_ovs_conf
import neutron.conf.plugins.ml2.drivers.ovs_conf
import neutron.conf.quota
import neutron.conf.service
@ -255,7 +256,10 @@ def list_ml2_conf_opts():
('securitygroup',
neutron.conf.agent.securitygroups_rpc.security_group_opts),
('l2pop',
neutron.conf.plugins.ml2.drivers.l2pop.l2_population_options)
neutron.conf.plugins.ml2.drivers.l2pop.l2_population_options),
('ovs_driver',
neutron.conf.plugins.ml2.drivers.openvswitch.mech_ovs_conf.
ovs_driver_opts)
]

View File

@ -22,6 +22,7 @@ from neutron_lib.plugins.ml2 import api
from oslo_log import log
import six
from neutron._i18n import _
from neutron.db import provisioning_blocks
LOG = log.getLogger(__name__)
@ -132,6 +133,34 @@ class AgentMechanismDriverBase(api.MechanismDriver):
return True. Otherwise, it must return False.
"""
def blacklist_supported_vnic_types(self, vnic_types, blacklist):
"""Validate the blacklist and blacklist the supported_vnic_types
:param vnic_types: The supported_vnic_types list
:param blacklist: The blacklist as in vnic_type_blacklist
:return The blacklisted vnic_types
"""
if not blacklist:
return vnic_types
# Not valid values in the blacklist:
if not all(bl in vnic_types for bl in blacklist):
raise ValueError(_("Not all of the items from vnic_type_blacklist "
"are valid vnic_types for %(agent)s mechanism "
"driver. The valid values are: "
"%(valid_vnics)s.") %
{'agent': self.agent_type,
'valid_vnics': vnic_types})
supported_vnic_types = [vnic_t for vnic_t in vnic_types if
vnic_t not in blacklist]
# Nothing left in the supported vnict types list:
if len(supported_vnic_types) < 1:
raise ValueError(_("All possible vnic_types were blacklisted for "
"%s mechanism driver!") % self.agent_type)
return supported_vnic_types
@six.add_metaclass(abc.ABCMeta)
class SimpleAgentMechanismDriverBase(AgentMechanismDriverBase):

View File

@ -23,6 +23,7 @@ from oslo_config import cfg
from oslo_log import log
from neutron.agent import securitygroups_rpc
from neutron.conf.plugins.ml2.drivers.openvswitch import mech_ovs_conf
from neutron.plugins.ml2.drivers import mech_agent
from neutron.plugins.ml2.drivers.openvswitch.agent.common \
import constants as a_const
@ -34,6 +35,8 @@ LOG = log.getLogger(__name__)
IPTABLES_FW_DRIVER_FULL = ("neutron.agent.linux.iptables_firewall."
"OVSHybridIptablesFirewallDriver")
mech_ovs_conf.register_ovs_mech_driver_opts()
class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
"""Attach to networks using openvswitch L2 agent.
@ -60,8 +63,18 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
super(OpenvswitchMechanismDriver, self).__init__(
constants.AGENT_TYPE_OVS,
portbindings.VIF_TYPE_OVS,
vif_details, supported_vnic_types=[portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT])
vif_details)
# TODO(lajoskatona): move this blacklisting to
# SimpleAgentMechanismDriverBase. By that e blacklisting and validation
# of the vnic_types would be available for all mechanism drivers.
self.supported_vnic_types = self.blacklist_supported_vnic_types(
vnic_types=[portbindings.VNIC_NORMAL, portbindings.VNIC_DIRECT],
blacklist=cfg.CONF.OVS_DRIVER.vnic_type_blacklist
)
LOG.info("%s's supported_vnic_types: %s",
self.agent_type, self.supported_vnic_types)
ovs_qos_driver.register()
log_driver.register()

View File

@ -13,6 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_config import fixture as config_fixture
from neutron_lib.api.definitions import portbindings
from neutron_lib.plugins.ml2 import api
@ -171,6 +174,31 @@ class FakePortContext(api.PortContext):
pass
class MechDriverConfFixture(config_fixture.Config):
def __init__(self, conf=cfg.CONF, blacklist_cfg=None,
registration_func=None):
"""ConfigFixture for vnic_type_blacklist
:param conf: The driver configuration object
:param blacklist_cfg: A dictionary in the form
{'group': {'opt': 'value'}}, i.e.:
{'OVS_DRIVER': {'vnic_type_blacklist':
['foo']}}
:param registration_func: The method which do the config group's
registration.
"""
super(MechDriverConfFixture, self).__init__(conf)
self.blacklist_cfg = blacklist_cfg
self.registration_func = registration_func
def setUp(self):
super(MechDriverConfFixture, self).setUp()
self.registration_func(self.conf)
for group, option in self.blacklist_cfg.items():
self.config(group=group, **option)
class AgentMechanismBaseTestCase(base.BaseTestCase):
# The following must be overridden for the specific mechanism
# driver being tested:

View File

@ -21,6 +21,7 @@ from neutron_lib import constants
from neutron_lib.plugins.ml2 import api
from oslo_config import cfg
from neutron.conf.plugins.ml2.drivers.openvswitch import mech_ovs_conf
from neutron.plugins.ml2.drivers.openvswitch.agent.common import (
constants as a_const)
from neutron.plugins.ml2.drivers.openvswitch.mech_driver import (
@ -296,3 +297,61 @@ class OpenvswitchMechanismSRIOVTestCase(OpenvswitchMechanismBaseTestCase):
context = self._make_port_ctx(self.AGENTS, profile=profile)
self.driver.bind_port(context)
mocked_bind_port.assert_called()
class OpenvswitchMechVnicTypesTestCase(OpenvswitchMechanismBaseTestCase):
def setUp(self):
self.blacklist_cfg = {
'OVS_DRIVER': {
'vnic_type_blacklist': []
}
}
self.default_supported_vnics = [portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT]
super(OpenvswitchMechVnicTypesTestCase, self).setUp()
def test_default_vnic_types(self):
self.assertEqual([portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT],
self.driver.supported_vnic_types)
def test_vnic_type_blacklist_valid_item(self):
self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = \
[portbindings.VNIC_DIRECT]
fake_conf = cfg.CONF
fake_conf_fixture = base.MechDriverConfFixture(
fake_conf, self.blacklist_cfg,
mech_ovs_conf.register_ovs_mech_driver_opts)
self.useFixture(fake_conf_fixture)
test_driver = mech_openvswitch.OpenvswitchMechanismDriver()
supported_vnic_types = test_driver.supported_vnic_types
self.assertNotIn(portbindings.VNIC_DIRECT, supported_vnic_types)
self.assertEqual(len(self.default_supported_vnics) - 1,
len(supported_vnic_types))
def test_vnic_type_blacklist_not_valid_item(self):
self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = ['foo']
fake_conf = cfg.CONF
fake_conf_fixture = base.MechDriverConfFixture(
fake_conf, self.blacklist_cfg,
mech_ovs_conf.register_ovs_mech_driver_opts)
self.useFixture(fake_conf_fixture)
self.assertRaises(ValueError,
mech_openvswitch.OpenvswitchMechanismDriver)
def test_vnic_type_blacklist_all_items(self):
self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = \
[portbindings.VNIC_NORMAL, portbindings.VNIC_DIRECT]
fake_conf = cfg.CONF
fake_conf_fixture = base.MechDriverConfFixture(
fake_conf, self.blacklist_cfg,
mech_ovs_conf.register_ovs_mech_driver_opts)
self.useFixture(fake_conf_fixture)
self.assertRaises(ValueError,
mech_openvswitch.OpenvswitchMechanismDriver)

View File

@ -0,0 +1,9 @@
---
other:
- |
Add new configuration group ``ovs_driver`` and new configuration option
under it ``vnic_type_blacklist``, to make the previously hardcoded
``supported_vnic_types`` parameter of the OpenvswitchMechanismDriver
configurable.
The ``vnic_types`` listed in the blacklist will be removed from the
supported_vnic_types list.