macvtap: ML2 mech driver for macvtap network attachments
This driver uses the vif_type 'macvtap'. It enriches the vif_details with the corresponding attributes required by nova [1] to support macvtap attachments for libvirt qemu/kvm guests. The review is submitted in three parts: - Part 1 Common functions that are used by the ml2 driver and the agent - Part 2 (this part) The Mechanism Driver to support port binding for macvtap attachments - Part 3 The Macvtap L2 Agent. [1] https://review.openstack.org/#/c/182283 Change-Id: I206f58a21c36e55de957d8a23993aa9bc26d1595 Partial-Bug: #1480979
This commit is contained in:
parent
bfcad8eec7
commit
eb9bda12d2
|
@ -46,6 +46,9 @@ PROFILE = 'binding:profile'
|
||||||
CAP_PORT_FILTER = 'port_filter'
|
CAP_PORT_FILTER = 'port_filter'
|
||||||
OVS_HYBRID_PLUG = 'ovs_hybrid_plug'
|
OVS_HYBRID_PLUG = 'ovs_hybrid_plug'
|
||||||
VIF_DETAILS_VLAN = 'vlan'
|
VIF_DETAILS_VLAN = 'vlan'
|
||||||
|
VIF_DETAILS_MACVTAP_SOURCE = 'macvtap_source'
|
||||||
|
VIF_DETAILS_MACVTAP_MODE = 'macvtap_mode'
|
||||||
|
VIF_DETAILS_PHYSICAL_INTERFACE = 'physical_interface'
|
||||||
|
|
||||||
# The keys below are used in the VIF_DETAILS attribute to convey
|
# The keys below are used in the VIF_DETAILS attribute to convey
|
||||||
# information related to the configuration of the vhost-user VIF driver.
|
# information related to the configuration of the vhost-user VIF driver.
|
||||||
|
@ -63,6 +66,10 @@ VHOST_USER_SOCKET = 'vhostuser_socket'
|
||||||
# method should be used when binding the
|
# method should be used when binding the
|
||||||
# vhost-user vif.
|
# vhost-user vif.
|
||||||
VHOST_USER_OVS_PLUG = 'vhostuser_ovs_plug'
|
VHOST_USER_OVS_PLUG = 'vhostuser_ovs_plug'
|
||||||
|
|
||||||
|
# VIF_TYPE: vif_types are required by Nova to determine which vif_driver to
|
||||||
|
# use to attach a virtual server to the network
|
||||||
|
|
||||||
# - vhost-user: The vhost-user interface type is a standard virtio interface
|
# - vhost-user: The vhost-user interface type is a standard virtio interface
|
||||||
# provided by qemu 2.1+. This constant defines the neutron side
|
# provided by qemu 2.1+. This constant defines the neutron side
|
||||||
# of the vif binding type to provide a common definition
|
# of the vif binding type to provide a common definition
|
||||||
|
@ -75,7 +82,15 @@ VIF_TYPE_DISTRIBUTED = 'distributed'
|
||||||
VIF_TYPE_OVS = 'ovs'
|
VIF_TYPE_OVS = 'ovs'
|
||||||
VIF_TYPE_BRIDGE = 'bridge'
|
VIF_TYPE_BRIDGE = 'bridge'
|
||||||
VIF_TYPE_OTHER = 'other'
|
VIF_TYPE_OTHER = 'other'
|
||||||
|
# vif_type_macvtap: Tells Nova that the macvtap vif_driver should be used to
|
||||||
|
# create a vif. It does not require the VNIC_TYPE_MACVTAP,
|
||||||
|
# which is defined further below. E.g. Macvtap agent uses
|
||||||
|
# vnic_type 'normal'.
|
||||||
|
VIF_TYPE_MACVTAP = 'macvtap'
|
||||||
|
|
||||||
|
# VNIC_TYPE: It's used to determine which mechanism driver to use to bind a
|
||||||
|
# port. It can be specified via the Neutron API. Default is normal,
|
||||||
|
# used by OVS and LinuxBridge agent.
|
||||||
VNIC_NORMAL = 'normal'
|
VNIC_NORMAL = 'normal'
|
||||||
VNIC_DIRECT = 'direct'
|
VNIC_DIRECT = 'direct'
|
||||||
VNIC_MACVTAP = 'macvtap'
|
VNIC_MACVTAP = 'macvtap'
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Copyright (c) 2016 IBM Corp.
|
||||||
|
#
|
||||||
|
# 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 oslo_log import log
|
||||||
|
|
||||||
|
from neutron.common import constants
|
||||||
|
from neutron.extensions import portbindings
|
||||||
|
from neutron.plugins.common import constants as p_constants
|
||||||
|
from neutron.plugins.ml2 import driver_api as api
|
||||||
|
from neutron.plugins.ml2.drivers.macvtap import macvtap_common
|
||||||
|
from neutron.plugins.ml2.drivers import mech_agent
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
MACVTAP_MODE_BRIDGE = 'bridge'
|
||||||
|
|
||||||
|
|
||||||
|
class MacvtapMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
||||||
|
"""Attach to networks using Macvtap L2 agent.
|
||||||
|
|
||||||
|
The MacvtapMechanismDriver integrates the ml2 plugin with the
|
||||||
|
macvtap L2 agent. Port binding with this driver requires the
|
||||||
|
macvtap agent to be running on the port's host, and that agent
|
||||||
|
to have connectivity to at least one segment of the port's
|
||||||
|
network.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(MacvtapMechanismDriver, self).__init__(
|
||||||
|
constants.AGENT_TYPE_MACVTAP,
|
||||||
|
portbindings.VIF_TYPE_MACVTAP,
|
||||||
|
{portbindings.CAP_PORT_FILTER: False})
|
||||||
|
|
||||||
|
def get_allowed_network_types(self, agent):
|
||||||
|
return [p_constants.TYPE_FLAT, p_constants.TYPE_VLAN]
|
||||||
|
|
||||||
|
def get_mappings(self, agent):
|
||||||
|
return agent['configurations'].get('interface_mappings', {})
|
||||||
|
|
||||||
|
def check_vlan_transparency(self, context):
|
||||||
|
"""Macvtap driver vlan transparency support."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def try_to_bind_segment_for_agent(self, context, segment, agent):
|
||||||
|
if self.check_segment_for_agent(segment, agent):
|
||||||
|
vif_details_segment = self.vif_details
|
||||||
|
mappings = self.get_mappings(agent)
|
||||||
|
interface = mappings[segment['physical_network']]
|
||||||
|
network_type = segment[api.NETWORK_TYPE]
|
||||||
|
|
||||||
|
if network_type == p_constants.TYPE_VLAN:
|
||||||
|
vlan_id = segment[api.SEGMENTATION_ID]
|
||||||
|
macvtap_src = macvtap_common.get_vlan_device_name(interface,
|
||||||
|
vlan_id)
|
||||||
|
vif_details_segment['vlan'] = vlan_id
|
||||||
|
else:
|
||||||
|
macvtap_src = interface
|
||||||
|
|
||||||
|
vif_details_segment['physical_interface'] = interface
|
||||||
|
vif_details_segment['macvtap_source'] = macvtap_src
|
||||||
|
vif_details_segment['macvtap_mode'] = MACVTAP_MODE_BRIDGE
|
||||||
|
LOG.debug("Macvtap vif_details added to context binding: %s",
|
||||||
|
vif_details_segment)
|
||||||
|
context.set_binding(segment[api.ID], self.vif_type,
|
||||||
|
vif_details_segment)
|
||||||
|
return True
|
||||||
|
return False
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Copyright (c) 2015 IBM Corp.
|
||||||
|
# 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.common import constants
|
||||||
|
from neutron.extensions import portbindings
|
||||||
|
from neutron.plugins.ml2.drivers.macvtap.mech_driver import mech_macvtap
|
||||||
|
from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
|
||||||
|
|
||||||
|
|
||||||
|
class MacvtapMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
|
||||||
|
VIF_TYPE = portbindings.VIF_TYPE_MACVTAP
|
||||||
|
CAP_PORT_FILTER = False
|
||||||
|
AGENT_TYPE = constants.AGENT_TYPE_MACVTAP
|
||||||
|
|
||||||
|
GOOD_MAPPINGS = {'fake_physical_network': 'fake_if'}
|
||||||
|
GOOD_CONFIGS = {'interface_mappings': GOOD_MAPPINGS}
|
||||||
|
|
||||||
|
BAD_MAPPINGS = {'wrong_physical_network': 'wrong_if'}
|
||||||
|
BAD_CONFIGS = {'interface_mappings': BAD_MAPPINGS}
|
||||||
|
|
||||||
|
AGENTS = [{'alive': True,
|
||||||
|
'configurations': GOOD_CONFIGS,
|
||||||
|
'host': 'host'}]
|
||||||
|
AGENTS_DEAD = [{'alive': False,
|
||||||
|
'configurations': GOOD_CONFIGS,
|
||||||
|
'host': 'dead_host'}]
|
||||||
|
AGENTS_BAD = [{'alive': False,
|
||||||
|
'configurations': GOOD_CONFIGS,
|
||||||
|
'host': 'bad_host_1'},
|
||||||
|
{'alive': True,
|
||||||
|
'configurations': BAD_CONFIGS,
|
||||||
|
'host': 'bad_host_2'}]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(MacvtapMechanismBaseTestCase, self).setUp()
|
||||||
|
self.driver = mech_macvtap.MacvtapMechanismDriver()
|
||||||
|
self.driver.initialize()
|
||||||
|
|
||||||
|
|
||||||
|
class MacvtapMechanismGenericTestCase(MacvtapMechanismBaseTestCase,
|
||||||
|
base.AgentMechanismGenericTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MacvtapMechanismFlatTestCase(MacvtapMechanismBaseTestCase,
|
||||||
|
base.AgentMechanismFlatTestCase):
|
||||||
|
def test_type_flat_vif_details(self):
|
||||||
|
context = base.FakePortContext(self.AGENT_TYPE,
|
||||||
|
self.AGENTS,
|
||||||
|
self.FLAT_SEGMENTS,
|
||||||
|
vnic_type=self.VNIC_TYPE)
|
||||||
|
self.driver.bind_port(context)
|
||||||
|
vif_details = context._bound_vif_details
|
||||||
|
|
||||||
|
self.assertIsNone(vif_details.get(portbindings.VIF_DETAILS_VLAN))
|
||||||
|
self.assertEqual("bridge", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_MACVTAP_MODE))
|
||||||
|
self.assertEqual("fake_if", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_PHYSICAL_INTERFACE))
|
||||||
|
self.assertEqual("fake_if", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_MACVTAP_SOURCE))
|
||||||
|
|
||||||
|
|
||||||
|
class MacvtapMechanismVlanTestCase(MacvtapMechanismBaseTestCase,
|
||||||
|
base.AgentMechanismVlanTestCase):
|
||||||
|
def test_type_vlan_vif_details(self):
|
||||||
|
context = base.FakePortContext(self.AGENT_TYPE,
|
||||||
|
self.AGENTS,
|
||||||
|
self.VLAN_SEGMENTS,
|
||||||
|
vnic_type=self.VNIC_TYPE)
|
||||||
|
self.driver.bind_port(context)
|
||||||
|
vif_details = context._bound_vif_details
|
||||||
|
|
||||||
|
self.assertEqual(1234, vif_details.get(portbindings.VIF_DETAILS_VLAN))
|
||||||
|
self.assertEqual("bridge", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_MACVTAP_MODE))
|
||||||
|
self.assertEqual("fake_if", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_PHYSICAL_INTERFACE))
|
||||||
|
self.assertEqual("fake_if.1234", vif_details.get(
|
||||||
|
portbindings.VIF_DETAILS_MACVTAP_SOURCE))
|
|
@ -91,6 +91,7 @@ neutron.ml2.mechanism_drivers =
|
||||||
logger = neutron.tests.unit.plugins.ml2.drivers.mechanism_logger:LoggerMechanismDriver
|
logger = neutron.tests.unit.plugins.ml2.drivers.mechanism_logger:LoggerMechanismDriver
|
||||||
test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver
|
test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver
|
||||||
linuxbridge = neutron.plugins.ml2.drivers.linuxbridge.mech_driver.mech_linuxbridge:LinuxbridgeMechanismDriver
|
linuxbridge = neutron.plugins.ml2.drivers.linuxbridge.mech_driver.mech_linuxbridge:LinuxbridgeMechanismDriver
|
||||||
|
macvtap = neutron.plugins.ml2.drivers.macvtap.mech_driver.mech_macvtap:MacvtapMechanismDriver
|
||||||
openvswitch = neutron.plugins.ml2.drivers.openvswitch.mech_driver.mech_openvswitch:OpenvswitchMechanismDriver
|
openvswitch = neutron.plugins.ml2.drivers.openvswitch.mech_driver.mech_openvswitch:OpenvswitchMechanismDriver
|
||||||
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
|
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
|
||||||
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
|
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
|
||||||
|
|
Loading…
Reference in New Issue