Merge "Remove nova-cells-v1 job from experimental queue"
diff --git a/HACKING.rst b/HACKING.rst
index 1559fc6..204b3c7 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -457,7 +457,7 @@
by modifying Tempest's `lib installation script`_ for previous branches
(because DevStack is branched).
-.. _lib installation script: https://git.openstack.org/cgit/openstack-dev/devstack/tree/lib/tempest
+.. _lib installation script: https://opendev.org/openstack/devstack/src/branch/master/lib/tempest
2. Bug fix on core project needing Tempest changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/README.rst b/README.rst
index 73930f1..e8206ee 100644
--- a/README.rst
+++ b/README.rst
@@ -61,7 +61,7 @@
#. You first need to install Tempest. This is done with pip after you check out
the Tempest repo::
- $ git clone https://git.openstack.org/openstack/tempest
+ $ git clone https://opendev.org/openstack/tempest
$ pip install tempest/
This can be done within a venv, but the assumption for this guide is that
diff --git a/REVIEWING.rst b/REVIEWING.rst
index 31fedce..498ce66 100644
--- a/REVIEWING.rst
+++ b/REVIEWING.rst
@@ -187,4 +187,4 @@
Note that such a policy should be used judiciously, as we should strive to
have two +2's on each patch set, prior to approval.
-.. _example: https://review.openstack.org/#/c/611032/
+.. _example: https://review.opendev.org/#/c/611032/
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 4b1c145..b4f06e3 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -406,6 +406,14 @@
.. _2.63: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id57
+ * `2.70`_
+
+ .. _2.70: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id63
+
+ * `2.71`_
+
+ .. _2.71: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id64
+
* Volume
* `3.3`_
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index dc0e94c..a9e2059 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -43,7 +43,7 @@
In order to create the basic structure with base classes and test directories
you can use the tempest-plugin-cookiecutter project::
- > pip install -U cookiecutter && cookiecutter https://git.openstack.org/openstack/tempest-plugin-cookiecutter
+ > pip install -U cookiecutter && cookiecutter https://opendev.org/openstack/tempest-plugin-cookiecutter
Cloning into 'tempest-plugin-cookiecutter'...
remote: Counting objects: 17, done.
diff --git a/releasenotes/notes/correct-port-profile-config-option-d67f5cb31f1bc34c.yaml b/releasenotes/notes/correct-port-profile-config-option-d67f5cb31f1bc34c.yaml
index 7510d47..2830aa2 100644
--- a/releasenotes/notes/correct-port-profile-config-option-d67f5cb31f1bc34c.yaml
+++ b/releasenotes/notes/correct-port-profile-config-option-d67f5cb31f1bc34c.yaml
@@ -1,7 +1,7 @@
---
fixes:
- |
- Patch https://review.openstack.org/#/c/499575/ introduced
+ Patch https://review.opendev.org/#/c/499575/ introduced
support creating Neutron port with certain capabilities.
Currently capabilities list interpreted as string this change
fix it.
diff --git a/releasenotes/notes/lib_api_microversion_fixture-f52308fc6b6b89f2.yaml b/releasenotes/notes/lib_api_microversion_fixture-f52308fc6b6b89f2.yaml
new file mode 100644
index 0000000..d707fc7
--- /dev/null
+++ b/releasenotes/notes/lib_api_microversion_fixture-f52308fc6b6b89f2.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ New library interface to set the API microversion on Service Clients.
+ ``APIMicroversionFixture,`` can be used to set the API microversion
+ on multiple services. This Fixture will take care of reseting the service
+ microversion to None once test is finished.
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 624a99e..e71e642 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -17,11 +17,11 @@
from oslo_log import log as logging
-from tempest.api.compute import api_microversion_fixture
from tempest.common import compute
from tempest.common import waiters
from tempest import config
from tempest import exceptions
+from tempest.lib.common import api_microversion_fixture
from tempest.lib.common import api_version_request
from tempest.lib.common import api_version_utils
from tempest.lib.common.utils import data_utils
@@ -470,7 +470,7 @@
def setUp(self):
super(BaseV2ComputeTest, self).setUp()
self.useFixture(api_microversion_fixture.APIMicroversionFixture(
- self.request_microversion))
+ compute_microversion=self.request_microversion))
@classmethod
def create_volume(cls, image_ref=None, **kwargs):
diff --git a/tempest/api/identity/v3/test_catalog.py b/tempest/api/identity/v3/test_catalog.py
index deec2dc..bc95f0d 100644
--- a/tempest/api/identity/v3/test_catalog.py
+++ b/tempest/api/identity/v3/test_catalog.py
@@ -22,8 +22,8 @@
@decorators.idempotent_id('56b57ced-22b8-4127-9b8a-565dfb0207e2')
def test_catalog_standardization(self):
- # http://git.openstack.org/cgit/openstack/service-types-authority
- # /tree/service-types.yaml
+ # https://opendev.org/openstack/service-types-authority
+ # /src/branch/master/service-types.yaml
standard_service_values = [{'name': 'keystone', 'type': 'identity'},
{'name': 'nova', 'type': 'compute'},
{'name': 'glance', 'type': 'image'},
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 7e8cc8e..5bd3fce 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -36,6 +36,7 @@
body = self.admin_networks_client.create_network(**post_body)
network = body['network']
self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
self.admin_networks_client.delete_network, network['id'])
return network
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index be0c4c6..adc4dda 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -16,6 +16,7 @@
from tempest.api.network import base
from tempest.common import utils
from tempest import config
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
CONF = config.CONF
@@ -57,14 +58,18 @@
# Create floating ip from admin user
floating_ip_admin = self.admin_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
- self.addCleanup(self.admin_floating_ips_client.delete_floatingip,
- floating_ip_admin['floatingip']['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.admin_floating_ips_client.delete_floatingip,
+ floating_ip_admin['floatingip']['id'])
# Create floating ip from alt user
body = self.alt_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
floating_ip_alt = body['floatingip']
- self.addCleanup(self.alt_floating_ips_client.delete_floatingip,
- floating_ip_alt['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.alt_floating_ips_client.delete_floatingip,
+ floating_ip_alt['id'])
# List floating ips from admin
body = self.admin_floating_ips_client.list_floatingips()
floating_ip_ids_admin = [f['id'] for f in body['floatingips']]
@@ -91,8 +96,10 @@
tenant_id=self.network['tenant_id'],
port_id=self.port['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
- created_floating_ip['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
+ created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['tenant_id'])
self.assertIsNotNone(created_floating_ip['floating_ip_address'])
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 9d1e2a7..0db038d 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -17,6 +17,7 @@
from tempest.common import identity
from tempest.common import utils
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -58,11 +59,13 @@
# Create two networks
n1 = self.admin_networks_client.create_network(
tenant_id=self.project['id'])
- self.addCleanup(self.admin_networks_client.delete_network,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_networks_client.delete_network,
n1['network']['id'])
n2 = self.admin_networks_client.create_network(
tenant_id=self.project['id'])
- self.addCleanup(self.admin_networks_client.delete_network,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_networks_client.delete_network,
n2['network']['id'])
# Try to create a third network while the quota is two
@@ -71,5 +74,6 @@
r"Quota exceeded for resources: \['network'\].*"):
n3 = self.admin_networks_client.create_network(
tenant_id=self.project['id'])
- self.addCleanup(self.admin_networks_client.delete_network,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_networks_client.delete_network,
n3['network']['id'])
diff --git a/tempest/api/network/admin/test_ports.py b/tempest/api/network/admin/test_ports.py
index 05363db..edfda6e 100644
--- a/tempest/api/network/admin/test_ports.py
+++ b/tempest/api/network/admin/test_ports.py
@@ -14,6 +14,7 @@
# under the License.
from tempest.api.network import base
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
@@ -37,7 +38,9 @@
"binding:host_id": self.host_id}
body = self.admin_ports_client.create_port(**post_body)
port = body['port']
- self.addCleanup(self.admin_ports_client.delete_port, port['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.admin_ports_client.delete_port, port['id'])
host_id = port['binding:host_id']
self.assertIsNotNone(host_id)
self.assertEqual(self.host_id, host_id)
@@ -47,7 +50,9 @@
post_body = {"network_id": self.network['id']}
body = self.admin_ports_client.create_port(**post_body)
port = body['port']
- self.addCleanup(self.admin_ports_client.delete_port, port['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.admin_ports_client.delete_port, port['id'])
update_body = {"binding:host_id": self.host_id}
body = self.admin_ports_client.update_port(port['id'], **update_body)
updated_port = body['port']
@@ -61,7 +66,9 @@
post_body = {"network_id": self.network['id']}
body = self.admin_ports_client.create_port(**post_body)
port = body['port']
- self.addCleanup(self.admin_ports_client.delete_port, port['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.admin_ports_client.delete_port, port['id'])
# Update the port's binding attributes so that is now 'bound'
# to a host
@@ -85,7 +92,8 @@
body = self.admin_ports_client.create_port(
network_id=self.network['id'])
port = body['port']
- self.addCleanup(self.admin_ports_client.delete_port, port['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_ports_client.delete_port, port['id'])
body = self.admin_ports_client.show_port(port['id'])
show_port = body['port']
self.assertEqual(port['binding:host_id'],
diff --git a/tempest/api/network/admin/test_routers.py b/tempest/api/network/admin/test_routers.py
index 6ce86fb..a4a057c 100644
--- a/tempest/api/network/admin/test_routers.py
+++ b/tempest/api/network/admin/test_routers.py
@@ -20,6 +20,7 @@
from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
CONF = config.CONF
@@ -38,7 +39,8 @@
# associate a cleanup with created routers to avoid quota limits
router = self.create_router(name, admin_state_up,
external_network_id, enable_snat)
- self.addCleanup(self._cleanup_router, router)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self._cleanup_router, router)
return router
@classmethod
@@ -62,7 +64,8 @@
name = data_utils.rand_name('router-')
create_body = self.admin_routers_client.create_router(
name=name, tenant_id=project_id)
- self.addCleanup(self.admin_routers_client.delete_router,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router,
create_body['router']['id'])
self.assertEqual(project_id, create_body['router']['tenant_id'])
@@ -92,7 +95,8 @@
'enable_snat': enable_snat}
create_body = self.admin_routers_client.create_router(
name=name, external_gateway_info=external_gateway_info)
- self.addCleanup(self.admin_routers_client.delete_router,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router,
create_body['router']['id'])
# Verify snat attributes after router creation
self._verify_router_gateway(create_body['router']['id'],
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 93478e6..270f802 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -18,6 +18,7 @@
from tempest.api.network import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
@@ -62,7 +63,8 @@
name = data_utils.rand_name('router')
router = self.admin_routers_client.create_router(name=name,
distributed=True)
- self.addCleanup(self.admin_routers_client.delete_router,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router,
router['router']['id'])
self.assertTrue(router['router']['distributed'])
@@ -82,7 +84,8 @@
name = data_utils.rand_name('router')
router = self.admin_routers_client.create_router(name=name,
distributed=False)
- self.addCleanup(self.admin_routers_client.delete_router,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router,
router['router']['id'])
self.assertFalse(router['router']['distributed'])
@@ -112,8 +115,8 @@
ha=False,
tenant_id=tenant_id)
router_id = router['router']['id']
- self.addCleanup(self.admin_routers_client.delete_router,
- router_id)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router, router_id)
self.assertFalse(router['router']['distributed'])
router = self.admin_routers_client.update_router(
router_id, distributed=True)
diff --git a/tempest/api/network/admin/test_routers_negative.py b/tempest/api/network/admin/test_routers_negative.py
index 9356bcc..fdcc977 100644
--- a/tempest/api/network/admin/test_routers_negative.py
+++ b/tempest/api/network/admin/test_routers_negative.py
@@ -18,6 +18,7 @@
from tempest.api.network import base
from tempest.common import utils
from tempest import config
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -42,7 +43,8 @@
# At first create a address from public_network_id
port = self.admin_ports_client.create_port(
network_id=CONF.network.public_network_id)['port']
- self.addCleanup(self.admin_ports_client.delete_port,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_ports_client.delete_port,
port_id=port['id'])
# Add used ip and subnet_id in external_fixed_ips
fixed_ip = {
diff --git a/tempest/api/network/base_security_groups.py b/tempest/api/network/base_security_groups.py
index b8d677a..32f2cdd 100644
--- a/tempest/api/network/base_security_groups.py
+++ b/tempest/api/network/base_security_groups.py
@@ -15,6 +15,7 @@
from tempest.api.network import base
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
class BaseSecGroupTest(base.BaseNetworkTest):
@@ -24,7 +25,8 @@
name = data_utils.rand_name('secgroup-')
group_create_body = (
self.security_groups_client.create_security_group(name=name))
- self.addCleanup(self._delete_security_group,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self._delete_security_group,
group_create_body['security_group']['id'])
self.assertEqual(group_create_body['security_group']['name'], name)
return group_create_body, name
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index dec3413..d393207 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -17,6 +17,7 @@
from tempest.api.network import base
from tempest.common import utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
@@ -62,7 +63,8 @@
network_id=self.network['id'],
allowed_address_pairs=allowed_address_pairs)
port_id = body['port']['id']
- self.addCleanup(self.ports_client.delete_port, port_id)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_id)
# Confirm port was created with allowed address pair attribute
body = self.ports_client.list_ports()
@@ -76,7 +78,8 @@
# Create a port without allowed address pair
body = self.ports_client.create_port(network_id=self.network['id'])
port_id = body['port']['id']
- self.addCleanup(self.ports_client.delete_port, port_id)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_id)
if mac_address is None:
mac_address = self.mac_address
@@ -106,7 +109,8 @@
# Create an ip _address and mac_address through port create
resp = self.ports_client.create_port(network_id=self.network['id'])
newportid = resp['port']['id']
- self.addCleanup(self.ports_client.delete_port, newportid)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, newportid)
ipaddress = resp['port']['fixed_ips'][0]['ip_address']
macaddress = resp['port']['mac_address']
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 0d42033..8e94429 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -16,6 +16,7 @@
from tempest.api.network import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
@@ -62,7 +63,8 @@
network_id=self.network['id'],
extra_dhcp_opts=self.extra_dhcp_opts)
port_id = body['port']['id']
- self.addCleanup(self.ports_client.delete_port, port_id)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_id)
# Confirm port created has Extra DHCP Options
body = self.ports_client.list_ports()
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 504bfa8..9704c73 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -18,6 +18,7 @@
from tempest.common.utils import data_utils
from tempest.common.utils import net_utils
from tempest import config
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
CONF = config.CONF
@@ -77,8 +78,10 @@
floating_network_id=self.ext_net_id,
port_id=self.ports[0]['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
- created_floating_ip['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
+ created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['tenant_id'])
self.assertIsNotNone(created_floating_ip['floating_ip_address'])
@@ -125,14 +128,19 @@
self.assertIsNone(updated_floating_ip['fixed_ip_address'])
self.assertIsNone(updated_floating_ip['router_id'])
+ # Explicity test deletion of floating IP
+ self.floating_ips_client.delete_floatingip(created_floating_ip['id'])
+
@decorators.idempotent_id('e1f6bffd-442f-4668-b30e-df13f2705e77')
def test_floating_ip_delete_port(self):
# Create a floating IP
body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
created_floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
- created_floating_ip['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
+ created_floating_ip['id'])
# Create a port
port = self.ports_client.create_port(network_id=self.network['id'])
created_port = port['port']
@@ -158,24 +166,36 @@
floating_network_id=self.ext_net_id,
port_id=self.ports[1]['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
- created_floating_ip['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
+ created_floating_ip['id'])
self.assertEqual(created_floating_ip['router_id'], self.router['id'])
network_name = data_utils.rand_name(self.__class__.__name__)
network2 = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network2['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network,
+ network2['id'])
subnet2 = self.create_subnet(network2)
- self.addCleanup(self.subnets_client.delete_subnet, subnet2['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet2['id'])
router2 = self.create_router(external_network_id=self.ext_net_id)
- self.addCleanup(self.routers_client.delete_router, router2['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.delete_router, router2['id'])
self.create_router_interface(router2['id'], subnet2['id'])
- self.addCleanup(self.routers_client.remove_router_interface,
- router2['id'], subnet_id=subnet2['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
+ router2['id'], subnet_id=subnet2['id'])
port_other_router = self.create_port(network2)
- self.addCleanup(self.ports_client.delete_port,
- port_other_router['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port,
+ port_other_router['id'])
# Associate floating IP to the other port on another router
floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
@@ -194,8 +214,10 @@
port_id=self.ports[1]['id'],
fixed_ip_address=self.ports[1]['fixed_ips'][0]['ip_address'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
- created_floating_ip['id'])
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
+ created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertEqual(created_floating_ip['fixed_ip_address'],
self.ports[1]['fixed_ips'][0]['ip_address'])
@@ -218,14 +240,16 @@
body = self.ports_client.create_port(network_id=self.network['id'],
fixed_ips=fixed_ips)
port = body['port']
- self.addCleanup(self.ports_client.delete_port, port['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port['id'])
# Create floating ip
body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
port_id=port['id'],
fixed_ip_address=list_ips[0])
floating_ip = body['floatingip']
- self.addCleanup(self.floating_ips_client.delete_floatingip,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.floating_ips_client.delete_floatingip,
floating_ip['id'])
self.assertIsNotNone(floating_ip['id'])
self.assertEqual(floating_ip['fixed_ip_address'], list_ips[0])
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index e904a81..1688c9d 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -17,6 +17,7 @@
from tempest.api.network import base
from tempest.common import utils
from tempest import config
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -81,6 +82,7 @@
floating_network_id=self.ext_net_id)
floating_ip = body['floatingip']
self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
self.floating_ips_client.delete_floatingip, floating_ip['id'])
# Associate floating IP to the other port
self.assertRaises(
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index ed8eb52..eba1f6c 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -160,7 +160,8 @@
def test_create_update_delete_network_subnet(self):
# Create a network
network = self.create_network()
- self.addCleanup(self.networks_client.delete_network, network['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network['id'])
net_id = network['id']
self.assertEqual('ACTIVE', network['status'])
# Verify network update
@@ -176,6 +177,8 @@
body = self.subnets_client.update_subnet(subnet_id, name=new_name)
updated_subnet = body['subnet']
self.assertEqual(updated_subnet['name'], new_name)
+ # Verify network delete
+ self.networks_client.delete_network(network['id'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
@@ -313,7 +316,8 @@
@decorators.idempotent_id('3d3852eb-3009-49ec-97ac-5ce83b73010a')
def test_update_subnet_gw_dns_host_routes_dhcp(self):
network = self.create_network()
- self.addCleanup(self.networks_client.delete_network, network['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(
network, **self.subnet_dict(['gateway', 'host_routes',
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 25976ce..93a4631 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -23,6 +23,7 @@
from tempest.common import custom_matchers
from tempest.common import utils
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from tempest.lib import exceptions
@@ -52,7 +53,8 @@
def _create_subnet(self, network, gateway='',
cidr=None, mask_bits=None, **kwargs):
subnet = self.create_subnet(network, gateway, cidr, mask_bits)
- self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet['id'])
return subnet
def _create_network(self, network_name=None, **kwargs):
@@ -60,7 +62,8 @@
self.__class__.__name__)
network = self.networks_client.create_network(
name=network_name, **kwargs)['network']
- self.addCleanup(self.networks_client.delete_network,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network,
network['id'])
return network
@@ -116,13 +119,15 @@
mask_bits=address.prefixlen,
**allocation_pools)
body = self.ports_client.create_port(network_id=net_id)
- self.addCleanup(self.ports_client.delete_port, body['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, body['port']['id'])
port = body['port']
ip_address = port['fixed_ips'][0]['ip_address']
start_ip_address = allocation_pools['allocation_pools'][0]['start']
end_ip_address = allocation_pools['allocation_pools'][0]['end']
ip_range = netaddr.IPRange(start_ip_address, end_ip_address)
self.assertIn(ip_address, ip_range)
+ self.ports_client.delete_port(port['id'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('c9a685bd-e83f-499c-939f-9f7863ca259f')
@@ -168,9 +173,11 @@
self._create_subnet(network)
# Create two ports
port_1 = self.ports_client.create_port(network_id=network['id'])
- self.addCleanup(self.ports_client.delete_port, port_1['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_1['port']['id'])
port_2 = self.ports_client.create_port(network_id=network['id'])
- self.addCleanup(self.ports_client.delete_port, port_2['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_2['port']['id'])
# List ports filtered by fixed_ips
port_1_fixed_ip = port_1['port']['fixed_ips'][0]['ip_address']
fixed_ips = 'ip_address=' + port_1_fixed_ip
@@ -219,11 +226,13 @@
fixed_ips = [{'subnet_id': subnet['id'], 'ip_address': ip_address_1}]
port_1 = self.ports_client.create_port(network_id=network['id'],
fixed_ips=fixed_ips)
- self.addCleanup(self.ports_client.delete_port, port_1['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_1['port']['id'])
fixed_ips = [{'subnet_id': subnet['id'], 'ip_address': ip_address_2}]
port_2 = self.ports_client.create_port(network_id=network['id'],
fixed_ips=fixed_ips)
- self.addCleanup(self.ports_client.delete_port, port_2['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port_2['port']['id'])
# Scenario 1: List port1 (port2 is filtered out)
if ip_address_1[:-1] != ip_address_2[:-1]:
@@ -272,12 +281,14 @@
network = self._create_network()
self._create_subnet(network)
router = self.create_router()
- self.addCleanup(self.routers_client.delete_router, router['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.delete_router, router['id'])
port = self.ports_client.create_port(network_id=network['id'])
# Add router interface to port created above
self.routers_client.add_router_interface(router['id'],
port_id=port['port']['id'])
- self.addCleanup(self.routers_client.remove_router_interface,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
router['id'], port_id=port['port']['id'])
# List ports filtered by router_id
port_list = self.ports_client.list_ports(device_id=router['id'])
@@ -311,7 +322,8 @@
# Create a port with multiple IP addresses
port = self.create_port(network,
fixed_ips=fixed_ips)
- self.addCleanup(self.ports_client.delete_port, port['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port['id'])
self.assertEqual(2, len(port['fixed_ips']))
check_fixed_ips = [subnet_1['id'], subnet_2['id']]
for item in port['fixed_ips']:
@@ -334,7 +346,8 @@
for name in security_groups_names:
group_create_body = sec_grps_client.create_security_group(
name=name)
- self.addCleanup(self.security_groups_client.delete_security_group,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.security_groups_client.delete_security_group,
group_create_body['security_group']['id'])
security_groups_list.append(group_create_body['security_group']
['id'])
@@ -342,7 +355,8 @@
sec_grp_name = data_utils.rand_name('secgroup')
security_group = sec_grps_client.create_security_group(
name=sec_grp_name)
- self.addCleanup(self.security_groups_client.delete_security_group,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.security_groups_client.delete_security_group,
security_group['security_group']['id'])
post_body = {
"name": data_utils.rand_name('port-'),
@@ -351,7 +365,8 @@
"admin_state_up": True,
"fixed_ips": fixed_ip_1}
body = self.ports_client.create_port(**post_body)
- self.addCleanup(self.ports_client.delete_port, body['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, body['port']['id'])
port = body['port']
# Update the port with security groups
@@ -402,7 +417,8 @@
# Create a new port with user defined mac
body = self.ports_client.create_port(network_id=self.network['id'],
mac_address=free_mac_address)
- self.addCleanup(self.ports_client.delete_port, body['port']['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, body['port']['id'])
port = body['port']
body = self.ports_client.show_port(port['id'])
show_port = body['port']
@@ -418,7 +434,8 @@
network = self._create_network()
self._create_subnet(network)
port = self.create_port(network, security_groups=[])
- self.addCleanup(self.ports_client.delete_port, port['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port, port['id'])
self.assertIsNotNone(port['security_groups'])
self.assertEmpty(port['security_groups'])
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index be3cf65..f223fa4 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -20,6 +20,7 @@
from tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
CONF = config.CONF
@@ -89,10 +90,11 @@
network_name = data_utils.rand_name(self.__class__.__name__)
network = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
- self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet['id'])
router = self.create_router()
self.addCleanup(self.delete_router, router)
# Add router interface with subnet id
@@ -114,8 +116,8 @@
network_name = data_utils.rand_name(self.__class__.__name__)
network = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
router = self.create_router()
@@ -126,7 +128,8 @@
interface = self.routers_client.add_router_interface(
router['id'],
port_id=port_body['port']['id'])
- self.addCleanup(self.routers_client.remove_router_interface,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.routers_client.remove_router_interface,
router['id'], port_id=port_body['port']['id'])
self.assertIn('subnet_id', interface.keys())
self.assertIn('port_id', interface.keys())
@@ -135,6 +138,8 @@
interface['port_id'])
self.assertEqual(show_port_body['port']['device_id'],
router['id'])
+ self.routers_client.remove_router_interface(
+ router['id'], port_id=port_body['port']['id'])
@decorators.idempotent_id('cbe42f84-04c2-11e7-8adb-fa163e4fa634')
@utils.requires_ext(extension='ext-gw-mode', service='network')
@@ -160,7 +165,8 @@
# Create a router and set gateway to fixed_ip
router = self.admin_routers_client.create_router(
external_gateway_info=external_gateway_info)['router']
- self.addCleanup(self.admin_routers_client.delete_router,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.admin_routers_client.delete_router,
router_id=router['id'])
# Examine router's gateway is equal to fixed_ip
self.assertEqual(router['external_gateway_info'][
@@ -188,10 +194,12 @@
network_name = data_utils.rand_name(self.__class__.__name__)
network = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network,
network['id'])
subnet = self.create_subnet(network, cidr=next_cidr)
- self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet['id'])
next_cidr = next_cidr.next()
# Add router interface with subnet id
@@ -254,18 +262,20 @@
network_name = data_utils.rand_name(self.__class__.__name__)
network01 = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network01['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network01['id'])
network_name = data_utils.rand_name(self.__class__.__name__)
network02 = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network02['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network02['id'])
subnet01 = self.create_subnet(network01)
- self.addCleanup(self.subnets_client.delete_subnet, subnet01['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet01['id'])
sub02_cidr = self.cidr.next()
subnet02 = self.create_subnet(network02, cidr=sub02_cidr)
- self.addCleanup(self.subnets_client.delete_subnet, subnet02['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet02['id'])
router = self.create_router()
self.addCleanup(self.delete_router, router)
interface01 = self._add_router_interface_with_subnet_id(router['id'],
@@ -282,10 +292,11 @@
network_name = data_utils.rand_name(self.__class__.__name__)
network = self.networks_client.create_network(
name=network_name)['network']
- self.addCleanup(self.networks_client.delete_network,
- network['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.networks_client.delete_network, network['id'])
subnet = self.create_subnet(network)
- self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.subnets_client.delete_subnet, subnet['id'])
router = self.create_router()
self.addCleanup(self.delete_router, router)
fixed_ip = [{'subnet_id': subnet['id']}]
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index ffc1fca..ea68005 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -16,6 +16,7 @@
from tempest.api.network import base_security_groups as base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
@@ -49,8 +50,8 @@
)
sec_group_rule = rule_create_body['security_group_rule']
- self.addCleanup(self._delete_security_group_rule,
- sec_group_rule['id'])
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self._delete_security_group_rule, sec_group_rule['id'])
expected = {'direction': direction, 'protocol': protocol,
'ethertype': ethertype, 'port_range_min': port_range_min,
@@ -104,6 +105,8 @@
self.assertEqual(show_body['security_group']['name'], new_name)
self.assertEqual(show_body['security_group']['description'],
new_description)
+ # Delete security group
+ self._delete_security_group(group_create_body['security_group']['id'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('cfb99e0e-7410-4a3d-8a0c-959a63ee77e9')
@@ -138,6 +141,8 @@
for rule in rule_list_body['security_group_rules']]
self.assertIn(rule_create_body['security_group_rule']['id'],
rule_list)
+ self._delete_security_group_rule(
+ rule_create_body['security_group_rule']['id'])
@decorators.idempotent_id('87dfbcf9-1849-43ea-b1e4-efa3eeae9f71')
def test_create_security_group_rule_with_additional_args(self):
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 49d9742..d76a323 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -156,3 +156,53 @@
cmd_why = 'sudo ls -lR /dev'
LOG.info("Contents of /dev: %s", self.exec_command(cmd_why))
raise
+
+ def nc_listen_host(self, port=80, protocol='tcp'):
+ """Creates persistent nc server listening on the given TCP / UDP port
+
+ :port: the port to start listening on.
+ :protocol: the protocol used by the server. TCP by default.
+ """
+ udp = '-u' if protocol.lower() == 'udp' else ''
+ cmd = "sudo nc %(udp)s -p %(port)s -lk -e echo foolish &" % {
+ 'udp': udp, 'port': port}
+ return self.exec_command(cmd)
+
+ def nc_host(self, host, port=80, protocol='tcp', expected_response=None):
+ """Check connectivity to TCP / UDP port at host via nc
+
+ :host: an IP against which the connectivity will be tested.
+ :port: the port to check connectivity against.
+ :protocol: the protocol used by nc to send packets. TCP by default.
+ :expected_response: string representing the expected response
+ from server.
+ :raises SSHExecCommandFailed: if an expected response is given and it
+ does not match the actual server response.
+ """
+ udp = '-u' if protocol.lower() == 'udp' else ''
+ cmd = 'echo "bar" | nc -w 1 %(udp)s %(host)s %(port)s' % {
+ 'udp': udp, 'host': host, 'port': port}
+ response = self.exec_command(cmd)
+
+ # sending an UDP packet will always succeed. we need to check
+ # the response.
+ if (expected_response is not None and
+ expected_response != response.strip()):
+ raise tempest.lib.exceptions.SSHExecCommandFailed(
+ command=cmd, exit_status=0, stdout=response, stderr='')
+ return response
+
+ def icmp_check(self, host, nic=None):
+ """Wrapper for icmp connectivity checks"""
+ return self.ping_host(host, nic=nic)
+
+ def udp_check(self, host, **kwargs):
+ """Wrapper for udp connectivity checks."""
+ kwargs.pop('nic', None)
+ return self.nc_host(host, protocol='udp', expected_response='foolish',
+ **kwargs)
+
+ def tcp_check(self, host, **kwargs):
+ """Wrapper for tcp connectivity checks."""
+ kwargs.pop('nic', None)
+ return self.nc_host(host, **kwargs)
diff --git a/tempest/config.py b/tempest/config.py
index f692a4b..e3ac47c 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -1052,7 +1052,12 @@
choices=["udhcpc", "dhclient", ""],
help='DHCP client used by images to renew DCHP lease. '
'If left empty, update operation will be skipped. '
- 'Supported clients: "udhcpc", "dhclient"')
+ 'Supported clients: "udhcpc", "dhclient"'),
+ cfg.StrOpt('protocol',
+ default='icmp',
+ choices=('icmp', 'tcp', 'udp'),
+ help='The protocol used in security groups tests to check '
+ 'connectivity.'),
]
diff --git a/tempest/lib/api_schema/response/compute/v2_16/servers.py b/tempest/lib/api_schema/response/compute/v2_16/servers.py
index 72b84f5..fc81ff7 100644
--- a/tempest/lib/api_schema/response/compute/v2_16/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_16/servers.py
@@ -168,3 +168,6 @@
servers.rebuild_server_with_admin_pass)
show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
get_remote_consoles = copy.deepcopy(servers.get_remote_consoles)
+attach_volume = copy.deepcopy(servers.attach_volume)
+show_volume_attachment = copy.deepcopy(servers.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_19/servers.py b/tempest/lib/api_schema/response/compute/v2_19/servers.py
index e3e8ad1..b6c3c14 100644
--- a/tempest/lib/api_schema/response/compute/v2_19/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_19/servers.py
@@ -58,3 +58,6 @@
list_servers = copy.deepcopy(serversv216.list_servers)
show_server_diagnostics = copy.deepcopy(serversv216.show_server_diagnostics)
get_remote_consoles = copy.deepcopy(serversv216.get_remote_consoles)
+attach_volume = copy.deepcopy(serversv216.attach_volume)
+show_volume_attachment = copy.deepcopy(serversv216.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(serversv216.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_26/servers.py b/tempest/lib/api_schema/response/compute/v2_26/servers.py
index 8e62dc3..5a0f987 100644
--- a/tempest/lib/api_schema/response/compute/v2_26/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_26/servers.py
@@ -101,3 +101,6 @@
list_servers = copy.deepcopy(servers219.list_servers)
show_server_diagnostics = copy.deepcopy(servers219.show_server_diagnostics)
get_remote_consoles = copy.deepcopy(servers219.get_remote_consoles)
+attach_volume = copy.deepcopy(servers219.attach_volume)
+show_volume_attachment = copy.deepcopy(servers219.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers219.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_3/servers.py b/tempest/lib/api_schema/response/compute/v2_3/servers.py
index 18fb352..1674c1b 100644
--- a/tempest/lib/api_schema/response/compute/v2_3/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_3/servers.py
@@ -173,3 +173,6 @@
rebuild_server_with_admin_pass = copy.deepcopy(
servers.rebuild_server_with_admin_pass)
show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
+attach_volume = copy.deepcopy(servers.attach_volume)
+show_volume_attachment = copy.deepcopy(servers.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_47/servers.py b/tempest/lib/api_schema/response/compute/v2_47/servers.py
index 0fbacd3..d580f2c 100644
--- a/tempest/lib/api_schema/response/compute/v2_47/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_47/servers.py
@@ -66,3 +66,6 @@
update_tag = copy.deepcopy(servers226.update_tag)
delete_tag = copy.deepcopy(servers226.delete_tag)
list_servers = copy.deepcopy(servers226.list_servers)
+attach_volume = copy.deepcopy(servers226.attach_volume)
+show_volume_attachment = copy.deepcopy(servers226.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers226.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_48/servers.py b/tempest/lib/api_schema/response/compute/v2_48/servers.py
index 84b5a2a..e2e45bc 100644
--- a/tempest/lib/api_schema/response/compute/v2_48/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_48/servers.py
@@ -129,3 +129,6 @@
rebuild_server = copy.deepcopy(servers247.rebuild_server)
rebuild_server_with_admin_pass = copy.deepcopy(
servers247.rebuild_server_with_admin_pass)
+attach_volume = copy.deepcopy(servers247.attach_volume)
+show_volume_attachment = copy.deepcopy(servers247.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers247.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_54/servers.py b/tempest/lib/api_schema/response/compute/v2_54/servers.py
index 099e1b8..2c2bff0 100644
--- a/tempest/lib/api_schema/response/compute/v2_54/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_54/servers.py
@@ -55,3 +55,6 @@
check_tag_existence = copy.deepcopy(servers248.check_tag_existence)
update_tag = copy.deepcopy(servers248.update_tag)
delete_tag = copy.deepcopy(servers248.delete_tag)
+attach_volume = copy.deepcopy(servers248.attach_volume)
+show_volume_attachment = copy.deepcopy(servers248.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers248.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_57/servers.py b/tempest/lib/api_schema/response/compute/v2_57/servers.py
index 0099a2b..aa57d25 100644
--- a/tempest/lib/api_schema/response/compute/v2_57/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_57/servers.py
@@ -59,3 +59,6 @@
check_tag_existence = copy.deepcopy(servers254.check_tag_existence)
update_tag = copy.deepcopy(servers254.update_tag)
delete_tag = copy.deepcopy(servers254.delete_tag)
+attach_volume = copy.deepcopy(servers254.attach_volume)
+show_volume_attachment = copy.deepcopy(servers254.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers254.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_6/servers.py b/tempest/lib/api_schema/response/compute/v2_6/servers.py
index d5774de..922bf79 100644
--- a/tempest/lib/api_schema/response/compute/v2_6/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_6/servers.py
@@ -28,6 +28,9 @@
rebuild_server_with_admin_pass = copy.deepcopy(
servers.rebuild_server_with_admin_pass)
show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
+attach_volume = copy.deepcopy(servers.attach_volume)
+show_volume_attachment = copy.deepcopy(servers.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers.list_volume_attachments)
# NOTE: The consolidated remote console API got introduced with v2.6
# with bp/consolidate-console-api. See Nova commit 578bafeda
diff --git a/tempest/lib/api_schema/response/compute/v2_63/servers.py b/tempest/lib/api_schema/response/compute/v2_63/servers.py
index 3c3d41c..01910aa 100644
--- a/tempest/lib/api_schema/response/compute/v2_63/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_63/servers.py
@@ -73,3 +73,6 @@
check_tag_existence = copy.deepcopy(servers257.check_tag_existence)
update_tag = copy.deepcopy(servers257.update_tag)
delete_tag = copy.deepcopy(servers257.delete_tag)
+attach_volume = copy.deepcopy(servers257.attach_volume)
+show_volume_attachment = copy.deepcopy(servers257.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers257.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_70/__init__.py b/tempest/lib/api_schema/response/compute/v2_70/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_70/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_70/servers.py b/tempest/lib/api_schema/response/compute/v2_70/servers.py
new file mode 100644
index 0000000..5ca4cc8
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_70/servers.py
@@ -0,0 +1,80 @@
+# 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 copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import servers as servers2_1
+from tempest.lib.api_schema.response.compute.v2_63 import servers as servers263
+
+
+###########################################################################
+#
+# 2.70:
+#
+# Exposes virtual device tags for volume attachments and virtual interfaces
+# (ports). A tag parameter is added to the response body for the following
+# APIs:
+#
+# Volumes
+#
+# - GET /servers/{server_id}/os-volume_attachments (list)
+# - GET /servers/{server_id}/os-volume_attachments/{volume_id} (show)
+# - POST /servers/{server_id}/os-volume_attachments (attach)
+#
+# Ports
+#
+# - GET /servers/{server_id}/os-interface (list)
+# - GET /servers/{server_id}/os-interface/{port_id} (show)
+# - POST /servers/{server_id}/os-interface (attach)
+#
+###########################################################################
+
+attach_volume = copy.deepcopy(servers2_1.attach_volume)
+attach_volume['response_body']['properties']['volumeAttachment'][
+ 'properties'].update({'tag': {'type': ['string', 'null']}})
+attach_volume['response_body']['properties']['volumeAttachment'][
+ 'required'].append('tag')
+
+show_volume_attachment = copy.deepcopy(servers2_1.show_volume_attachment)
+show_volume_attachment['response_body']['properties']['volumeAttachment'][
+ 'properties'].update({'tag': {'type': ['string', 'null']}})
+show_volume_attachment['response_body']['properties'][
+ 'volumeAttachment']['required'].append('tag')
+
+list_volume_attachments = copy.deepcopy(servers2_1.list_volume_attachments)
+list_volume_attachments['response_body']['properties']['volumeAttachments'][
+ 'items']['properties'].update({'tag': {'type': ['string', 'null']}})
+list_volume_attachments['response_body']['properties'][
+ 'volumeAttachments']['items']['required'].append('tag')
+
+# TODO(mriedem): Handle the os-interface changes when there is a test that
+# needs them from this microversion onward.
+
+# NOTE(lajoskatona): Below are the unchanged schema in this microversion. We
+# need to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.63 ***
+list_servers_detail = copy.deepcopy(servers263.list_servers_detail)
+rebuild_server = copy.deepcopy(servers263.rebuild_server)
+rebuild_server_with_admin_pass = copy.deepcopy(
+ servers263.rebuild_server_with_admin_pass)
+update_server = copy.deepcopy(servers263.update_server)
+get_server = copy.deepcopy(servers263.get_server)
+list_servers = copy.deepcopy(servers263.list_servers)
+show_server_diagnostics = copy.deepcopy(servers263.show_server_diagnostics)
+get_remote_consoles = copy.deepcopy(servers263.get_remote_consoles)
+list_tags = copy.deepcopy(servers263.list_tags)
+update_all_tags = copy.deepcopy(servers263.update_all_tags)
+delete_all_tags = copy.deepcopy(servers263.delete_all_tags)
+check_tag_existence = copy.deepcopy(servers263.check_tag_existence)
+update_tag = copy.deepcopy(servers263.update_tag)
+delete_tag = copy.deepcopy(servers263.delete_tag)
diff --git a/tempest/lib/api_schema/response/compute/v2_71/__init__.py b/tempest/lib/api_schema/response/compute/v2_71/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_71/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_71/servers.py b/tempest/lib/api_schema/response/compute/v2_71/servers.py
new file mode 100644
index 0000000..0c526fb
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_71/servers.py
@@ -0,0 +1,81 @@
+# 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 copy
+
+from tempest.lib.api_schema.response.compute.v2_70 import servers as servers270
+
+
+###########################################################################
+#
+# 2.71:
+#
+# The server_groups parameter will be in the response body of the following
+# APIs to list the server groups to which the server belongs:
+#
+# - GET /servers/{server_id} (show)
+# - PUT /servers/{server_id} (update)
+# - POST /servers/{server_id}/action (rebuild)
+#
+###########################################################################
+
+# The "server_groups" parameter will always be present and contain at most one
+# UUID entry.
+server_groups = {
+ 'type': 'array',
+ 'minItems': 0,
+ 'maxItems': 1,
+ 'items': {
+ 'type': 'string',
+ 'format': 'uuid'
+ }
+}
+
+rebuild_server = copy.deepcopy(servers270.rebuild_server)
+rebuild_server['response_body']['properties']['server'][
+ 'properties'].update({'server_groups': server_groups})
+rebuild_server['response_body']['properties']['server'][
+ 'required'].append('server_groups')
+
+rebuild_server_with_admin_pass = copy.deepcopy(
+ servers270.rebuild_server_with_admin_pass)
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+ 'properties'].update({'server_groups': server_groups})
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+ 'required'].append('server_groups')
+
+update_server = copy.deepcopy(servers270.update_server)
+update_server['response_body']['properties']['server'][
+ 'properties'].update({'server_groups': server_groups})
+update_server['response_body']['properties']['server'][
+ 'required'].append('server_groups')
+
+get_server = copy.deepcopy(servers270.get_server)
+get_server['response_body']['properties']['server'][
+ 'properties'].update({'server_groups': server_groups})
+get_server['response_body']['properties']['server'][
+ 'required'].append('server_groups')
+
+# NOTE(lajoskatona): Below are the unchanged schema in this microversion. We
+# need to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.70 ***
+list_servers_details = copy.deepcopy(servers270.list_servers_detail)
+list_servers = copy.deepcopy(servers270.list_servers)
+show_server_diagnostics = copy.deepcopy(servers270.show_server_diagnostics)
+get_remote_consoles = copy.deepcopy(servers270.get_remote_consoles)
+list_tags = copy.deepcopy(servers270.list_tags)
+update_all_tags = copy.deepcopy(servers270.update_all_tags)
+delete_all_tags = copy.deepcopy(servers270.delete_all_tags)
+check_tag_existence = copy.deepcopy(servers270.check_tag_existence)
+update_tag = copy.deepcopy(servers270.update_tag)
+delete_tag = copy.deepcopy(servers270.delete_tag)
diff --git a/tempest/lib/api_schema/response/compute/v2_8/servers.py b/tempest/lib/api_schema/response/compute/v2_8/servers.py
index df7847f..3dbab3f 100644
--- a/tempest/lib/api_schema/response/compute/v2_8/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_8/servers.py
@@ -35,3 +35,6 @@
rebuild_server_with_admin_pass = copy.deepcopy(
servers.rebuild_server_with_admin_pass)
show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
+attach_volume = copy.deepcopy(servers.attach_volume)
+show_volume_attachment = copy.deepcopy(servers.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers.list_volume_attachments)
diff --git a/tempest/lib/api_schema/response/compute/v2_9/servers.py b/tempest/lib/api_schema/response/compute/v2_9/servers.py
index 55f8e75..ee0313d 100644
--- a/tempest/lib/api_schema/response/compute/v2_9/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_9/servers.py
@@ -54,3 +54,6 @@
list_servers = copy.deepcopy(servers.list_servers)
show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
get_remote_consoles = copy.deepcopy(servers.get_remote_consoles)
+attach_volume = copy.deepcopy(servers.attach_volume)
+show_volume_attachment = copy.deepcopy(servers.show_volume_attachment)
+list_volume_attachments = copy.deepcopy(servers.list_volume_attachments)
diff --git a/tempest/lib/common/api_microversion_fixture.py b/tempest/lib/common/api_microversion_fixture.py
new file mode 100644
index 0000000..3837138
--- /dev/null
+++ b/tempest/lib/common/api_microversion_fixture.py
@@ -0,0 +1,82 @@
+# Copyright 2019 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import fixtures
+
+from tempest.lib.services.compute import base_compute_client
+from tempest.lib.services.placement import base_placement_client
+from tempest.lib.services.volume import base_client as base_volume_client
+
+
+class APIMicroversionFixture(fixtures.Fixture):
+ """API Microversion Fixture to set service microversion.
+
+ This class provides the fixture to set and reset the microversion
+ on service client. Service client has global variable to set the
+ microversion for that service API request.
+ For example: base_compute_client.COMPUTE_MICROVERSION
+ Global variable is always risky to set directly which can affect the
+ other test's API request also. This class provides a way to reset the
+ service microversion once test finish the API request.
+ This class can be used with useFixture: Example::
+
+ def setUp(self):
+ super(BaseV2ComputeTest, self).setUp()
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ compute_microversion=self.compute_request_microversion))
+
+ Or you can set microversion on multiple services together::
+
+ def setUp(self):
+ super(ScenarioTest, self).setUp()
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ compute_microversion=self.compute_request_microversion,
+ volume_microversion=self.volume_request_microversion))
+
+ Current supported services:
+ - Compute
+ - Volume
+ - Placement
+
+ :param str compute_microversion: microvesion to be set on compute
+ service clients
+ :param str volume_microversion: microvesion to be set on volume
+ service clients
+ :param str placement_microversion: microvesion to be set on placement
+ service clients
+ """
+
+ def __init__(self, compute_microversion=None, volume_microversion=None,
+ placement_microversion=None):
+ self.compute_microversion = compute_microversion
+ self.volume_microversion = volume_microversion
+ self.placement_microversion = placement_microversion
+
+ def _setUp(self):
+ super(APIMicroversionFixture, self)._setUp()
+ if self.compute_microversion:
+ base_compute_client.COMPUTE_MICROVERSION = (
+ self.compute_microversion)
+ if self.volume_microversion:
+ base_volume_client.VOLUME_MICROVERSION = self.volume_microversion
+ if self.placement_microversion:
+ base_placement_client.PLACEMENT_MICROVERSION = (
+ self.placement_microversion)
+
+ self.addCleanup(self._reset_microversion)
+
+ def _reset_microversion(self):
+ base_compute_client.COMPUTE_MICROVERSION = None
+ base_volume_client.VOLUME_MICROVERSION = None
+ base_placement_client.PLACEMENT_MICROVERSION = None
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 18e08cc..f2270f8 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -33,6 +33,8 @@
from tempest.lib.api_schema.response.compute.v2_57 import servers as schemav257
from tempest.lib.api_schema.response.compute.v2_6 import servers as schemav26
from tempest.lib.api_schema.response.compute.v2_63 import servers as schemav263
+from tempest.lib.api_schema.response.compute.v2_70 import servers as schemav270
+from tempest.lib.api_schema.response.compute.v2_71 import servers as schemav271
from tempest.lib.api_schema.response.compute.v2_8 import servers as schemav28
from tempest.lib.api_schema.response.compute.v2_9 import servers as schemav29
from tempest.lib.common import rest_client
@@ -55,7 +57,9 @@
{'min': '2.48', 'max': '2.53', 'schema': schemav248},
{'min': '2.54', 'max': '2.56', 'schema': schemav254},
{'min': '2.57', 'max': '2.62', 'schema': schemav257},
- {'min': '2.63', 'max': None, 'schema': schemav263}]
+ {'min': '2.63', 'max': '2.69', 'schema': schemav263},
+ {'min': '2.70', 'max': '2.70', 'schema': schemav270},
+ {'min': '2.71', 'max': None, 'schema': schemav271}]
def __init__(self, auth_provider, service, region,
enable_instance_password=True, **kwargs):
@@ -426,6 +430,7 @@
resp, body = self.post('servers/%s/os-volume_attachments' % server_id,
post_body)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.attach_volume, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -460,6 +465,7 @@
resp, body = self.get('servers/%s/os-volume_attachments/%s' % (
server_id, volume_id))
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.show_volume_attachment, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -473,6 +479,7 @@
resp, body = self.get('servers/%s/os-volume_attachments' % (
server_id))
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.list_volume_attachments, resp, body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 86d37f1..aa06fd0 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -979,24 +979,33 @@
raise
def check_remote_connectivity(self, source, dest, should_succeed=True,
- nic=None):
- """assert ping server via source ssh connection
+ nic=None, protocol='icmp'):
+ """check server connectivity via source ssh connection
- :param source: RemoteClient: an ssh connection from which to ping
- :param dest: an IP to ping against
- :param should_succeed: boolean: should ping succeed or not
- :param nic: specific network interface to ping from
+ :param source: RemoteClient: an ssh connection from which to execute
+ the check
+ :param dest: an IP to check connectivity against
+ :param should_succeed: boolean should connection succeed or not
+ :param nic: specific network interface to test connectivity from
+ :param protocol: the protocol used to test connectivity with.
+ :returns: True, if the connection succeeded and it was expected to
+ succeed. False otherwise.
"""
- def ping_remote():
+ method_name = '%s_check' % protocol
+ connectivity_checker = getattr(source, method_name)
+
+ def connect_remote():
try:
- source.ping_host(dest, nic=nic)
+ connectivity_checker(dest, nic=nic)
except lib_exc.SSHExecCommandFailed:
- LOG.warning('Failed to ping IP: %s via a ssh connection '
- 'from: %s.', dest, source.ssh_client.host)
+ LOG.warning('Failed to check %(protocol)s connectivity for '
+ 'IP %(dest)s via a ssh connection from: %(src)s.',
+ dict(protocol=protocol, dest=dest,
+ src=source.ssh_client.host))
return not should_succeed
return should_succeed
- result = test_utils.call_until_true(ping_remote,
+ result = test_utils.call_until_true(connect_remote,
CONF.validation.ping_timeout, 1)
if result:
return
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 438ee01..8de6614 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -166,9 +166,10 @@
if self._sysconfig_network_scripts_dir_exists(ssh):
try:
ssh.exec_command(
- 'echo -e "DEVICE=%(nic)s\\nIPV6INIT=yes" | '
+ 'echo -e "DEVICE=%(nic)s\\nNAME=%(nic)s\\nIPV6INIT=yes" | '
'sudo tee /etc/sysconfig/network-scripts/ifcfg-%(nic)s; '
- 'sudo /sbin/service network restart' % {'nic': nic})
+ 'sudo nmcli connection reload' % {'nic': nic})
+ ssh.exec_command('sudo nmcli connection up %s' % nic)
except exceptions.SSHExecCommandFailed as e:
# NOTE(slaweq): Sometimes it can happen that this SSH command
# will fail because of some error from network manager in
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 2b7926a..9cbd831 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -395,24 +395,22 @@
self.check_remote_connectivity(source=access_point_ssh,
dest=self._get_server_ip(server))
- def _test_cross_tenant_block(self, source_tenant, dest_tenant):
+ def _test_cross_tenant_block(self, source_tenant, dest_tenant, ruleset):
# if public router isn't defined, then dest_tenant access is via
# floating-ip
+ protocol = ruleset['protocol']
access_point_ssh = self._connect_to_access_point(source_tenant)
ip = self._get_server_ip(dest_tenant.access_point,
floating=self.floating_ip_access)
self.check_remote_connectivity(source=access_point_ssh, dest=ip,
- should_succeed=False)
+ should_succeed=False, protocol=protocol)
- def _test_cross_tenant_allow(self, source_tenant, dest_tenant):
+ def _test_cross_tenant_allow(self, source_tenant, dest_tenant, ruleset):
"""check for each direction:
creating rule for tenant incoming traffic enables only 1way traffic
"""
- ruleset = dict(
- protocol='icmp',
- direction='ingress'
- )
+ protocol = ruleset['protocol']
sec_group_rules_client = (
dest_tenant.manager.security_group_rules_client)
self._create_security_group_rule(
@@ -423,10 +421,10 @@
access_point_ssh = self._connect_to_access_point(source_tenant)
ip = self._get_server_ip(dest_tenant.access_point,
floating=self.floating_ip_access)
- self.check_remote_connectivity(access_point_ssh, ip)
+ self.check_remote_connectivity(access_point_ssh, ip, protocol=protocol)
# test that reverse traffic is still blocked
- self._test_cross_tenant_block(dest_tenant, source_tenant)
+ self._test_cross_tenant_block(dest_tenant, source_tenant, ruleset)
# allow reverse traffic and check
sec_group_rules_client = (
@@ -440,7 +438,8 @@
access_point_ssh_2 = self._connect_to_access_point(dest_tenant)
ip = self._get_server_ip(source_tenant.access_point,
floating=self.floating_ip_access)
- self.check_remote_connectivity(access_point_ssh_2, ip)
+ self.check_remote_connectivity(access_point_ssh_2, ip,
+ protocol=protocol)
def _verify_mac_addr(self, tenant):
"""Verify that VM has the same ip, mac as listed in port"""
@@ -470,6 +469,17 @@
self._log_console_output(
servers=[tenant.access_point], client=client)
+ def _create_protocol_ruleset(self, protocol, port=80):
+ if protocol == 'icmp':
+ ruleset = dict(protocol='icmp',
+ direction='ingress')
+ else:
+ ruleset = dict(protocol=protocol,
+ port_range_min=port,
+ port_range_max=port,
+ direction='ingress')
+ return ruleset
+
@decorators.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
@utils.services('compute', 'network')
def test_cross_tenant_traffic(self):
@@ -484,8 +494,18 @@
# cross tenant check
source_tenant = self.primary_tenant
dest_tenant = self.alt_tenant
- self._test_cross_tenant_block(source_tenant, dest_tenant)
- self._test_cross_tenant_allow(source_tenant, dest_tenant)
+
+ protocol = CONF.scenario.protocol
+ LOG.debug("Testing cross tenant traffic for %s protocol",
+ protocol)
+ if protocol in ['udp', 'tcp']:
+ for tenant in [source_tenant, dest_tenant]:
+ access_point = self._connect_to_access_point(tenant)
+ access_point.nc_listen_host(protocol=protocol)
+
+ ruleset = self._create_protocol_ruleset(protocol)
+ self._test_cross_tenant_block(source_tenant, dest_tenant, ruleset)
+ self._test_cross_tenant_allow(source_tenant, dest_tenant, ruleset)
except Exception:
self._log_console_output_for_all_tenants()
raise
diff --git a/tempest/tests/lib/test_api_microversion_fixture.py b/tempest/tests/lib/test_api_microversion_fixture.py
new file mode 100644
index 0000000..ad98ed0
--- /dev/null
+++ b/tempest/tests/lib/test_api_microversion_fixture.py
@@ -0,0 +1,58 @@
+# Copyright 2019 NEC Corporation.
+#
+# 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 tempest.lib.common import api_microversion_fixture
+from tempest.lib.services.compute import base_compute_client
+from tempest.lib.services.placement import base_placement_client
+from tempest.lib.services.volume import base_client
+from tempest.tests import base
+
+
+class TestAPIMicroversionFixture(base.TestCase):
+ def setUp(self):
+ super(TestAPIMicroversionFixture, self).setUp()
+ # Verify that all the microversion are reset back to None
+ # by Fixture.
+ self.assertIsNone(base_compute_client.COMPUTE_MICROVERSION)
+ self.assertIsNone(base_client.VOLUME_MICROVERSION)
+ self.assertIsNone(base_placement_client.PLACEMENT_MICROVERSION)
+
+ def test_compute_microversion(self):
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ compute_microversion='2.10'))
+ self.assertEqual('2.10', base_compute_client.COMPUTE_MICROVERSION)
+ self.assertIsNone(base_client.VOLUME_MICROVERSION)
+ self.assertIsNone(base_placement_client.PLACEMENT_MICROVERSION)
+
+ def test_volume_microversion(self):
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ volume_microversion='3.10'))
+ self.assertIsNone(base_compute_client.COMPUTE_MICROVERSION)
+ self.assertEqual('3.10', base_client.VOLUME_MICROVERSION)
+ self.assertIsNone(base_placement_client.PLACEMENT_MICROVERSION)
+
+ def test_placement_microversion(self):
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ placement_microversion='1.10'))
+ self.assertIsNone(base_compute_client.COMPUTE_MICROVERSION)
+ self.assertIsNone(base_client.VOLUME_MICROVERSION)
+ self.assertEqual('1.10', base_placement_client.PLACEMENT_MICROVERSION)
+
+ def test_multiple_service_microversion(self):
+ self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+ compute_microversion='2.10', volume_microversion='3.10',
+ placement_microversion='1.10'))
+ self.assertEqual('2.10', base_compute_client.COMPUTE_MICROVERSION)
+ self.assertEqual('3.10', base_client.VOLUME_MICROVERSION)
+ self.assertEqual('1.10', base_placement_client.PLACEMENT_MICROVERSION)
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 3772774..746cb34 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -19,9 +19,9 @@
#
# In order to function correctly, the environment in which the
# script runs must have
-# * network access to the review.openstack.org Gerrit API
+# * network access to the review.opendev.org Gerrit API
# working directory
-# * network access to https://git.openstack.org/cgit
+# * network access to https://opendev.org/openstack
import json
import re
@@ -36,7 +36,7 @@
from urllib2 import HTTPError
-url = 'https://review.openstack.org/projects/'
+url = 'https://review.opendev.org/projects/'
# This is what a project looks like
'''
@@ -59,7 +59,8 @@
def has_tempest_plugin(proj):
try:
r = urllib.urlopen(
- "https://git.openstack.org/cgit/%s/plain/setup.cfg" % proj)
+ "https://opendev.org/%s/raw/branch/"
+ "master/setup.cfg" % proj)
except HTTPError as err:
if err.code == 404:
return False
diff --git a/tools/generate-tempest-plugins-list.sh b/tools/generate-tempest-plugins-list.sh
index 17a4059..b4e5430 100755
--- a/tools/generate-tempest-plugins-list.sh
+++ b/tools/generate-tempest-plugins-list.sh
@@ -28,9 +28,9 @@
# * the environment variable git_dir pointing to the location
# * of said git repositories
# ) OR (
-# * network access to the review.openstack.org Gerrit API
+# * network access to the review.opendev.org Gerrit API
# working directory
-# * network access to https://git.openstack.org/cgit
+# * network access to https://opendev.org/openstack
# ))
#
# If a file named doc/source/data/tempest-plugins-registry.header or
@@ -69,8 +69,8 @@
i=0
for plugin in ${sorted_plugins}; do
i=$((i+1))
- giturl="https://git.openstack.org/openstack/${plugin}"
- gitlink="https://git.openstack.org/cgit/openstack/${plugin}"
+ giturl="https://opendev.org/openstack/${plugin}"
+ gitlink="https://opendev.org/openstack/${plugin}"
printf "%-3s %-${name_col_len}s %s\n" "$i" "${plugin}" "\`${giturl} <${gitlink}>\`__"
done
diff --git a/tools/tempest-plugin-sanity.sh b/tools/tempest-plugin-sanity.sh
index 6bb87c5..b291fcc 100644
--- a/tools/tempest-plugin-sanity.sh
+++ b/tools/tempest-plugin-sanity.sh
@@ -46,20 +46,20 @@
# List of projects having tempest plugin stale or unmaintained for a long time
# (6 months or more)
# TODO(masayukig): Some of these can be removed from BLACKLIST in the future.
-# barbican-tempest-plugin: https://review.openstack.org/#/c/634631/
+# barbican-tempest-plugin: https://review.opendev.org/#/c/634631/
# cyborg-tempest-plugin: https://review.opendev.org/659687
-# intel-nfv-ci-tests: https://review.openstack.org/#/c/634640/
-# networking-ansible: https://review.openstack.org/#/c/634647/
-# networking-generic-switch: https://review.openstack.org/#/c/634846/
-# networking-l2gw-tempest-plugin: https://review.openstack.org/#/c/635093/
-# networking-midonet: https://review.openstack.org/#/c/635096/
-# networking-plumgrid: https://review.openstack.org/#/c/635096/
-# networking-spp: https://review.openstack.org/#/c/635098/
-# neutron-dynamic-routing: https://review.openstack.org/#/c/637718/
-# neutron-vpnaas: https://review.openstack.org/#/c/637719/
-# nova-lxd: https://review.openstack.org/#/c/638334/
-# valet: https://review.openstack.org/#/c/638339/
-# vitrage-tempest-plugin: https://review.openstack.org/#/c/639003/
+# intel-nfv-ci-tests: https://review.opendev.org/#/c/634640/
+# networking-ansible: https://review.opendev.org/#/c/634647/
+# networking-generic-switch: https://review.opendev.org/#/c/634846/
+# networking-l2gw-tempest-plugin: https://review.opendev.org/#/c/635093/
+# networking-midonet: https://review.opendev.org/#/c/635096/
+# networking-plumgrid: https://review.opendev.org/#/c/635096/
+# networking-spp: https://review.opendev.org/#/c/635098/
+# neutron-dynamic-routing: https://review.opendev.org/#/c/637718/
+# neutron-vpnaas: https://review.opendev.org/#/c/637719/
+# nova-lxd: https://review.opendev.org/#/c/638334/
+# valet: https://review.opendev.org/#/c/638339/
+
BLACKLIST="
barbican-tempest-plugin
cyborg-tempest-plugin
@@ -74,18 +74,17 @@
neutron-vpnaas
nova-lxd
valet
-vitrage-tempest-plugin
"
# Function to clone project using zuul-cloner or from git
function clone_project() {
if [ -e /usr/zuul-env/bin/zuul-cloner ]; then
/usr/zuul-env/bin/zuul-cloner --cache-dir /opt/git \
- https://git.openstack.org \
+ https://opendev.org \
openstack/"$1"
elif [ -e /usr/bin/git ]; then
- /usr/bin/git clone https://git.openstack.org/openstack/"$1" \
+ /usr/bin/git clone https://opendev.org/openstack/"$1" \
openstack/"$1"
fi
diff --git a/tox.ini b/tox.ini
index 9bee3dd..48a2baa 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,7 +9,7 @@
VIRTUAL_ENV={envdir}
OS_TEST_PATH=./tempest/test_discover
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
[testenv]
@@ -25,7 +25,7 @@
install_command = pip install {opts} {packages}
whitelist_externals = *
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
@@ -173,7 +173,7 @@
[testenv:venv]
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/doc/requirements.txt
commands = {posargs}
@@ -188,7 +188,7 @@
[testenv:docs]
basepython = python3
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/doc/requirements.txt
commands =
@@ -221,7 +221,7 @@
import_exceptions = tempest.services
[flake8]
-# E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved. For further detail see https://review.openstack.org/#/c/36788/
+# E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved. For further detail see https://review.opendev.org/#/c/36788/
# E123 skipped because it is ignored by default in the default pep8
# E129 skipped because it is too limiting when combined with other rules
# W504 skipped because it is overeager and unnecessary
@@ -234,7 +234,7 @@
[testenv:releasenotes]
basepython = python3
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/doc/requirements.txt
commands =