# Neutron OpenVSwitch Plugin.
# @author: Sumit Naiksatam, Cisco Systems, Inc.
-import distutils.version as dist_version
import os
-import platform
import sys
import time
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
devices.add(device)
return devices
+ 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:
+ 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):
- 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_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 (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'))
+ elif self.vxlan_mcast_supported():
+ self.vxlan_mode = lconst.VXLAN_MCAST
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'))
+ raise exceptions.VxlanNetworkUnsupported()
LOG.debug(_('Using %s VXLAN mode'), self.vxlan_mode)
def fdb_ip_entry_exists(self, mac, ip, interface):
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
"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.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_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)
+
+ 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 _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("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)
-
- 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_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)
-
- 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)
+ 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):