Merge "Bump OVN version for master jobs"
diff --git a/devstack/functions.sh b/devstack/functions.sh
index 8d8a4bf..f758ff6 100644
--- a/devstack/functions.sh
+++ b/devstack/functions.sh
@@ -85,3 +85,15 @@
fi
iniset $TEMPEST_CONFIG neutron_plugin_options advanced_image_flavor_ref $flavor_ref
}
+
+
+function create_flavor_for_advance_image {
+ local name=$1
+ local ram=$2
+ local disk=$3
+ local vcpus=$4
+
+ if [[ -z $(openstack flavor list | grep $name) ]]; then
+ openstack flavor create --ram $ram --disk $disk --vcpus $vcpus $name
+ fi
+}
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
index 7a46014..2e3ac20 100644
--- a/devstack/plugin.sh
+++ b/devstack/plugin.sh
@@ -20,6 +20,7 @@
test-config)
echo_summary "Configuring neutron-tempest-plugin tempest options"
configure_advanced_image
+ create_flavor_for_advance_image ntp_image_384M 384 4 1
configure_flavor_for_advanced_image
esac
fi
diff --git a/neutron_tempest_plugin/api/test_address_groups.py b/neutron_tempest_plugin/api/test_address_groups.py
index 478d3b2..69f22d0 100644
--- a/neutron_tempest_plugin/api/test_address_groups.py
+++ b/neutron_tempest_plugin/api/test_address_groups.py
@@ -28,6 +28,119 @@
ADDRESS_GROUP_NAME = 'test-address-group'
+class AddressGroupTest(base.BaseAdminNetworkTest):
+
+ credentials = ['primary', 'admin']
+ required_extensions = ['address-group']
+
+ @decorators.idempotent_id('496fef1b-22ce-483b-ab93-d28bf46954b0')
+ def test_address_group_lifecycle(self):
+ ag_description = "Test AG description"
+ ag_name = data_utils.rand_name(ADDRESS_GROUP_NAME)
+ addresses = ['10.10.10.3/32', '192.168.0.10/24', '2001:db8::f00/64']
+ expected_addresses = [
+ '10.10.10.3/32', '192.168.0.0/24', '2001:db8::/64']
+ ag = self.create_address_group(
+ description=ag_description,
+ name=ag_name,
+ addresses=addresses)
+ self.assertEqual(ag_description, ag['description'])
+ self.assertEqual(ag_name, ag['name'])
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(ag['addresses']))
+
+ new_description = 'New AG description'
+ updated_ag = self.client.update_address_group(
+ ag['id'], description=new_description)['address_group']
+ self.assertEqual(new_description, updated_ag['description'])
+ self.assertEqual(ag_name, updated_ag['name'])
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+ self.client.delete_address_group(ag['id'])
+ with testtools.ExpectedException(exceptions.NotFound):
+ self.client.show_address_group(ag['id'])
+
+ @decorators.idempotent_id('8a42029a-40eb-4b44-a7cf-38500046f9b8')
+ def test_address_group_create_with_wrong_address(self):
+ with testtools.ExpectedException(exceptions.BadRequest):
+ self.create_address_group(
+ name=data_utils.rand_name(ADDRESS_GROUP_NAME),
+ addresses=['10.20.30.40'])
+
+ with testtools.ExpectedException(exceptions.BadRequest):
+ self.create_address_group(
+ name=data_utils.rand_name(ADDRESS_GROUP_NAME),
+ addresses=['this is bad IP address'])
+
+ @decorators.idempotent_id('27c03921-bb12-4b9a-b32e-7083bc90ff1f')
+ def test_edit_addresses_in_address_group(self):
+ addresses = ['10.10.10.3/32', '192.168.0.10/24', '2001:db8::f00/64']
+ expected_addresses = [
+ '10.10.10.3/32', '192.168.0.0/24', '2001:db8::/64']
+ ag = self.create_address_group(
+ name=data_utils.rand_name(ADDRESS_GROUP_NAME),
+ addresses=addresses)
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(ag['addresses']))
+
+ added_addresses = ['10.20.30.40/32']
+ self.client.add_addresses_to_address_group(
+ ag['id'], addresses=added_addresses)
+ updated_ag = self.client.show_address_group(ag['id'])['address_group']
+ expected_addresses += added_addresses
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+ removed_addresses = [expected_addresses.pop(0)]
+ self.client.remove_addresses_from_address_group(
+ ag['id'], addresses=removed_addresses)
+ updated_ag = self.client.show_address_group(ag['id'])['address_group']
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+ @decorators.idempotent_id('feec6747-b4b8-49e3-8cff-817d3f097f2c')
+ def test_add_wrong_address_to_address_group(self):
+ addresses = ['10.10.10.3/32', '192.168.0.10/24', '2001:db8::f00/64']
+ expected_addresses = [
+ '10.10.10.3/32', '192.168.0.0/24', '2001:db8::/64']
+ ag = self.create_address_group(
+ name=data_utils.rand_name(ADDRESS_GROUP_NAME),
+ addresses=addresses)
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(ag['addresses']))
+ with testtools.ExpectedException(exceptions.BadRequest):
+ self.client.add_addresses_to_address_group(
+ ag['id'], addresses=['this is bad IP address'])
+ updated_ag = self.client.show_address_group(ag['id'])['address_group']
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+ @decorators.idempotent_id('74f6fd4c-257b-4725-887b-470e96960e24')
+ def test_remove_wrong_address_from_address_group(self):
+ addresses = ['10.10.10.3/32', '192.168.0.10/24', '2001:db8::f00/64']
+ expected_addresses = [
+ '10.10.10.3/32', '192.168.0.0/24', '2001:db8::/64']
+ ag = self.create_address_group(
+ name=data_utils.rand_name(ADDRESS_GROUP_NAME),
+ addresses=addresses)
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(ag['addresses']))
+ with testtools.ExpectedException(exceptions.NotFound):
+ self.client.remove_addresses_from_address_group(
+ ag['id'], addresses=['10.200.200.200'])
+ updated_ag = self.client.show_address_group(ag['id'])['address_group']
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+ with testtools.ExpectedException(exceptions.BadRequest):
+ self.client.remove_addresses_from_address_group(
+ ag['id'], addresses=['this is bad IP address'])
+ updated_ag = self.client.show_address_group(ag['id'])['address_group']
+ self.assertListEqual(
+ sorted(expected_addresses), sorted(updated_ag['addresses']))
+
+
class RbacSharedAddressGroupTest(base.BaseAdminNetworkTest):
force_tenant_isolation = True
diff --git a/neutron_tempest_plugin/api/test_extra_dhcp_options.py b/neutron_tempest_plugin/api/test_extra_dhcp_options.py
index 844666a..91c270d 100644
--- a/neutron_tempest_plugin/api/test_extra_dhcp_options.py
+++ b/neutron_tempest_plugin/api/test_extra_dhcp_options.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from neutron_lib import constants
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -48,9 +49,14 @@
cls.ip_server = ('123.123.123.45' if cls._ip_version == 4
else '2015::badd')
cls.extra_dhcp_opts = [
- {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
- {'opt_value': cls.ip_tftp, 'opt_name': 'tftp-server'},
- {'opt_value': cls.ip_server, 'opt_name': 'server-ip-address'}
+ {'opt_value': 'pxelinux.0',
+ 'opt_name': 'bootfile-name'}, # default ip_version is 4
+ {'opt_value': cls.ip_tftp,
+ 'opt_name': 'tftp-server',
+ 'ip_version': cls._ip_version},
+ {'opt_value': cls.ip_server,
+ 'opt_name': 'server-ip-address',
+ 'ip_version': cls._ip_version}
]
@decorators.idempotent_id('d2c17063-3767-4a24-be4f-a23dbfa133c9')
@@ -85,8 +91,11 @@
self.assertEqual(len(retrieved), len(extra_dhcp_opts))
for retrieved_option in retrieved:
for option in extra_dhcp_opts:
+ # default ip_version is 4
+ ip_version = option.get('ip_version', constants.IP_VERSION_4)
if (retrieved_option['opt_value'] == option['opt_value'] and
- retrieved_option['opt_name'] == option['opt_name']):
+ retrieved_option['opt_name'] == option['opt_name'] and
+ retrieved_option['ip_version'] == ip_version):
break
else:
self.fail('Extra DHCP option not found in port %s' %
diff --git a/neutron_tempest_plugin/api/test_trunk.py b/neutron_tempest_plugin/api/test_trunk.py
index 1f83bd8..26f8de8 100644
--- a/neutron_tempest_plugin/api/test_trunk.py
+++ b/neutron_tempest_plugin/api/test_trunk.py
@@ -247,21 +247,23 @@
@classmethod
def skip_checks(cls):
super(TrunkTestMtusJSONBase, cls).skip_checks()
- if not all(cls.is_type_driver_enabled(t) for t in ['gre', 'vxlan']):
- msg = "Either vxlan or gre type driver not enabled."
+ if not all(cls.is_type_driver_enabled(t) for t in ['vlan', 'vxlan']):
+ msg = "Either vxlan or vlan type driver not enabled."
raise cls.skipException(msg)
def setUp(self):
super(TrunkTestMtusJSONBase, self).setUp()
+ physnet_name = CONF.neutron_plugin_options.provider_vlans[0]
- # VXLAN autocomputed MTU (1450) is smaller than that of GRE (1458)
+ # VXLAN autocomputed MTU (1450) is smaller than that of VLAN (1480)
self.smaller_mtu_net = self.create_network(
name=data_utils.rand_name('vxlan-net'),
provider_network_type='vxlan')
self.larger_mtu_net = self.create_network(
- name=data_utils.rand_name('gre-net'),
- provider_network_type='gre')
+ name=data_utils.rand_name('vlan-net'),
+ provider_network_type='vlan',
+ provider_physical_network=physnet_name)
self.smaller_mtu_port = self.create_port(self.smaller_mtu_net)
self.smaller_mtu_port_2 = self.create_port(self.smaller_mtu_net)
diff --git a/neutron_tempest_plugin/common/utils.py b/neutron_tempest_plugin/common/utils.py
index 1526ecf..898e4b9 100644
--- a/neutron_tempest_plugin/common/utils.py
+++ b/neutron_tempest_plugin/common/utils.py
@@ -204,6 +204,8 @@
def __exit__(self, type, value, traceback):
self.server_ssh.exec_command('sudo killall nc || killall nc')
- self.server_ssh.exec_command('sudo killall tail || killall tail')
+ self.server_ssh.exec_command(
+ 'sudo killall tail || killall tail || echo "True"')
self.client_ssh.exec_command('sudo killall nc || killall nc')
- self.client_ssh.exec_command('sudo killall tail || killall tail')
+ self.client_ssh.exec_command(
+ 'sudo killall tail || killall tail || echo "True"')
diff --git a/neutron_tempest_plugin/scenario/test_ipv6.py b/neutron_tempest_plugin/scenario/test_ipv6.py
index 4237d4f..32fb581 100644
--- a/neutron_tempest_plugin/scenario/test_ipv6.py
+++ b/neutron_tempest_plugin/scenario/test_ipv6.py
@@ -43,35 +43,41 @@
"""
ip_command = ip.IPCommand(ssh)
nic = ip_command.get_nic_name_by_mac(ipv6_port['mac_address'])
+ ip_command.set_link(nic, "up")
- # NOTE(slaweq): on RHEL based OS ifcfg file for new interface is
- # needed to make IPv6 working on it, so if
- # /etc/sysconfig/network-scripts directory exists ifcfg-%(nic)s file
- # should be added in it
- if sysconfig_network_scripts_dir_exists(ssh):
+
+def configure_eth_connection_profile_NM(ssh):
+ """Prepare a Network manager profile for ipv6 port
+
+ By default the NetworkManager uses IPv6 privacy
+ format it isn't supported by neutron then we create
+ a ether profile with eui64 supported format
+
+ @param ssh: RemoteClient ssh instance to server
+ """
+ # NOTE(ccamposr): on RHEL based OS we need a ether profile with
+ # eui64 format
+ if nmcli_command_exists(ssh):
try:
- ssh.execute_script(
- 'echo -e "DEVICE=%(nic)s\\nNAME=%(nic)s\\nIPV6INIT=yes" | '
- 'tee /etc/sysconfig/network-scripts/ifcfg-%(nic)s; '
- 'nmcli connection reload' % {'nic': nic},
- become_root=True)
- ssh.execute_script('nmcli connection up %s' % nic,
+ ssh.execute_script('nmcli connection add type ethernet con-name '
+ 'ether ifname "*"', become_root=True)
+ ssh.execute_script('nmcli con mod ether ipv6.addr-gen-mode eui64',
become_root=True)
+
except lib_exc.SSHExecCommandFailed as e:
# NOTE(slaweq): Sometimes it can happen that this SSH command
# will fail because of some error from network manager in
# guest os.
# But even then doing ip link set up below is fine and
# IP address should be configured properly.
- LOG.debug("Error during restarting %(nic)s interface on "
- "instance. Error message: %(error)s",
- {'nic': nic, 'error': e})
- ip_command.set_link(nic, "up")
+ LOG.debug("Error creating NetworkManager profile. "
+ "Error message: %(error)s",
+ {'error': e})
-def sysconfig_network_scripts_dir_exists(ssh):
+def nmcli_command_exists(ssh):
return "False" not in ssh.execute_script(
- 'test -d /etc/sysconfig/network-scripts/ || echo "False"')
+ 'if ! type nmcli > /dev/null ; then echo "False"; fi')
class IPv6Test(base.BaseTempestTestCase):
@@ -165,6 +171,8 @@
# And plug VM to the second IPv6 network
ipv6_port = self.create_port(ipv6_networks[1])
+ # Add NetworkManager profile with ipv6 eui64 format to guest OS
+ configure_eth_connection_profile_NM(ssh_client)
self.create_interface(vm['id'], ipv6_port['id'])
ip.wait_for_interface_status(
self.os_primary.interfaces_client, vm['id'],
diff --git a/neutron_tempest_plugin/scenario/test_mac_learning.py b/neutron_tempest_plugin/scenario/test_mac_learning.py
new file mode 100644
index 0000000..736d46c
--- /dev/null
+++ b/neutron_tempest_plugin/scenario/test_mac_learning.py
@@ -0,0 +1,210 @@
+# Copyright 2021 Red Hat, Inc
+# 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 oslo_log import log
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from neutron_tempest_plugin.common import ssh
+from neutron_tempest_plugin.common import utils
+from neutron_tempest_plugin import config
+from neutron_tempest_plugin import exceptions
+from neutron_tempest_plugin.scenario import base
+
+
+CONF = config.CONF
+LOG = log.getLogger(__name__)
+
+
+# -s0 -l -c5 &> /tmp/tcpdump_out &
+def get_receiver_script(result_file, packets_expected):
+ """Script that listen icmp echos and write the output on result_file."""
+ return """#!/bin/bash
+export LC_ALL=en_US.UTF-8
+tcpdump -i any -n -v 'icmp[icmptype] = icmp-echoreply or icmp[icmptype] = \
+icmp-echo' -s0 -l -c%(packets_expected)d &> %(result_file)s &
+ """ % {'result_file': result_file,
+ 'packets_expected': packets_expected}
+
+
+def get_sender_script(result_file, receiver_address, completed_message):
+ """Script that sends packets to the receiver server."""
+ return """#!/bin/bash
+export LC_ALL=en_US.UTF-8
+ping -c 5 %(address)s
+echo '%(completed_message)s' > %(result_file)s &
+ """ % {'result_file': result_file,
+ 'address': receiver_address,
+ 'completed_message': completed_message}
+
+
+class MacLearningTest(base.BaseTempestTestCase):
+
+ credentials = ['primary', 'admin']
+ force_tenant_isolation = False
+
+ # Import configuration options
+ available_type_drivers = (
+ CONF.neutron_plugin_options.available_type_drivers)
+
+ completed_message = "Done!"
+ output_file = "/tmp/tcpdump_out"
+ sender_output_file = "/tmp/sender_out"
+ sender_script_file = "/tmp/ping.sh"
+ receiver_script_file = "/tmp/traffic.sh"
+
+ @classmethod
+ def skip_checks(cls):
+ super(MacLearningTest, cls).skip_checks()
+ advanced_image_available = (
+ CONF.neutron_plugin_options.advanced_image_ref or
+ CONF.neutron_plugin_options.default_image_is_advanced)
+ if not advanced_image_available:
+ skip_reason = "This test requires advanced tools to be executed"
+ raise cls.skipException(skip_reason)
+
+ @classmethod
+ def resource_setup(cls):
+ super(MacLearningTest, cls).resource_setup()
+
+ if CONF.neutron_plugin_options.default_image_is_advanced:
+ cls.flavor_ref = CONF.compute.flavor_ref
+ cls.image_ref = CONF.compute.image_ref
+ cls.username = CONF.validation.image_ssh_user
+ else:
+ cls.flavor_ref = (
+ CONF.neutron_plugin_options.advanced_image_flavor_ref)
+ cls.image_ref = CONF.neutron_plugin_options.advanced_image_ref
+ cls.username = CONF.neutron_plugin_options.advanced_image_ssh_user
+
+ # Setup basic topology for servers so that we can log into them
+ # It's important to keep port security and DHCP disabled for this test
+ cls.network = cls.create_network(port_security_enabled=False)
+ cls.subnet = cls.create_subnet(cls.network, enable_dhcp=False)
+ cls.router = cls.create_router_by_client()
+ cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+
+ cls.keypair = cls.create_keypair()
+
+ def _create_server(self):
+ name = data_utils.rand_name("maclearning-server")
+ server = self.create_server(
+ flavor_ref=self.flavor_ref,
+ image_ref=self.image_ref,
+ key_name=self.keypair['name'], name=name,
+ networks=[{'uuid': self.network['id']}],
+ config_drive='True')['server']
+ self.wait_for_server_active(server)
+ self.wait_for_guest_os_ready(server)
+ server['port'] = self.client.list_ports(
+ network_id=self.network['id'], device_id=server['id'])['ports'][0]
+ server['fip'] = self.create_floatingip(port=server['port'])
+ server['ssh_client'] = ssh.Client(server['fip']['floating_ip_address'],
+ self.username,
+ pkey=self.keypair['private_key'])
+ return server
+
+ def _check_cmd_installed_on_server(self, ssh_client, server_id, cmd):
+ try:
+ ssh_client.execute_script('which %s' % cmd)
+ except exceptions.SSHScriptFailed:
+ raise self.skipException(
+ "%s is not available on server %s" % (cmd, server_id))
+
+ def _prepare_sender(self, server, address):
+ check_script = get_sender_script(self.sender_output_file, address,
+ self.completed_message)
+ self._check_cmd_installed_on_server(server['ssh_client'], server['id'],
+ 'tcpdump')
+ server['ssh_client'].execute_script(
+ 'echo "%s" > %s' % (check_script, self.sender_script_file))
+
+ def _prepare_listener(self, server, n_packets):
+ check_script = get_receiver_script(
+ result_file=self.output_file,
+ packets_expected=n_packets)
+ self._check_cmd_installed_on_server(server['ssh_client'], server['id'],
+ 'tcpdump')
+ server['ssh_client'].execute_script(
+ 'echo "%s" > %s' % (check_script, self.receiver_script_file))
+
+ @decorators.idempotent_id('013686ac-23b1-23e4-8361-10b1c98a2861')
+ def test_mac_learning_vms_on_same_network(self):
+ """Test mac learning works in a network.
+
+ The receiver server will receive all the sent packets.
+ The non receiver should not receive any.
+
+ """
+ sender = self._create_server()
+ receiver = self._create_server()
+ non_receiver = self._create_server()
+
+ def check_server_result(server, expected_result, output_file):
+ result = server['ssh_client'].execute_script(
+ "cat {path} || echo '{path} not exists yet'".format(
+ path=output_file))
+ LOG.debug("VM result: %s", result)
+ return expected_result in result
+
+ # Prepare the server that is intended to receive the packets
+ self._prepare_listener(receiver, 5)
+
+ # Prepare the server that is not intended receive of the packets.
+ self._prepare_listener(non_receiver, 2)
+
+ # Run the scripts
+ for server in [receiver, non_receiver]:
+ server['ssh_client'].execute_script(
+ "bash %s" % self.receiver_script_file, become_root=True)
+
+ # Prepare the server that will make the ping.
+ target_ip = receiver['port']['fixed_ips'][0]['ip_address']
+ self._prepare_sender(sender, address=target_ip)
+
+ LOG.debug("The receiver IP is: %s", target_ip)
+ # Run the sender node script
+ sender['ssh_client'].execute_script(
+ "bash %s" % self.sender_script_file, become_root=True)
+
+ # Check if the message was sent.
+ utils.wait_until_true(
+ lambda: check_server_result(
+ sender, self.completed_message,
+ self.sender_output_file),
+ exception=RuntimeError(
+ "Sender script wasn't executed properly"))
+
+ # Check receiver server
+ receiver_expected_result = '5 packets captured'
+ utils.wait_until_true(
+ lambda: check_server_result(receiver,
+ receiver_expected_result, self.output_file),
+ exception=RuntimeError(
+ 'Receiver server did not receive expected packet'))
+
+ # Check the non_receiver server
+ non_receiver_expected_result = '0 packets captured'
+ try:
+ LOG.debug("Try killing non-receiver tcpdump")
+ non_receiver['ssh_client'].execute_script(
+ "killall tcpdump && sleep 2", become_root=True)
+ except exceptions.SSHScriptFailed:
+ LOG.debug("Killing tcpdump failed")
+ self.assertTrue(check_server_result(non_receiver,
+ non_receiver_expected_result,
+ self.output_file),
+ 'Non targeted server received unexpected packets')
+ return
diff --git a/neutron_tempest_plugin/services/network/json/network_client.py b/neutron_tempest_plugin/services/network/json/network_client.py
index 2678d73..d4eff84 100644
--- a/neutron_tempest_plugin/services/network/json/network_client.py
+++ b/neutron_tempest_plugin/services/network/json/network_client.py
@@ -1126,3 +1126,21 @@
self.uri_prefix, resource_type, resource_id, tag)
resp, body = self.delete(uri)
self.expected_success(204, resp.status)
+
+ def add_addresses_to_address_group(self, address_group_id, addresses):
+ uri = '%s/address-groups/%s/add_addresses' % (
+ self.uri_prefix, address_group_id)
+ request_body = {'addresses': addresses}
+ resp, response_body = self.put(uri, jsonutils.dumps(request_body))
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(
+ resp, jsonutils.loads(response_body))
+
+ def remove_addresses_from_address_group(self, address_group_id, addresses):
+ uri = '%s/address-groups/%s/remove_addresses' % (
+ self.uri_prefix, address_group_id)
+ request_body = {'addresses': addresses}
+ resp, response_body = self.put(uri, jsonutils.dumps(request_body))
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(
+ resp, jsonutils.loads(response_body))
diff --git a/setup.cfg b/setup.cfg
index 144569f..136aa0f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,12 +1,12 @@
[metadata]
name = neutron-tempest-plugin
summary = Tempest plugin for Neutron Project
-description-file =
+description_file =
README.rst
author = OpenStack
-author-email = openstack-discuss@lists.openstack.org
-home-page = https://opendev.org/openstack/neutron-tempest-plugin
-python-requires = >=3.6
+author_email = openstack-discuss@lists.openstack.org
+home_page = https://opendev.org/openstack/neutron-tempest-plugin
+python_requires = >=3.6
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index 04fe323..880e64f 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -112,7 +112,7 @@
CIRROS_VERSION: 0.5.1
IMAGE_URLS: https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img
ADVANCED_IMAGE_NAME: ubuntu-18.04-server-cloudimg-amd64
- ADVANCED_INSTANCE_TYPE: ds512M
+ ADVANCED_INSTANCE_TYPE: ntp_image_384M
ADVANCED_INSTANCE_USER: ubuntu
BUILD_TIMEOUT: 784
tempest_concurrency: 3 # out of 4
diff --git a/zuul.d/master_jobs.yaml b/zuul.d/master_jobs.yaml
index f6781b1..0c6785d 100644
--- a/zuul.d/master_jobs.yaml
+++ b/zuul.d/master_jobs.yaml
@@ -88,25 +88,16 @@
- ipv6_metadata
tempest_test_regex: ^neutron_tempest_plugin\.api
devstack_services:
- # Disable OVN services
- br-ex-tcpdump: false
- br-int-flows: false
- ovn-controller: false
- ovn-northd: false
- ovs-vswitchd: false
- ovsdb-server: false
- q-ovn-metadata-agent: false
- # Neutron services
- q-agt: true
- q-dhcp: true
- q-l3: true
- q-meta: true
- q-metering: true
neutron-log: true
devstack_localrc:
- Q_AGENT: openvswitch
- Q_ML2_TENANT_NETWORK_TYPE: vxlan
- Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
+ # TODO(lucasagomes): Re-enable MOD_WSGI after
+ # https://bugs.launchpad.net/neutron/+bug/1912359 is implemented
+ NEUTRON_DEPLOY_MOD_WSGI: false
+ # TODO(ralonsoh): remove OVN_BUILD_FROM_SOURCE once the OS packages
+ # include at least OVN v20.12.0.
+ OVN_BUILD_FROM_SOURCE: True
+ OVN_BRANCH: "v21.03.0"
+ OVS_BRANCH: "8dc1733eaea866dce033b3c44853e1b09bf59fc7"
devstack_local_conf:
post-config:
# NOTE(slaweq): We can get rid of this hardcoded absolute path when
@@ -129,6 +120,7 @@
- ^tox.ini$
- ^neutron/agent/.*$
- ^neutron/privileged/.*$
+ - ^neutron_lib/tests/unit/.*$
- ^neutron_tempest_plugin/scenario/.*$
@@ -275,6 +267,34 @@
- ^neutron/plugins/ml2/drivers/ovn/.*$
- job:
+ name: neutron-tempest-plugin-scenario-openvswitch-distributed-dhcp
+ parent: neutron-tempest-plugin-scenario-openvswitch
+ timeout: 10000
+ vars:
+ # NOTE: DHCP extra options and dns services aren't supported with
+ # distributed DHCP L2 agent extension
+ tempest_exclude_regex: "\
+ (^neutron_tempest_plugin.scenario.test_dhcp.DHCPTest.test_extra_dhcp_opts)|\
+ (^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
+ devstack_services:
+ q-dhcp: false
+ q-distributed-dhcp: true
+
+- job:
+ name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-distributed-dhcp
+ parent: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
+ timeout: 10000
+ vars:
+ # NOTE: DHCP extra options and dns services aren't supported with
+ # distributed DHCP L2 agent extension
+ tempest_exclude_regex: "\
+ (^neutron_tempest_plugin.scenario.test_dhcp.DHCPTest.test_extra_dhcp_opts)|\
+ (^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
+ devstack_services:
+ q-dhcp: false
+ q-distributed-dhcp: true
+
+- job:
name: neutron-tempest-plugin-scenario-linuxbridge
parent: neutron-tempest-plugin-scenario
timeout: 10000
@@ -303,7 +323,13 @@
network_available_features: *available_features
# TODO(eolivare): remove VLAN Transparency tests from blacklist
# when bug https://bugs.launchpad.net/neutron/+bug/1907548 will be fixed
- tempest_exclude_regex: "(^neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest)"
+ # TODO(slaweq): remove
+ # test_established_tcp_session_after_re_attachinging_sg from the
+ # exclude regex when bug https://bugs.launchpad.net/neutron/+bug/1936911
+ # will be fixed
+ tempest_exclude_regex: "\
+ (^neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest)|\
+ (^neutron_tempest_plugin.scenario.test_security_groups.NetworkSecGroupTest.test_established_tcp_session_after_re_attachinging_sg)"
devstack_localrc:
Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions + network_api_extensions_linuxbridge) | join(',') }}"
@@ -403,7 +429,6 @@
q-meta: false
q-metering: false
q-qos: true
- tls-proxy: true
# Cinder services
c-api: false
c-bak: false
@@ -495,17 +520,34 @@
CIRROS_VERSION: 0.5.1
IMAGE_URLS: https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img
ADVANCED_IMAGE_NAME: ubuntu-18.04-server-cloudimg-amd64
- ADVANCED_INSTANCE_TYPE: ds512M
+ ADVANCED_INSTANCE_TYPE: ntp_image_384M
ADVANCED_INSTANCE_USER: ubuntu
BUILD_TIMEOUT: 784
+ Q_AGENT: openvswitch
+ Q_ML2_TENANT_NETWORK_TYPE: vxlan
+ Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
devstack_plugins:
neutron: https://opendev.org/openstack/neutron.git
neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git
tempest_plugins:
- neutron-tempest-plugin
devstack_services:
- tls-proxy: false
+ tls-proxy: true
tempest: true
+ # Disable OVN services
+ br-ex-tcpdump: false
+ br-int-flows: false
+ ovn-controller: false
+ ovn-northd: false
+ ovs-vswitchd: false
+ ovsdb-server: false
+ q-ovn-metadata-agent: false
+ # Neutron services
+ q-agt: true
+ q-dhcp: true
+ q-l3: true
+ q-meta: true
+ q-metering: true
neutron-dns: true
neutron-qos: true
neutron-segments: true
@@ -580,7 +622,16 @@
group-vars:
subnode:
devstack_services:
- tls-proxy: false
+ tls-proxy: true
+ br-ex-tcpdump: false
+ br-int-flows: false
+ # Disable OVN services
+ ovn-controller: false
+ ovn-northd: false
+ ovs-vswitchd: false
+ ovsdb-server: false
+ q-ovn-metadata-agent: false
+ # Neutron services
q-agt: true
q-l3: true
q-meta: true
@@ -598,6 +649,9 @@
s-proxy: false
devstack_localrc:
USE_PYTHON3: true
+ Q_AGENT: openvswitch
+ Q_ML2_TENANT_NETWORK_TYPE: vxlan
+ Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
devstack_local_conf:
post-config:
$NEUTRON_CONF:
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 969f80a..08fb58c 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -20,6 +20,8 @@
experimental:
jobs:
- neutron-tempest-plugin-dvr-multinode-scenario
+ - neutron-tempest-plugin-scenario-openvswitch-distributed-dhcp
+ - neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-distributed-dhcp
- project-template:
diff --git a/zuul.d/queens_jobs.yaml b/zuul.d/queens_jobs.yaml
index 9701548..0b56b32 100644
--- a/zuul.d/queens_jobs.yaml
+++ b/zuul.d/queens_jobs.yaml
@@ -141,6 +141,7 @@
CIRROS_VERSION: 0.3.5
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-queens
@@ -169,6 +170,7 @@
Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -243,3 +245,4 @@
USE_PYTHON3: false
CIRROS_VERSION: 0.3.5
TEMPEST_PLUGINS: '"/opt/stack/designate-tempest-plugin /opt/stack/neutron-tempest-plugin"'
+ ADVANCED_INSTANCE_TYPE: ds512M
diff --git a/zuul.d/rocky_jobs.yaml b/zuul.d/rocky_jobs.yaml
index 11e4c9a..5cb6125 100644
--- a/zuul.d/rocky_jobs.yaml
+++ b/zuul.d/rocky_jobs.yaml
@@ -167,6 +167,7 @@
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -226,6 +227,7 @@
<<: *scenario_vars_rocky
devstack_localrc:
USE_PYTHON3: True
+ ADVANCED_INSTANCE_TYPE: ds512M
branches: ^(?!stable/rocky).*$
irrelevant-files: *openvswitch-scenario-irrelevant-files
@@ -263,6 +265,7 @@
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -330,6 +333,7 @@
<<: *openvswitch_vars_rocky
devstack_localrc:
USE_PYTHON3: True
+ ADVANCED_INSTANCE_TYPE: ds512M
branches: ^(?!stable/rocky).*$
irrelevant-files: *iptables_hybrid_irrelevant_files
@@ -352,6 +356,7 @@
Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -403,6 +408,7 @@
Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
+ ADVANCED_INSTANCE_TYPE: ds512M
branches: ^(?!stable/rocky).*$
- job:
@@ -435,7 +441,7 @@
CIRROS_VERSION: 0.5.1
IMAGE_URLS: https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img
ADVANCED_IMAGE_NAME: ubuntu-18.04-server-cloudimg-amd64
- ADVANCED_INSTANCE_TYPE: ds512M
+ ADVANCED_INSTANCE_TYPE: ntp_image_384M
ADVANCED_INSTANCE_USER: ubuntu
BUILD_TIMEOUT: 784
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
@@ -609,6 +615,7 @@
devstack_localrc:
USE_PYTHON3: false
TEMPEST_PLUGINS: '"/opt/stack/designate-tempest-plugin /opt/stack/neutron-tempest-plugin"'
+ ADVANCED_INSTANCE_TYPE: ds512M
branches:
- stable/rocky
diff --git a/zuul.d/stein_jobs.yaml b/zuul.d/stein_jobs.yaml
index 40bca7c..f84df2a 100644
--- a/zuul.d/stein_jobs.yaml
+++ b/zuul.d/stein_jobs.yaml
@@ -130,6 +130,7 @@
network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_L3_CONF:
@@ -177,6 +178,7 @@
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -263,6 +265,7 @@
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions + network_api_extensions_linuxbridge) | join(',') }}"
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch,linuxbridge
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -335,3 +338,5 @@
vars:
branch_override: stable/stein
network_api_extensions_common: *api_extensions
+ devstack_localrc:
+ ADVANCED_INSTANCE_TYPE: ds512M
diff --git a/zuul.d/train_jobs.yaml b/zuul.d/train_jobs.yaml
index a623251..5caf127 100644
--- a/zuul.d/train_jobs.yaml
+++ b/zuul.d/train_jobs.yaml
@@ -135,6 +135,7 @@
network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_L3_CONF:
@@ -160,6 +161,7 @@
network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_L3_CONF:
@@ -185,6 +187,7 @@
network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ ADVANCED_INSTANCE_TYPE: ds512M
devstack_local_conf:
post-config:
$NEUTRON_L3_CONF:
@@ -217,6 +220,8 @@
vars:
branch_override: stable/train
network_api_extensions_common: *api_extensions
+ devstack_localrc:
+ ADVANCED_INSTANCE_TYPE: ds512M
- job:
name: neutron-tempest-plugin-sfc-train