Merge "Check vxlan enablement via modinfo"

This commit is contained in:
Jenkins 2014-03-17 22:52:36 +00:00 committed by Gerrit Code Review
commit cc48a40da6
4 changed files with 170 additions and 76 deletions

View File

@ -308,5 +308,9 @@ class NetworkVxlanPortRangeError(NeutronException):
message = _("Invalid network VXLAN port range: '%(vxlan_range)s'")
class VxlanNetworkUnsupported(NeutronException):
message = _("VXLAN Network unsupported.")
class DuplicatedExtension(NeutronException):
message = _("Found duplicate extension: %(alias)s")

View File

@ -22,9 +22,7 @@
# Neutron OpenVSwitch Plugin.
# @author: Sumit Naiksatam, Cisco Systems, Inc.
import distutils.version as dist_version
import os
import platform
import sys
import time
@ -38,6 +36,7 @@ from neutron.agent import rpc as agent_rpc
from neutron.agent import securitygroups_rpc as sg_rpc
from neutron.common import config as logging_config
from neutron.common import constants
from neutron.common import exceptions
from neutron.common import topics
from neutron.common import utils as q_utils
from neutron import context
@ -514,29 +513,74 @@ class LinuxBridgeManager:
devices.add(device)
return devices
def check_vxlan_support(self):
kernel_version = dist_version.LooseVersion(platform.release())
if cfg.CONF.VXLAN.l2_population and (
kernel_version > dist_version.LooseVersion(
lconst.MIN_VXLAN_KVER[lconst.VXLAN_UCAST])) and (
ip_lib.iproute_arg_supported(['bridge', 'fdb'],
'append', self.root_helper)):
self.vxlan_mode = lconst.VXLAN_UCAST
elif (kernel_version > dist_version.LooseVersion(
lconst.MIN_VXLAN_KVER[lconst.VXLAN_MCAST])) and (
ip_lib.iproute_arg_supported(['ip', 'link', 'add',
'type', 'vxlan'], 'proxy',
self.root_helper)):
if cfg.CONF.VXLAN.vxlan_group:
self.vxlan_mode = lconst.VXLAN_MCAST
else:
self.vxlan_mode = lconst.VXLAN_NONE
LOG.warning(_('VXLAN muticast group must be provided in '
'vxlan_group option to enable VXLAN'))
def vxlan_ucast_supported(self):
if not cfg.CONF.VXLAN.l2_population:
return False
if not ip_lib.iproute_arg_supported(
['bridge', 'fdb'], 'append', self.root_helper):
LOG.warning(_('Option "%(option)s" must be supported by command '
'"%(command)s" to enable %(mode)s mode') %
{'option': 'append',
'command': 'bridge fdb',
'mode': 'VXLAN UCAST'})
return False
for segmentation_id in range(1, constants.MAX_VXLAN_VNI + 1):
if not self.device_exists(
self.get_vxlan_device_name(segmentation_id)):
break
else:
self.vxlan_mode = lconst.VXLAN_NONE
LOG.warning(_('Unable to use VXLAN, it requires at least 3.8 '
'linux kernel and iproute2 3.8'))
LOG.error(_('No valid Segmentation ID to perform UCAST test.'))
return False
test_iface = self.ensure_vxlan(segmentation_id)
try:
utils.execute(
cmd=['bridge', 'fdb', 'append', constants.FLOODING_ENTRY[0],
'dev', test_iface, 'dst', '1.1.1.1'],
root_helper=self.root_helper)
return True
except RuntimeError:
return False
finally:
self.delete_vxlan(test_iface)
def vxlan_mcast_supported(self):
if not cfg.CONF.VXLAN.vxlan_group:
LOG.warning(_('VXLAN muticast group must be provided in '
'vxlan_group option to enable VXLAN MCAST mode'))
return False
if not ip_lib.iproute_arg_supported(
['ip', 'link', 'add', 'type', 'vxlan'],
'proxy', self.root_helper):
LOG.warning(_('Option "%(option)s" must be supported by command '
'"%(command)s" to enable %(mode)s mode') %
{'option': 'proxy',
'command': 'ip link add type vxlan',
'mode': 'VXLAN MCAST'})
return False
return True
def vxlan_module_supported(self):
try:
utils.execute(cmd=['modinfo', 'vxlan'])
return True
except RuntimeError:
return False
def check_vxlan_support(self):
self.vxlan_mode = lconst.VXLAN_NONE
if not self.vxlan_module_supported():
LOG.error(_('Linux kernel vxlan module and iproute2 3.8 or above '
'are required to enable VXLAN.'))
raise exceptions.VxlanNetworkUnsupported()
if self.vxlan_ucast_supported():
self.vxlan_mode = lconst.VXLAN_UCAST
elif self.vxlan_mcast_supported():
self.vxlan_mode = lconst.VXLAN_MCAST
else:
raise exceptions.VxlanNetworkUnsupported()
LOG.debug(_('Using %s VXLAN mode'), self.vxlan_mode)
def fdb_ip_entry_exists(self, mac, ip, interface):

View File

@ -28,9 +28,6 @@ VXLAN_NONE = 'not_supported'
VXLAN_MCAST = 'multicast_flooding'
VXLAN_UCAST = 'unicast_flooding'
# Corresponding minimal kernel versions requirements
MIN_VXLAN_KVER = {VXLAN_MCAST: '3.8', VXLAN_UCAST: '3.11'}
# TODO(rkukura): Eventually remove this function, which provides
# temporary backward compatibility with pre-Havana RPC and DB vlan_id

View File

@ -24,6 +24,7 @@ import testtools
from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils
from neutron.common import constants
from neutron.common import exceptions
from neutron.openstack.common.rpc import common as rpc_common
from neutron.plugins.common import constants as p_const
from neutron.plugins.linuxbridge.agent import linuxbridge_neutron_agent
@ -646,59 +647,107 @@ class TestLinuxBridgeManager(base.BaseTestCase):
"removed": set(["dev3"])
})
def _check_vxlan_support(self, kernel_version, vxlan_proxy_supported,
fdb_append_supported, l2_population,
expected_mode):
def iproute_supported_side_effect(*args):
if args[1] == 'proxy':
return vxlan_proxy_supported
elif args[1] == 'append':
return fdb_append_supported
def _check_vxlan_support(self, expected, vxlan_module_supported,
vxlan_ucast_supported, vxlan_mcast_supported):
with contextlib.nested(
mock.patch("platform.release", return_value=kernel_version),
mock.patch.object(ip_lib, 'iproute_arg_supported',
side_effect=iproute_supported_side_effect),
) as (kver_fn, ip_arg_fn):
self.lbm.check_vxlan_support()
self.assertEqual(self.lbm.vxlan_mode, expected_mode)
mock.patch.object(self.lbm, 'vxlan_module_supported',
return_value=vxlan_module_supported),
mock.patch.object(self.lbm, 'vxlan_ucast_supported',
return_value=vxlan_ucast_supported),
mock.patch.object(self.lbm, 'vxlan_mcast_supported',
return_value=vxlan_mcast_supported)):
if expected == lconst.VXLAN_NONE:
self.assertRaises(exceptions.VxlanNetworkUnsupported,
self.lbm.check_vxlan_support)
self.assertEqual(expected, self.lbm.vxlan_mode)
else:
self.lbm.check_vxlan_support()
self.assertEqual(expected, self.lbm.vxlan_mode)
def test_vxlan_mode_ucast(self):
self._check_vxlan_support(kernel_version='3.12',
vxlan_proxy_supported=True,
fdb_append_supported=True,
l2_population=True,
expected_mode=lconst.VXLAN_MCAST)
def test_check_vxlan_support(self):
self._check_vxlan_support(expected=lconst.VXLAN_UCAST,
vxlan_module_supported=True,
vxlan_ucast_supported=True,
vxlan_mcast_supported=True)
self._check_vxlan_support(expected=lconst.VXLAN_MCAST,
vxlan_module_supported=True,
vxlan_ucast_supported=False,
vxlan_mcast_supported=True)
def test_vxlan_mode_mcast(self):
self._check_vxlan_support(kernel_version='3.12',
vxlan_proxy_supported=True,
fdb_append_supported=False,
l2_population=True,
expected_mode=lconst.VXLAN_MCAST)
self._check_vxlan_support(kernel_version='3.10',
vxlan_proxy_supported=True,
fdb_append_supported=True,
l2_population=True,
expected_mode=lconst.VXLAN_MCAST)
self._check_vxlan_support(expected=lconst.VXLAN_NONE,
vxlan_module_supported=False,
vxlan_ucast_supported=False,
vxlan_mcast_supported=False)
self._check_vxlan_support(expected=lconst.VXLAN_NONE,
vxlan_module_supported=True,
vxlan_ucast_supported=False,
vxlan_mcast_supported=False)
def test_vxlan_mode_unsupported(self):
self._check_vxlan_support(kernel_version='3.7',
vxlan_proxy_supported=True,
fdb_append_supported=True,
l2_population=False,
expected_mode=lconst.VXLAN_NONE)
self._check_vxlan_support(kernel_version='3.10',
vxlan_proxy_supported=False,
fdb_append_supported=False,
l2_population=False,
expected_mode=lconst.VXLAN_NONE)
cfg.CONF.set_override('vxlan_group', '', 'VXLAN')
self._check_vxlan_support(kernel_version='3.12',
vxlan_proxy_supported=True,
fdb_append_supported=True,
l2_population=True,
expected_mode=lconst.VXLAN_NONE)
def _check_vxlan_module_supported(self, expected, execute_side_effect):
with mock.patch.object(
utils, 'execute',
side_effect=execute_side_effect):
self.assertEqual(expected, self.lbm.vxlan_module_supported())
def test_vxlan_module_supported(self):
self._check_vxlan_module_supported(
expected=True,
execute_side_effect=None)
self._check_vxlan_module_supported(
expected=False,
execute_side_effect=RuntimeError())
def _check_vxlan_ucast_supported(
self, expected, l2_population, iproute_arg_supported, fdb_append):
cfg.CONF.set_override('l2_population', l2_population, 'VXLAN')
with contextlib.nested(
mock.patch.object(
self.lbm, 'device_exists', return_value=False),
mock.patch.object(self.lbm, 'delete_vxlan', return_value=None),
mock.patch.object(self.lbm, 'ensure_vxlan', return_value=None),
mock.patch.object(
utils, 'execute',
side_effect=None if fdb_append else RuntimeError()),
mock.patch.object(
ip_lib, 'iproute_arg_supported',
return_value=iproute_arg_supported)):
self.assertEqual(expected, self.lbm.vxlan_ucast_supported())
def test_vxlan_ucast_supported(self):
self._check_vxlan_ucast_supported(
expected=False,
l2_population=False, iproute_arg_supported=True, fdb_append=True)
self._check_vxlan_ucast_supported(
expected=False,
l2_population=True, iproute_arg_supported=False, fdb_append=True)
self._check_vxlan_ucast_supported(
expected=False,
l2_population=True, iproute_arg_supported=True, fdb_append=False)
self._check_vxlan_ucast_supported(
expected=True,
l2_population=True, iproute_arg_supported=True, fdb_append=True)
def _check_vxlan_mcast_supported(
self, expected, vxlan_group, iproute_arg_supported):
cfg.CONF.set_override('vxlan_group', vxlan_group, 'VXLAN')
with mock.patch.object(
ip_lib, 'iproute_arg_supported',
return_value=iproute_arg_supported):
self.assertEqual(expected, self.lbm.vxlan_mcast_supported())
def test_vxlan_mcast_supported(self):
self._check_vxlan_mcast_supported(
expected=False,
vxlan_group='',
iproute_arg_supported=True)
self._check_vxlan_mcast_supported(
expected=False,
vxlan_group='224.0.0.1',
iproute_arg_supported=False)
self._check_vxlan_mcast_supported(
expected=True,
vxlan_group='224.0.0.1',
iproute_arg_supported=True)
class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):