Check that VXLAN is not in use in LB VXLAN check

The Linux bridge VXLAN supported check was only checking that the
test interface didn't exist instead of checking that both the interface
and the VXLAN didn't exist. This caused it to fail on startup if
a VXLAN interface existed under a different name using one of the
VXLANs that the agent tried to test support with.

This patch adds a check to ensure that the VXLAN ID isn't in use as well.

Closes-Bug: #1470579
Change-Id: I3a91ce54da86e319b7a4485dfae3fc99885383d4
This commit is contained in:
Kevin Benton 2015-07-29 16:32:43 -07:00
parent 50d662d95a
commit a8d1b72180
4 changed files with 40 additions and 5 deletions

View File

@ -723,6 +723,14 @@ class IpNetnsCommand(IpCommandBase):
return False
def vxlan_in_use(segmentation_id, namespace=None):
"""Return True if VXLAN VNID is in use by an interface, else False."""
ip_wrapper = IPWrapper(namespace=namespace)
interfaces = ip_wrapper.netns.execute(["ip", "-d", "link", "list"],
check_exit_code=True)
return 'vxlan id %s ' % segmentation_id in interfaces
def device_exists(device_name, namespace=None):
"""Return True if the device exists in the namespace."""
try:

View File

@ -31,6 +31,7 @@ from oslo_log import log as logging
import oslo_messaging
from oslo_service import loopingcall
from oslo_service import service
from oslo_utils import excutils
from six import moves
from neutron.agent.linux import bridge_lib
@ -248,7 +249,19 @@ class LinuxBridgeManager(object):
args['tos'] = cfg.CONF.VXLAN.tos
if cfg.CONF.VXLAN.l2_population:
args['proxy'] = True
int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args)
try:
int_vxlan = self.ip.add_vxlan(interface, segmentation_id,
**args)
except RuntimeError:
with excutils.save_and_reraise_exception() as ctxt:
# perform this check after an attempt rather than before
# to avoid excessive lookups and a possible race condition.
if ip_lib.vxlan_in_use(segmentation_id):
ctxt.reraise = False
LOG.error(_LE("Unable to create VXLAN interface for "
"VNI %s because it is in use by another "
"interface."), segmentation_id)
return None
int_vxlan.link.set_up()
LOG.debug("Done creating vxlan interface %s", interface)
return interface
@ -526,10 +539,11 @@ class LinuxBridgeManager(object):
test_iface = None
for seg_id in moves.range(1, p_const.MAX_VXLAN_VNI + 1):
if not ip_lib.device_exists(
self.get_vxlan_device_name(seg_id)):
test_iface = self.ensure_vxlan(seg_id)
break
if (ip_lib.device_exists(self.get_vxlan_device_name(seg_id))
or ip_lib.vxlan_in_use(seg_id)):
continue
test_iface = self.ensure_vxlan(seg_id)
break
else:
LOG.error(_LE('No valid Segmentation ID to perform UCAST test.'))
return False

View File

@ -101,6 +101,18 @@ class IpLibTestCase(IpLibTestFramework):
self.assertFalse(
ip_lib.device_exists(attr.name, namespace=attr.namespace))
def test_vxlan_exists(self):
attr = self.generate_device_details()
ip = ip_lib.IPWrapper(namespace=attr.namespace)
ip.netns.add(attr.namespace)
self.addCleanup(ip.netns.delete, attr.namespace)
self.assertFalse(ip_lib.vxlan_in_use(9999, namespace=attr.namespace))
device = ip.add_vxlan(attr.name, 9999)
self.addCleanup(self._safe_delete_device, device)
self.assertTrue(ip_lib.vxlan_in_use(9999, namespace=attr.namespace))
device.link.delete()
self.assertFalse(ip_lib.vxlan_in_use(9999, namespace=attr.namespace))
def test_ipwrapper_get_device_by_ip(self):
attr = self.generate_device_details()
self.manage_device(attr)

View File

@ -873,6 +873,7 @@ class TestLinuxBridgeManager(base.BaseTestCase):
self, expected, l2_population, iproute_arg_supported, fdb_append):
cfg.CONF.set_override('l2_population', l2_population, 'VXLAN')
with mock.patch.object(ip_lib, 'device_exists', return_value=False),\
mock.patch.object(ip_lib, 'vxlan_in_use', return_value=False),\
mock.patch.object(self.lbm,
'delete_vxlan',
return_value=None),\