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 6945f525f4
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'") message = _("Invalid network VXLAN port range: '%(vxlan_range)s'")
class VxlanNetworkUnsupported(NeutronException):
message = _("VXLAN Network unsupported.")
class DuplicatedExtension(NeutronException): class DuplicatedExtension(NeutronException):
message = _("Found duplicate extension: %(alias)s") message = _("Found duplicate extension: %(alias)s")

View File

@ -22,9 +22,7 @@
# Neutron OpenVSwitch Plugin. # Neutron OpenVSwitch Plugin.
# @author: Sumit Naiksatam, Cisco Systems, Inc. # @author: Sumit Naiksatam, Cisco Systems, Inc.
import distutils.version as dist_version
import os import os
import platform
import sys import sys
import time 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.agent import securitygroups_rpc as sg_rpc
from neutron.common import config as logging_config from neutron.common import config as logging_config
from neutron.common import constants from neutron.common import constants
from neutron.common import exceptions
from neutron.common import topics from neutron.common import topics
from neutron.common import utils as q_utils from neutron.common import utils as q_utils
from neutron import context from neutron import context
@ -514,29 +513,74 @@ class LinuxBridgeManager:
devices.add(device) devices.add(device)
return devices return devices
def check_vxlan_support(self): def vxlan_ucast_supported(self):
kernel_version = dist_version.LooseVersion(platform.release()) if not cfg.CONF.VXLAN.l2_population:
if cfg.CONF.VXLAN.l2_population and ( return False
kernel_version > dist_version.LooseVersion( if not ip_lib.iproute_arg_supported(
lconst.MIN_VXLAN_KVER[lconst.VXLAN_UCAST])) and ( ['bridge', 'fdb'], 'append', self.root_helper):
ip_lib.iproute_arg_supported(['bridge', 'fdb'], LOG.warning(_('Option "%(option)s" must be supported by command '
'append', self.root_helper)): '"%(command)s" to enable %(mode)s mode') %
self.vxlan_mode = lconst.VXLAN_UCAST {'option': 'append',
elif (kernel_version > dist_version.LooseVersion( 'command': 'bridge fdb',
lconst.MIN_VXLAN_KVER[lconst.VXLAN_MCAST])) and ( 'mode': 'VXLAN UCAST'})
ip_lib.iproute_arg_supported(['ip', 'link', 'add', return False
'type', 'vxlan'], 'proxy', for segmentation_id in range(1, constants.MAX_VXLAN_VNI + 1):
self.root_helper)): if not self.device_exists(
if cfg.CONF.VXLAN.vxlan_group: self.get_vxlan_device_name(segmentation_id)):
self.vxlan_mode = lconst.VXLAN_MCAST break
else:
self.vxlan_mode = lconst.VXLAN_NONE
LOG.warning(_('VXLAN muticast group must be provided in '
'vxlan_group option to enable VXLAN'))
else: else:
self.vxlan_mode = lconst.VXLAN_NONE LOG.error(_('No valid Segmentation ID to perform UCAST test.'))
LOG.warning(_('Unable to use VXLAN, it requires at least 3.8 ' return False
'linux kernel and iproute2 3.8'))
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) LOG.debug(_('Using %s VXLAN mode'), self.vxlan_mode)
def fdb_ip_entry_exists(self, mac, ip, interface): def fdb_ip_entry_exists(self, mac, ip, interface):

View File

@ -28,9 +28,6 @@ VXLAN_NONE = 'not_supported'
VXLAN_MCAST = 'multicast_flooding' VXLAN_MCAST = 'multicast_flooding'
VXLAN_UCAST = 'unicast_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 # TODO(rkukura): Eventually remove this function, which provides
# temporary backward compatibility with pre-Havana RPC and DB vlan_id # 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 ip_lib
from neutron.agent.linux import utils from neutron.agent.linux import utils
from neutron.common import constants from neutron.common import constants
from neutron.common import exceptions
from neutron.openstack.common.rpc import common as rpc_common from neutron.openstack.common.rpc import common as rpc_common
from neutron.plugins.common import constants as p_const from neutron.plugins.common import constants as p_const
from neutron.plugins.linuxbridge.agent import linuxbridge_neutron_agent from neutron.plugins.linuxbridge.agent import linuxbridge_neutron_agent
@ -646,59 +647,107 @@ class TestLinuxBridgeManager(base.BaseTestCase):
"removed": set(["dev3"]) "removed": set(["dev3"])
}) })
def _check_vxlan_support(self, kernel_version, vxlan_proxy_supported, def _check_vxlan_support(self, expected, vxlan_module_supported,
fdb_append_supported, l2_population, vxlan_ucast_supported, vxlan_mcast_supported):
expected_mode):
def iproute_supported_side_effect(*args):
if args[1] == 'proxy':
return vxlan_proxy_supported
elif args[1] == 'append':
return fdb_append_supported
with contextlib.nested( with contextlib.nested(
mock.patch("platform.release", return_value=kernel_version), mock.patch.object(self.lbm, 'vxlan_module_supported',
mock.patch.object(ip_lib, 'iproute_arg_supported', return_value=vxlan_module_supported),
side_effect=iproute_supported_side_effect), mock.patch.object(self.lbm, 'vxlan_ucast_supported',
) as (kver_fn, ip_arg_fn): return_value=vxlan_ucast_supported),
self.lbm.check_vxlan_support() mock.patch.object(self.lbm, 'vxlan_mcast_supported',
self.assertEqual(self.lbm.vxlan_mode, expected_mode) 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): def test_check_vxlan_support(self):
self._check_vxlan_support(kernel_version='3.12', self._check_vxlan_support(expected=lconst.VXLAN_UCAST,
vxlan_proxy_supported=True, vxlan_module_supported=True,
fdb_append_supported=True, vxlan_ucast_supported=True,
l2_population=True, vxlan_mcast_supported=True)
expected_mode=lconst.VXLAN_MCAST) 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(expected=lconst.VXLAN_NONE,
self._check_vxlan_support(kernel_version='3.12', vxlan_module_supported=False,
vxlan_proxy_supported=True, vxlan_ucast_supported=False,
fdb_append_supported=False, vxlan_mcast_supported=False)
l2_population=True, self._check_vxlan_support(expected=lconst.VXLAN_NONE,
expected_mode=lconst.VXLAN_MCAST) vxlan_module_supported=True,
self._check_vxlan_support(kernel_version='3.10', vxlan_ucast_supported=False,
vxlan_proxy_supported=True, vxlan_mcast_supported=False)
fdb_append_supported=True,
l2_population=True,
expected_mode=lconst.VXLAN_MCAST)
def test_vxlan_mode_unsupported(self): def _check_vxlan_module_supported(self, expected, execute_side_effect):
self._check_vxlan_support(kernel_version='3.7', with mock.patch.object(
vxlan_proxy_supported=True, utils, 'execute',
fdb_append_supported=True, side_effect=execute_side_effect):
l2_population=False, self.assertEqual(expected, self.lbm.vxlan_module_supported())
expected_mode=lconst.VXLAN_NONE)
self._check_vxlan_support(kernel_version='3.10', def test_vxlan_module_supported(self):
vxlan_proxy_supported=False, self._check_vxlan_module_supported(
fdb_append_supported=False, expected=True,
l2_population=False, execute_side_effect=None)
expected_mode=lconst.VXLAN_NONE) self._check_vxlan_module_supported(
cfg.CONF.set_override('vxlan_group', '', 'VXLAN') expected=False,
self._check_vxlan_support(kernel_version='3.12', execute_side_effect=RuntimeError())
vxlan_proxy_supported=True,
fdb_append_supported=True, def _check_vxlan_ucast_supported(
l2_population=True, self, expected, l2_population, iproute_arg_supported, fdb_append):
expected_mode=lconst.VXLAN_NONE) 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): class TestLinuxBridgeRpcCallbacks(base.BaseTestCase):