This adjusts the _device_to_port_id function in ML2
to recognize other interfaces that belong to Neutron
under different name prefixes.
Adds unit tests to achieve full converage of _device_to_port_id
method.
Closes-Bug: #
1443710
Change-Id: I80284ee67e5876cf5689e49e1592ca1351ae5fa1
from neutron.agent.l3 import namespaces
from neutron.agent.linux import ip_lib
+from neutron.common import constants
LOG = logging.getLogger(__name__)
SNAT_NS_PREFIX = 'snat-'
-SNAT_INT_DEV_PREFIX = 'sg-'
+SNAT_INT_DEV_PREFIX = constants.SNAT_INT_DEV_PREFIX
class SnatNamespace(namespaces.Namespace):
# Device names start with "tap"
TAP_DEVICE_PREFIX = 'tap'
+# The vswitch side of a veth pair for a nova iptables filter setup
+VETH_DEVICE_PREFIX = 'qvo'
+# prefix for SNAT interface in DVR
+SNAT_INT_DEV_PREFIX = 'sg-'
+
+# Possible prefixes to partial port IDs in interface names used by the OVS,
+# Linux Bridge, and IVS VIF drivers in Nova and the neutron agents. See the
+# 'get_ovs_interfaceid' method in Nova (nova/virt/libvirt/vif.py) for details.
+INTERFACE_PREFIXES = (TAP_DEVICE_PREFIX, VETH_DEVICE_PREFIX,
+ SNAT_INT_DEV_PREFIX)
ATTRIBUTES_TO_UPDATE = 'attributes_to_update'
return ports
- def _device_to_port_id(self, device):
+ @staticmethod
+ def _device_to_port_id(device):
# REVISIT(rkukura): Consider calling into MechanismDrivers to
# process device names, or having MechanismDrivers supply list
# of device prefixes to strip.
- if device.startswith(const.TAP_DEVICE_PREFIX):
- return device[len(const.TAP_DEVICE_PREFIX):]
- else:
- # REVISIT(irenab): Consider calling into bound MD to
- # handle the get_device_details RPC, then remove the 'else' clause
- if not uuidutils.is_uuid_like(device):
- port = db.get_port_from_device_mac(device)
- if port:
- return port.id
+ for prefix in const.INTERFACE_PREFIXES:
+ if device.startswith(prefix):
+ return device[len(prefix):]
+ # REVISIT(irenab): Consider calling into bound MD to
+ # handle the get_device_details RPC
+ if not uuidutils.is_uuid_like(device):
+ port = db.get_port_from_device_mac(device)
+ if port:
+ return port.id
return device
from neutron.extensions import portbindings
from neutron.extensions import providernet as pnet
from neutron import manager
+from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants as p_const
from neutron.plugins.ml2.common import exceptions as ml2_exc
from neutron.plugins.ml2 import config
with testtools.ExpectedException(exc.PortBound):
self._test_check_mac_update_allowed(portbindings.VIF_TYPE_OVS)
+ def test__device_to_port_id_prefix_names(self):
+ input_output = [('sg-abcdefg', 'abcdefg'),
+ ('tap123456', '123456'),
+ ('qvo567890', '567890')]
+ for device, expected in input_output:
+ self.assertEqual(expected,
+ ml2_plugin.Ml2Plugin._device_to_port_id(device))
+
+ def test__device_to_port_id_mac_address(self):
+ with self.port() as p:
+ mac = p['port']['mac_address']
+ port_id = p['port']['id']
+ self.assertEqual(port_id,
+ ml2_plugin.Ml2Plugin._device_to_port_id(mac))
+
+ def test__device_to_port_id_not_uuid_not_mac(self):
+ dev = '1234567'
+ self.assertEqual(dev, ml2_plugin.Ml2Plugin._device_to_port_id(dev))
+
+ def test__device_to_port_id_UUID(self):
+ port_id = uuidutils.generate_uuid()
+ self.assertEqual(port_id,
+ ml2_plugin.Ml2Plugin._device_to_port_id(port_id))
+
class TestMl2DvrPortsV2(TestMl2PortsV2):
def setUp(self):