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'
|
||||
OVS_HYBRID_PLUG = 'ovs_hybrid_plug'
|
||||
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
|
||||
# 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
|
||||
# vhost-user vif.
|
||||
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
|
||||
# provided by qemu 2.1+. This constant defines the neutron side
|
||||
# of the vif binding type to provide a common definition
|
||||
|
@ -75,7 +82,15 @@ VIF_TYPE_DISTRIBUTED = 'distributed'
|
|||
VIF_TYPE_OVS = 'ovs'
|
||||
VIF_TYPE_BRIDGE = 'bridge'
|
||||
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_DIRECT = 'direct'
|
||||
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
|
||||
test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver
|
||||
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
|
||||
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
|
||||
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
|
||||
|
|
Loading…
Reference in New Issue