Merge "cases associated with the port"
diff --git a/neutron_tempest_plugin/api/admin/test_dhcp_agent_scheduler.py b/neutron_tempest_plugin/api/admin/test_dhcp_agent_scheduler.py
index d0adcb8..9dc4438 100644
--- a/neutron_tempest_plugin/api/admin/test_dhcp_agent_scheduler.py
+++ b/neutron_tempest_plugin/api/admin/test_dhcp_agent_scheduler.py
@@ -13,6 +13,7 @@
# under the License.
from neutron_lib import constants
+from neutron_lib.utils import test
from tempest.lib import decorators
from neutron_tempest_plugin.api import base
@@ -33,6 +34,7 @@
cls.cidr = cls.subnet['cidr']
cls.port = cls.create_port(cls.network)
+ @test.unstable_test("bug 1906654")
@decorators.idempotent_id('f164801e-1dd8-4b8b-b5d3-cc3ac77cfaa5')
def test_dhcp_port_status_active(self):
diff --git a/neutron_tempest_plugin/api/admin/test_ports.py b/neutron_tempest_plugin/api/admin/test_ports.py
index 9c94322..6f51b1c 100644
--- a/neutron_tempest_plugin/api/admin/test_ports.py
+++ b/neutron_tempest_plugin/api/admin/test_ports.py
@@ -14,7 +14,6 @@
# under the License.
import netaddr
-import six
from neutron_lib import constants as const
from tempest.common import utils
@@ -123,8 +122,8 @@
self.assertIn('resource_request', port)
vnic_trait = 'CUSTOM_VNIC_TYPE_%s' % vnic_type.upper()
physnet_trait = 'CUSTOM_PHYSNET_%s' % self.physnet_name.upper()
- six.assertCountEqual(self, [physnet_trait, vnic_trait],
- port['resource_request']['required'])
+ self.assertCountEqual([physnet_trait, vnic_trait],
+ port['resource_request']['required'])
self.assertEqual(
{'NET_BW_EGR_KILOBIT_PER_SEC': self.EGRESS_KBPS,
diff --git a/neutron_tempest_plugin/api/admin/test_quotas.py b/neutron_tempest_plugin/api/admin/test_quotas.py
index ae773c8..0cf474e 100644
--- a/neutron_tempest_plugin/api/admin/test_quotas.py
+++ b/neutron_tempest_plugin/api/admin/test_quotas.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -145,7 +144,7 @@
# as requested for tenant
quota_set = self.admin_client.show_details_quota(tenant_id)
quota_set = quota_set['quota']
- for key, value in six.iteritems(new_quotas):
+ for key, value in new_quotas.items():
self.assertEqual(new_quotas[key]['limit'],
quota_set[key]['limit'])
self.assertEqual(new_quotas[key]['reserved'],
@@ -155,5 +154,5 @@
# validate 'default' action for old extension
quota_limit = self.admin_client.show_quotas(tenant_id)['quota']
- for key, value in six.iteritems(new_quotas):
+ for key, value in new_quotas.items():
self.assertEqual(new_quotas[key]['limit'], quota_limit[key])
diff --git a/neutron_tempest_plugin/api/admin/test_tag.py b/neutron_tempest_plugin/api/admin/test_tag.py
index 7879b4c..eae7977 100644
--- a/neutron_tempest_plugin/api/admin/test_tag.py
+++ b/neutron_tempest_plugin/api/admin/test_tag.py
@@ -28,13 +28,13 @@
def _get_and_compare_tags(self, tags):
res_body = self.client.get_tags(self.resource, self.res_id)
- self.assertItemsEqual(tags, res_body['tags'])
+ self.assertCountEqual(tags, res_body['tags'])
def _test_tag_operations(self):
# create and get tags
tags = ['red', 'blue']
res_body = self.client.update_tags(self.resource, self.res_id, tags)
- self.assertItemsEqual(tags, res_body['tags'])
+ self.assertCountEqual(tags, res_body['tags'])
self._get_and_compare_tags(tags)
# add a tag
@@ -52,7 +52,7 @@
# replace tags
tags = ['red', 'yellow', 'purple']
res_body = self.client.update_tags(self.resource, self.res_id, tags)
- self.assertItemsEqual(tags, res_body['tags'])
+ self.assertCountEqual(tags, res_body['tags'])
self._get_and_compare_tags(tags)
# get tag
@@ -477,7 +477,7 @@
# nothing specific about networks here, just a resource that is
# available in all setups
res_body = self.client.get_tags('networks', res_id)
- self.assertItemsEqual(tags, res_body['tags'])
+ self.assertCountEqual(tags, res_body['tags'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('74c56fb1-a3b1-4a62-a8d2-d04dca6bd4cd')
diff --git a/neutron_tempest_plugin/api/base.py b/neutron_tempest_plugin/api/base.py
index 1b02211..4833c71 100644
--- a/neutron_tempest_plugin/api/base.py
+++ b/neutron_tempest_plugin/api/base.py
@@ -140,6 +140,17 @@
cls.conntrack_helpers = []
@classmethod
+ def reserve_external_subnet_cidrs(cls):
+ client = cls.os_admin.network_client
+ ext_nets = client.list_networks(
+ **{"router:external": True})['networks']
+ for ext_net in ext_nets:
+ ext_subnets = client.list_subnets(
+ network_id=ext_net['id'])['subnets']
+ for ext_subnet in ext_subnets:
+ cls.reserve_subnet_cidr(ext_subnet['cidr'])
+
+ @classmethod
def resource_cleanup(cls):
if CONF.service_available.neutron:
# Clean up trunks
@@ -478,7 +489,7 @@
"""
if not cls.try_reserve_subnet_cidr(addr, **ipnetwork_kwargs):
- raise ValueError('Subnet CIDR already reserved: %r'.format(
+ raise ValueError('Subnet CIDR already reserved: {0!r}'.format(
addr))
@classmethod
@@ -558,6 +569,8 @@
"""Wrapper utility that returns a test port."""
if CONF.network.port_vnic_type and 'binding:vnic_type' not in kwargs:
kwargs['binding:vnic_type'] = CONF.network.port_vnic_type
+ if CONF.network.port_profile and 'binding:profile' not in kwargs:
+ kwargs['binding:profile'] = CONF.network.port_profile
body = cls.client.create_port(network_id=network['id'],
**kwargs)
port = body['port']
@@ -700,6 +713,12 @@
return pf
@classmethod
+ def update_port_forwarding(cls, fip_id, pf_id, client=None, **kwargs):
+ """Wrapper utility for update_port_forwarding."""
+ client = client or cls.client
+ return client.update_port_forwarding(fip_id, pf_id, **kwargs)
+
+ @classmethod
def delete_port_forwarding(cls, pf, client=None):
"""Delete port forwarding
diff --git a/neutron_tempest_plugin/api/test_allowed_address_pair.py b/neutron_tempest_plugin/api/test_allowed_address_pair.py
index dd48382..7b11638 100644
--- a/neutron_tempest_plugin/api/test_allowed_address_pair.py
+++ b/neutron_tempest_plugin/api/test_allowed_address_pair.py
@@ -81,7 +81,7 @@
body = self.client.update_port(
port_id, allowed_address_pairs=allowed_address_pairs)
allowed_address_pair = body['port']['allowed_address_pairs']
- self.assertItemsEqual(allowed_address_pair, allowed_address_pairs)
+ self.assertCountEqual(allowed_address_pair, allowed_address_pairs)
@decorators.idempotent_id('9599b337-272c-47fd-b3cf-509414414ac4')
def test_update_port_with_address_pair(self):
diff --git a/neutron_tempest_plugin/api/test_port_forwarding_negative.py b/neutron_tempest_plugin/api/test_port_forwarding_negative.py
index 76dd6ee..386cbed 100644
--- a/neutron_tempest_plugin/api/test_port_forwarding_negative.py
+++ b/neutron_tempest_plugin/api/test_port_forwarding_negative.py
@@ -12,6 +12,7 @@
# 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 tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions
@@ -81,3 +82,43 @@
internal_ip_address=port['fixed_ips'][0]['ip_address'],
internal_port=1111, external_port=5555,
protocol="tcp")
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('e9d3ffb6-e5bf-421d-acaa-ee6010dfbf14')
+ def test_out_of_range_ports(self):
+ port = self.create_port(self.network)
+ fip_for_pf = self.create_floatingip()
+
+ pf_params = {
+ 'internal_port_id': port['id'],
+ 'internal_ip_address': port['fixed_ips'][0]['ip_address'],
+ 'internal_port': 1111,
+ 'external_port': 3333,
+ 'protocol': "tcp"}
+ pf = self.create_port_forwarding(fip_for_pf['id'], **pf_params)
+
+ # Check: Invalid input for external_port update
+ self.assertRaises(
+ exceptions.BadRequest,
+ self.update_port_forwarding,
+ fip_for_pf['id'], pf['id'], external_port=108343)
+
+ # Check: Invalid input for internal_port update
+ self.assertRaises(
+ exceptions.BadRequest,
+ self.update_port_forwarding,
+ fip_for_pf['id'], pf['id'], internal_port=108343)
+
+ # Check: Invalid input for external_port create
+ pf_params['internal_port'] = 4444
+ pf_params['external_port'] = 333333
+ self.assertRaises(
+ exceptions.BadRequest,
+ self.create_port_forwarding, fip_for_pf['id'], **pf_params)
+
+ # Check: Invalid input for internal_port create
+ pf_params['internal_port'] = 444444
+ pf_params['external_port'] = 3333
+ self.assertRaises(
+ exceptions.BadRequest,
+ self.create_port_forwarding, fip_for_pf['id'], **pf_params)
diff --git a/neutron_tempest_plugin/api/test_port_forwardings.py b/neutron_tempest_plugin/api/test_port_forwardings.py
index 82c3a34..79cce39 100644
--- a/neutron_tempest_plugin/api/test_port_forwardings.py
+++ b/neutron_tempest_plugin/api/test_port_forwardings.py
@@ -124,31 +124,10 @@
fip = self.client.show_floatingip(fip['id'])['floatingip']
self.assertEqual(0, len(fip['port_forwardings']))
- @decorators.idempotent_id('8202cded-7e82-4420-9585-c091105404f6')
- def test_associate_2_port_forwardings_to_floating_ip(self):
- fip = self.create_floatingip()
- forwardings_data = [(1111, 2222), (3333, 4444)]
- created_pfs = []
- for data in forwardings_data:
- internal_port = data[0]
- external_port = data[1]
- port = self.create_port(self.network)
- created_pf = self.create_port_forwarding(
- fip['id'],
- internal_port_id=port['id'],
- internal_ip_address=port['fixed_ips'][0]['ip_address'],
- internal_port=internal_port, external_port=external_port,
- protocol="tcp")
- self.assertEqual(internal_port, created_pf['internal_port'])
- self.assertEqual(external_port, created_pf['external_port'])
- self.assertEqual('tcp', created_pf['protocol'])
- self.assertEqual(port['fixed_ips'][0]['ip_address'],
- created_pf['internal_ip_address'])
- created_pfs.append(created_pf)
-
+ def _verify_created_pfs(self, fip_id, created_pfs):
# Check that all PFs are visible in Floating IP details
- fip = self.client.show_floatingip(fip['id'])['floatingip']
- self.assertEqual(len(forwardings_data), len(fip['port_forwardings']))
+ fip = self.client.show_floatingip(fip_id)['floatingip']
+ self.assertEqual(len(created_pfs), len(fip['port_forwardings']))
for pf in created_pfs:
expected_pf = {
'external_port': pf['external_port'],
@@ -160,13 +139,73 @@
# Test list of port forwardings
port_forwardings = self.client.list_port_forwardings(
fip['id'])['port_forwardings']
- self.assertEqual(len(forwardings_data), len(port_forwardings))
+ self.assertEqual(len(created_pfs), len(port_forwardings))
for pf in created_pfs:
expected_pf = pf.copy()
expected_pf.pop('client')
expected_pf.pop('floatingip_id')
self.assertIn(expected_pf, port_forwardings)
+ def _create_and_validate_pf(self, fip_id, internal_port_id,
+ internal_ip_address, internal_port,
+ external_port, protocol):
+ created_pf = self.create_port_forwarding(
+ fip_id,
+ internal_port_id=internal_port_id,
+ internal_ip_address=internal_ip_address,
+ internal_port=internal_port,
+ external_port=external_port,
+ protocol=protocol)
+ self.assertEqual(internal_port, created_pf['internal_port'])
+ self.assertEqual(external_port, created_pf['external_port'])
+ self.assertEqual(protocol, created_pf['protocol'])
+ self.assertEqual(internal_ip_address,
+ created_pf['internal_ip_address'])
+ return created_pf
+
+ @decorators.idempotent_id('8202cded-7e82-4420-9585-c091105404f6')
+ def test_associate_2_port_forwardings_to_floating_ip(self):
+ fip = self.create_floatingip()
+ forwardings_data = [(1111, 2222), (3333, 4444)]
+ created_pfs = []
+ for data in forwardings_data:
+ internal_port = data[0]
+ external_port = data[1]
+ port = self.create_port(self.network)
+ created_pf = self._create_and_validate_pf(
+ fip_id=fip['id'],
+ internal_port_id=port['id'],
+ internal_ip_address=port['fixed_ips'][0]['ip_address'],
+ internal_port=internal_port, external_port=external_port,
+ protocol="tcp")
+ created_pfs.append(created_pf)
+ self._verify_created_pfs(fip['id'], created_pfs)
+
+ @decorators.idempotent_id('a7e6cc48-8a9b-49be-82fb-cef6f5c29381')
+ def test_associate_port_forwarding_to_2_fixed_ips(self):
+ fip = self.create_floatingip()
+ port = self.create_port(self.network)
+ internal_subnet_id = port['fixed_ips'][0]['subnet_id']
+ # Add a second fixed_ip address to port (same subnet)
+ port['fixed_ips'].append({'subnet_id': internal_subnet_id})
+ port = self.update_port(port, fixed_ips=port['fixed_ips'])
+ internal_ip_address1 = port['fixed_ips'][0]['ip_address']
+ internal_ip_address2 = port['fixed_ips'][1]['ip_address']
+ forwardings_data = [(4001, internal_ip_address1),
+ (4002, internal_ip_address2)]
+ created_pfs = []
+ for data in forwardings_data:
+ external_port = data[0]
+ internal_ip_address = data[1]
+ created_pf = self._create_and_validate_pf(
+ fip_id=fip['id'],
+ internal_port_id=port['id'],
+ internal_ip_address=internal_ip_address,
+ internal_port=123, external_port=external_port,
+ protocol="tcp")
+ created_pfs.append(created_pf)
+ self._verify_created_pfs(fip['id'], created_pfs)
+
@decorators.idempotent_id('6a34e811-66d1-4f63-aa4d-9013f15deb62')
def test_associate_port_forwarding_to_used_floating_ip(self):
port_for_fip = self.create_port(self.network)
diff --git a/neutron_tempest_plugin/api/test_ports.py b/neutron_tempest_plugin/api/test_ports.py
index 8b0cd0a..ca3368c 100644
--- a/neutron_tempest_plugin/api/test_ports.py
+++ b/neutron_tempest_plugin/api/test_ports.py
@@ -150,28 +150,6 @@
expected = [s['id'], s['id']]
self.assertEqual(expected, subnets)
- @decorators.idempotent_id('9700828d-86eb-4f21-9fa3-da487a2d77f2')
- @utils.requires_ext(extension="uplink-status-propagation",
- service="network")
- def test_create_port_with_propagate_uplink_status(self):
- body = self.create_port(self.network, propagate_uplink_status=True)
- self.assertTrue(body['propagate_uplink_status'])
- body = self.client.list_ports(id=body['id'])['ports'][0]
- self.assertTrue(body['propagate_uplink_status'])
- body = self.client.show_port(body['id'])['port']
- self.assertTrue(body['propagate_uplink_status'])
-
- @decorators.idempotent_id('c396a880-0c7b-409d-a80b-800a3d09bdc4')
- @utils.requires_ext(extension="uplink-status-propagation",
- service="network")
- def test_create_port_without_propagate_uplink_status(self):
- body = self.create_port(self.network)
- self.assertFalse(body['propagate_uplink_status'])
- body = self.client.list_ports(id=body['id'])['ports'][0]
- self.assertFalse(body['propagate_uplink_status'])
- body = self.client.show_port(body['id'])['port']
- self.assertFalse(body['propagate_uplink_status'])
-
class PortsSearchCriteriaTest(base.BaseSearchCriteriaTest):
diff --git a/neutron_tempest_plugin/api/test_ports_negative.py b/neutron_tempest_plugin/api/test_ports_negative.py
new file mode 100644
index 0000000..e327c25
--- /dev/null
+++ b/neutron_tempest_plugin/api/test_ports_negative.py
@@ -0,0 +1,76 @@
+# 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_lib.db import constants as db_const
+from oslo_utils import uuidutils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from neutron_tempest_plugin.api import base
+
+LONG_NAME_NG = 'z' * (db_const.NAME_FIELD_SIZE + 1)
+LONG_DESCRIPTION_NG = 'z' * (db_const.LONG_DESCRIPTION_FIELD_SIZE + 1)
+
+
+class PortsNegativeTestJSON(base.BaseNetworkTest):
+
+ @classmethod
+ def resource_setup(cls):
+ super(PortsNegativeTestJSON, cls).resource_setup()
+ cls.network = cls.create_network()
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('0cbd256a-a6d4-4afa-a039-44cc13704bab')
+ def test_add_port_with_too_long_name(self):
+ self.assertRaises(lib_exc.BadRequest,
+ self.create_port,
+ self.network, name=LONG_NAME_NG)
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('e10da38c-1071-49c9-95c2-0c451e18ae31')
+ def test_add_port_with_too_long_description(self):
+ self.assertRaises(lib_exc.BadRequest,
+ self.create_port,
+ self.network, description=LONG_DESCRIPTION_NG)
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('5b69a905-3a84-43a4-807a-1a67ab85caeb')
+ def test_add_port_with_nonexist_tenant_id(self):
+ self.assertRaises(lib_exc.BadRequest,
+ self.create_port,
+ self.network,
+ project_id=uuidutils.generate_uuid())
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('7cf473ae-7ec8-4834-ae17-9ef6ec6b8a32')
+ def test_add_port_with_nonexist_network_id(self):
+ network = self.network
+ network['id'] = uuidutils.generate_uuid()
+ self.assertRaises(lib_exc.NotFound,
+ self.create_port,
+ network)
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('cad2d349-25fa-490e-9675-cd2ea24164bc')
+ def test_add_port_with_nonexist_security_groups_id(self):
+ self.assertRaises(lib_exc.NotFound,
+ self.create_port,
+ self.network,
+ security_groups=[uuidutils.generate_uuid()])
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('9b0a4152-9aa4-4169-9b2c-579609e2fb4a')
+ def test_add_port_with_illegal_ip(self):
+ self.assertRaises(lib_exc.BadRequest,
+ self.create_port,
+ self.network,
+ allowed_address_pairs=[{"ip_address: 12.12.12.a"}])
diff --git a/neutron_tempest_plugin/api/test_routers_negative.py b/neutron_tempest_plugin/api/test_routers_negative.py
index 5f24732..86d58e2 100644
--- a/neutron_tempest_plugin/api/test_routers_negative.py
+++ b/neutron_tempest_plugin/api/test_routers_negative.py
@@ -19,6 +19,10 @@
import testtools
from neutron_tempest_plugin.api import base_routers as base
+from neutron_tempest_plugin import config
+
+
+CONF = config.CONF
class RoutersNegativeTestBase(base.BaseRouterTest):
@@ -67,6 +71,44 @@
client2.add_router_interface_with_subnet_id(
self.router['id'], subnet['id'])
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('8010d27e-4ab7-4ea3-98b1-3995b7910efd')
+ def test_add_interface_in_use(self):
+ port = self.create_port(self.network)
+ self.client.add_router_interface_with_port_id(
+ self.router['id'], port['id'])
+ self.assertRaises(
+ lib_exc.Conflict,
+ self.client.add_router_interface_with_port_id,
+ self.router['id'], port['id'])
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('ed84c800-ee29-4b76-9419-d6d7b143fc47')
+ def test_add_interface_port_nonexist(self):
+ # port id is not a valid UUID
+ invalid_id = data_utils.rand_name('port')
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.client.add_router_interface_with_port_id,
+ self.router['id'], invalid_id)
+
+ @decorators.attr(type='negative')
+ @decorators.idempotent_id('dad7a8ba-2726-11eb-82dd-74e5f9e2a801')
+ def test_remove_associated_ports(self):
+ self.client.update_router(
+ self.router['id'],
+ external_gateway_info={
+ 'network_id': CONF.network.public_network_id})
+ network = self.create_network()
+ subnet = self.create_subnet(network)
+ self.create_router_interface(self.router['id'], subnet['id'])
+ port_ids = [
+ item['id'] for item in self.admin_client.list_ports(
+ device_id=self.router['id'])['ports']]
+ for port_id in port_ids:
+ with testtools.ExpectedException(lib_exc.Conflict):
+ self.admin_client.delete_port(port_id)
+
class DvrRoutersNegativeTest(RoutersNegativeTestBase):
diff --git a/neutron_tempest_plugin/api/test_security_groups.py b/neutron_tempest_plugin/api/test_security_groups.py
index dd1597c..afce414 100644
--- a/neutron_tempest_plugin/api/test_security_groups.py
+++ b/neutron_tempest_plugin/api/test_security_groups.py
@@ -538,3 +538,32 @@
# make sure the rbac-policy is invisible to the tenant for which it's
# being shared
self.assertFalse(self.client.list_rbac_policies()['rbac_policies'])
+
+
+class SecGroupSearchCriteriaTest(base.BaseSearchCriteriaTest):
+
+ required_extensions = ['security-group']
+ resource = 'security-group'
+
+ @classmethod
+ def resource_setup(cls):
+ super(SecGroupSearchCriteriaTest, cls).resource_setup()
+ cls.security_group = cls.create_security_group()
+ for name in cls.resource_names:
+ cls.create_security_group(name=name)
+
+ @decorators.idempotent_id('0064aa80-8a29-442d-a8de-9101af8210fa')
+ def test_list_sorts_by_name_asc(self):
+ self._test_list_sorts_asc()
+
+ @decorators.idempotent_id('35e86832-53cd-4e63-97ec-31a2413da591')
+ def test_list_sorts_by_name_desc(self):
+ self._test_list_sorts_desc()
+
+ @decorators.idempotent_id('b9654cdc-80bc-43f8-844e-dfe88fd2f125')
+ def test_list_pagination(self):
+ self._test_list_pagination()
+
+ @decorators.idempotent_id('5c78bd57-e6e9-4e71-a05c-9c4082a3f139')
+ def test_list_no_pagination_limit_0(self):
+ self._test_list_no_pagination_limit_0()
diff --git a/neutron_tempest_plugin/bgpvpn/scenario/manager.py b/neutron_tempest_plugin/bgpvpn/scenario/manager.py
index 8a5f9f2..4ff1c0d 100644
--- a/neutron_tempest_plugin/bgpvpn/scenario/manager.py
+++ b/neutron_tempest_plugin/bgpvpn/scenario/manager.py
@@ -462,8 +462,8 @@
port_map = [(p["id"], fxip["ip_address"])
for p in ports
for fxip in p["fixed_ips"]
- if netutils.is_valid_ipv4(fxip["ip_address"])
- and p['status'] in p_status]
+ if netutils.is_valid_ipv4(fxip["ip_address"]) and
+ p['status'] in p_status]
inactive = [p for p in ports if p['status'] != 'ACTIVE']
if inactive:
LOG.warning("Instance has ports that are not ACTIVE: %s", inactive)
diff --git a/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
index 937b0dc..14b0572 100644
--- a/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
+++ b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
@@ -353,6 +353,7 @@
self._update_l3_bgpvpn(rts=[self.RT1], import_rts=[], export_rts=[])
self._check_l3_bgpvpn()
+ @test.unstable_test("bug 1897408")
@decorators.idempotent_id('c8bfd695-f731-47a6-86e3-3dfa492e08e0')
@utils.services('compute', 'network')
def test_bgpvpn_update_rt_and_keep_local_connectivity_variant1(self):
@@ -404,6 +405,7 @@
self._check_l3_bgpvpn(self.servers[0], self.servers[2])
self._check_l3_bgpvpn(self.servers[1], self.servers[3])
+ @test.unstable_test("bug 1897408")
@decorators.idempotent_id('758a8731-5070-4b1e-9a66-d6ff05bb5be1')
@utils.services('compute', 'network')
def test_bgpvpn_update_rt_and_keep_local_connectivity_variant2(self):
@@ -544,6 +546,7 @@
to_server_ip=IP_C_S1_1,
validate_server=destination_srv_2)
+ @test.unstable_test("bug 1897408")
@decorators.idempotent_id('f762e6ac-920e-4d0f-aa67-02bdd4ab8433')
@utils.services('compute', 'network')
def test_bgpvpn_tenant_separation_and_local_connectivity(self):
diff --git a/neutron_tempest_plugin/common/ip.py b/neutron_tempest_plugin/common/ip.py
index a286d6b..d981770 100644
--- a/neutron_tempest_plugin/common/ip.py
+++ b/neutron_tempest_plugin/common/ip.py
@@ -36,13 +36,19 @@
sudo = 'sudo'
ip_path = '/sbin/ip'
- def __init__(self, ssh_client=None, timeout=None):
+ def __init__(self, ssh_client=None, timeout=None, namespace=None):
self.ssh_client = ssh_client
self.timeout = timeout
+ self.namespace = namespace
def get_command(self, obj, *command):
- command_line = '{sudo!s} {ip_path!r} {object!s} {command!s}'.format(
- sudo=self.sudo, ip_path=self.ip_path, object=obj,
+ command_line = '{sudo!s} {ip_path!r} '.format(sudo=self.sudo,
+ ip_path=self.ip_path)
+ if self.namespace:
+ command_line += 'netns exec {ns_name!s} {ip_path!r} '.format(
+ ns_name=self.namespace, ip_path=self.ip_path)
+ command_line += '{object!s} {command!s}'.format(
+ object=obj,
command=subprocess.list2cmdline([str(c) for c in command]))
return command_line
@@ -84,6 +90,13 @@
self.add_address(address=subport_ip, device=subport_device)
return subport_device
+ def list_namespaces(self):
+ namespaces_output = self.execute("netns")
+ ns_list = []
+ for ns_line in namespaces_output.split("\n"):
+ ns_list.append(ns_line.split(" ", 1)[0])
+ return ns_list
+
def list_addresses(self, device=None, ip_addresses=None, port=None,
subnets=None):
command = ['list']
@@ -295,7 +308,7 @@
for address in list_ip_addresses(addresses=addresses, port=port):
return address.device.name
- msg = "Port %r fixed IPs not found on server.".format(port['id'])
+ msg = "Port {0!r} fixed IPs not found on server.".format(port['id'])
raise ValueError(msg)
@@ -308,20 +321,24 @@
netaddr.IPNetwork(subnet['cidr']).prefixlen)
-def arp_table():
+def arp_table(namespace=None):
# 192.168.0.16 0x1 0x2 dc:a6:32:06:56:51 * enp0s31f6
regex_str = (r"([^ ]+)\s+(0x\d+)\s+(0x\d+)\s+(\w{2}\:\w{2}\:\w{2}\:\w{2}\:"
r"\w{2}\:\w{2})\s+([\w+\*]+)\s+([\-\w]+)")
regex = re.compile(regex_str)
arp_table = []
- with open('/proc/net/arp', 'r') as proc_file:
- for line in proc_file.readlines():
- m = regex.match(line)
- if m:
- arp_table.append(ARPregister(
- ip_address=m.group(1), hw_type=m.group(2),
- flags=m.group(3), mac_address=m.group(4),
- mask=m.group(5), device=m.group(6)))
+ cmd = ""
+ if namespace:
+ cmd = "sudo ip netns exec %s " % namespace
+ cmd += "cat /proc/net/arp"
+ arp_entries = shell.execute(cmd).stdout.split("\n")
+ for line in arp_entries:
+ m = regex.match(line)
+ if m:
+ arp_table.append(ARPregister(
+ ip_address=m.group(1), hw_type=m.group(2),
+ flags=m.group(3), mac_address=m.group(4),
+ mask=m.group(5), device=m.group(6)))
return arp_table
diff --git a/neutron_tempest_plugin/common/ssh.py b/neutron_tempest_plugin/common/ssh.py
index fa731d8..8334521 100644
--- a/neutron_tempest_plugin/common/ssh.py
+++ b/neutron_tempest_plugin/common/ssh.py
@@ -19,7 +19,6 @@
from oslo_log import log
import paramiko
-import six
from tempest.lib.common import ssh
from tempest.lib import exceptions
import tenacity
@@ -33,13 +32,7 @@
RETRY_EXCEPTIONS = (exceptions.TimeoutException, paramiko.SSHException,
- socket.error)
-if six.PY2:
- # NOTE(ralonsoh): TimeoutError was added in 3.3 and corresponds to
- # OSError(errno.ETIMEDOUT)
- RETRY_EXCEPTIONS += (OSError, )
-else:
- RETRY_EXCEPTIONS += (TimeoutError, )
+ socket.error, TimeoutError)
class Client(ssh.Client):
@@ -293,6 +286,13 @@
command=shell, host=self.host, script=script, stderr=stderr,
stdout=stdout, exit_status=exit_status)
+ def get_hostname(self):
+ """Retrieve the remote machine hostname"""
+ try:
+ return self.exec_command('hostname')
+ except exceptions.SSHExecCommandFailed:
+ return self.exec_command('cat /etc/hostname')
+
def _buffer_to_string(data_buffer, encoding):
return data_buffer.decode(encoding).replace("\r\n", "\n").replace(
diff --git a/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py b/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
index f085e6d..0dd18f1 100644
--- a/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
+++ b/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
@@ -13,7 +13,6 @@
# under the License.
import netaddr
-import six
from tempest.common import utils
from tempest import config
@@ -212,7 +211,7 @@
# show a created firewall rule
fw_rule = self.firewall_rules_client.show_firewall_rule(
self.fw_rule_1['id'])
- for key, value in six.iteritems(fw_rule['firewall_rule']):
+ for key, value in fw_rule['firewall_rule'].items():
if key != 'firewall_policy_id':
self.assertEqual(self.fw_rule_1[key], value)
# This check is placed because we cannot modify policy during
@@ -258,7 +257,7 @@
fw_policy = self.firewall_policies_client.show_firewall_policy(
self.fw_policy_1['id'])
fw_policy = fw_policy['firewall_policy']
- for key, value in six.iteritems(fw_policy):
+ for key, value in fw_policy.items():
self.assertEqual(self.fw_policy_1[key], value)
@decorators.idempotent_id('48dfcd75-3924-479d-bb65-b3ed33397663')
@@ -283,7 +282,7 @@
fwg_id)
fwg = firewall_group['firewall_group']
- for key, value in six.iteritems(fwg):
+ for key, value in fwg.items():
if key == 'status':
continue
self.assertEqual(created_firewall_group[key], value)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
index 6720c22..5cdd524 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
@@ -26,29 +26,8 @@
CONF = config.CONF
-def _setup_client_args(auth_provider):
- """Set up ServiceClient arguments using config settings. """
- service = CONF.network.catalog_type or 'network'
- region = CONF.network.region or 'regionOne'
- endpoint_type = CONF.network.endpoint_type
- build_interval = CONF.network.build_interval
- build_timeout = CONF.network.build_timeout
-
- # The disable_ssl appears in identity
- disable_ssl_certificate_validation = (
- CONF.identity.disable_ssl_certificate_validation)
- ca_certs = CONF.identity.ca_certificates_file
-
- # Trace in debug section
- trace_requests = CONF.debug.trace_requests
-
- return [auth_provider, service, region, endpoint_type,
- build_interval, build_timeout,
- disable_ssl_certificate_validation, ca_certs,
- trace_requests]
-
-
class BgpSpeakerTestJSONBase(base.BaseAdminNetworkTest):
+ credentials = ['primary', 'admin']
default_bgp_speaker_args = {'local_as': '1234',
'ip_version': 4,
@@ -65,18 +44,20 @@
super(BgpSpeakerTestJSONBase, self).setUp()
@classmethod
- def _setup_bgp_admin_client(cls):
- mgr = cls.get_client_manager(credential_type='admin')
- auth_provider = mgr.auth_provider
- client_args = _setup_client_args(auth_provider)
- cls.bgp_adm_client = bgp_client.BgpSpeakerClientJSON(*client_args)
+ def setup_clients(cls):
+ super(BgpSpeakerTestJSONBase, cls).setup_clients()
+ cls.bgp_client = cls.os_primary.bgp_client
+ cls.bgp_adm_client = cls.os_admin.bgp_client
@classmethod
- def _setup_bgp_non_admin_client(cls):
- mgr = cls.get_client_manager()
- auth_provider = mgr.auth_provider
- client_args = _setup_client_args(auth_provider)
- cls.bgp_client = bgp_client.BgpSpeakerClientJSON(*client_args)
+ def get_client_manager(cls, credential_type=None, roles=None,
+ force_new=None):
+ manager = super(BgpSpeakerTestJSONBase, cls).get_client_manager(
+ credential_type=credential_type,
+ roles=roles,
+ force_new=force_new
+ )
+ return bgp_client.Manager(manager.credentials)
@classmethod
def resource_setup(cls):
@@ -89,8 +70,6 @@
cls.admin_floatingips = []
cls.admin_routers = []
cls.ext_net_id = CONF.network.public_network_id
- cls._setup_bgp_admin_client()
- cls._setup_bgp_non_admin_client()
@classmethod
def resource_cleanup(cls):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
index f752436..b4be57b 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
@@ -19,7 +19,6 @@
import time
import netaddr
-import six
from os_ken.tests.integrated.common import docker_base as ctn_base
from tempest.common import utils
@@ -125,10 +124,10 @@
while True:
with self.lock:
try:
- yield (i, str(six.next(subnet_gen)))
+ yield (i, str(next(subnet_gen)))
except StopIteration:
subnet_gen = netaddr.iter_iprange(start, end, step=step)
- yield (i, str(six.next(subnet_gen)))
+ yield (i, str(next(subnet_gen)))
i += 1
def net_resource_cleanup(self):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
index 1bcf5b1..643620f 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
from tempest import config
from neutron_tempest_plugin.neutron_dynamic_routing.scenario import base
@@ -28,7 +27,7 @@
def _test_check_neighbor_established(self, ip_version):
self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -47,7 +46,7 @@
def _test_check_advertised_tenant_network(self, ip_version):
self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -73,7 +72,7 @@
tnets = []
tnets_cidr = []
for i in range(0, 3):
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -102,7 +101,7 @@
for (bgp_peer_args, r_as_ip) in zip(self.bgp_peer_args,
self.r_as_ip):
bgp_peer_args['peer_ip'] = r_as_ip.split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -124,7 +123,7 @@
for (bgp_peer_args, r_as_ip) in zip(self.bgp_peer_args,
self.r_as_ip):
bgp_peer_args['peer_ip'] = r_as_ip.split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
index 1c680f9..90a6815 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
@@ -15,7 +15,6 @@
# under the License.
from os_ken.tests.integrated.common import docker_base as ctn_base
-import six
from tempest import config
from tempest.lib import decorators
@@ -31,7 +30,7 @@
@decorators.idempotent_id('cc615252-c6cb-4d75-a70e-608fb2c3736a')
def test_schedule_added_speaker(self):
self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -51,7 +50,7 @@
@decorators.idempotent_id('ce98c33c-0ffa-49ae-b365-da836406793b')
def test_unschedule_deleted_speaker(self):
self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
@@ -77,7 +76,7 @@
@decorators.idempotent_id('aa6c565c-ded3-413b-8dc9-3928b3b0e38f')
def test_remove_add_speaker_agent(self):
self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
- num, subnet = six.next(self.tnet_gen)
+ num, subnet = next(self.tnet_gen)
mask = '/' + str(self.TPool.prefixlen)
TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
cidr=subnet + mask, router=None)
diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py
index 9223893..752e536 100644
--- a/neutron_tempest_plugin/scenario/base.py
+++ b/neutron_tempest_plugin/scenario/base.py
@@ -21,6 +21,7 @@
from neutron_lib.api import validators
from neutron_lib import constants as neutron_lib_constants
from oslo_log import log
+from paramiko import ssh_exception as ssh_exc
from tempest.common.utils import net_utils
from tempest.common import waiters
from tempest.lib.common.utils import data_utils
@@ -121,9 +122,11 @@
if not kwargs.get('security_groups'):
kwargs['security_groups'] = [{'name': 'default'}]
- client = self.os_primary.servers_client
- if kwargs.get('availability_zone'):
- client = self.os_admin.servers_client
+ client = kwargs.pop('client', None)
+ if client is None:
+ client = self.os_primary.servers_client
+ if kwargs.get('availability_zone'):
+ client = self.os_admin.servers_client
server = client.create_server(
flavorRef=flavor_ref,
@@ -139,6 +142,10 @@
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
client.delete_server,
server['server']['id'])
+
+ self.wait_for_server_active(server['server'], client=client)
+ self.wait_for_guest_os_ready(server['server'], client=client)
+
return server
@classmethod
@@ -252,19 +259,20 @@
server_kwargs['name'] = server_name
self.server = self.create_server(**server_kwargs)
- self.wait_for_server_active(self.server['server'])
self.port = self.client.list_ports(network_id=self.network['id'],
device_id=self.server[
'server']['id'])['ports'][0]
self.fip = self.create_floatingip(port=self.port)
- def check_connectivity(self, host, ssh_user, ssh_key,
- servers=None, ssh_timeout=None):
- ssh_client = ssh.Client(host, ssh_user,
- pkey=ssh_key, timeout=ssh_timeout)
+ def check_connectivity(self, host, ssh_user=None, ssh_key=None,
+ servers=None, ssh_timeout=None, ssh_client=None):
+ # Either ssh_client or ssh_user+ssh_key is mandatory.
+ if ssh_client is None:
+ ssh_client = ssh.Client(host, ssh_user,
+ pkey=ssh_key, timeout=ssh_timeout)
try:
ssh_client.test_connection_auth()
- except lib_exc.SSHTimeout as ssh_e:
+ except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
LOG.debug(ssh_e)
self._log_console_output(servers)
self._log_local_network_status()
@@ -294,15 +302,32 @@
"for the console log", server['id'])
def _log_local_network_status(self):
- local_routes = ip_utils.IPCommand().list_routes()
- LOG.debug('Local routes:\n%s', '\n'.join(str(r) for r in local_routes))
- arp_table = ip_utils.arp_table()
- LOG.debug('Local ARP table:\n%s', '\n'.join(str(r) for r in arp_table))
+ self._log_ns_network_status()
+ for ns_name in ip_utils.IPCommand().list_namespaces():
+ self._log_ns_network_status(ns_name=ns_name)
+
+ def _log_ns_network_status(self, ns_name=None):
+ try:
+ local_ips = ip_utils.IPCommand(namespace=ns_name).list_addresses()
+ local_routes = ip_utils.IPCommand(namespace=ns_name).list_routes()
+ arp_table = ip_utils.arp_table()
+ except exceptions.ShellCommandFailed:
+ LOG.debug('Namespace %s has been deleted synchronously during the '
+ 'host network collection process', ns_name)
+ return
+
+ LOG.debug('Namespace %s; IP Addresses:\n%s',
+ ns_name, '\n'.join(str(r) for r in local_ips))
+ LOG.debug('Namespace %s; Local routes:\n%s',
+ ns_name, '\n'.join(str(r) for r in local_routes))
+ LOG.debug('Namespace %s; Local ARP table:\n%s',
+ ns_name, '\n'.join(str(r) for r in arp_table))
def _check_remote_connectivity(self, source, dest, count,
should_succeed=True,
nic=None, mtu=None, fragmentation=True,
- timeout=None, pattern=None):
+ timeout=None, pattern=None,
+ forbid_packet_loss=False):
"""check ping server via source ssh connection
:param source: RemoteClient: an ssh connection from which to ping
@@ -314,6 +339,7 @@
:param fragmentation: Flag for packet fragmentation
:param timeout: Timeout for all ping packet(s) to succeed
:param pattern: hex digits included in ICMP messages
+ :param forbid_packet_loss: forbid or allow some lost packets
:returns: boolean -- should_succeed == ping
:returns: ping is false if ping failed
"""
@@ -352,6 +378,10 @@
return not should_succeed
LOG.debug('ping result: %s', result)
+ if forbid_packet_loss and ' 0% packet loss' not in result:
+ LOG.debug('Packet loss detected')
+ return not should_succeed
+
if validators.validate_ip_address(dest) is None:
# Assert that the return traffic was from the correct
# source address.
@@ -366,18 +396,21 @@
nic=None, mtu=None, fragmentation=True,
servers=None, timeout=None,
ping_count=CONF.validation.ping_count,
- pattern=None):
+ pattern=None, forbid_packet_loss=False):
try:
self.assertTrue(self._check_remote_connectivity(
source, dest, ping_count, should_succeed, nic, mtu,
fragmentation,
- timeout=timeout, pattern=pattern))
- except lib_exc.SSHTimeout as ssh_e:
+ timeout=timeout, pattern=pattern,
+ forbid_packet_loss=forbid_packet_loss))
+ except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
LOG.debug(ssh_e)
self._log_console_output(servers)
+ self._log_local_network_status()
raise
except AssertionError:
self._log_console_output(servers)
+ self._log_local_network_status()
raise
def ping_ip_address(self, ip_address, should_succeed=True,
@@ -445,7 +478,30 @@
self.wait_for_server_status(
server, constants.SERVER_STATUS_ACTIVE, client)
- def check_servers_hostnames(self, servers, timeout=None, log_errors=True):
+ def wait_for_guest_os_ready(self, server, client=None):
+ if not CONF.compute_feature_enabled.console_output:
+ LOG.debug('Console output not supported, cannot check if server '
+ '%s is ready.', server['id'])
+ return
+
+ client = client or self.os_primary.servers_client
+
+ def system_booted():
+ console_output = client.get_console_output(server['id'])['output']
+ for line in console_output.split('\n'):
+ if 'login:' in line.lower():
+ return True
+ return False
+
+ try:
+ utils.wait_until_true(system_booted, sleep=5)
+ except utils.WaitTimeout:
+ LOG.debug("No correct output in console of server %s found. "
+ "Guest operating system status can't be checked.",
+ server['id'])
+
+ def check_servers_hostnames(self, servers, timeout=None, log_errors=True,
+ external_port=None):
"""Compare hostnames of given servers with their names."""
try:
for server in servers:
@@ -453,7 +509,7 @@
if timeout:
kwargs['timeout'] = timeout
try:
- kwargs['port'] = (
+ kwargs['port'] = external_port or (
server['port_forwarding_tcp']['external_port'])
except KeyError:
pass
@@ -463,16 +519,18 @@
pkey=self.keypair['private_key'],
**kwargs)
self.assertIn(server['name'],
- ssh_client.exec_command('hostname'))
- except lib_exc.SSHTimeout as ssh_e:
+ ssh_client.get_hostname())
+ except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
LOG.debug(ssh_e)
if log_errors:
self._log_console_output(servers)
+ self._log_local_network_status()
raise
except AssertionError as assert_e:
LOG.debug(assert_e)
if log_errors:
self._log_console_output(servers)
+ self._log_local_network_status()
raise
def ensure_nc_listen(self, ssh_client, port, protocol, echo_msg=None,
@@ -497,9 +555,10 @@
return ssh_client.execute_script(
get_ncat_server_cmd(port, protocol, echo_msg),
become_root=True, combine_stderr=True)
- except lib_exc.SSHTimeout as ssh_e:
+ except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
LOG.debug(ssh_e)
self._log_console_output(servers)
+ self._log_local_network_status()
raise
def nc_client(self, ip_address, port, protocol):
diff --git a/neutron_tempest_plugin/scenario/test_connectivity.py b/neutron_tempest_plugin/scenario/test_connectivity.py
index 1a7468a..66c4789 100644
--- a/neutron_tempest_plugin/scenario/test_connectivity.py
+++ b/neutron_tempest_plugin/scenario/test_connectivity.py
@@ -65,6 +65,7 @@
for vm in vms:
self.wait_for_server_active(vm['server'])
+ self.wait_for_guest_os_ready(vm['server'])
return vms
@@ -231,6 +232,7 @@
networks=[{'uuid': network['id']}],
security_groups=[{'name': self.secgroup['name']}])
self.wait_for_server_active(vm['server'])
+ self.wait_for_guest_os_ready(vm['server'])
vm_port = self.client.list_ports(
network_id=network['id'], device_id=vm['server']['id'])['ports'][0]
diff --git a/neutron_tempest_plugin/scenario/test_dhcp.py b/neutron_tempest_plugin/scenario/test_dhcp.py
new file mode 100644
index 0000000..b95eaa2
--- /dev/null
+++ b/neutron_tempest_plugin/scenario/test_dhcp.py
@@ -0,0 +1,94 @@
+# 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 paramiko import ssh_exception as ssh_exc
+from tempest.common import utils
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from neutron_tempest_plugin.common import ssh
+from neutron_tempest_plugin import config
+from neutron_tempest_plugin.scenario import base
+
+CONF = config.CONF
+LOG = log.getLogger(__name__)
+
+
+class DHCPTest(base.BaseTempestTestCase):
+
+ credentials = ['primary', 'admin']
+ force_tenant_isolation = False
+
+ @classmethod
+ def resource_setup(cls):
+ super(DHCPTest, cls).resource_setup()
+ cls.rand_name = data_utils.rand_name(
+ cls.__name__.rsplit('.', 1)[-1])
+ cls.network = cls.create_network(name=cls.rand_name)
+ cls.subnet = cls.create_subnet(
+ network=cls.network, name=cls.rand_name)
+ cls.router = cls.create_router_by_client()
+ cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+ cls.keypair = cls.create_keypair(name=cls.rand_name)
+ cls.security_group = cls.create_security_group(name=cls.rand_name)
+ cls.create_loginable_secgroup_rule(cls.security_group['id'])
+
+ @utils.requires_ext(extension='extra_dhcp_opt', service='network')
+ @decorators.idempotent_id('58f7c094-1980-4e03-b0d3-6c4dd27217b1')
+ def test_extra_dhcp_opts(self):
+ """This test case tests DHCP extra options configured for Neutron port.
+
+ Test is checking just extra option "15" which is domain-name
+ according to the RFC 2132:
+ https://tools.ietf.org/html/rfc2132#section-5.3
+
+ To test that option, there is spawned VM connected to the port with
+ configured extra_dhcp_opts and test asserts that search domain name is
+ configured inside VM in /etc/resolv.conf file
+ """
+
+ test_domain = "test.domain"
+ extra_dhcp_opts = [
+ {'opt_name': 'domain-name',
+ 'opt_value': '"%s"' % test_domain}]
+ port = self.create_port(
+ network=self.network, name=self.rand_name,
+ security_groups=[self.security_group['id']],
+ extra_dhcp_opts=extra_dhcp_opts)
+ floating_ip = self.create_floatingip(port=port)
+
+ server = self.create_server(
+ flavor_ref=CONF.compute.flavor_ref,
+ image_ref=CONF.compute.image_ref,
+ key_name=self.keypair['name'],
+ networks=[{'port': port['id']}])
+ self.wait_for_server_active(server['server'])
+ self.wait_for_guest_os_ready(server['server'])
+
+ try:
+ ssh_client = ssh.Client(
+ floating_ip['floating_ip_address'],
+ CONF.validation.image_ssh_user,
+ pkey=self.keypair['private_key'])
+ vm_resolv_conf = ssh_client.exec_command(
+ "cat /etc/resolv.conf")
+ self.assertIn(test_domain, vm_resolv_conf)
+ except (lib_exc.SSHTimeout,
+ ssh_exc.AuthenticationException,
+ AssertionError) as error:
+ LOG.debug(error)
+ self._log_console_output([server])
+ self._log_local_network_status()
+ raise
diff --git a/neutron_tempest_plugin/scenario/test_floatingip.py b/neutron_tempest_plugin/scenario/test_floatingip.py
index 7c59d3a..262f429 100644
--- a/neutron_tempest_plugin/scenario/test_floatingip.py
+++ b/neutron_tempest_plugin/scenario/test_floatingip.py
@@ -341,6 +341,15 @@
def resource_setup(cls):
super(FloatingIPQosTest, cls).resource_setup()
+ def skip_if_no_extension_enabled_in_l3_agents(self, extension):
+ l3_agents = self.os_admin.network_client.list_agents(
+ binary='neutron-l3-agent')['agents']
+ for agent in l3_agents:
+ if extension in agent['configurations'].get('extensions', []):
+ return
+ raise self.skipTest("No L3 agent with '%s' extension enabled found." %
+ extension)
+
@decorators.idempotent_id('5eb48aea-eaba-4c20-8a6f-7740070a0aa3')
def test_qos(self):
"""Test floating IP is binding to a QoS policy with
@@ -351,6 +360,8 @@
received / elapsed time.
"""
+ self.skip_if_no_extension_enabled_in_l3_agents("fip_qos")
+
self._test_basic_resources()
policy_id = self._create_qos_policy()
ssh_client = self._create_ssh_client()
@@ -417,6 +428,7 @@
servers.append(server)
for server in servers:
self.wait_for_server_active(server)
+ self.wait_for_guest_os_ready(server)
self.fip = self.create_floatingip(port=ports[0])
self.check_connectivity(self.fip['floating_ip_address'],
@@ -434,8 +446,7 @@
# The FIP is now associated with the port of the second server.
try:
- common_utils.wait_until_true(_wait_for_fip_associated,
- timeout=15, sleep=3)
+ common_utils.wait_until_true(_wait_for_fip_associated, sleep=3)
except common_utils.WaitTimeout:
self._log_console_output(servers[-1:])
self.fail(
diff --git a/neutron_tempest_plugin/scenario/test_internal_dns.py b/neutron_tempest_plugin/scenario/test_internal_dns.py
index d19286c..406af3d 100644
--- a/neutron_tempest_plugin/scenario/test_internal_dns.py
+++ b/neutron_tempest_plugin/scenario/test_internal_dns.py
@@ -52,13 +52,14 @@
{'name': self.security_groups[-1]['name']}],
name='leia')
self.wait_for_server_active(leia['server'])
+ self.wait_for_guest_os_ready(leia['server'])
ssh_client = ssh.Client(
self.fip['floating_ip_address'],
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'])
- self.assertIn('luke', ssh_client.exec_command('hostname'))
+ self.assertIn('luke', ssh_client.get_hostname())
leia_port = self.client.list_ports(
network_id=self.network['id'],
diff --git a/neutron_tempest_plugin/scenario/test_ipv6.py b/neutron_tempest_plugin/scenario/test_ipv6.py
index 02e2846..4237d4f 100644
--- a/neutron_tempest_plugin/scenario/test_ipv6.py
+++ b/neutron_tempest_plugin/scenario/test_ipv6.py
@@ -15,6 +15,7 @@
from neutron_lib import constants as lib_constants
from oslo_log import log
+from paramiko import ssh_exception as ssh_exc
from tempest.common import utils as tempest_utils
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -83,6 +84,7 @@
@tempest_utils.requires_ext(extension="router", service="network")
def resource_setup(cls):
super(IPv6Test, cls).resource_setup()
+ cls.reserve_external_subnet_cidrs()
cls._setup_basic_resources()
@classmethod
@@ -108,16 +110,22 @@
return True
return False
- # Set NIC with IPv6 to be UP and wait until IPv6 address will be
- # configured on this NIC
- turn_nic6_on(ssh_client, ipv6_port)
- # And check if IPv6 address will be properly configured on this NIC
- utils.wait_until_true(
- lambda: guest_has_address(ipv6_address),
- timeout=120,
- exception=RuntimeError(
- "Timed out waiting for IP address {!r} to be configured in "
- "the VM {!r}.".format(ipv6_address, vm['id'])))
+ try:
+ # Set NIC with IPv6 to be UP and wait until IPv6 address will be
+ # configured on this NIC
+ turn_nic6_on(ssh_client, ipv6_port)
+ # And check if IPv6 address will be properly configured on this NIC
+ utils.wait_until_true(
+ lambda: guest_has_address(ipv6_address),
+ timeout=120,
+ exception=RuntimeError(
+ "Timed out waiting for IP address {!r} to be configured "
+ "in the VM {!r}.".format(ipv6_address, vm['id'])))
+ except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
+ LOG.debug(ssh_e)
+ self._log_console_output([vm])
+ self._log_local_network_status()
+ raise
def _test_ipv6_hotplug(self, ra_mode, address_mode):
ipv6_networks = [self.create_network() for _ in range(2)]
@@ -138,6 +146,7 @@
}
vm = self.create_server(**server_kwargs)['server']
self.wait_for_server_active(vm)
+ self.wait_for_guest_os_ready(vm)
ipv4_port = self.client.list_ports(
network_id=self.network['id'],
device_id=vm['id'])['ports'][0]
diff --git a/neutron_tempest_plugin/scenario/test_metadata.py b/neutron_tempest_plugin/scenario/test_metadata.py
new file mode 100644
index 0000000..91ecc97
--- /dev/null
+++ b/neutron_tempest_plugin/scenario/test_metadata.py
@@ -0,0 +1,149 @@
+# Copyright 2020 Ericsson Software Technology
+#
+# 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 collections
+
+from neutron_lib import constants as nlib_const
+from oslo_log import log as logging
+from tempest.common import utils
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+import testtools
+
+from neutron_tempest_plugin.common import ssh
+from neutron_tempest_plugin import config
+from neutron_tempest_plugin.scenario import base
+
+LOG = logging.getLogger(__name__)
+CONF = config.CONF
+
+Server = collections.namedtuple(
+ 'Server', ['floating_ip', 'server', 'ssh_client'])
+
+
+class MetadataTest(base.BaseTempestTestCase):
+
+ """Test metadata access over IPv6 tenant subnet.
+
+ Please note that there is metadata over IPv4 test coverage in tempest:
+
+ tempest.scenario.test_server_basic_ops\
+ .TestServerBasicOps.test_server_basic_ops
+ """
+
+ credentials = ['primary', 'admin']
+ force_tenant_isolation = False
+
+ @classmethod
+ def skip_checks(cls):
+ super(MetadataTest, cls).skip_checks()
+ if not utils.is_network_feature_enabled('ipv6_metadata'):
+ raise cls.skipException("Metadata over IPv6 is not enabled")
+
+ @classmethod
+ def resource_setup(cls):
+ super(MetadataTest, cls).resource_setup()
+ cls.rand_name = data_utils.rand_name(
+ cls.__name__.rsplit('.', 1)[-1])
+ cls.reserve_external_subnet_cidrs()
+ cls.network = cls.create_network(name=cls.rand_name)
+ cls.subnet_v4 = cls.create_subnet(
+ network=cls.network, name=cls.rand_name)
+ cls.subnet_v6 = cls.create_subnet(
+ network=cls.network, name=cls.rand_name, ip_version=6)
+ cls.router = cls.create_router_by_client()
+ cls.create_router_interface(cls.router['id'], cls.subnet_v4['id'])
+ cls.create_router_interface(cls.router['id'], cls.subnet_v6['id'])
+ cls.keypair = cls.create_keypair(name=cls.rand_name)
+ cls.security_group = cls.create_security_group(name=cls.rand_name)
+ cls.create_loginable_secgroup_rule(cls.security_group['id'])
+
+ def _create_server_with_network(self, network, use_advanced_image=False):
+ port = self._create_server_port(network=network)
+ floating_ip = self.create_floatingip(port=port)
+ ssh_client = self._create_ssh_client(
+ floating_ip=floating_ip, use_advanced_image=use_advanced_image)
+ server = self._create_server(port=port,
+ use_advanced_image=use_advanced_image)
+ return Server(
+ floating_ip=floating_ip, server=server, ssh_client=ssh_client)
+
+ def _create_server_port(self, network=None, **params):
+ network = network or self.network
+ return self.create_port(network=network, name=self.rand_name,
+ security_groups=[self.security_group['id']],
+ **params)
+
+ def _create_server(self, port, use_advanced_image=False, **params):
+ if use_advanced_image:
+ flavor_ref = CONF.neutron_plugin_options.advanced_image_flavor_ref
+ image_ref = CONF.neutron_plugin_options.advanced_image_ref
+ else:
+ flavor_ref = CONF.compute.flavor_ref
+ image_ref = CONF.compute.image_ref
+ return self.create_server(flavor_ref=flavor_ref,
+ image_ref=image_ref,
+ key_name=self.keypair['name'],
+ networks=[{'port': port['id']}],
+ **params)['server']
+
+ def _create_ssh_client(self, floating_ip, use_advanced_image=False):
+ if use_advanced_image:
+ username = CONF.neutron_plugin_options.advanced_image_ssh_user
+ else:
+ username = CONF.validation.image_ssh_user
+ return ssh.Client(host=floating_ip['floating_ip_address'],
+ username=username,
+ pkey=self.keypair['private_key'])
+
+ def _assert_has_ssh_connectivity(self, ssh_client):
+ ssh_client.exec_command('true')
+
+ def _get_primary_interface(self, ssh_client):
+ out = ssh_client.exec_command(
+ "ip -6 -br address show scope link up | head -1 | cut -d ' ' -f1")
+ interface = out.strip()
+ if not interface:
+ self.fail(
+ 'Could not find a single interface '
+ 'with an IPv6 link-local address.')
+ return interface
+
+ @testtools.skipUnless(
+ CONF.neutron_plugin_options.advanced_image_ref or
+ CONF.neutron_plugin_options.default_image_is_advanced,
+ 'Advanced image is required to run this test.')
+ @decorators.idempotent_id('e680949a-f1cc-11ea-b49a-cba39bbbe5ad')
+ def test_metadata_routed(self):
+ use_advanced_image = (
+ not CONF.neutron_plugin_options.default_image_is_advanced)
+
+ vm = self._create_server_with_network(
+ self.network, use_advanced_image=use_advanced_image)
+ self.wait_for_server_active(server=vm.server)
+ self.wait_for_guest_os_ready(vm.server)
+ self._assert_has_ssh_connectivity(vm.ssh_client)
+ interface = self._get_primary_interface(vm.ssh_client)
+
+ out = vm.ssh_client.exec_command(
+ 'curl http://[%(address)s%%25%(interface)s]/' % {
+ 'address': nlib_const.METADATA_V6_IP,
+ 'interface': interface})
+ self.assertIn('latest', out)
+
+ out = vm.ssh_client.exec_command(
+ 'curl http://[%(address)s%%25%(interface)s]/openstack/' % {
+ 'address': nlib_const.METADATA_V6_IP,
+ 'interface': interface})
+ self.assertIn('latest', out)
diff --git a/neutron_tempest_plugin/scenario/test_multicast.py b/neutron_tempest_plugin/scenario/test_multicast.py
index b2ea8ae..79f835e 100644
--- a/neutron_tempest_plugin/scenario/test_multicast.py
+++ b/neutron_tempest_plugin/scenario/test_multicast.py
@@ -201,6 +201,7 @@
security_groups=[{'name': self.secgroup['security_group']['name']}]
)['server']
self.wait_for_server_active(server)
+ self.wait_for_guest_os_ready(server)
port = self.client.list_ports(
network_id=self.network['id'], device_id=server['id'])['ports'][0]
server['fip'] = self.create_floatingip(port=port)
diff --git a/neutron_tempest_plugin/scenario/test_port_forwardings.py b/neutron_tempest_plugin/scenario/test_port_forwardings.py
index da1db1b..a4711ae 100644
--- a/neutron_tempest_plugin/scenario/test_port_forwardings.py
+++ b/neutron_tempest_plugin/scenario/test_port_forwardings.py
@@ -14,6 +14,7 @@
# under the License.
from neutron_lib import constants
+from neutron_lib.utils import test
from oslo_log import log
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -44,9 +45,14 @@
cls.secgroup = cls.create_security_group(
name=data_utils.rand_name("test_port_secgroup"))
cls.create_loginable_secgroup_rule(secgroup_id=cls.secgroup['id'])
+ udp_sg_rule = {'protocol': constants.PROTO_NAME_UDP,
+ 'direction': constants.INGRESS_DIRECTION,
+ 'remote_ip_prefix': '0.0.0.0/0'}
+ cls.create_secgroup_rules(
+ [udp_sg_rule], secgroup_id=cls.secgroup['id'])
cls.keypair = cls.create_keypair()
- def _prepare_resources(self, num_servers, internal_tcp_port, protocol,
+ def _prepare_resources(self, num_servers, internal_tcp_port=22,
external_port_base=1025):
servers = []
for i in range(1, num_servers + 1):
@@ -64,6 +70,7 @@
networks=[{'port': port['id']}])['server']
server['name'] = name
self.wait_for_server_active(server)
+ self.wait_for_guest_os_ready(server)
server['port_forwarding_tcp'] = self.create_port_forwarding(
self.fip['id'],
internal_port_id=port['id'],
@@ -81,7 +88,7 @@
servers.append(server)
return servers
- def _test_udp_port_forwarding(self, servers):
+ def _test_udp_port_forwarding(self, servers, timeout=None):
def _message_received(server, ssh_client, expected_msg):
self.nc_listen(ssh_client,
@@ -102,22 +109,21 @@
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'],
port=server['port_forwarding_tcp']['external_port'])
+ wait_params = {
+ 'exception': RuntimeError(
+ "Timed out waiting for message from server {!r} ".format(
+ server['id']))
+ }
+ if timeout:
+ wait_params['timeout'] = timeout
utils.wait_until_true(
lambda: _message_received(server, ssh_client, expected_msg),
- exception=RuntimeError(
- "Timed out waiting for message from server {!r} ".format(
- server['id'])))
+ **wait_params)
@decorators.idempotent_id('ab40fc48-ca8d-41a0-b2a3-f6679c847bfe')
def test_port_forwarding_to_2_servers(self):
- udp_sg_rule = {'protocol': constants.PROTO_NAME_UDP,
- 'direction': constants.INGRESS_DIRECTION,
- 'remote_ip_prefix': '0.0.0.0/0'}
- self.create_secgroup_rules(
- [udp_sg_rule], secgroup_id=self.secgroup['id'])
- servers = self._prepare_resources(
- num_servers=2, internal_tcp_port=22,
- protocol=constants.PROTO_NAME_TCP)
+ servers = self._prepare_resources(num_servers=2,
+ external_port_base=1035)
# Test TCP port forwarding by SSH to each server
self.check_servers_hostnames(servers)
# And now test UDP port forwarding using nc
@@ -125,25 +131,16 @@
@decorators.idempotent_id('aa19d46c-a4a6-11ea-bb37-0242ac130002')
def test_port_forwarding_editing_and_deleting_tcp_rule(self):
- server = self._prepare_resources(
- num_servers=1, internal_tcp_port=22,
- protocol=constants.PROTO_NAME_TCP,
- external_port_base=1035)
+ test_ext_port = 3333
+ server = self._prepare_resources(num_servers=1,
+ external_port_base=1045)
fip_id = server[0]['port_forwarding_tcp']['floatingip_id']
pf_id = server[0]['port_forwarding_tcp']['id']
# Check connectivity with the original parameters
self.check_servers_hostnames(server)
- # Use a reasonable timeout to verify that connections will not
- # happen. Default would be 196 seconds, which is an overkill.
- test_ssh_connect_timeout = 6
-
- # Update external port and check connectivity with original parameters
- # Port under server[0]['port_forwarding_tcp']['external_port'] should
- # not answer at this point.
-
- def fip_pf_connectivity():
+ def fip_pf_connectivity(test_ssh_connect_timeout=60):
try:
self.check_servers_hostnames(
server, timeout=test_ssh_connect_timeout)
@@ -152,9 +149,13 @@
return False
def no_fip_pf_connectivity():
- return not fip_pf_connectivity()
+ return not fip_pf_connectivity(6)
- self.client.update_port_forwarding(fip_id, pf_id, external_port=3333)
+ # Update external port and check connectivity with original parameters
+ # Port under server[0]['port_forwarding_tcp']['external_port'] should
+ # not answer at this point.
+ self.client.update_port_forwarding(fip_id, pf_id,
+ external_port=test_ext_port)
utils.wait_until_true(
no_fip_pf_connectivity,
exception=RuntimeError(
@@ -164,7 +165,7 @@
server[0]['port_forwarding_tcp']['external_port'])))
# Check connectivity with the new parameters
- server[0]['port_forwarding_tcp']['external_port'] = 3333
+ server[0]['port_forwarding_tcp']['external_port'] = test_ext_port
utils.wait_until_true(
fip_pf_connectivity,
exception=RuntimeError(
@@ -184,3 +185,106 @@
"port {!r} is still possible.".format(
server[0]['id'],
server[0]['port_forwarding_tcp']['external_port'])))
+
+ @test.unstable_test("bug 1896735")
+ @decorators.idempotent_id('6d05b1b2-6109-4c30-b402-1503f4634acb')
+ def test_port_forwarding_editing_and_deleting_udp_rule(self):
+ test_ext_port = 3344
+ server = self._prepare_resources(num_servers=1,
+ external_port_base=1055)
+ fip_id = server[0]['port_forwarding_udp']['floatingip_id']
+ pf_id = server[0]['port_forwarding_udp']['id']
+
+ # Check connectivity with the original parameters
+ self.check_servers_hostnames(server)
+
+ def fip_pf_udp_connectivity(test_udp_timeout=60):
+ try:
+ self._test_udp_port_forwarding(server, test_udp_timeout)
+ return True
+ except (AssertionError, RuntimeError):
+ return False
+
+ def no_fip_pf_udp_connectivity():
+ return not fip_pf_udp_connectivity(6)
+
+ # Update external port and check connectivity with original parameters
+ # Port under server[0]['port_forwarding_udp']['external_port'] should
+ # not answer at this point.
+ self.client.update_port_forwarding(fip_id, pf_id,
+ external_port=test_ext_port)
+ utils.wait_until_true(
+ no_fip_pf_udp_connectivity,
+ exception=RuntimeError(
+ "Connection to the server {!r} through "
+ "port {!r} is still possible.".format(
+ server[0]['id'],
+ server[0]['port_forwarding_udp']['external_port'])))
+
+ # Check connectivity with the new parameters
+ server[0]['port_forwarding_udp']['external_port'] = test_ext_port
+ utils.wait_until_true(
+ fip_pf_udp_connectivity,
+ exception=RuntimeError(
+ "Connection to the server {!r} through "
+ "port {!r} is not possible.".format(
+ server[0]['id'],
+ server[0]['port_forwarding_udp']['external_port'])))
+
+ # Remove port forwarding and ensure connection stops working.
+ self.client.delete_port_forwarding(fip_id, pf_id)
+ self.assertRaises(lib_exc.NotFound, self.client.get_port_forwarding,
+ fip_id, pf_id)
+ utils.wait_until_true(
+ no_fip_pf_udp_connectivity,
+ exception=RuntimeError(
+ "Connection to the server {!r} through "
+ "port {!r} is still possible.".format(
+ server[0]['id'],
+ server[0]['port_forwarding_udp']['external_port'])))
+
+ @test.unstable_test("bug 1896735")
+ @decorators.idempotent_id('5971881d-06a0-459e-b636-ce5d1929e2d4')
+ def test_port_forwarding_to_2_fixed_ips(self):
+ port = self.create_port(self.network,
+ security_groups=[self.secgroup['id']])
+ name = data_utils.rand_name("server-0")
+ server = self.create_server(flavor_ref=CONF.compute.flavor_ref,
+ image_ref=CONF.compute.image_ref, key_name=self.keypair['name'],
+ name=name, networks=[{'port': port['id']}])['server']
+ server['name'] = name
+ self.wait_for_server_active(server)
+ self.wait_for_guest_os_ready(server)
+
+ # Add a second fixed_ip address to port (same subnet)
+ internal_subnet_id = port['fixed_ips'][0]['subnet_id']
+ port['fixed_ips'].append({'subnet_id': internal_subnet_id})
+ port = self.update_port(port, fixed_ips=port['fixed_ips'])
+ internal_ip_address1 = port['fixed_ips'][0]['ip_address']
+ internal_ip_address2 = port['fixed_ips'][1]['ip_address']
+ pfs = []
+ for ip_address, external_port in [(internal_ip_address1, 1066),
+ (internal_ip_address2, 1067)]:
+ pf = self.create_port_forwarding(
+ self.fip['id'], internal_port_id=port['id'],
+ internal_ip_address=ip_address,
+ internal_port=22, external_port=external_port,
+ protocol=constants.PROTO_NAME_TCP)
+ pfs.append(pf)
+
+ test_ssh_connect_timeout = 32
+ number_of_connects = 0
+ for pf in pfs:
+ try:
+ self.check_servers_hostnames(
+ [server], timeout=test_ssh_connect_timeout,
+ external_port=pf['external_port'])
+ number_of_connects += 1
+ except (AssertionError, lib_exc.SSHTimeout):
+ pass
+
+ # TODO(flaviof): Quite possibly, the server is using only one of the
+ # fixed ips associated with the neutron port. Being so, we should not
+ # fail the test, as long as at least one connection was successful.
+ self.assertGreaterEqual(
+ number_of_connects, 1, "Did not connect via FIP port forwarding")
diff --git a/neutron_tempest_plugin/scenario/test_qos.py b/neutron_tempest_plugin/scenario/test_qos.py
index 938d2b0..77520a7 100644
--- a/neutron_tempest_plugin/scenario/test_qos.py
+++ b/neutron_tempest_plugin/scenario/test_qos.py
@@ -175,6 +175,7 @@
server = self.create_server(**server_kwargs)
self.wait_for_server_active(server['server'])
+ self.wait_for_guest_os_ready(server['server'])
self.check_connectivity(self.fip['floating_ip_address'],
CONF.validation.image_ssh_user,
keypair['private_key'])
@@ -190,32 +191,26 @@
@decorators.idempotent_id('00682a0c-b72e-11e8-b81e-8c16450ea513')
def test_qos_basic_and_update(self):
- """This test covers both:
+ """This test covers following scenarios:
- 1) Basic QoS functionality
- This is a basic test that check that a QoS policy with
- a bandwidth limit rule is applied correctly by sending
- a file from the instance to the test node.
- Then calculating the bandwidth every ~1 sec by the number of bits
- received / elapsed time.
+ 1) Create a QoS policy associated with the network.
+ Expected result: BW is limited according the values set in
+ QoS policy rule.
- 2) Update QoS policy
- Administrator has the ability to update existing QoS policy,
- this test is planned to verify that:
- - actual BW is affected as expected after updating QoS policy.
- Test scenario:
- 1) Associating QoS Policy with "Original_bandwidth"
- to the test node
- 2) BW validation - by downloading file on test node.
- ("Original_bandwidth" is expected)
- 3) Updating existing QoS Policy to a new BW value
- "Updated_bandwidth"
- 4) BW validation - by downloading file on test node.
- ("Updated_bandwidth" is expected)
- Note:
- There are two options to associate QoS policy to VM:
- "Neutron Port" or "Network", in this test
- both options are covered.
+ 2) Update QoS policy associated with the network.
+ Expected result: BW is limited according the new values
+ set in QoS policy rule.
+
+ 3) Create a new QoS policy associated with the VM port.
+ Expected result: BW is limited according the values set in
+ new QoS policy rule.
+ Note: Neutron port is prioritized higher than Network, means
+ that: "Neutron Port Priority" is also covered.
+
+ 4) Update QoS policy associated with the VM port.
+ Expected result: BW is limited according the new values set
+ in QoS policy rule.
+
"""
# Setup resources
@@ -243,7 +238,10 @@
self.fip['floating_ip_address'],
port=self.NC_PORT),
timeout=self.CHECK_TIMEOUT,
- sleep=1)
+ sleep=1,
+ exception=RuntimeError(
+ 'Failed scenario: "Create a QoS policy associated with'
+ ' the network" Actual BW is not as expected!'))
# As admin user update QoS rule
self.os_admin.network_client.update_bandwidth_limit_rule(
@@ -260,7 +258,10 @@
port=self.NC_PORT,
expected_bw=QoSTest.LIMIT_BYTES_SEC * 2),
timeout=self.CHECK_TIMEOUT,
- sleep=1)
+ sleep=1,
+ exception=RuntimeError(
+ 'Failed scenario: "Update QoS policy associated with'
+ ' the network" Actual BW is not as expected!'))
# Create a new QoS policy
bw_limit_policy_id_new = self._create_qos_policy()
@@ -283,7 +284,10 @@
self.fip['floating_ip_address'],
port=self.NC_PORT),
timeout=self.CHECK_TIMEOUT,
- sleep=1)
+ sleep=1,
+ exception=RuntimeError(
+ 'Failed scenario: "Create a new QoS policy associated with'
+ ' the VM port" Actual BW is not as expected!'))
# As admin user update QoS rule
self.os_admin.network_client.update_bandwidth_limit_rule(
@@ -300,7 +304,10 @@
port=self.NC_PORT,
expected_bw=QoSTest.LIMIT_BYTES_SEC * 3),
timeout=self.CHECK_TIMEOUT,
- sleep=1)
+ sleep=1,
+ exception=RuntimeError(
+ 'Failed scenario: "Update QoS policy associated with'
+ ' the VM port" Actual BW is not as expected!'))
@decorators.idempotent_id('66e5673e-0522-11ea-8d71-362b9e155667')
def test_attach_previously_used_port_to_new_instance(self):
diff --git a/neutron_tempest_plugin/scenario/test_security_groups.py b/neutron_tempest_plugin/scenario/test_security_groups.py
index 23a5224..9059a2f 100644
--- a/neutron_tempest_plugin/scenario/test_security_groups.py
+++ b/neutron_tempest_plugin/scenario/test_security_groups.py
@@ -33,13 +33,15 @@
required_extensions = ['router', 'security-group']
def _verify_http_connection(self, ssh_client, ssh_server,
- test_ip, test_port, should_pass=True):
+ test_ip, test_port, servers, should_pass=True):
"""Verify if HTTP connection works using remote hosts.
:param ssh.Client ssh_client: The client host active SSH client.
:param ssh.Client ssh_server: The HTTP server host active SSH client.
:param string test_ip: IP address of HTTP server
:param string test_port: Port of HTTP server
+ :param list servers: List of servers for which console output will be
+ logged in case when test case
:param bool should_pass: Wheter test should pass or not.
:return: if passed or not
@@ -57,6 +59,8 @@
except Exception as e:
if not should_pass:
return
+ self._log_console_output(servers)
+ self._log_local_network_status()
raise e
@classmethod
@@ -378,6 +382,7 @@
ssh_clients[0],
ssh_clients[2],
test_ip, port,
+ servers,
should_pass=False)
# add two remote-group rules with port-ranges
@@ -399,7 +404,8 @@
self._verify_http_connection(
ssh_clients[0],
ssh_clients[2],
- test_ip, port)
+ test_ip, port,
+ servers)
@decorators.idempotent_id('f07d0159-8f9e-4faa-87f5-a869ab0ad490')
def test_intra_sg_isolation(self):
diff --git a/neutron_tempest_plugin/scenario/test_trunk.py b/neutron_tempest_plugin/scenario/test_trunk.py
index 585af06..8f260ea 100644
--- a/neutron_tempest_plugin/scenario/test_trunk.py
+++ b/neutron_tempest_plugin/scenario/test_trunk.py
@@ -15,6 +15,7 @@
import collections
from neutron_lib import constants
+from neutron_lib.utils import test
from oslo_log import log as logging
from tempest.common import utils as tutils
from tempest.lib.common.utils import data_utils
@@ -161,6 +162,7 @@
def _configure_vlan_subport(self, vm, vlan_tag, vlan_subnet):
self.wait_for_server_active(server=vm.server)
+ self.wait_for_guest_os_ready(vm.server)
self._wait_for_trunk(trunk=vm.trunk)
self._wait_for_port(port=vm.port)
self._wait_for_port(port=vm.subport)
@@ -199,6 +201,7 @@
vm2 = self._create_server_with_trunk_port()
for vm in (vm1, vm2):
self.wait_for_server_active(server=vm.server)
+ self.wait_for_guest_os_ready(vm.server)
self._wait_for_trunk(vm.trunk)
self._assert_has_ssh_connectivity(vm.ssh_client)
@@ -244,6 +247,7 @@
self._wait_for_trunk(vm.trunk)
self._assert_has_ssh_connectivity(vm1.ssh_client)
+ @test.unstable_test("bug 1897796")
@testtools.skipUnless(
(CONF.neutron_plugin_options.advanced_image_ref or
CONF.neutron_plugin_options.default_image_is_advanced),
@@ -267,6 +271,9 @@
use_advanced_image=use_advanced_image)
for vm in [vm1, vm2]:
+ self.check_connectivity(
+ host=vm.floating_ip['floating_ip_address'],
+ ssh_client=vm.ssh_client)
self._configure_vlan_subport(vm=vm,
vlan_tag=vlan_tag,
vlan_subnet=vlan_subnet)
@@ -325,6 +332,7 @@
use_advanced_image=use_advanced_image)
for role in ['migrate', 'connection_test']:
self.wait_for_server_active(servers[role].server)
+ self.wait_for_guest_os_ready(servers[role].server)
self._configure_vlan_subport(vm=servers[role],
vlan_tag=vlan_tag,
vlan_subnet=vlan_subnet)
@@ -377,6 +385,7 @@
vlan_subnet=vlan_subnet)
for vm in vms:
self.wait_for_server_active(vm.server)
+ self.wait_for_guest_os_ready(vm.server)
# allow ICMP traffic
sg_rule = self.create_pingable_secgroup_rule(self.security_group['id'])
diff --git a/neutron_tempest_plugin/services/bgp/bgp_client.py b/neutron_tempest_plugin/services/bgp/bgp_client.py
index ae51427..7d46e29 100644
--- a/neutron_tempest_plugin/services/bgp/bgp_client.py
+++ b/neutron_tempest_plugin/services/bgp/bgp_client.py
@@ -15,6 +15,25 @@
from oslo_serialization import jsonutils
from tempest.lib.common import rest_client
+from neutron_tempest_plugin.api import clients as manager
+from neutron_tempest_plugin import config
+
+
+CONF = config.CONF
+
+
+class Manager(manager.Manager):
+ def __init__(self, credentials=None, service=None):
+ super(Manager, self).__init__(credentials, service)
+ self.bgp_client = BgpSpeakerClientJSON(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
+
class BgpSpeakerClientJSON(rest_client.RestClient):
diff --git a/neutron_tempest_plugin/services/network/json/network_client.py b/neutron_tempest_plugin/services/network/json/network_client.py
index f056c7f..2678d73 100644
--- a/neutron_tempest_plugin/services/network/json/network_client.py
+++ b/neutron_tempest_plugin/services/network/json/network_client.py
@@ -11,9 +11,9 @@
# under the License.
import time
+from urllib import parse as urlparse
from oslo_serialization import jsonutils
-from six.moves.urllib import parse as urlparse
from tempest.lib.common import rest_client as service_client
from tempest.lib import exceptions as lib_exc
@@ -923,8 +923,6 @@
return service_client.ResponseBody(resp, body)
def list_security_groups(self, **kwargs):
- post_body = {'security_groups': kwargs}
- body = jsonutils.dumps(post_body)
uri = '%s/security-groups' % self.uri_prefix
if kwargs:
uri += '?' + urlparse.urlencode(kwargs, doseq=1)
@@ -941,8 +939,6 @@
return service_client.ResponseBody(resp, body)
def list_ports(self, **kwargs):
- post_body = {'ports': kwargs}
- body = jsonutils.dumps(post_body)
uri = '%s/ports' % self.uri_prefix
if kwargs:
uri += '?' + urlparse.urlencode(kwargs, doseq=1)
@@ -952,8 +948,6 @@
return service_client.ResponseBody(resp, body)
def list_floatingips(self, **kwargs):
- post_body = {'floatingips': kwargs}
- body = jsonutils.dumps(post_body)
uri = '%s/floatingips' % self.uri_prefix
if kwargs:
uri += '?' + urlparse.urlencode(kwargs, doseq=1)
diff --git a/neutron_tempest_plugin/sfc/tests/scenario/test_sfc.py b/neutron_tempest_plugin/sfc/tests/scenario/test_sfc.py
index 995868a..2f091e0 100644
--- a/neutron_tempest_plugin/sfc/tests/scenario/test_sfc.py
+++ b/neutron_tempest_plugin/sfc/tests/scenario/test_sfc.py
@@ -14,6 +14,7 @@
import time
+from neutron_lib.utils import test
from oslo_log import log
from tempest.common import utils
from tempest import config
@@ -953,6 +954,7 @@
username=self.ssh_user,
private_key=self.keypair['private_key'])
+ @test.unstable_test("bug 1897753")
@decorators.idempotent_id('f970f6b3-6541-47ac-a9ea-f769be1e21ba')
@utils.services('compute', 'network')
def test_update_port_pair_group_remove_port_pairs(self):
diff --git a/playbooks/linuxbridge-scenario-pre-run.yaml b/playbooks/linuxbridge-scenario-pre-run.yaml
new file mode 100644
index 0000000..26586f6
--- /dev/null
+++ b/playbooks/linuxbridge-scenario-pre-run.yaml
@@ -0,0 +1,7 @@
+- hosts: all
+ tasks:
+ # TODO(slaweq): remove it when nftables will support syntax for src and
+ # destination IP addresses in arp tables:
+ - include_role:
+ name: legacy_ebtables
+ when: ansible_distribution_release | lower == 'focal'
diff --git a/requirements.txt b/requirements.txt
index 3edf7dc..47dd923 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,6 @@
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
paramiko>=2.0.0 # LGPLv2.1+
-six>=1.10.0 # MIT
tempest>=17.1.0 # Apache-2.0
tenacity>=3.2.1 # Apache-2.0
ddt>=1.0.1 # MIT
diff --git a/test-requirements.txt b/test-requirements.txt
index 6cbe947..bf1c626 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-hacking<0.13,>=0.12.0 # Apache-2.0
+hacking>=3.2.0,<3.3.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0
flake8-import-order==0.12 # LGPLv3
diff --git a/tox.ini b/tox.ini
index 760cc47..3c18fbf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,7 +14,7 @@
OS_STDOUT_CAPTURE={env:OS_STDOUT_CAPTURE:true}
OS_STDERR_CAPTURE={env:OS_STDERR_CAPTURE:true}
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/test-requirements.txt
commands = stestr run --slowest {posargs}
@@ -53,7 +53,8 @@
# E128 continuation line under-indented for visual indent
# E129 visually indented line with same indent as next logical line
# N530 direct neutron imports not allowed
-ignore = E126,E128,E129,N530
+# W504 line break after binary operator
+ignore = E126,E128,E129,N530,W504
# H106: Don't put vim configuration in source files
# H203: Use assertIs(Not)None to check for None
# H204: Use assert(Not)Equal to check for equality
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index db59ac0..cc1479b 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -17,13 +17,14 @@
devstack_localrc:
USE_PYTHON3: true
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
+ CIRROS_VERSION: 0.5.1
+ BUILD_TIMEOUT: 784
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
tempest: true
neutron-dns: true
neutron-qos: true
@@ -36,6 +37,17 @@
neutron-tag-ports-during-bulk-creation: true
br-ex-tcpdump: true
br-int-flows: true
+ # Cinder services
+ c-api: false
+ c-bak: false
+ c-sch: false
+ c-vol: false
+ cinder: false
+ # We don't need Swift to be run in the Neutron jobs
+ s-account: false
+ s-container: false
+ s-object: false
+ s-proxy: false
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -62,11 +74,6 @@
$NEUTRON_DHCP_CONF:
agent:
availability_zone: nova
- /etc/neutron/api-paste.ini:
- composite:neutronapi_v2_0:
- use: call:neutron.auth:pipeline_factory
- noauth: cors request_id catch_errors osprofiler extensions neutronapiapp_v2_0
- keystone: cors request_id catch_errors osprofiler authtoken keystonecontext extensions neutronapiapp_v2_0
test-config:
$TEMPEST_CONFIG:
neutron_plugin_options:
@@ -97,14 +104,16 @@
# default test timeout set to 1200 seconds may be not enough if job is
# run on slow node
tempest_test_timeout: 2400
- tempest_test_regex: ^neutron_tempest_plugin\.scenario
+ tempest_test_regex: "\
+ (^neutron_tempest_plugin.scenario)|\
+ (^tempest.api.compute.servers.test_attach_interfaces)|\
+ (^tempest.api.compute.servers.test_multiple_create)"
devstack_localrc:
PHYSICAL_NETWORK: default
- IMAGE_URLS: https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
- ADVANCED_IMAGE_NAME: ubuntu-16.04-server-cloudimg-amd64-disk1
+ 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_USER: ubuntu
BUILD_TIMEOUT: 784
- devstack_services:
- cinder: true
-
+ tempest_concurrency: 3 # out of 4
diff --git a/zuul.d/master_jobs.yaml b/zuul.d/master_jobs.yaml
index 45862c8..5325f67 100644
--- a/zuul.d/master_jobs.yaml
+++ b/zuul.d/master_jobs.yaml
@@ -79,9 +79,13 @@
- uplink-status-propagation
network_api_extensions_tempest:
- dvr
+ network_available_features: &available_features
+ - ipv6_metadata
tempest_test_regex: ^neutron_tempest_plugin\.api
devstack_services:
neutron-log: true
+ devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: true
devstack_local_conf:
post-config:
# NOTE(slaweq): We can get rid of this hardcoded absolute path when
@@ -99,6 +103,7 @@
timeout: 10000
vars:
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
Q_AGENT: openvswitch
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
@@ -118,6 +123,8 @@
bridge_mappings: public:br-ex
test-config:
$TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
neutron_plugin_options:
available_type_drivers: flat,vlan,local,vxlan
@@ -127,6 +134,7 @@
timeout: 10000
vars:
network_api_extensions: *api_extensions
+ network_available_features: *available_features
# TODO(slaweq): remove trunks subport_connectivity test from blacklist
# when bug https://bugs.launchpad.net/neutron/+bug/1838760 will be fixed
tempest_black_regex: "(^neutron_tempest_plugin.scenario.test_trunk.TrunkTest.test_subport_connectivity)"
@@ -151,6 +159,8 @@
firewall_driver: iptables_hybrid
test-config:
$TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
neutron_plugin_options:
available_type_drivers: flat,vlan,local,vxlan
@@ -158,8 +168,12 @@
name: neutron-tempest-plugin-scenario-linuxbridge
parent: neutron-tempest-plugin-scenario
timeout: 10000
+ roles:
+ - zuul: openstack/neutron
+ pre-run: playbooks/linuxbridge-scenario-pre-run.yaml
vars:
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
@@ -178,6 +192,8 @@
type_drivers: flat,vlan,local,vxlan
test-config:
$TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
neutron_plugin_options:
available_type_drivers: flat,vlan,local,vxlan
q_agent: linuxbridge
@@ -188,9 +204,17 @@
timeout: 10000
vars:
network_api_extensions: *api_extensions
- # TODO(haleyb): Remove this blacklist when
+ # TODO(haleyb): Remove IPv6Test from blacklist when
# https://bugs.launchpad.net/neutron/+bug/1881558 is fixed.
- tempest_black_regex: "(?:neutron_tempest_plugin.scenario.test_ipv6.IPv6Test)"
+ # TODO(slaweq): Remove test_trunk_subport_lifecycle test from the
+ # blacklist when bug https://bugs.launchpad.net/neutron/+bug/1885900 will
+ # be fixed
+ # TODO(jlibosva): Remove the NetworkWritableMtuTest test from the list
+ # once east/west fragmentation is supported in core OVN
+ tempest_black_regex: "\
+ (?:neutron_tempest_plugin.scenario.test_ipv6.IPv6Test)|\
+ (^neutron_tempest_plugin.scenario.test_trunk.TrunkTest.test_trunk_subport_lifecycle)|\
+ (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
devstack_localrc:
Q_AGENT: ovn
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
@@ -202,10 +226,6 @@
ENABLE_CHASSIS_AS_GW: true
OVN_L3_CREATE_PUBLIC_NETWORK: true
OVN_DBS_LOG_LEVEL: dbg
- # TODO(mjozefcz): Stop compiling OVS modules when meter action in kernel
- # will be released in Ubuntu Bionic.
- # More info: https://mail.openvswitch.org/pipermail/ovs-discuss/2018-December/048009.html
- OVN_BUILD_MODULES: True
ENABLE_TLS: True
OVN_IGMP_SNOOPING_ENABLE: True
devstack_services:
@@ -221,13 +241,19 @@
q-l3: false
q-meta: false
q-metering: false
+ q-qos: true
+ tls-proxy: true
+ # Cinder services
+ c-api: false
+ c-bak: false
+ c-sch: false
+ c-vol: false
+ cinder: false
s-account: false
s-container-sync: false
s-container: false
s-object: false
s-proxy: false
- tls-proxy: true
- q-qos: true
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -238,6 +264,8 @@
type_drivers: local,flat,vlan,geneve
test-config:
$TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
neutron_plugin_options:
available_type_drivers: local,flat,vlan,geneve
is_igmp_snooping_enabled: True
@@ -271,8 +299,9 @@
USE_PYTHON3: true
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_dvr) | join(',') }}"
PHYSICAL_NETWORK: default
- IMAGE_URLS: https://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
- ADVANCED_IMAGE_NAME: ubuntu-16.04-server-cloudimg-amd64-disk1
+ 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_USER: ubuntu
BUILD_TIMEOUT: 784
@@ -290,7 +319,17 @@
neutron-trunk: true
neutron-log: true
neutron-port-forwarding: true
- cinder: true
+ # Cinder services
+ c-api: false
+ c-bak: false
+ c-sch: false
+ c-vol: false
+ cinder: false
+ # We don't need Swift to be run in the Neutron jobs
+ s-account: false
+ s-container: false
+ s-object: false
+ s-proxy: false
devstack_local_conf:
post-config:
$NEUTRON_CONF:
@@ -336,6 +375,8 @@
keystone: "cors request_id catch_errors osprofiler authtoken keystonecontext extensions neutronapiapp_v2_0"
test-config:
$TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: *available_features
neutron_plugin_options:
provider_vlans: foo,
agent_availability_zone: nova
@@ -353,6 +394,14 @@
neutron-trunk: true
neutron-log: true
neutron-port-forwarding: true
+ # Cinder services
+ c-bak: false
+ c-vol: false
+ # We don't need Swift to be run in the Neutron jobs
+ s-account: false
+ s-container: false
+ s-object: false
+ s-proxy: false
devstack_localrc:
USE_PYTHON3: true
devstack_local_conf:
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 3086d6c..dc6e56c 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -3,7 +3,11 @@
check:
jobs:
- neutron-tempest-plugin-api
- - neutron-tempest-plugin-designate-scenario
+ - neutron-tempest-plugin-designate-scenario:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
- neutron-tempest-plugin-scenario-linuxbridge
- neutron-tempest-plugin-scenario-openvswitch
- neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
@@ -27,7 +31,6 @@
check:
jobs:
- neutron-tempest-plugin-api-queens
- - neutron-tempest-plugin-dvr-multinode-scenario-queens
- neutron-tempest-plugin-scenario-linuxbridge-queens
- neutron-tempest-plugin-scenario-openvswitch-queens
gate:
@@ -45,7 +48,11 @@
check:
jobs:
- neutron-tempest-plugin-api-rocky
- - neutron-tempest-plugin-designate-scenario-rocky
+ - neutron-tempest-plugin-designate-scenario-rocky:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
- neutron-tempest-plugin-scenario-linuxbridge-rocky
- neutron-tempest-plugin-scenario-openvswitch-rocky
- neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-rocky
@@ -64,7 +71,11 @@
check:
jobs:
- neutron-tempest-plugin-api-stein
- - neutron-tempest-plugin-designate-scenario-stein
+ - neutron-tempest-plugin-designate-scenario-stein:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
- neutron-tempest-plugin-scenario-linuxbridge-stein
- neutron-tempest-plugin-scenario-openvswitch-stein
- neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-stein
@@ -83,7 +94,11 @@
check:
jobs:
- neutron-tempest-plugin-api-train
- - neutron-tempest-plugin-designate-scenario-train
+ - neutron-tempest-plugin-designate-scenario-train:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
- neutron-tempest-plugin-scenario-linuxbridge-train
- neutron-tempest-plugin-scenario-openvswitch-train
- neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-train
@@ -102,7 +117,11 @@
check:
jobs:
- neutron-tempest-plugin-api-ussuri
- - neutron-tempest-plugin-designate-scenario-ussuri
+ - neutron-tempest-plugin-designate-scenario-ussuri:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
- neutron-tempest-plugin-scenario-linuxbridge-ussuri
- neutron-tempest-plugin-scenario-openvswitch-ussuri
- neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-ussuri
@@ -117,6 +136,30 @@
- neutron-tempest-plugin-dvr-multinode-scenario-ussuri
+- project-template:
+ name: neutron-tempest-plugin-jobs-victoria
+ check:
+ jobs:
+ - neutron-tempest-plugin-api-victoria
+ - neutron-tempest-plugin-designate-scenario-victoria:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1891309
+ # will be fixed
+ voting: false
+ - neutron-tempest-plugin-scenario-linuxbridge-victoria
+ - neutron-tempest-plugin-scenario-openvswitch-victoria
+ - neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-victoria
+ - neutron-tempest-plugin-scenario-ovn-victoria
+ gate:
+ jobs:
+ - neutron-tempest-plugin-api-victoria
+ #TODO(slaweq): Move neutron-tempest-plugin-dvr-multinode-scenario out of
+ # the experimental queue when it will be more stable
+ experimental:
+ jobs:
+ - neutron-tempest-plugin-dvr-multinode-scenario-victoria
+
+
- project:
templates:
- build-openstack-docs-pti
@@ -124,6 +167,7 @@
- neutron-tempest-plugin-jobs-stein
- neutron-tempest-plugin-jobs-train
- neutron-tempest-plugin-jobs-ussuri
+ - neutron-tempest-plugin-jobs-victoria
- check-requirements
- tempest-plugin-jobs
- release-notes-jobs-python3
@@ -132,9 +176,11 @@
- neutron-tempest-plugin-sfc
- neutron-tempest-plugin-sfc-train
- neutron-tempest-plugin-sfc-ussuri
+ - neutron-tempest-plugin-sfc-victoria
- neutron-tempest-plugin-bgpvpn-bagpipe
- neutron-tempest-plugin-bgpvpn-bagpipe-train
- neutron-tempest-plugin-bgpvpn-bagpipe-ussuri
+ - neutron-tempest-plugin-bgpvpn-bagpipe-victoria
- neutron-tempest-plugin-fwaas-train:
# TODO(slaweq): switch it to be voting when bug
# https://bugs.launchpad.net/neutron/+bug/1858645 will be fixed
@@ -145,8 +191,10 @@
voting: false
- neutron-tempest-plugin-dynamic-routing
- neutron-tempest-plugin-dynamic-routing-ussuri
+ - neutron-tempest-plugin-dynamic-routing-victoria
- neutron-tempest-plugin-vpnaas
- neutron-tempest-plugin-vpnaas-ussuri
+ - neutron-tempest-plugin-vpnaas-victoria
gate:
jobs:
diff --git a/zuul.d/queens_jobs.yaml b/zuul.d/queens_jobs.yaml
index 2b52978..e1ecc00 100644
--- a/zuul.d/queens_jobs.yaml
+++ b/zuul.d/queens_jobs.yaml
@@ -65,8 +65,12 @@
- trunk-details
network_api_extensions_tempest:
- dvr
+ network_available_features: &available_features
+ -
devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
USE_PYTHON3: false
+ CIRROS_VERSION: 0.3.5
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
@@ -86,6 +90,7 @@
vars:
branch_override: stable/queens
network_api_extensions: *api_extensions
+ network_available_features: *available_features
# TODO(slaweq): remove trunks subport_connectivity test from blacklist
# when bug https://bugs.launchpad.net/neutron/+bug/1838760 will be fixed
# NOTE(bcafarel): remove DNS test as queens pinned version does not have
@@ -95,13 +100,17 @@
(^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
devstack_localrc:
USE_PYTHON3: false
+ CIRROS_VERSION: 0.3.5
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-queens
- parent: neutron-tempest-plugin-scenario-linuxbridge
+ parent: neutron-tempest-plugin-scenario
nodeset: openstack-single-node-xenial
+ timeout: 10000
+ roles:
+ - zuul: openstack/neutron
override-checkout: stable/queens
required-projects:
- openstack/devstack-gate
@@ -112,21 +121,37 @@
vars:
branch_override: stable/queens
network_api_extensions: *api_extensions
+ network_available_features: *available_features
# NOTE(bcafarel): remove DNS test as queens pinned version does not have
# fix for https://bugs.launchpad.net/neutron/+bug/1826419
tempest_black_regex: "\
(^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
devstack_localrc:
USE_PYTHON3: false
+ CIRROS_VERSION: 0.3.5
+ Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
devstack_local_conf:
+ post-config:
+ $NEUTRON_CONF:
+ DEFAULT:
+ enable_dvr: false
+ AGENT:
+ debug_iptables_rules: true
+ # NOTE(slaweq): We can get rid of this hardcoded absolute path when
+ # devstack-tempest job will be switched to use lib/neutron instead of
+ # lib/neutron-legacy
+ /$NEUTRON_CORE_PLUGIN_CONF:
+ ml2:
+ type_drivers: flat,vlan,local,vxlan
test-config:
# NOTE: ignores linux bridge's trunk delete on bound port test
- # for queens branch (as https://review.opendev.org/#/c/605589/
- # fix will not apply for queens branch)
+ # for rocky branch (as https://review.opendev.org/#/c/605589/
+ # fix will not apply for rocky branch)
$TEMPEST_CONFIG:
neutron_plugin_options:
+ available_type_drivers: flat,vlan,local,vxlan
q_agent: None
- job:
@@ -152,6 +177,7 @@
(^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
devstack_localrc:
USE_PYTHON3: false
+ CIRROS_VERSION: 0.3.5
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
- job:
@@ -176,4 +202,5 @@
(^neutron_tempest_plugin.scenario.test_internal_dns.InternalDNSTest.test_dns_domain_and_name)"
devstack_localrc:
USE_PYTHON3: false
+ CIRROS_VERSION: 0.3.5
TEMPEST_PLUGINS: '"/opt/stack/designate-tempest-plugin /opt/stack/neutron-tempest-plugin"'
diff --git a/zuul.d/rocky_jobs.yaml b/zuul.d/rocky_jobs.yaml
index a45cae8..4b6145b 100644
--- a/zuul.d/rocky_jobs.yaml
+++ b/zuul.d/rocky_jobs.yaml
@@ -75,6 +75,7 @@
network_api_extensions_tempest:
- dvr
devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
USE_PYTHON3: false
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
@@ -108,6 +109,8 @@
vars: &scenario_vars_rocky
branch_override: stable/rocky
network_api_extensions: *api_extensions
+ network_available_features: &available_features
+ -
devstack_localrc:
USE_PYTHON3: false
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
@@ -176,10 +179,13 @@
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-rocky
- parent: neutron-tempest-plugin-scenario-linuxbridge
+ parent: neutron-tempest-plugin-scenario
+ timeout: 10000
description: |
This job run on py2 for stable/rocky gate.
nodeset: openstack-single-node-xenial
+ roles:
+ - zuul: openstack/neutron
override-checkout: stable/rocky
required-projects: *required-projects-rocky
vars: &linuxbridge_vars_rocky
@@ -187,15 +193,29 @@
network_api_extensions: *api_extensions
devstack_localrc:
USE_PYTHON3: false
+ Q_AGENT: linuxbridge
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
devstack_local_conf:
+ post-config:
+ $NEUTRON_CONF:
+ DEFAULT:
+ enable_dvr: false
+ AGENT:
+ debug_iptables_rules: true
+ # NOTE(slaweq): We can get rid of this hardcoded absolute path when
+ # devstack-tempest job will be switched to use lib/neutron instead of
+ # lib/neutron-legacy
+ /$NEUTRON_CORE_PLUGIN_CONF:
+ ml2:
+ type_drivers: flat,vlan,local,vxlan
test-config:
# NOTE: ignores linux bridge's trunk delete on bound port test
# for rocky branch (as https://review.opendev.org/#/c/605589/
# fix will not apply for rocky branch)
$TEMPEST_CONFIG:
neutron_plugin_options:
+ available_type_drivers: flat,vlan,local,vxlan
q_agent: None
# NOTE(bcafarel): newer tests, unstable on rocky branch
tempest_black_regex: "\
@@ -206,17 +226,23 @@
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-rocky
- parent: neutron-tempest-plugin-scenario-linuxbridge
+ parent: neutron-tempest-plugin-scenario
nodeset: openstack-single-node-xenial
+ timeout: 10000
description: |
This job run on py3 for other than stable/rocky gate
which is nothing but neutron-tempest-pluign master gate.
+ roles:
+ - zuul: openstack/neutron
override-checkout: stable/rocky
required-projects: *required-projects-rocky
vars:
<<: *linuxbridge_vars_rocky
devstack_localrc:
USE_PYTHON3: True
+ Q_AGENT: linuxbridge
+ NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ TEMPEST_PLUGINS: /opt/stack/neutron-tempest-plugin
branches: ^(?!stable/rocky).*$
- job:
diff --git a/zuul.d/stein_jobs.yaml b/zuul.d/stein_jobs.yaml
index 1c9e299..9de8384 100644
--- a/zuul.d/stein_jobs.yaml
+++ b/zuul.d/stein_jobs.yaml
@@ -1,6 +1,7 @@
- job:
name: neutron-tempest-plugin-api-stein
parent: neutron-tempest-plugin-api
+ nodeset: openstack-single-node-bionic
override-checkout: stable/stein
vars:
branch_override: stable/stein
@@ -72,42 +73,73 @@
- uplink-status-propagation
network_api_extensions_tempest:
- dvr
+ network_available_features: &available_features
+ -
devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
- job:
name: neutron-tempest-plugin-scenario-openvswitch-stein
parent: neutron-tempest-plugin-scenario-openvswitch
+ nodeset: openstack-single-node-bionic
override-checkout: stable/stein
vars:
branch_override: stable/stein
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-stein
parent: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
+ nodeset: openstack-single-node-bionic
override-checkout: stable/stein
vars:
branch_override: stable/stein
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-stein
parent: neutron-tempest-plugin-scenario-linuxbridge
+ nodeset: openstack-single-node-bionic
override-checkout: stable/stein
vars:
branch_override: stable/stein
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-dvr-multinode-scenario-stein
parent: neutron-tempest-plugin-dvr-multinode-scenario
+ nodeset: openstack-two-node-bionic
override-checkout: stable/stein
vars:
network_api_extensions_common: *api_extensions
@@ -116,6 +148,7 @@
- job:
name: neutron-tempest-plugin-designate-scenario-stein
parent: neutron-tempest-plugin-designate-scenario
+ nodeset: openstack-single-node-bionic
override-checkout: stable/stein
required-projects:
- openstack/devstack-gate
diff --git a/zuul.d/train_jobs.yaml b/zuul.d/train_jobs.yaml
index 132873b..0785924 100644
--- a/zuul.d/train_jobs.yaml
+++ b/zuul.d/train_jobs.yaml
@@ -1,6 +1,7 @@
- job:
name: neutron-tempest-plugin-api-train
parent: neutron-tempest-plugin-api
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
@@ -77,42 +78,73 @@
- uplink-status-propagation
network_api_extensions_tempest:
- dvr
+ network_available_features: &available_features
+ -
devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
- job:
name: neutron-tempest-plugin-scenario-openvswitch-train
parent: neutron-tempest-plugin-scenario-openvswitch
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-train
parent: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-train
parent: neutron-tempest-plugin-scenario-linuxbridge
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-dvr-multinode-scenario-train
parent: neutron-tempest-plugin-dvr-multinode-scenario
+ nodeset: openstack-two-node-bionic
override-checkout: stable/train
vars:
network_api_extensions_common: *api_extensions
@@ -121,6 +153,7 @@
- job:
name: neutron-tempest-plugin-designate-scenario-train
parent: neutron-tempest-plugin-designate-scenario
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
@@ -129,6 +162,7 @@
- job:
name: neutron-tempest-plugin-sfc-train
parent: neutron-tempest-plugin-sfc
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
@@ -137,6 +171,7 @@
- job:
name: neutron-tempest-plugin-bgpvpn-bagpipe-train
parent: neutron-tempest-plugin-bgpvpn-bagpipe
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
@@ -145,6 +180,7 @@
- job:
name: neutron-tempest-plugin-fwaas-train
parent: neutron-tempest-plugin-fwaas-ussuri
+ nodeset: openstack-single-node-bionic
override-checkout: stable/train
vars:
branch_override: stable/train
diff --git a/zuul.d/ussuri_jobs.yaml b/zuul.d/ussuri_jobs.yaml
index a9e578e..b71a460 100644
--- a/zuul.d/ussuri_jobs.yaml
+++ b/zuul.d/ussuri_jobs.yaml
@@ -1,6 +1,7 @@
- job:
name: neutron-tempest-plugin-api-ussuri
parent: neutron-tempest-plugin-api
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
@@ -81,52 +82,92 @@
- uplink-status-propagation
network_api_extensions_tempest:
- dvr
+ network_available_features: &available_features
+ -
devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
+
- job:
name: neutron-tempest-plugin-scenario-openvswitch-ussuri
parent: neutron-tempest-plugin-scenario-openvswitch
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
+
- job:
name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-ussuri
parent: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-linuxbridge-ussuri
parent: neutron-tempest-plugin-scenario-linuxbridge
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
network_api_extensions: *api_extensions
+ network_available_features: *available_features
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+ neutron_plugin_options:
+ ipv6_metadata: False
- job:
name: neutron-tempest-plugin-scenario-ovn-ussuri
parent: neutron-tempest-plugin-scenario-ovn
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
network_api_extensions: *api_extensions
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ # TODO(mjozefcz): Stop compiling OVS modules when meter action in kernel
+ # will be released in Ubuntu Bionic.
+ # More info: https://mail.openvswitch.org/pipermail/ovs-discuss/2018-December/048009.html
+ OVN_BUILD_MODULES: True
+ # TODO(skaplons): v2.13.1 is incompatible with kernel 4.15.0-118, sticking to commit hash until new v2.13 tag is created
+ OVS_BRANCH: 0047ca3a0290f1ef954f2c76b31477cf4b9755f5
- job:
name: neutron-tempest-plugin-dvr-multinode-scenario-ussuri
parent: neutron-tempest-plugin-dvr-multinode-scenario
+ nodeset: openstack-two-node-bionic
override-checkout: stable/ussuri
vars:
network_api_extensions_common: *api_extensions
@@ -135,6 +176,7 @@
- job:
name: neutron-tempest-plugin-designate-scenario-ussuri
parent: neutron-tempest-plugin-designate-scenario
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
@@ -143,6 +185,7 @@
- job:
name: neutron-tempest-plugin-sfc-ussuri
parent: neutron-tempest-plugin-sfc
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
@@ -151,6 +194,7 @@
- job:
name: neutron-tempest-plugin-bgpvpn-bagpipe-ussuri
parent: neutron-tempest-plugin-bgpvpn-bagpipe
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
@@ -159,6 +203,7 @@
- job:
name: neutron-tempest-plugin-fwaas-ussuri
parent: neutron-tempest-plugin-base
+ nodeset: openstack-single-node-bionic
timeout: 10800
override-checkout: stable/ussuri
required-projects:
@@ -182,6 +227,7 @@
- job:
name: neutron-tempest-plugin-dynamic-routing-ussuri
parent: neutron-tempest-plugin-dynamic-routing
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
@@ -190,6 +236,7 @@
- job:
name: neutron-tempest-plugin-vpnaas-ussuri
parent: neutron-tempest-plugin-vpnaas
+ nodeset: openstack-single-node-bionic
override-checkout: stable/ussuri
vars:
branch_override: stable/ussuri
diff --git a/zuul.d/victoria_jobs.yaml b/zuul.d/victoria_jobs.yaml
new file mode 100644
index 0000000..5543ea7
--- /dev/null
+++ b/zuul.d/victoria_jobs.yaml
@@ -0,0 +1,205 @@
+- job:
+ name: neutron-tempest-plugin-api-victoria
+ parent: neutron-tempest-plugin-api
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ # TODO(slaweq): find a way to put this list of extensions in
+ # neutron repository and keep it different per branch,
+ # then it could be removed from here
+ network_api_extensions_common: &api_extensions
+ - address-scope
+ - agent
+ - allowed-address-pairs
+ - auto-allocated-topology
+ - availability_zone
+ - binding
+ - default-subnetpools
+ - dhcp_agent_scheduler
+ - dns-domain-ports
+ - dns-integration
+ - empty-string-filtering
+ - expose-port-forwarding-in-fip
+ - expose-l3-conntrack-helper
+ - ext-gw-mode
+ - external-net
+ - extra_dhcp_opt
+ - extraroute
+ - extraroute-atomic
+ - filter-validation
+ - fip-port-details
+ - flavors
+ - floating-ip-port-forwarding
+ - floatingip-pools
+ - ip-substring-filtering
+ - l3-conntrack-helper
+ - l3-flavors
+ - l3-ha
+ - l3_agent_scheduler
+ - logging
+ - metering
+ - multi-provider
+ - net-mtu
+ - net-mtu-writable
+ - network-ip-availability
+ - network_availability_zone
+ - network-segment-range
+ - pagination
+ - port-resource-request
+ - port-mac-address-regenerate
+ - port-security
+ - port-security-groups-filtering
+ - project-id
+ - provider
+ - qos
+ - qos-bw-minimum-ingress
+ - qos-fip
+ - quotas
+ - quota_details
+ - rbac-address-scope
+ - rbac-policies
+ - rbac-security-groups
+ - rbac-subnetpool
+ - router
+ - router-admin-state-down-before-update
+ - router_availability_zone
+ - security-group
+ - segment
+ - service-type
+ - sorting
+ - standard-attr-description
+ - standard-attr-revisions
+ - standard-attr-segment
+ - standard-attr-tag
+ - standard-attr-timestamp
+ - subnet_allocation
+ - subnet-dns-publish-fixed-ip
+ - subnetpool-prefix-ops
+ - tag-ports-during-bulk-creation
+ - trunk
+ - trunk-details
+ - uplink-status-propagation
+ network_api_extensions_tempest:
+ - dvr
+ network_available_features: &available_features
+ - ipv6_metadata
+ devstack_localrc:
+ NEUTRON_DEPLOY_MOD_WSGI: false
+ NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
+
+- job:
+ name: neutron-tempest-plugin-scenario-openvswitch-victoria
+ parent: neutron-tempest-plugin-scenario-openvswitch
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions: *api_extensions
+ network_available_features: *available_features
+ devstack_localrc:
+ NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
+ neutron_plugin_options:
+ ipv6_metadata: False
+
+- job:
+ name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid-victoria
+ parent: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
+ override-checkout: stable-victoria
+ vars:
+ branch_override: stable-victoria
+ network_api_extensions: *api_extensions
+ network_available_features: *available_features
+ devstack_localrc:
+ NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
+ neutron_plugin_options:
+ ipv6_metadata: False
+
+- job:
+ name: neutron-tempest-plugin-scenario-linuxbridge-victoria
+ parent: neutron-tempest-plugin-scenario-linuxbridge
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions: *api_extensions
+ network_available_features: *available_features
+ devstack_localrc:
+ NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: "{{ network_available_features | join(',') }}"
+ neutron_plugin_options:
+ ipv6_metadata: False
+
+- job:
+ name: neutron-tempest-plugin-scenario-ovn-victoria
+ parent: neutron-tempest-plugin-scenario-ovn
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions: *api_extensions
+ devstack_localrc:
+ NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ network-feature-enabled:
+ available_features: ""
+
+- job:
+ name: neutron-tempest-plugin-dvr-multinode-scenario-victoria
+ parent: neutron-tempest-plugin-dvr-multinode-scenario
+ override-checkout: stable/victoria
+ vars:
+ network_api_extensions_common: *api_extensions
+ branch_override: stable/victoria
+
+- job:
+ name: neutron-tempest-plugin-designate-scenario-victoria
+ parent: neutron-tempest-plugin-designate-scenario
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions_common: *api_extensions
+
+- job:
+ name: neutron-tempest-plugin-sfc-victoria
+ parent: neutron-tempest-plugin-sfc
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions_common: *api_extensions
+
+- job:
+ name: neutron-tempest-plugin-bgpvpn-bagpipe-victoria
+ parent: neutron-tempest-plugin-bgpvpn-bagpipe
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions: *api_extensions
+
+- job:
+ name: neutron-tempest-plugin-dynamic-routing-victoria
+ parent: neutron-tempest-plugin-dynamic-routing
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions_common: *api_extensions
+
+- job:
+ name: neutron-tempest-plugin-vpnaas-victoria
+ parent: neutron-tempest-plugin-vpnaas
+ override-checkout: stable/victoria
+ vars:
+ branch_override: stable/victoria
+ network_api_extensions_common: *api_extensions