# License for the specific language governing permissions and limitations
# under the License.
-import distutils.version as dist_version
-import os
-import re
-
from oslo.config import cfg
from neutron.agent.linux import ip_lib
self.run_ofctl("del-flows", [])
def get_port_ofport(self, port_name):
- return self.db_get_val("Interface", port_name, "ofport")
+ ofport = self.db_get_val("Interface", port_name, "ofport")
+ # This can return a non-integer string, like '[]' so ensure a
+ # common failure case
+ try:
+ int(ofport)
+ return ofport
+ except ValueError:
+ return constants.INVALID_OFPORT
def get_datapath_id(self):
return self.db_get_val('Bridge',
"options:in_key=flow",
"options:out_key=flow"])
self.run_vsctl(vsctl_command)
- return self.get_port_ofport(port_name)
+ ofport = self.get_port_ofport(port_name)
+ if (tunnel_type == p_const.TYPE_VXLAN and
+ ofport == constants.INVALID_OFPORT):
+ LOG.error(_('Unable to create VXLAN tunnel port. Please ensure '
+ 'that an openvswitch version that supports VXLAN is '
+ 'installed.'))
+ return ofport
def add_patch_port(self, local_name, remote_name):
self.run_vsctl(["add-port", self.br_name, local_name,
msg = _('Unable to determine mac address for %s') % self.br_name
raise Exception(msg)
+ def __enter__(self):
+ self.create()
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ self.destroy()
+
def get_bridge_for_iface(root_helper, iface):
args = ["ovs-vsctl", "--timeout=%d" % cfg.CONF.ovs_vsctl_timeout,
LOG.exception(_("Unable to retrieve bridges. Exception: %s"), e)
-def get_installed_ovs_usr_version(root_helper):
- args = ["ovs-vsctl", "--version"]
- try:
- cmd = utils.execute(args, root_helper=root_helper)
- ver = re.findall("\d+\.\d+", cmd)[0]
- return ver
- except Exception:
- LOG.exception(_("Unable to retrieve OVS userspace version."))
-
-
-def get_installed_ovs_klm_version():
- args = ["modinfo", "openvswitch"]
- try:
- cmd = utils.execute(args)
- for line in cmd.split('\n'):
- if 'version: ' in line and not 'srcversion' in line:
- ver = re.findall("\d+\.\d+", line)
- return ver[0]
- except Exception:
- LOG.exception(_("Unable to retrieve OVS kernel module version."))
-
-
-def get_installed_kernel_version():
- try:
- return os.uname()[2].split('-', 1)[0]
- except IndexError:
- LOG.exception(_("Unable to retrieve installed Linux kernel version."))
-
-
def get_bridge_external_bridge_id(root_helper, bridge):
args = ["ovs-vsctl", "--timeout=2", "br-get-external-id",
bridge, "bridge-id"]
return None
-def _compare_installed_and_required_version(
- installed_kernel_version, installed_version, required_version,
- check_type, version_type):
- if installed_kernel_version:
- if dist_version.StrictVersion(
- installed_kernel_version) >= dist_version.StrictVersion(
- constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN):
- return
- if installed_version:
- if dist_version.StrictVersion(
- installed_version) < dist_version.StrictVersion(
- required_version):
- msg = (_('Failed %(ctype)s version check for Open '
- 'vSwitch with %(vtype)s support. To use '
- '%(vtype)s tunnels with OVS, please ensure '
- 'the OVS version is %(required)s or newer!') %
- {'ctype': check_type, 'vtype': version_type,
- 'required': required_version})
- raise SystemError(msg)
- else:
- msg = (_('Unable to determine %(ctype)s version for Open '
- 'vSwitch with %(vtype)s support. To use '
- '%(vtype)s tunnels with OVS, please ensure '
- 'that the version is %(required)s or newer!') %
- {'ctype': check_type, 'vtype': version_type,
- 'required': required_version})
- raise SystemError(msg)
-
-
-def check_ovs_vxlan_version(root_helper):
- min_required_version = constants.MINIMUM_OVS_VXLAN_VERSION
- installed_klm_version = get_installed_ovs_klm_version()
- installed_kernel_version = get_installed_kernel_version()
- installed_usr_version = get_installed_ovs_usr_version(root_helper)
- LOG.debug(_("Checking OVS version for VXLAN support "
- "installed klm version is %(klm)s, installed Linux version is "
- "%(kernel)s, installed user version is %(usr)s ") %
- {'klm': installed_klm_version,
- 'kernel': installed_kernel_version,
- 'usr': installed_usr_version})
- # First check the userspace version
- _compare_installed_and_required_version(None, installed_usr_version,
- min_required_version,
- 'userspace', 'VXLAN')
- # Now check the kernel version
- _compare_installed_and_required_version(installed_kernel_version,
- installed_klm_version,
- min_required_version,
- 'kernel', 'VXLAN')
-
-
def _build_flow_expr_str(flow_dict, cmd):
flow_expr_arr = []
actions = None
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2014 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from neutron.agent.linux import ovs_lib
+from neutron.common import utils
+from neutron.plugins.common import constants as const
+from neutron.plugins.openvswitch.common import constants as ovs_const
+
+
+def vxlan_supported(root_helper, from_ip='192.0.2.1', to_ip='192.0.2.2'):
+ name = "vxlantest-" + utils.get_random_string(6)
+ with ovs_lib.OVSBridge(name, root_helper) as br:
+ port = br.add_tunnel_port(from_ip, to_ip, const.TYPE_VXLAN)
+ return port != ovs_const.INVALID_OFPORT
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2014 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import sys
+
+from neutron.cmd.sanity import checks
+from neutron.common import config
+from neutron.openstack.common import log as logging
+from oslo.config import cfg
+
+
+LOG = logging.getLogger(__name__)
+cfg.CONF.import_group('AGENT', 'neutron.plugins.openvswitch.common.config')
+
+
+class BoolOptCallback(cfg.BoolOpt):
+ def __init__(self, name, callback, **kwargs):
+ self.callback = callback
+ super(BoolOptCallback, self).__init__(name, **kwargs)
+
+
+def check_ovs_vxlan():
+ result = checks.vxlan_supported(root_helper=cfg.CONF.AGENT.root_helper)
+ if not result:
+ LOG.error(_('Check for Open vSwitch VXLAN support failed. '
+ 'Please ensure that the version of openvswitch '
+ 'being used has VXLAN support.'))
+ return result
+
+
+# Define CLI opts to test specific features, with a calback for the test
+OPTS = [
+ BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False,
+ help=_('Check for vxlan support')),
+]
+
+
+def enable_tests_from_config():
+ """If a test can depend on configuration, use this function to set the
+ appropriate CLI option to enable that test. It will then be possible to
+ run all necessary tests, just by passing in the appropriate configs.
+ """
+
+ if 'vxlan' in cfg.CONF.AGENT.tunnel_types:
+ cfg.CONF.set_override('ovs_vxlan', True)
+
+
+def all_tests_passed():
+ res = True
+ for opt in OPTS:
+ if cfg.CONF.get(opt.name):
+ res &= opt.callback()
+ return res
+
+
+def main():
+ cfg.CONF.register_cli_opts(OPTS)
+ cfg.CONF.set_override('use_stderr', True)
+ config.setup_logging(cfg.CONF)
+ config.parse(sys.argv[1:], default_config_files=[])
+
+ if cfg.CONF.config_file:
+ enable_tests_from_config()
+
+ return 0 if all_tests_passed() else 1
max_overflow=20, pool_timeout=10)
-def parse(args):
+def parse(args, **kwargs):
cfg.CONF(args=args, project='neutron',
- version='%%prog %s' % version.version_info.release_string())
+ version='%%prog %s' % version.version_info.release_string(),
+ **kwargs)
# Validate that the base_mac is of the correct format
msg = attributes._validate_regex(cfg.CONF.base_mac,
self.local_ip = local_ip
self.tunnel_count = 0
self.vxlan_udp_port = cfg.CONF.AGENT.vxlan_udp_port
- self._check_ovs_version()
if self.enable_tunneling:
self.setup_tunnel_br(tun_br)
# Collect additional bridges to monitor
# Initialize iteration counter
self.iter_num = 0
- def _check_ovs_version(self):
- if p_const.TYPE_VXLAN in self.tunnel_types:
- try:
- ovs_lib.check_ovs_vxlan_version(self.root_helper)
- except SystemError:
- LOG.exception(_("Agent terminated"))
- raise SystemExit(1)
-
def _report_state(self):
# How many devices are likely used by a VM
self.agent_state.get('configurations')['devices'] = (
self.local_ip = local_ip
self.tunnel_count = 0
self.vxlan_udp_port = cfg.CONF.AGENT.vxlan_udp_port
- self._check_ovs_version()
self.tun_br = None
if self.enable_tunneling:
self.setup_tunnel_br(tun_br)
# Initialize iteration counter
self.iter_num = 0
- def _check_ovs_version(self):
- if p_const.TYPE_VXLAN in self.tunnel_types:
- try:
- ovs_lib.check_ovs_vxlan_version(self.root_helper)
- except SystemError:
- LOG.exception(_("Agent terminated"))
- raise SystemExit(1)
-
def _check_arp_responder_support(self):
'''Check if OVS supports to modify ARP headers.
VETH_INTEGRATION_PREFIX = 'int-'
VETH_PHYSICAL_PREFIX = 'phy-'
-# The minimum version of OVS which supports VXLAN tunneling
-MINIMUM_OVS_VXLAN_VERSION = "1.10"
-
-# The first version of the Linux kernel with converged VXLAN code for OVS
-MINIMUM_LINUX_KERNEL_OVS_VXLAN = "3.13.0"
-
# The different types of tunnels
TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN]
# The default respawn interval for the ovsdb monitor
DEFAULT_OVSDBMON_RESPAWN = 30
+
+# Special return value for an invalid OVS ofport
+INVALID_OFPORT = '-1'
+++ /dev/null
-# Copyright 2014 Cisco Systems, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from neutron.agent.linux import ovs_lib
-from neutron.plugins.common import constants as p_const
-from neutron.tests.functional.agent.linux import base as base_agent
-
-
-PORT_PREFIX = 'testp-'
-INVALID_OFPORT_ID = '-1'
-
-
-class TestOVSAgentVXLAN(base_agent.BaseOVSLinuxTestCase):
-
- def setUp(self):
- super(TestOVSAgentVXLAN, self).setUp()
-
- self._check_test_requirements()
-
- def _check_test_requirements(self):
- self.check_sudo_enabled()
- self.check_command(['which', 'ovs-vsctl'],
- 'Exit code: 1', 'ovs-vsctl is not installed')
- self.check_command(['sudo', '-n', 'ovs-vsctl', 'show'],
- 'Exit code: 1',
- 'password-less sudo not granted for ovs-vsctl')
-
- def test_ovs_lib_vxlan_version_check(self):
- """Verify VXLAN versions match
-
- This function compares the return values of functionally checking if
- VXLAN is supported with the ovs_lib programmatic check. It will fail
- if the two do not align.
- """
- expected = self.is_vxlan_supported()
- actual = self.is_ovs_lib_vxlan_supported()
- self.assertEqual(actual, expected)
-
- def is_ovs_lib_vxlan_supported(self):
- try:
- ovs_lib.check_ovs_vxlan_version(self.root_helper)
- except SystemError:
- return False
- else:
- return True
-
- def is_vxlan_supported(self):
- bridge = self.create_ovs_bridge()
- vxlan_port = self.create_resource(
- PORT_PREFIX,
- bridge.add_tunnel_port,
- "10.10.10.10",
- "10.10.10.20",
- p_const.TYPE_VXLAN)
-
- return vxlan_port != INVALID_OFPORT_ID
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2014 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+
+from neutron.cmd.sanity import checks
+from neutron.tests import base
+
+
+class OVSSanityTestCase(base.BaseTestCase):
+ def setUp(self):
+ super(OVSSanityTestCase, self).setUp()
+
+ self.root_helper = 'sudo'
+
+ def check_sudo_enabled(self):
+ if os.environ.get('OS_SUDO_TESTING') not in base.TRUE_STRING:
+ self.skipTest('testing with sudo is not enabled')
+
+ def test_ovs_vxlan_support_runs(self):
+ """This test just ensures that the test in neutron-sanity-check
+ can run through without error, without mocking anything out
+ """
+ self.check_sudo_enabled()
+ checks.vxlan_supported(self.root_helper)
from neutron.common import exceptions
from neutron.openstack.common import jsonutils
from neutron.openstack.common import uuidutils
-from neutron.plugins.openvswitch.common import constants
+from neutron.plugins.openvswitch.common import constants as const
from neutron.tests import base
from neutron.tests import tools
["ovs-vsctl", self.TO, "get", "Interface", pname, "ofport"],
root_helper=self.root_helper)
+ def test_get_port_ofport_non_int(self):
+ pname = "tap99"
+ ofport = "[]"
+ self.execute.return_value = ofport
+ self.assertEqual(self.br.get_port_ofport(pname), const.INVALID_OFPORT)
+ self.execute.assert_called_once_with(
+ ["ovs-vsctl", self.TO, "get", "Interface", pname, "ofport"],
+ root_helper=self.root_helper)
+
def test_get_datapath_id(self):
datapath_id = '"0000b67f4fbcc149"'
self.execute.return_value = datapath_id
self.assertIsNone(self._test_get_vif_port_by_id('tap99id', data,
"br-ext"))
- def _check_ovs_vxlan_version(self, installed_usr_version,
- installed_klm_version,
- installed_kernel_version,
- expecting_ok):
- with mock.patch(
- 'neutron.agent.linux.ovs_lib.get_installed_ovs_klm_version'
- ) as klm_cmd:
- with mock.patch(
- 'neutron.agent.linux.ovs_lib.get_installed_ovs_usr_version'
- ) as usr_cmd:
- with mock.patch(
- 'neutron.agent.linux.ovs_lib.get_installed_kernel_version'
- ) as kernel_cmd:
- try:
- klm_cmd.return_value = installed_klm_version
- usr_cmd.return_value = installed_usr_version
- kernel_cmd.return_value = installed_kernel_version
- ovs_lib.check_ovs_vxlan_version(root_helper='sudo')
- version_ok = True
- except SystemError:
- version_ok = False
- self.assertEqual(version_ok, expecting_ok)
-
- def test_check_minimum_version(self):
- min_vxlan_ver = constants.MINIMUM_OVS_VXLAN_VERSION
- min_kernel_ver = constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN
- self._check_ovs_vxlan_version(min_vxlan_ver, min_vxlan_ver,
- min_kernel_ver, expecting_ok=True)
-
- def test_check_future_version(self):
- install_ver = str(float(constants.MINIMUM_OVS_VXLAN_VERSION) + 0.01)
- min_kernel_ver = constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN
- self._check_ovs_vxlan_version(install_ver, install_ver,
- min_kernel_ver, expecting_ok=True)
-
- def test_check_fail_version(self):
- install_ver = str(float(constants.MINIMUM_OVS_VXLAN_VERSION) - 0.01)
- min_kernel_ver = constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN
- self._check_ovs_vxlan_version(install_ver, install_ver,
- min_kernel_ver, expecting_ok=False)
-
- def test_check_fail_no_version(self):
- min_kernel_ver = constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN
- self._check_ovs_vxlan_version(None, None,
- min_kernel_ver,
- expecting_ok=False)
-
- def test_check_fail_klm_version(self):
- min_vxlan_ver = constants.MINIMUM_OVS_VXLAN_VERSION
- min_kernel_ver = OVS_LINUX_KERN_VERS_WITHOUT_VXLAN
- install_ver = str(float(min_vxlan_ver) - 0.01)
- self._check_ovs_vxlan_version(min_vxlan_ver,
- install_ver,
- min_kernel_ver,
- expecting_ok=False)
-
- def test_check_pass_kernel_version(self):
- min_vxlan_ver = constants.MINIMUM_OVS_VXLAN_VERSION
- min_kernel_ver = constants.MINIMUM_LINUX_KERNEL_OVS_VXLAN
- self._check_ovs_vxlan_version(min_vxlan_ver, min_vxlan_ver,
- min_kernel_ver, expecting_ok=True)
-
def test_ofctl_arg_supported(self):
with mock.patch('neutron.common.utils.get_random_string') as utils:
utils.return_value = 'test'
self._verify_mock_calls()
def test_construct_vxlan(self):
- with mock.patch.object(ovs_lib, 'get_installed_ovs_klm_version',
- return_value="1.10") as klm_ver:
- with mock.patch.object(ovs_lib, 'get_installed_ovs_usr_version',
- return_value="1.10") as usr_ver:
- with mock.patch.object(ovs_lib, 'get_installed_kernel_version',
- return_value=(
- constants.
- MINIMUM_LINUX_KERNEL_OVS_VXLAN
- )) as kernel_ver:
- ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
- self.TUN_BRIDGE,
- '10.0.0.1',
- self.NET_MAPPING,
- 'sudo', 2, ['vxlan'],
- self.VETH_MTU)
- klm_ver.assert_called_once_with()
- kernel_ver.assert_called_once_with()
- usr_ver.assert_called_once_with('sudo')
+ ovs_neutron_agent.OVSNeutronAgent(self.INT_BRIDGE,
+ self.TUN_BRIDGE,
+ '10.0.0.1',
+ self.NET_MAPPING,
+ 'sudo', 2, ['vxlan'],
+ self.VETH_MTU)
self._verify_mock_calls()
def test_provision_local_vlan(self):
neutron-vpn-agent = neutron.services.vpn.agent:main
neutron-metering-agent = neutron.services.metering.agents.metering_agent:main
neutron-ofagent-agent = ryu.cmd.ofa_neutron_agent:main
+ neutron-sanity-check = neutron.cmd.sanity_check:main
neutron.core_plugins =
bigswitch = neutron.plugins.bigswitch.plugin:NeutronRestProxyV2
brocade = neutron.plugins.brocade.NeutronPlugin:BrocadePluginV2