Merge "Cap jsonschema 3.2.0 as the minimal version"
diff --git a/.zuul.yaml b/.zuul.yaml
index 87e277c..dfa9add 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -676,7 +676,6 @@
voting: false
irrelevant-files: *tempest-irrelevant-files
- devstack-plugin-ceph-tempest-py3:
- voting: false
irrelevant-files: *tempest-irrelevant-files
- neutron-grenade-multinode:
irrelevant-files: *tempest-irrelevant-files
@@ -718,6 +717,8 @@
irrelevant-files: *tempest-irrelevant-files
- tempest-ipv6-only:
irrelevant-files: *tempest-irrelevant-files-2
+ - devstack-plugin-ceph-tempest-py3:
+ irrelevant-files: *tempest-irrelevant-files
experimental:
jobs:
- tempest-cinder-v2-api:
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 36828e0..c43e420 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -193,10 +193,6 @@
There are also options in the ``scenario`` section for images:
#. ``img_file``
-#. ``img_dir``
-#. ``aki_img_file``
-#. ``ari_img_file``
-#. ``ami_img_file``
#. ``img_container_format``
#. ``img_disk_format``
@@ -205,13 +201,9 @@
Tempest where an image file is located and describe its metadata for when it is
uploaded.
-The behavior of these options is a bit convoluted (which will likely be fixed in
-future versions). You first need to specify ``img_dir``, which is the directory
-in which Tempest will look for the image files. First, it will check if the
-filename set for ``img_file`` could be found in ``img_dir``. If it is found then
-the ``img_container_format`` and ``img_disk_format`` options are used to upload
-that image to glance. However, if it is not found, Tempest will look for the
-three uec image file name options as a fallback. If neither is found, the tests
+You first need to specify full path of the image using ``img_file`` option.
+If it is found then the ``img_container_format`` and ``img_disk_format``
+options are used to upload that image to glance. If it's not found, the tests
requiring an image to upload will fail.
It is worth pointing out that using `cirros`_ is a very good choice for running
diff --git a/doc/source/sampleconf.rst b/doc/source/sampleconf.rst
index c290140..45164a3 100644
--- a/doc/source/sampleconf.rst
+++ b/doc/source/sampleconf.rst
@@ -10,4 +10,6 @@
The sample configuration can also be viewed in `file form <_static/tempest.conf.sample>`_.
-.. literalinclude:: _static/tempest.conf.sample
+.. only:: html
+
+ .. literalinclude:: _static/tempest.conf.sample
diff --git a/releasenotes/notes/Remove-deprecated-image-scenario-options-b573c60e873ab451.yaml b/releasenotes/notes/Remove-deprecated-image-scenario-options-b573c60e873ab451.yaml
new file mode 100644
index 0000000..018d01d
--- /dev/null
+++ b/releasenotes/notes/Remove-deprecated-image-scenario-options-b573c60e873ab451.yaml
@@ -0,0 +1,15 @@
+---
+upgrade:
+ - |
+ The following deprecated image scenario options are removed after a ~4
+ year deprecation period.
+
+ * ``ami_img_file``
+ * ``ari_img_file``
+ * ``aki_img_file``
+
+ Starting Tempest 25.0.0 release, CONF.scenario.img_file need a full path
+ for the image. CONF.scenario.img_dir was deprecated and will be removed
+ in the next release. Till Tempest 25.0.0, old behavior is maintained and
+ keep working but starting Tempest 26.0.0, you need to specify the full path
+ in CONF.scenario.img_file config option.
diff --git a/releasenotes/notes/Set-default-of-operator_role-to-member-f9c3abd2ebde23b7.yaml b/releasenotes/notes/Set-default-of-operator_role-to-member-f9c3abd2ebde23b7.yaml
new file mode 100644
index 0000000..980f4ca
--- /dev/null
+++ b/releasenotes/notes/Set-default-of-operator_role-to-member-f9c3abd2ebde23b7.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ ``Member`` role has been deprecated and replaced by ``member``. Therefore
+ the default value of config option ``[object-storage].operator_role`` is
+ changed to ``member``. (Fixes bug #1330132)
diff --git a/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml b/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml
new file mode 100644
index 0000000..dfee1db
--- /dev/null
+++ b/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Concurrency parameter for account-generator command was accepting
+ negative values and zero. The concurrency parameter now accepts only
+ positive numbers. When a negative value or zero is passed to the
+ program then the program ends and help is displayed.
diff --git a/releasenotes/notes/network-swap-to-project_id-a1d7fdf6c5e1cf44.yaml b/releasenotes/notes/network-swap-to-project_id-a1d7fdf6c5e1cf44.yaml
new file mode 100644
index 0000000..4cf0c76
--- /dev/null
+++ b/releasenotes/notes/network-swap-to-project_id-a1d7fdf6c5e1cf44.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ [`blueprint blueprint adopt-oslo-versioned-objects-for-db <https://blueprints.launchpad.net/neutron/+spec/adopt-oslo-versioned-objects-for-db>`_]
+ Any reference to "tenant_id" in Network objects is replaced with
+ "project_id".
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index f42f53a..d6b6b7e 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -107,7 +107,10 @@
"""
def verify_flavor_response_extension(flavor):
# check some extensions for the flavor create/show/detail response
- self.assertEqual(flavor['swap'], '')
+ if self.is_requested_microversion_compatible('2.74'):
+ self.assertEqual(flavor['swap'], '')
+ else:
+ self.assertEqual(flavor['swap'], 0)
self.assertEqual(int(flavor['rxtx_factor']), 1)
self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'], 0)
self.assertEqual(flavor['os-flavor-access:is_public'], True)
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index 033caa8..a4d7d3f 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -43,6 +43,9 @@
Expect all services to be returned when the request contains invalid
parameters.
"""
+ if not self.is_requested_microversion_compatible('2.74'):
+ raise self.skipException(
+ "From microversion 2.75 invalid parameters are not allowed.")
services = self.client.list_services()['services']
services_xxx = (self.client.list_services(xxx='nova-compute')
['services'])
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 5a646f9..1247494 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -122,15 +122,17 @@
def _create_server_and_rescue_image(self, hw_rescue_device=None,
hw_rescue_bus=None,
block_device_mapping_v2=None):
+
+ server_id = self.create_test_server(
+ wait_until='ACTIVE')['id']
+ image_id = self.create_image_from_server(
+ server_id, wait_until='ACTIVE')['id']
+
if block_device_mapping_v2:
server_id = self.create_test_server(
wait_until='ACTIVE',
block_device_mapping_v2=block_device_mapping_v2)['id']
- else:
- server_id = self.create_test_server(wait_until='ACTIVE')['id']
- image_id = self.create_image_from_server(server_id,
- wait_until='ACTIVE')['id']
if hw_rescue_bus:
self.images_client.update_image(
image_id, [dict(add='/hw_rescue_bus',
@@ -193,6 +195,7 @@
min_microversion = '2.87'
+ @decorators.attr(type='slow')
@decorators.idempotent_id('48f123cb-922a-4065-8db6-b9a9074a556b')
def test_stable_device_rescue_bfv_blank_volume(self):
block_device_mapping_v2 = [{
@@ -205,6 +208,7 @@
block_device_mapping_v2=block_device_mapping_v2)
self._test_stable_device_rescue(server_id, rescue_image_id)
+ @decorators.attr(type='slow')
@decorators.idempotent_id('e4636333-c928-40fc-98b7-70a23eef4224')
def test_stable_device_rescue_bfv_image_volume(self):
block_device_mapping_v2 = [{
@@ -217,19 +221,3 @@
hw_rescue_device='disk', hw_rescue_bus='virtio',
block_device_mapping_v2=block_device_mapping_v2)
self._test_stable_device_rescue(server_id, rescue_image_id)
-
- @decorators.idempotent_id('7fcc5d2c-130e-4750-95f5-7343f9d0a2f3')
- def test_stable_device_rescue_bfv_snapshot_volume(self):
- volume_id = self.create_volume()['id']
- self.volumes_client.set_bootable_volume(volume_id, bootable=True)
- snapshot_id = self.create_volume_snapshot(volume_id)['id']
- block_device_mapping_v2 = [{
- "boot_index": "0",
- "source_type": "snapshot",
- "volume_size": CONF.volume.volume_size,
- "uuid": snapshot_id,
- "destination_type": "volume"}]
- server_id, rescue_image_id = self._create_server_and_rescue_image(
- hw_rescue_device='disk', hw_rescue_bus='virtio',
- block_device_mapping_v2=block_device_mapping_v2)
- self._test_stable_device_rescue(server_id, rescue_image_id)
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index fa1c47f..cb05f39 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import operator
+
from oslo_utils import timeutils
import six
@@ -40,6 +42,15 @@
authenticated_token = self.non_admin_client.show_token(
subject_token)['token']
# sanity checking to make sure they are indeed the same token
+ # If there are roles in the token, sort the roles
+ authenticated_token_roles = authenticated_token.get("roles")
+ if authenticated_token_roles:
+ authenticated_token["roles"] = authenticated_token_roles.sort(
+ key=operator.itemgetter('id'))
+ token_body_roles = token_body.get("roles")
+ if token_body_roles:
+ token_body["roles"] = token_body_roles.sort(
+ key=operator.itemgetter('id'))
self.assertEqual(authenticated_token, token_body)
# test to see if token has been properly authenticated
self.assertEqual(authenticated_token['user']['id'], user_id)
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 adc4dda..7d41019 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -93,7 +93,7 @@
# Creates a floating IP
body = self.admin_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
- tenant_id=self.network['tenant_id'],
+ project_id=self.network['project_id'],
port_id=self.port['id'])
created_floating_ip = body['floatingip']
self.addCleanup(
@@ -101,7 +101,7 @@
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['project_id'])
self.assertIsNotNone(created_floating_ip['floating_ip_address'])
self.assertEqual(created_floating_ip['port_id'], self.port['id'])
self.assertEqual(created_floating_ip['floating_network_id'],
@@ -116,8 +116,8 @@
self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
self.assertEqual(shown_floating_ip['floating_network_id'],
self.ext_net_id)
- self.assertEqual(shown_floating_ip['tenant_id'],
- self.network['tenant_id'])
+ self.assertEqual(shown_floating_ip['project_id'],
+ self.network['project_id'])
self.assertEqual(shown_floating_ip['floating_ip_address'],
created_floating_ip['floating_ip_address'])
self.assertEqual(shown_floating_ip['port_id'], self.port['id'])
diff --git a/tempest/api/network/admin/test_metering_extensions.py b/tempest/api/network/admin/test_metering_extensions.py
index 5063fef..942b66c 100644
--- a/tempest/api/network/admin/test_metering_extensions.py
+++ b/tempest/api/network/admin/test_metering_extensions.py
@@ -121,7 +121,7 @@
metering_label = body['metering_label']
self.assertEqual(self.metering_label['id'], metering_label['id'])
self.assertEqual(self.metering_label['tenant_id'],
- metering_label['tenant_id'])
+ metering_label['project_id'])
self.assertEqual(self.metering_label['name'], metering_label['name'])
self.assertEqual(self.metering_label['description'],
metering_label['description'])
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 0db038d..3562d6f 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -58,12 +58,12 @@
# Create two networks
n1 = self.admin_networks_client.create_network(
- tenant_id=self.project['id'])
+ project_id=self.project['id'])
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'])
+ project_id=self.project['id'])
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.admin_networks_client.delete_network,
n2['network']['id'])
@@ -73,7 +73,7 @@
lib_exc.Conflict,
r"Quota exceeded for resources: \['network'\].*"):
n3 = self.admin_networks_client.create_network(
- tenant_id=self.project['id'])
+ project_id=self.project['id'])
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_quotas.py b/tempest/api/network/admin/test_quotas.py
index ef5ebb6..8b7bfb1 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -67,7 +67,7 @@
non_default_quotas = self.admin_quotas_client.list_quotas()
found = False
for qs in non_default_quotas['quotas']:
- if qs['tenant_id'] == project_id:
+ if qs['project_id'] == project_id:
found = True
self.assertTrue(found)
@@ -81,7 +81,7 @@
self.admin_quotas_client.reset_quotas(project_id)
non_default_quotas = self.admin_quotas_client.list_quotas()
for q in non_default_quotas['quotas']:
- self.assertNotEqual(project_id, q['tenant_id'])
+ self.assertNotEqual(project_id, q['project_id'])
quota_set = self.admin_quotas_client.show_quotas(project_id)['quota']
default_quotas = self.admin_quotas_client.show_default_quotas(
project_id)['quota']
diff --git a/tempest/api/network/admin/test_routers.py b/tempest/api/network/admin/test_routers.py
index 41f97d8..417eb70 100644
--- a/tempest/api/network/admin/test_routers.py
+++ b/tempest/api/network/admin/test_routers.py
@@ -63,11 +63,11 @@
name = data_utils.rand_name('router-')
create_body = self.admin_routers_client.create_router(
- name=name, tenant_id=project_id)
+ name=name, project_id=project_id)
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'])
+ self.assertEqual(project_id, create_body['router']['project_id'])
@decorators.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
@utils.requires_ext(extension='ext-gw-mode', service='network')
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 270f802..291581c 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -106,14 +106,14 @@
attribute will be set to True
"""
name = data_utils.rand_name('router')
- tenant_id = self.routers_client.tenant_id
+ project_id = self.routers_client.project_id
# router needs to be in admin state down in order to be upgraded to DVR
# l3ha routers are not upgradable to dvr, make it explicitly non ha
router = self.admin_routers_client.create_router(name=name,
distributed=False,
admin_state_up=False,
ha=False,
- tenant_id=tenant_id)
+ project_id=project_id)
router_id = router['router']['id']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.admin_routers_client.delete_router, router_id)
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index aaa5497..abcbbf7 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -83,7 +83,7 @@
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['project_id'])
self.assertIsNotNone(created_floating_ip['floating_ip_address'])
self.assertEqual(created_floating_ip['port_id'], self.ports[0]['id'])
self.assertEqual(created_floating_ip['floating_network_id'],
@@ -97,8 +97,8 @@
self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
self.assertEqual(shown_floating_ip['floating_network_id'],
self.ext_net_id)
- self.assertEqual(shown_floating_ip['tenant_id'],
- created_floating_ip['tenant_id'])
+ self.assertEqual(shown_floating_ip['project_id'],
+ created_floating_ip['project_id'])
self.assertEqual(shown_floating_ip['floating_ip_address'],
created_floating_ip['floating_ip_address'])
self.assertEqual(shown_floating_ip['port_id'], self.ports[0]['id'])
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 10121de..c4ad720 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -192,9 +192,9 @@
port_list = self.ports_client.list_ports(fixed_ips=fixed_ips)
# Check that we got the desired port
ports = port_list['ports']
- tenant_ids = set([port['tenant_id'] for port in ports])
- self.assertEqual(len(tenant_ids), 1,
- 'Ports from multiple tenants are in the list resp')
+ project_ids = set([port['project_id'] for port in ports])
+ self.assertEqual(len(project_ids), 1,
+ 'Ports from multiple projects are in the list resp')
port_ids = [port['id'] for port in ports]
fixed_ips = [port['fixed_ips'] for port in ports]
port_net_ids = [port['network_id'] for port in ports]
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index 6599e43..80f790f 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -16,7 +16,6 @@
import tempfile
from tempest.api.object_storage import base
-from tempest.common import custom_matchers
from tempest.common import utils
from tempest.lib import decorators
@@ -76,17 +75,7 @@
resp = self._upload_archive(filepath)
self.containers.append(container_name)
- # When uploading an archived file with the bulk operation, the response
- # does not contain 'content-length' header. This is the special case,
- # therefore the existence of response headers is checked without
- # custom matcher.
- self.assertIn('transfer-encoding', resp.response)
- self.assertIn('content-type', resp.response)
- self.assertIn('x-trans-id', resp.response)
- self.assertIn('date', resp.response)
-
- # Check only the format of common headers with custom matcher
- self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
+ self.assertHeaders(resp.response, 'Account', 'PUT')
param = {'format': 'json'}
resp, body = self.account_client.list_account_containers(param)
@@ -113,17 +102,7 @@
data = '%s/%s\n%s' % (container_name, object_name, container_name)
resp = self.bulk_client.delete_bulk_data(data=data)
- # When deleting multiple files using the bulk operation, the response
- # does not contain 'content-length' header. This is the special case,
- # therefore the existence of response headers is checked without
- # custom matcher.
- self.assertIn('transfer-encoding', resp.response)
- self.assertIn('content-type', resp.response)
- self.assertIn('x-trans-id', resp.response)
- self.assertIn('date', resp.response)
-
- # Check only the format of common headers with custom matcher
- self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
+ self.assertHeaders(resp.response, 'Account', 'DELETE')
# Check if uploaded contents are completely deleted
self._check_contents_deleted(container_name)
@@ -139,17 +118,7 @@
resp = self.bulk_client.delete_bulk_data_with_post(data=data)
- # When deleting multiple files using the bulk operation, the response
- # does not contain 'content-length' header. This is the special case,
- # therefore the existence of response headers is checked without
- # custom matcher.
- self.assertIn('transfer-encoding', resp.response)
- self.assertIn('content-type', resp.response)
- self.assertIn('x-trans-id', resp.response)
- self.assertIn('date', resp.response)
-
- # Check only the format of common headers with custom matcher
- self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
+ self.assertHeaders(resp.response, 'Account', 'POST')
# Check if uploaded contents are completely deleted
self._check_contents_deleted(container_name)
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 322579c..bdcb5ae 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -123,7 +123,7 @@
self.assertEqual(object_content, obj_name[::-1].encode())
@decorators.attr(type='slow')
- @decorators.skip_because(bug='1317133')
+ @decorators.unstable_test(bug='1317133')
@decorators.idempotent_id('be008325-1bba-4925-b7dd-93b58f22ce9b')
@testtools.skipIf(
not CONF.object_storage_feature_enabled.container_sync,
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index c66776e..8bb2e6e 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -17,7 +17,6 @@
from oslo_serialization import jsonutils as json
from tempest.api.object_storage import base
-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
@@ -160,17 +159,7 @@
object_name,
params=params_del)
- # When deleting SLO using multipart manifest, the response contains
- # not 'content-length' but 'transfer-encoding' header. This is the
- # special case, therefore the existence of response headers is checked
- # outside of custom matcher.
- self.assertIn('transfer-encoding', resp)
- self.assertIn('content-type', resp)
- self.assertIn('x-trans-id', resp)
- self.assertIn('date', resp)
-
- # Check only the format of common headers with custom matcher
- self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+ self.assertHeaders(resp, 'Object', 'DELETE')
resp, body = self.container_client.list_container_objects(
self.container_name)
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index bcbcf43..7af5927 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -233,12 +233,15 @@
return group
def delete_group(self, group_id, delete_volumes=True):
- self.groups_client.delete_group(group_id, delete_volumes)
+ group_vols = []
if delete_volumes:
vols = self.volumes_client.list_volumes(detail=True)['volumes']
for vol in vols:
if vol['group_id'] == group_id:
- self.volumes_client.wait_for_resource_deletion(vol['id'])
+ group_vols.append(vol['id'])
+ self.groups_client.delete_group(group_id, delete_volumes)
+ for vol in group_vols:
+ self.volumes_client.wait_for_resource_deletion(vol)
self.groups_client.wait_for_resource_deletion(group_id)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index b230615..ff552a1 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -97,6 +97,7 @@
[OPTIONS] <accounts_file.yaml> -h``.
"""
+import argparse
import os
import traceback
@@ -199,6 +200,14 @@
LOG.info('%s generated successfully!', account_file)
+def positive_int(number):
+ number = int(number)
+ if number <= 0:
+ raise argparse.ArgumentTypeError("Concurrency value should be a "
+ "positive number")
+ return number
+
+
def _parser_add_args(parser):
parser.add_argument('-c', '--config-file',
metavar='/etc/tempest.conf',
@@ -228,7 +237,7 @@
help='Resources tag')
parser.add_argument('-r', '--concurrency',
default=1,
- type=int,
+ type=positive_int,
required=False,
dest='concurrency',
help='Concurrency count')
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 8d5bdbd..235d8e3 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -60,16 +60,16 @@
"""
import argparse
+import configparser
import os
import re
import sys
import traceback
+from urllib import parse as urlparse
from cliff import command
from oslo_log import log as logging
from oslo_serialization import jsonutils as json
-from six import moves
-from six.moves.urllib import parse as urlparse
from tempest import clients
from tempest.common import credentials_factory as credentials
@@ -439,9 +439,9 @@
if update:
conf_file = _get_config_file()
- CONF_PARSER = moves.configparser.ConfigParser()
+ CONF_PARSER = configparser.ConfigParser()
CONF_PARSER.optionxform = str
- CONF_PARSER.readfp(conf_file)
+ CONF_PARSER.read_file(conf_file)
# Indicate not to create network resources as part of getting credentials
net_resources = {
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index c702d88..f1adeab 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -62,8 +62,9 @@
# [1] https://bugs.launchpad.net/swift/+bug/1537811
# [2] http://tracker.ceph.com/issues/13582
if ('content-length' not in actual and
+ 'transfer-encoding' not in actual and
self._content_length_required(actual)):
- return NonExistentHeader('content-length')
+ return NonExistentHeaders(['content-length', 'transfer-encoding'])
if 'content-type' not in actual:
return NonExistentHeader('content-type')
if 'x-trans-id' not in actual:
@@ -192,6 +193,19 @@
return {}
+class NonExistentHeaders(object):
+ """Informs an error message in the case of missing certain headers"""
+
+ def __init__(self, headers):
+ self.headers = headers
+
+ def describe(self):
+ return "none of these headers exist: %s" % self.headers
+
+ def get_details(self):
+ return {}
+
+
class InvalidHeaderValue(object):
"""Informs an error message when a header contains a bad value"""
diff --git a/tempest/config.py b/tempest/config.py
index 204d977..11f9426 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -1021,7 +1021,7 @@
help="Number of seconds to wait while looping to check the "
"status of a container to container synchronization"),
cfg.StrOpt('operator_role',
- default='Member',
+ default='member',
help="Role to add to users created for swift tests to "
"enable creating containers"),
cfg.StrOpt('reseller_admin_role',
@@ -1068,11 +1068,13 @@
cfg.StrOpt('img_dir',
default='/opt/stack/new/devstack/files/images/'
'cirros-0.3.1-x86_64-uec',
- help='Directory containing image files',
+ help='Directory containing image files, this has been '
+ 'deprecated - img_file option contains a full path now.',
deprecated_for_removal=True),
cfg.StrOpt('img_file', deprecated_name='qcow2_img_file',
- default='cirros-0.3.1-x86_64-disk.img',
- help='Image file name'),
+ default='/opt/stack/new/devstack/files/images'
+ '/cirros-0.3.1-x86_64-disk.img',
+ help='Image full path.'),
cfg.StrOpt('img_disk_format',
default='qcow2',
help='Image disk format'),
@@ -1081,18 +1083,6 @@
help='Image container format'),
cfg.DictOpt('img_properties', help='Glance image properties. '
'Use for custom images which require them'),
- cfg.StrOpt('ami_img_file',
- default='cirros-0.3.1-x86_64-blank.img',
- help='AMI image file name',
- deprecated_for_removal=True),
- cfg.StrOpt('ari_img_file',
- default='cirros-0.3.1-x86_64-initrd',
- help='ARI image file name',
- deprecated_for_removal=True),
- cfg.StrOpt('aki_img_file',
- default='cirros-0.3.1-x86_64-vmlinuz',
- help='AKI image file name',
- deprecated_for_removal=True),
# TODO(yfried): add support for dhcpcd
cfg.StrOpt('dhcp_client',
default='udhcpc',
diff --git a/tempest/lib/api_schema/response/volume/snapshots.py b/tempest/lib/api_schema/response/volume/snapshots.py
index e9aeb64..9d52801 100644
--- a/tempest/lib/api_schema/response/volume/snapshots.py
+++ b/tempest/lib/api_schema/response/volume/snapshots.py
@@ -28,7 +28,7 @@
'status': {'type': 'string'},
'description': {'type': ['string', 'null']},
'created_at': parameter_types.date_time,
- 'name': {'type': 'string'},
+ 'name': {'type': ['string', 'null']},
'volume_id': {'type': 'string', 'format': 'uuid'},
'metadata': metadata,
'id': {'type': 'string', 'format': 'uuid'},
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index f27e926..8b82391 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -207,10 +207,10 @@
# our newly created user has a role on the newly created project.
if self.identity_version == 'v3' and not role_assigned:
try:
- self.creds_client.create_user_role('Member')
+ self.creds_client.create_user_role('member')
except lib_exc.Conflict:
- LOG.warning('Member role already exists, ignoring conflict.')
- self.creds_client.assign_user_role(user, project, 'Member')
+ LOG.warning('member role already exists, ignoring conflict.')
+ self.creds_client.assign_user_role(user, project, 'member')
creds = self.creds_client.get_credentials(user, project, user_password)
return cred_provider.TestResources(creds)
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 431a0a0..1d524f0 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -21,6 +21,7 @@
import jsonschema
from oslo_log import log as logging
+from oslo_log import versionutils
from oslo_serialization import jsonutils as json
import six
from six.moves import urllib
@@ -177,13 +178,27 @@
return self.auth_provider.credentials.tenant_name
@property
+ def project_id(self):
+ """The project id being used for requests
+
+ :rtype: string
+ :return: The project id being used for requests
+ """
+ return self.auth_provider.credentials.tenant_id
+
+ @property
def tenant_id(self):
"""The tenant/project id being used for requests
:rtype: string
:return: The tenant/project id being used for requests
"""
- return self.auth_provider.credentials.tenant_id
+ # NOTE(ralonsoh): this property should be deprecated, reference
+ # blueprint adopt-oslo-versioned-objects-for-db.
+ versionutils.report_deprecated_feature(
+ self.LOG, '"tenant_id" property is deprecated for removal, use '
+ '"project_id" instead')
+ return self.project_id
@property
def password(self):
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 3ceecda..6723516 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -206,7 +206,10 @@
def action(self, server_id, action_name,
schema=schema.server_actions_common_schema,
**kwargs):
- post_body = json.dumps({action_name: kwargs})
+ if 'body' in kwargs:
+ post_body = json.dumps(kwargs['body'])
+ else:
+ post_body = json.dumps({action_name: kwargs})
resp, body = self.post('servers/%s/action' % server_id,
post_body)
if body:
@@ -608,6 +611,15 @@
API reference:
https://docs.openstack.org/api-ref/compute/#unshelve-restore-shelved-server-unshelve-action
"""
+ # NOTE(gmann): pass None as request body if nothing is requested.
+ # Nova started the request body check since 2.77 microversion and only
+ # accept AZ or None as valid req body and reject the empty dict {}.
+ # Before 2.77 microverison anything is valid body as Nova does not
+ # check the request body but as per api-ref None is valid request
+ # body to pass so we do not need to check the requested microversion
+ # here and always default req body to None.
+ if not kwargs:
+ kwargs['body'] = {'unshelve': None}
return self.action(server_id, 'unshelve', **kwargs)
def shelve_offload_server(self, server_id, **kwargs):
diff --git a/tempest/lib/services/network/quotas_client.py b/tempest/lib/services/network/quotas_client.py
index 997d201..96cc65d 100644
--- a/tempest/lib/services/network/quotas_client.py
+++ b/tempest/lib/services/network/quotas_client.py
@@ -12,11 +12,33 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
+
from tempest.lib.services.network import base
+def _warning_deprecate_tenant_id(func):
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ _self = args[0]
+ # check length of arg to know whether 'tenant_id' is passed as
+ # positional arg or kwargs.
+ if len(args) < 2:
+ if 'tenant_id' in kwargs:
+ _self.LOG.warning(
+ 'positional arg name "tenant_id" is deprecated, for '
+ 'removal, please start using "project_id" instead')
+ elif 'project_id' in kwargs:
+ # fallback to deprecated name till deprecation phase.
+ kwargs['tenant_id'] = kwargs.pop('project_id')
+
+ return func(*args, **kwargs)
+ return inner
+
+
class QuotasClient(base.BaseNetworkClient):
+ @_warning_deprecate_tenant_id
def update_quotas(self, tenant_id, **kwargs):
"""Update quota for a project.
@@ -28,12 +50,14 @@
uri = '/quotas/%s' % tenant_id
return self.update_resource(uri, put_body)
+ @_warning_deprecate_tenant_id
def reset_quotas(self, tenant_id): # noqa
# NOTE: This noqa is for passing T111 check and we cannot rename
# to keep backwards compatibility.
uri = '/quotas/%s' % tenant_id
return self.delete_resource(uri)
+ @_warning_deprecate_tenant_id
def show_quotas(self, tenant_id, **fields):
"""Show quota for a project.
@@ -54,11 +78,13 @@
uri = '/quotas'
return self.list_resources(uri, **filters)
+ @_warning_deprecate_tenant_id
def show_default_quotas(self, tenant_id):
"""List default quotas for a project."""
uri = '/quotas/%s/default' % tenant_id
return self.show_resource(uri)
+ @_warning_deprecate_tenant_id
def show_quota_details(self, tenant_id):
"""Show quota details for a project."""
uri = '/quotas/%s/details.json' % tenant_id
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index efdfe8e..a80b77d 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import os
import subprocess
import netaddr
@@ -531,33 +532,32 @@
return image['id']
def glance_image_create(self):
- img_path = CONF.scenario.img_dir + "/" + CONF.scenario.img_file
- aki_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.aki_img_file
- ari_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ari_img_file
- ami_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ami_img_file
+ img_path = CONF.scenario.img_file
+ if not os.path.exists(img_path):
+ # TODO(kopecmartin): replace LOG.warning for rasing
+ # InvalidConfiguration exception after tempest 25.0.0 is
+ # released - there will be one release which accepts both
+ # behaviors in order to avoid many failures across CIs and etc.
+ LOG.warning(
+ 'Starting Tempest 25.0.0 release, CONF.scenario.img_file need '
+ 'a full path for the image. CONF.scenario.img_dir was '
+ 'deprecated and will be removed in the next release. Till '
+ 'Tempest 25.0.0, old behavior is maintained and keep working '
+ 'but starting Tempest 26.0.0, you need to specify the full '
+ 'path in CONF.scenario.img_file config option.')
+ img_path = os.path.join(CONF.scenario.img_dir, img_path)
img_container_format = CONF.scenario.img_container_format
img_disk_format = CONF.scenario.img_disk_format
img_properties = CONF.scenario.img_properties
LOG.debug("paths: img: %s, container_format: %s, disk_format: %s, "
- "properties: %s, ami: %s, ari: %s, aki: %s",
+ "properties: %s",
img_path, img_container_format, img_disk_format,
- img_properties, ami_img_path, ari_img_path, aki_img_path)
- try:
- image = self._image_create('scenario-img',
- img_container_format,
- img_path,
- disk_format=img_disk_format,
- properties=img_properties)
- except IOError:
- LOG.warning(
- "A(n) %s image was not found. Retrying with uec image.",
- img_disk_format)
- kernel = self._image_create('scenario-aki', 'aki', aki_img_path)
- ramdisk = self._image_create('scenario-ari', 'ari', ari_img_path)
- properties = {'kernel_id': kernel, 'ramdisk_id': ramdisk}
- image = self._image_create('scenario-ami', 'ami',
- path=ami_img_path,
- properties=properties)
+ img_properties)
+ image = self._image_create('scenario-img',
+ img_container_format,
+ img_path,
+ disk_format=img_disk_format,
+ properties=img_properties)
LOG.debug("image:%s", image)
return image
@@ -868,15 +868,15 @@
raise cls.skipException('Neutron not available')
def _create_network(self, networks_client=None,
- tenant_id=None,
+ project_id=None,
namestart='network-smoke-',
port_security_enabled=True, **net_dict):
if not networks_client:
networks_client = self.networks_client
- if not tenant_id:
- tenant_id = networks_client.tenant_id
+ if not project_id:
+ project_id = networks_client.project_id
name = data_utils.rand_name(namestart)
- network_kwargs = dict(name=name, tenant_id=tenant_id)
+ network_kwargs = dict(name=name, project_id=project_id)
if net_dict:
network_kwargs.update(net_dict)
# Neutron disables port security by default so we have to check the
@@ -901,14 +901,14 @@
if not subnets_client:
subnets_client = self.subnets_client
- def cidr_in_use(cidr, tenant_id):
+ def cidr_in_use(cidr, project_id):
"""Check cidr existence
:returns: True if subnet with cidr already exist in tenant
False else
"""
cidr_in_use = self.os_admin.subnets_client.list_subnets(
- tenant_id=tenant_id, cidr=cidr)['subnets']
+ project_id=project_id, cidr=cidr)['subnets']
return len(cidr_in_use) != 0
ip_version = kwargs.pop('ip_version', 4)
@@ -927,13 +927,13 @@
# blocks until an unallocated block is found.
for subnet_cidr in tenant_cidr.subnet(num_bits):
str_cidr = str(subnet_cidr)
- if cidr_in_use(str_cidr, tenant_id=network['tenant_id']):
+ if cidr_in_use(str_cidr, project_id=network['project_id']):
continue
subnet = dict(
name=data_utils.rand_name(namestart),
network_id=network['id'],
- tenant_id=network['tenant_id'],
+ project_id=network['project_id'],
cidr=str_cidr,
ip_version=ip_version,
**kwargs
@@ -1015,7 +1015,7 @@
kwargs = {
'floating_network_id': external_network_id,
'port_id': port_id,
- 'tenant_id': thing['tenant_id'],
+ 'tenant_id': thing.get('project_id') or thing['tenant_id'],
'fixed_ip_address': ip4,
}
if CONF.network.subnet_id:
@@ -1038,9 +1038,12 @@
floatingip_id = floating_ip['id']
def refresh():
- result = (self.floating_ips_client.
- show_floatingip(floatingip_id)['floatingip'])
- return status == result['status']
+ floating_ip = (self.floating_ips_client.
+ show_floatingip(floatingip_id)['floatingip'])
+ if status == floating_ip['status']:
+ LOG.info("FloatingIP: {fp} is at status: {st}"
+ .format(fp=floating_ip, st=status))
+ return status == floating_ip['status']
if not test_utils.call_until_true(refresh,
CONF.network.build_timeout,
@@ -1052,8 +1055,6 @@
"failed to reach status: {st}"
.format(fp=floating_ip, cst=floating_ip['status'],
st=status))
- LOG.info("FloatingIP: {fp} is at status: {st}"
- .format(fp=floating_ip, st=status))
def check_tenant_network_connectivity(self, server,
username,
@@ -1121,18 +1122,18 @@
self.fail(msg)
def _create_security_group(self, security_group_rules_client=None,
- tenant_id=None,
+ project_id=None,
namestart='secgroup-smoke',
security_groups_client=None):
if security_group_rules_client is None:
security_group_rules_client = self.security_group_rules_client
if security_groups_client is None:
security_groups_client = self.security_groups_client
- if tenant_id is None:
- tenant_id = security_groups_client.tenant_id
+ if project_id is None:
+ project_id = security_groups_client.project_id
secgroup = self._create_empty_security_group(
namestart=namestart, client=security_groups_client,
- tenant_id=tenant_id)
+ project_id=project_id)
# Add rules to the security group
rules = self._create_loginable_secgroup_rule(
@@ -1140,11 +1141,11 @@
secgroup=secgroup,
security_groups_client=security_groups_client)
for rule in rules:
- self.assertEqual(tenant_id, rule['tenant_id'])
+ self.assertEqual(project_id, rule['project_id'])
self.assertEqual(secgroup['id'], rule['security_group_id'])
return secgroup
- def _create_empty_security_group(self, client=None, tenant_id=None,
+ def _create_empty_security_group(self, client=None, project_id=None,
namestart='secgroup-smoke'):
"""Create a security group without rules.
@@ -1152,23 +1153,23 @@
- IPv4 egress to any
- IPv6 egress to any
- :param tenant_id: secgroup will be created in this tenant
+ :param project_id: secgroup will be created in this project
:returns: the created security group
"""
if client is None:
client = self.security_groups_client
- if not tenant_id:
- tenant_id = client.tenant_id
+ if not project_id:
+ project_id = client.project_id
sg_name = data_utils.rand_name(namestart)
sg_desc = sg_name + " description"
sg_dict = dict(name=sg_name,
description=sg_desc)
- sg_dict['tenant_id'] = tenant_id
+ sg_dict['project_id'] = project_id
result = client.create_security_group(**sg_dict)
secgroup = result['security_group']
self.assertEqual(secgroup['name'], sg_name)
- self.assertEqual(tenant_id, secgroup['tenant_id'])
+ self.assertEqual(project_id, secgroup['project_id'])
self.assertEqual(secgroup['description'], sg_desc)
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
@@ -1177,15 +1178,15 @@
def _create_security_group_rule(self, secgroup=None,
sec_group_rules_client=None,
- tenant_id=None,
+ project_id=None,
security_groups_client=None, **kwargs):
"""Create a rule from a dictionary of rule parameters.
Create a rule in a secgroup. if secgroup not defined will search for
- default secgroup in tenant_id.
+ default secgroup in project_id.
:param secgroup: the security group.
- :param tenant_id: if secgroup not passed -- the tenant in which to
+ :param project_id: if secgroup not passed -- the tenant in which to
search for default secgroup
:param kwargs: a dictionary containing rule parameters:
for example, to allow incoming ssh:
@@ -1200,18 +1201,18 @@
sec_group_rules_client = self.security_group_rules_client
if security_groups_client is None:
security_groups_client = self.security_groups_client
- if not tenant_id:
- tenant_id = security_groups_client.tenant_id
+ if not project_id:
+ project_id = security_groups_client.project_id
if secgroup is None:
- # Get default secgroup for tenant_id
+ # Get default secgroup for project_id
default_secgroups = security_groups_client.list_security_groups(
- name='default', tenant_id=tenant_id)['security_groups']
- msg = "No default security group for tenant %s." % (tenant_id)
+ name='default', project_id=project_id)['security_groups']
+ msg = "No default security group for project %s." % (project_id)
self.assertNotEmpty(default_secgroups, msg)
secgroup = default_secgroups[0]
ruleset = dict(security_group_id=secgroup['id'],
- tenant_id=secgroup['tenant_id'])
+ project_id=secgroup['project_id'])
ruleset.update(kwargs)
sg_rule = sec_group_rules_client.create_security_group_rule(**ruleset)
@@ -1277,7 +1278,7 @@
return rules
- def _get_router(self, client=None, tenant_id=None):
+ def _get_router(self, client=None, project_id=None):
"""Retrieve a router for the given tenant id.
If a public router has been configured, it will be returned.
@@ -1288,8 +1289,8 @@
"""
if not client:
client = self.routers_client
- if not tenant_id:
- tenant_id = client.tenant_id
+ if not project_id:
+ project_id = client.project_id
router_id = CONF.network.public_router_id
network_id = CONF.network.public_network_id
if router_id:
@@ -1299,7 +1300,7 @@
router = client.create_router(
name=data_utils.rand_name(self.__class__.__name__ + '-router'),
admin_state_up=True,
- tenant_id=tenant_id,
+ project_id=project_id,
external_gateway_info=dict(network_id=network_id))['router']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
client.delete_router, router['id'])
@@ -1310,14 +1311,14 @@
def create_networks(self, networks_client=None,
routers_client=None, subnets_client=None,
- tenant_id=None, dns_nameservers=None,
+ project_id=None, dns_nameservers=None,
port_security_enabled=True, **net_dict):
"""Create a network with a subnet connected to a router.
The baremetal driver is a special case since all nodes are
on the same shared network.
- :param tenant_id: id of tenant to create resources in.
+ :param project_id: id of project to create resources in.
:param dns_nameservers: list of dns servers to send to subnet.
:param port_security_enabled: whether or not port_security is enabled
:param net_dict: a dict containing experimental network information in
@@ -1342,11 +1343,11 @@
else:
network = self._create_network(
networks_client=networks_client,
- tenant_id=tenant_id,
+ project_id=project_id,
port_security_enabled=port_security_enabled,
**net_dict)
router = self._get_router(client=routers_client,
- tenant_id=tenant_id)
+ project_id=project_id)
subnet_kwargs = dict(network=network,
subnets_client=subnets_client)
# use explicit check because empty list is a valid option
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index d8584ec..6c1b3fa 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -297,9 +297,19 @@
ip_mask = CONF.network.project_network_mask_bits
# check if the address is not already in use, if not, set it
if ' ' + ip_address + '/' + str(ip_mask) not in ip_output:
- ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
- ip_address, ip_mask, new_nic))
- ssh_client.exec_command("sudo ip link set %s up" % new_nic)
+ try:
+ ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
+ ip_address, ip_mask, new_nic))
+ ssh_client.exec_command("sudo ip link set %s up" % new_nic)
+ except exceptions.SSHExecCommandFailed as exc:
+ if 'RTNETLINK answers: File exists' in str(exc):
+ LOG.debug(
+ 'IP address %(ip_address)s is already set in device '
+ '%(device)s\nPrevious "ip a" output: %(ip_output)s',
+ {'ip_address': ip_address, 'device': new_nic,
+ 'ip_output': ip_output})
+ else:
+ raise exc
def _get_server_nics(self, ssh_client):
reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
@@ -321,7 +331,7 @@
internal_ips = (
p['fixed_ips'][0]['ip_address'] for p in
self.os_admin.ports_client.list_ports(
- tenant_id=server['tenant_id'],
+ project_id=server['tenant_id'],
network_id=network['id'])['ports']
if p['device_owner'].startswith('network') or
p['device_owner'].startswith('compute')
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 9cbd831..3fc93e4 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -176,7 +176,7 @@
cls.primary_tenant = cls.TenantProperties(cls.os_primary)
cls.alt_tenant = cls.TenantProperties(cls.os_alt)
for tenant in [cls.primary_tenant, cls.alt_tenant]:
- cls.tenants[tenant.creds.tenant_id] = tenant
+ cls.tenants[tenant.creds.project_id] = tenant
cls.floating_ip_access = not CONF.network.public_router_id
@@ -199,14 +199,14 @@
def _create_tenant_security_groups(self, tenant):
access_sg = self._create_empty_security_group(
namestart='secgroup_access-',
- tenant_id=tenant.creds.tenant_id,
+ project_id=tenant.creds.project_id,
client=tenant.manager.security_groups_client
)
# don't use default secgroup since it allows in-project traffic
def_sg = self._create_empty_security_group(
namestart='secgroup_general-',
- tenant_id=tenant.creds.tenant_id,
+ project_id=tenant.creds.project_id,
client=tenant.manager.security_groups_client
)
tenant.security_groups.update(access=access_sg, default=def_sg)
@@ -536,7 +536,7 @@
# Create empty security group and add icmp rule in it
new_sg = self._create_empty_security_group(
namestart='secgroup_new-',
- tenant_id=new_tenant.creds.tenant_id,
+ project_id=new_tenant.creds.project_id,
client=new_tenant.manager.security_groups_client)
icmp_rule = dict(
protocol='icmp',
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index a33d4d4..a062d40 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -29,8 +29,10 @@
The following is the scenario outline:
* boot an instance and create a timestamp file in it
* snapshot the instance
+ * add version metadata to the snapshot image
* boot a second instance from the snapshot
* check the existence of the timestamp file in the second instance
+ * snapshot the instance again
"""
@@ -63,6 +65,11 @@
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
+ # add version metadata to the snapshot image
+ self.image_client.update_image(
+ snapshot_image['id'], [dict(add='/version',
+ value='8.0')])
+
# boot a second instance from the snapshot
server_from_snapshot = self.create_server(
image_id=snapshot_image['id'],
@@ -75,3 +82,6 @@
private_key=keypair['private_key'],
server=server_from_snapshot)
self.assertEqual(timestamp, timestamp2)
+
+ # snapshot the instance again
+ self.create_server_snapshot(server=server_from_snapshot)
diff --git a/tempest/tests/api/compute/test_base.py b/tempest/tests/api/compute/test_base.py
index 1593464..74d2625 100644
--- a/tempest/tests/api/compute/test_base.py
+++ b/tempest/tests/api/compute/test_base.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from oslo_utils import uuidutils
import six
diff --git a/tempest/tests/base.py b/tempest/tests/base.py
index 0b53b45..e8b2c98 100644
--- a/tempest/tests/base.py
+++ b/tempest/tests/base.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslotest import base
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index a962e37..7d764be 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_config import cfg
from tempest.cmd import account_generator
@@ -336,3 +337,24 @@
def setUp(self):
self.mock_domains()
super(TestDumpAccountsV3, self).setUp()
+
+
+class TestAccountGeneratorCliCheck(base.TestCase):
+
+ def setUp(self):
+ super(TestAccountGeneratorCliCheck, self).setUp()
+ self.account_generator = account_generator.TempestAccountGenerator(
+ app=mock.Mock(), app_args=mock.Mock())
+ self.parser = self.account_generator.get_parser("generator")
+
+ def test_account_generator_zero_concurrency(self):
+ error = self.assertRaises(
+ SystemExit, lambda: self.parser.parse_args(
+ ['-r', '0', 'accounts_file.yaml']))
+ self.assertTrue(error.code != 0)
+
+ def test_account_generator_negative_concurrency(self):
+ error = self.assertRaises(
+ SystemExit, lambda: self.parser.parse_args(
+ ['-r', '-1', 'accounts_file.yaml']))
+ self.assertTrue(error.code != 0)
diff --git a/tempest/tests/cmd/test_cleanup.py b/tempest/tests/cmd/test_cleanup.py
index 1618df9..69e735b 100644
--- a/tempest/tests/cmd/test_cleanup.py
+++ b/tempest/tests/cmd/test_cleanup.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import mock
+from unittest import mock
from tempest.cmd import cleanup
from tempest.tests import base
diff --git a/tempest/tests/cmd/test_run.py b/tempest/tests/cmd/test_run.py
index e9bbcc2..5d9ddfa 100644
--- a/tempest/tests/cmd/test_run.py
+++ b/tempest/tests/cmd/test_run.py
@@ -18,9 +18,9 @@
import shutil
import subprocess
import tempfile
+from unittest import mock
import fixtures
-import mock
import six
from tempest.cmd import run
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 8dbba38..721fd76 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -13,9 +13,9 @@
# under the License.
import os
+from unittest import mock
import fixtures
-import mock
from oslo_serialization import jsonutils as json
from tempest import clients
@@ -629,3 +629,23 @@
def test_contains_version_negative_data(self):
self.assertFalse(
verify_tempest_config.contains_version('v5.', ['v1.0', 'v2.0']))
+
+ def test_check_service_availability(self):
+ class FakeAuthProvider:
+ def get_auth(self):
+ return ('token',
+ {'serviceCatalog': [{'type': 'compute'},
+ {'type': 'image'},
+ {'type': 'volumev3'},
+ {'type': 'network'},
+ {'type': 'object-store'}]})
+
+ class Fake_os:
+ auth_provider = FakeAuthProvider()
+ auth_version = 'v2'
+ verify_tempest_config.CONF._config = fake_config.FakePrivate()
+ services = verify_tempest_config.check_service_availability(
+ Fake_os(), True)
+ self.assertEqual(
+ sorted(['nova', 'glance', 'neutron', 'swift', 'cinder']),
+ sorted(services))
diff --git a/tempest/tests/cmd/test_workspace.py b/tempest/tests/cmd/test_workspace.py
index 7a6b576..eae6202 100644
--- a/tempest/tests/cmd/test_workspace.py
+++ b/tempest/tests/cmd/test_workspace.py
@@ -16,12 +16,12 @@
import shutil
import subprocess
import tempfile
-
-from mock import patch
+from unittest.mock import patch
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
+
from tempest.cmd import workspace
from tempest.lib.common.utils import data_utils
from tempest.tests import base
diff --git a/tempest/tests/common/test_compute.py b/tempest/tests/common/test_compute.py
index c108be9..45a439c 100644
--- a/tempest/tests/common/test_compute.py
+++ b/tempest/tests/common/test_compute.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
from six.moves.urllib import parse as urlparse
-import mock
from tempest.common import compute
from tempest.tests import base
diff --git a/tempest/tests/common/test_credentials_factory.py b/tempest/tests/common/test_credentials_factory.py
index 7cf87f8..0ef3742 100644
--- a/tempest/tests/common/test_credentials_factory.py
+++ b/tempest/tests/common/test_credentials_factory.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_config import cfg
import testtools
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index e3bb836..5f8b990 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -13,8 +13,8 @@
# under the License.
import time
+from unittest import mock
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from tempest.common import waiters
diff --git a/tempest/tests/common/utils/test_net_utils.py b/tempest/tests/common/utils/test_net_utils.py
index 83c6bcc..51d86d1 100644
--- a/tempest/tests/common/utils/test_net_utils.py
+++ b/tempest/tests/common/utils/test_net_utils.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.common.utils import net_utils
from tempest.lib import exceptions as lib_exc
diff --git a/tempest/tests/lib/cli/test_execute.py b/tempest/tests/lib/cli/test_execute.py
index c069af5..a10e3bb 100644
--- a/tempest/tests/lib/cli/test_execute.py
+++ b/tempest/tests/lib/cli/test_execute.py
@@ -12,8 +12,8 @@
# under the License.
import subprocess
+from unittest import mock
-import mock
from tempest.lib.cli import base as cli_base
from tempest.lib import exceptions
diff --git a/tempest/tests/lib/cmd/__init__.py b/tempest/tests/lib/cmd/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/lib/cmd/__init__.py
diff --git a/tempest/tests/lib/cmd/test_check_uuid.py b/tempest/tests/lib/cmd/test_check_uuid.py
new file mode 100644
index 0000000..130f90a
--- /dev/null
+++ b/tempest/tests/lib/cmd/test_check_uuid.py
@@ -0,0 +1,138 @@
+# 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 importlib
+import tempfile
+from unittest import mock
+
+from tempest.lib.cmd import check_uuid
+from tempest.tests import base
+
+
+class TestSourcePatcher(base.TestCase):
+ def test_add_patch(self):
+ patcher = check_uuid.SourcePatcher()
+ fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
+ file_contents = 'first_line\nsecond_line'
+ fake_file.write(file_contents)
+ fake_file.close()
+ patcher.add_patch(fake_file.name, 'patch', 2)
+
+ source_file = patcher.source_files[fake_file.name]
+ self.assertEqual(1, len(patcher.patches))
+ (patch_id, patch), = patcher.patches.items()
+ self.assertEqual(patcher._quote('patch\n'), patch)
+ self.assertEqual('first_line\n{%s:s}second_line' % patch_id,
+ patcher._unquote(source_file))
+
+ def test_apply_patches(self):
+ fake_file = tempfile.NamedTemporaryFile("w+t")
+ patcher = check_uuid.SourcePatcher()
+ patcher.patches = {'fake-uuid': patcher._quote('patch\n')}
+ patcher.source_files = {
+ fake_file.name: patcher._quote('first_line\n') +
+ '{fake-uuid:s}second_line'}
+ with mock.patch('sys.stdout'):
+ patcher.apply_patches()
+
+ lines = fake_file.read().split('\n')
+ fake_file.close()
+ self.assertEqual(['first_line', 'patch', 'second_line'], lines)
+ self.assertFalse(patcher.patches)
+ self.assertFalse(patcher.source_files)
+
+
+class TestTestChecker(base.TestCase):
+ def _test_add_uuid_to_test(self, source_file):
+ class Fake_test_node():
+ lineno = 1
+ col_offset = 4
+ patcher = check_uuid.SourcePatcher()
+ checker = check_uuid.TestChecker(importlib.import_module('tempest'))
+ fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
+ fake_file.write(source_file)
+ fake_file.close()
+ checker._add_uuid_to_test(patcher, Fake_test_node(), fake_file.name)
+
+ self.assertEqual(1, len(patcher.patches))
+ self.assertEqual(1, len(patcher.source_files))
+ (patch_id, patch), = patcher.patches.items()
+ changed_source_file, = patcher.source_files.values()
+ self.assertEqual('{%s:s}%s' % (patch_id, patcher._quote(source_file)),
+ changed_source_file)
+ expected_patch_start = patcher._quote(
+ ' ' + check_uuid.DECORATOR_TEMPLATE.split('(')[0])
+ self.assertTrue(patch.startswith(expected_patch_start))
+
+ def test_add_uuid_to_test_def(self):
+ source_file = (" def test_test():\n"
+ " pass")
+ self._test_add_uuid_to_test(source_file)
+
+ def test_add_uuid_to_test_decorator(self):
+ source_file = (" @decorators.idempotent_id\n"
+ " def test_test():\n"
+ " pass")
+ self._test_add_uuid_to_test(source_file)
+
+ def test_add_import_for_test_uuid_no_tempest(self):
+ patcher = check_uuid.SourcePatcher()
+ checker = check_uuid.TestChecker(importlib.import_module('tempest'))
+ fake_file = tempfile.NamedTemporaryFile("w+t")
+
+ class Fake_src_parsed():
+ body = ['test_node']
+ checker._import_name = mock.Mock(return_value='fake_module')
+
+ checker._add_import_for_test_uuid(patcher, Fake_src_parsed(),
+ fake_file.name)
+ (patch_id, patch), = patcher.patches.items()
+ self.assertEqual(patcher._quote('\n' + check_uuid.IMPORT_LINE + '\n'),
+ patch)
+ self.assertEqual('{%s:s}' % patch_id,
+ patcher.source_files[fake_file.name])
+
+ def test_add_import_for_test_uuid_tempest(self):
+ patcher = check_uuid.SourcePatcher()
+ checker = check_uuid.TestChecker(importlib.import_module('tempest'))
+ fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
+ test1 = (" def test_test():\n"
+ " pass\n")
+ test2 = (" def test_another_test():\n"
+ " pass\n")
+ source_code = test1 + test2
+ fake_file.write(source_code)
+ fake_file.close()
+
+ def fake_import_name(node):
+ return node.name
+ checker._import_name = fake_import_name
+
+ class Fake_node():
+ def __init__(self, lineno, col_offset, name):
+ self.lineno = lineno
+ self.col_offset = col_offset
+ self.name = name
+
+ class Fake_src_parsed():
+ body = [Fake_node(1, 4, 'tempest.a_fake_module'),
+ Fake_node(3, 4, 'another_fake_module')]
+
+ checker._add_import_for_test_uuid(patcher, Fake_src_parsed(),
+ fake_file.name)
+ (patch_id, patch), = patcher.patches.items()
+ self.assertEqual(patcher._quote(check_uuid.IMPORT_LINE + '\n'),
+ patch)
+ expected_source = patcher._quote(test1) + '{' + patch_id + ':s}' +\
+ patcher._quote(test2)
+ self.assertEqual(expected_source,
+ patcher.source_files[fake_file.name])
diff --git a/tempest/tests/lib/common/test_cred_client.py b/tempest/tests/lib/common/test_cred_client.py
index 3dff16f..860a465 100644
--- a/tempest/tests/lib/common/test_cred_client.py
+++ b/tempest/tests/lib/common/test_cred_client.py
@@ -11,7 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.lib.common import cred_client
from tempest.tests import base
diff --git a/tempest/tests/lib/common/test_dynamic_creds.py b/tempest/tests/lib/common/test_dynamic_creds.py
index 4723458..e9073cc 100644
--- a/tempest/tests/lib/common/test_dynamic_creds.py
+++ b/tempest/tests/lib/common/test_dynamic_creds.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_config import cfg
from tempest.common import credentials_factory as credentials
@@ -110,7 +111,7 @@
(200,
{'roles': [{'id': id, 'name': name},
{'id': '1', 'name': 'FakeRole'},
- {'id': '2', 'name': 'Member'}]}))))
+ {'id': '2', 'name': 'member'}]}))))
return roles_fix
def _mock_list_2_roles(self):
@@ -139,7 +140,7 @@
return_value=(rest_client.ResponseBody
(200, {'roles': [
{'id': '1', 'name': 'FakeRole'},
- {'id': '2', 'name': 'Member'}]}))))
+ {'id': '2', 'name': 'member'}]}))))
return roles_fix
def _mock_list_ec2_credentials(self, user_id, tenant_id):
@@ -664,6 +665,6 @@
with mock.patch('tempest.lib.common.dynamic_creds.LOG') as log_mock:
creds._create_creds()
log_mock.warning.assert_called_once_with(
- "Member role already exists, ignoring conflict.")
+ "member role already exists, ignoring conflict.")
creds.creds_client.assign_user_role.assert_called_once_with(
- mock.ANY, mock.ANY, 'Member')
+ mock.ANY, mock.ANY, 'member')
diff --git a/tempest/tests/lib/common/test_preprov_creds.py b/tempest/tests/lib/common/test_preprov_creds.py
index 25df2a7..579363e 100644
--- a/tempest/tests/lib/common/test_preprov_creds.py
+++ b/tempest/tests/lib/common/test_preprov_creds.py
@@ -15,8 +15,8 @@
import hashlib
import os
import shutil
+from unittest import mock
-import mock
import six
import testtools
diff --git a/tempest/tests/lib/common/test_profiler.py b/tempest/tests/lib/common/test_profiler.py
index 59fa0364..166d831 100644
--- a/tempest/tests/lib/common/test_profiler.py
+++ b/tempest/tests/lib/common/test_profiler.py
@@ -10,7 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
import testtools
from tempest.lib.common import profiler
diff --git a/tempest/tests/lib/common/test_validation_resources.py b/tempest/tests/lib/common/test_validation_resources.py
index d5139f4..d50fd89 100644
--- a/tempest/tests/lib/common/test_validation_resources.py
+++ b/tempest/tests/lib/common/test_validation_resources.py
@@ -11,8 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from unittest import mock
+
import fixtures
-import mock
import testtools
from tempest.lib.common import validation_resources as vr
diff --git a/tempest/tests/lib/common/utils/linux/test_remote_client.py b/tempest/tests/lib/common/utils/linux/test_remote_client.py
index 7a21a5f..df23e63 100644
--- a/tempest/tests/lib/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/lib/common/utils/linux/test_remote_client.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.lib.common import ssh
from tempest.lib.common.utils.linux import remote_client
diff --git a/tempest/tests/lib/common/utils/test_test_utils.py b/tempest/tests/lib/common/utils/test_test_utils.py
index 865767b..bdc0ea4 100644
--- a/tempest/tests/lib/common/utils/test_test_utils.py
+++ b/tempest/tests/lib/common/utils/test_test_utils.py
@@ -14,8 +14,8 @@
# under the License.
import time
+from unittest import mock
-import mock
from tempest.lib.common import thread
from tempest.lib.common.utils import test_utils
diff --git a/tempest/tests/lib/services/compute/test_base_compute_client.py b/tempest/tests/lib/services/compute/test_base_compute_client.py
index 69e8542..5841ae4 100644
--- a/tempest/tests/lib/services/compute/test_base_compute_client.py
+++ b/tempest/tests/lib/services/compute/test_base_compute_client.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.lib.common import rest_client
from tempest.lib import exceptions
diff --git a/tempest/tests/lib/services/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index 86f6ad5..a82b255 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from tempest.lib.services.compute import base_compute_client
from tempest.lib.services.compute import servers_client
diff --git a/tempest/tests/lib/services/compute/test_services_client.py b/tempest/tests/lib/services/compute/test_services_client.py
index ba432e3..0c513cc 100644
--- a/tempest/tests/lib/services/compute/test_services_client.py
+++ b/tempest/tests/lib/services/compute/test_services_client.py
@@ -13,8 +13,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from tempest.lib.services.compute import base_compute_client
from tempest.lib.services.compute import services_client
diff --git a/tempest/tests/lib/services/identity/v2/test_token_client.py b/tempest/tests/lib/services/identity/v2/test_token_client.py
index 5b4e210..dc14a50 100644
--- a/tempest/tests/lib/services/identity/v2/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v2/test_token_client.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
diff --git a/tempest/tests/lib/services/identity/v3/test_token_client.py b/tempest/tests/lib/services/identity/v3/test_token_client.py
index 656e10a..1c2295d 100644
--- a/tempest/tests/lib/services/identity/v3/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_token_client.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
diff --git a/tempest/tests/lib/services/network/test_base_network_client.py b/tempest/tests/lib/services/network/test_base_network_client.py
index e121cec..a426397 100644
--- a/tempest/tests/lib/services/network/test_base_network_client.py
+++ b/tempest/tests/lib/services/network/test_base_network_client.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.lib.services.network import base as base_network_client
from tempest.tests.lib import fake_auth_provider
diff --git a/tempest/tests/lib/services/network/test_quotas_client.py b/tempest/tests/lib/services/network/test_quotas_client.py
index aa6c1a1..7dce4e1 100644
--- a/tempest/tests/lib/services/network/test_quotas_client.py
+++ b/tempest/tests/lib/services/network/test_quotas_client.py
@@ -52,7 +52,7 @@
}
}
- FAKE_QUOTA_TENANT_ID = "bab7d5c60cd041a0a36f7c4b6e1dd978"
+ FAKE_QUOTA_PROJECT_ID = "bab7d5c60cd041a0a36f7c4b6e1dd978"
FAKE_QUOTA_DETAILS = {
"quota": {
@@ -115,7 +115,7 @@
self.FAKE_PROJECT_QUOTAS,
bytes_body,
200,
- tenant_id=self.FAKE_QUOTA_TENANT_ID)
+ project_id=self.FAKE_QUOTA_PROJECT_ID)
def _test_show_default_quotas(self, bytes_body=False):
self.check_service_client_function(
@@ -124,7 +124,7 @@
self.FAKE_PROJECT_QUOTAS,
bytes_body,
200,
- tenant_id=self.FAKE_QUOTA_TENANT_ID)
+ project_id=self.FAKE_QUOTA_PROJECT_ID)
def _test_update_quotas(self, bytes_body=False):
self.check_service_client_function(
@@ -133,7 +133,7 @@
self.FAKE_PROJECT_QUOTAS,
bytes_body,
200,
- tenant_id=self.FAKE_QUOTA_TENANT_ID)
+ project_id=self.FAKE_QUOTA_PROJECT_ID)
def _test_show_quota_details(self, bytes_body=False):
self.check_service_client_function(
@@ -142,7 +142,7 @@
self.FAKE_QUOTA_DETAILS,
bytes_body,
200,
- tenant_id=self.FAKE_QUOTA_TENANT_ID)
+ project_id=self.FAKE_QUOTA_PROJECT_ID)
def test_reset_quotas(self):
self.check_service_client_function(
@@ -150,7 +150,7 @@
"tempest.lib.common.rest_client.RestClient.delete",
{},
status=204,
- tenant_id=self.FAKE_QUOTA_TENANT_ID)
+ project_id=self.FAKE_QUOTA_PROJECT_ID)
def test_list_quotas_with_str_body(self):
self._test_list_quotas()
diff --git a/tempest/tests/lib/services/network/test_security_group_rules_client.py b/tempest/tests/lib/services/network/test_security_group_rules_client.py
index b9c17a1..2ecc996 100644
--- a/tempest/tests/lib/services/network/test_security_group_rules_client.py
+++ b/tempest/tests/lib/services/network/test_security_group_rules_client.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils as json
from tempest.lib.services.network import base as network_base
diff --git a/tempest/tests/lib/services/network/test_security_groups_client.py b/tempest/tests/lib/services/network/test_security_groups_client.py
index f96805f..501883b 100644
--- a/tempest/tests/lib/services/network/test_security_groups_client.py
+++ b/tempest/tests/lib/services/network/test_security_groups_client.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils as json
from tempest.lib.services.network import base as network_base
diff --git a/tempest/tests/lib/services/object_storage/test_object_client.py b/tempest/tests/lib/services/object_storage/test_object_client.py
index 1749b03..c646d61 100644
--- a/tempest/tests/lib/services/object_storage/test_object_client.py
+++ b/tempest/tests/lib/services/object_storage/test_object_client.py
@@ -14,7 +14,7 @@
# under the License.
-import mock
+from unittest import mock
from tempest.lib import exceptions
from tempest.lib.services.object_storage import object_client
diff --git a/tempest/tests/lib/services/test_clients.py b/tempest/tests/lib/services/test_clients.py
index 43fd88f..f83064a 100644
--- a/tempest/tests/lib/services/test_clients.py
+++ b/tempest/tests/lib/services/test_clients.py
@@ -13,9 +13,9 @@
# the License.
import types
+from unittest import mock
import fixtures
-import mock
import six
import testtools
diff --git a/tempest/tests/lib/services/volume/v3/test_services_client.py b/tempest/tests/lib/services/volume/v3/test_services_client.py
index f65228f..c807bc2 100644
--- a/tempest/tests/lib/services/volume/v3/test_services_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_services_client.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils as json
from tempest.lib.services.volume.v3 import services_client
diff --git a/tempest/tests/lib/services/volume/v3/test_snapshot_manage_client.py b/tempest/tests/lib/services/volume/v3/test_snapshot_manage_client.py
index 1b88020..8309f7a 100644
--- a/tempest/tests/lib/services/volume/v3/test_snapshot_manage_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_snapshot_manage_client.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from oslo_serialization import jsonutils as json
diff --git a/tempest/tests/lib/services/volume/v3/test_transfers_client.py b/tempest/tests/lib/services/volume/v3/test_transfers_client.py
index d631fe7..1dfe2df 100644
--- a/tempest/tests/lib/services/volume/v3/test_transfers_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_transfers_client.py
@@ -14,8 +14,8 @@
# under the License.
import copy
+from unittest import mock
-import mock
from oslo_serialization import jsonutils as json
from tempest.lib.services.volume.v3 import transfers_client
diff --git a/tempest/tests/lib/services/volume/v3/test_volume_manage_client.py b/tempest/tests/lib/services/volume/v3/test_volume_manage_client.py
index 902f027..d4313a2 100644
--- a/tempest/tests/lib/services/volume/v3/test_volume_manage_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_volume_manage_client.py
@@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from oslo_serialization import jsonutils as json
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index 9c6cac7..e3c17e8 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -14,8 +14,8 @@
# under the License.
import abc
+from unittest import mock
-import mock
import six
import testtools
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index c849231..85048fb 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -13,8 +13,8 @@
# under the License.
import socket
+from unittest import mock
-import mock
import six
from six import StringIO
import testtools
diff --git a/tempest/tests/test_base_test.py b/tempest/tests/test_base_test.py
index 2b5a947..b154cd5 100644
--- a/tempest/tests/test_base_test.py
+++ b/tempest/tests/test_base_test.py
@@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_config import cfg
from tempest import clients
diff --git a/tempest/tests/test_imports.py b/tempest/tests/test_imports.py
index 6f1cfca..ad7bebb 100644
--- a/tempest/tests/test_imports.py
+++ b/tempest/tests/test_imports.py
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
from tempest.tests import base
diff --git a/tempest/tests/test_test.py b/tempest/tests/test_test.py
index 49fd010..72e8b6d 100644
--- a/tempest/tests/test_test.py
+++ b/tempest/tests/test_test.py
@@ -15,8 +15,8 @@
import os
import sys
+from unittest import mock
-import mock
from oslo_config import cfg
import testtools
diff --git a/test-requirements.txt b/test-requirements.txt
index 17a7d2a..17fa9f1 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,7 +2,6 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking>=3.0.1,<3.1.0;python_version>='3.5' # Apache-2.0
-mock>=2.0.0 # BSD
coverage!=4.4,>=4.0 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0
pycodestyle>=2.0.0,<2.6.0 # MIT
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 5ffef3e..530ce5e 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -52,6 +52,8 @@
'x/tap-as-a-service', # To avoid sanity-job failure
'x/valet', # https://review.opendev.org/#/c/638339/
'x/kingbird', # https://bugs.launchpad.net/kingbird/+bug/1869722
+ # vmware-nsx is blacklisted since https://review.opendev.org/#/c/736952
+ 'x/vmware-nsx-tempest-plugin',
]
url = 'https://review.opendev.org/projects/'
diff --git a/tools/tempest-integrated-gate-compute-blacklist.txt b/tools/tempest-integrated-gate-compute-blacklist.txt
index 8805262..2290751 100644
--- a/tools/tempest-integrated-gate-compute-blacklist.txt
+++ b/tools/tempest-integrated-gate-compute-blacklist.txt
@@ -11,3 +11,9 @@
tempest.scenario.test_object_storage_basic_ops.TestObjectStorageBasicOps.test_swift_basic_ops
tempest.scenario.test_object_storage_basic_ops.TestObjectStorageBasicOps.test_swift_acl_anonymous_download
tempest.scenario.test_volume_backup_restore.TestVolumeBackupRestore.test_volume_backup_restore
+
+# Skip test scenario when creating second image from instance
+# https://bugs.launchpad.net/tripleo/+bug/1881592
+# The test is most likely wrong and may fail if the fists image is create quickly.
+# FIXME: Either fix the test so it won't race or consider if we should cover the scenario at all.
+tempest.api.compute.images.test_images_oneserver_negative.ImagesOneServerNegativeTestJSON.test_create_second_image_when_first_image_is_being_saved
diff --git a/tools/tempest-plugin-sanity.sh b/tools/tempest-plugin-sanity.sh
index 2ff4aea..c983da9 100644
--- a/tools/tempest-plugin-sanity.sh
+++ b/tools/tempest-plugin-sanity.sh
@@ -66,7 +66,7 @@
# function to create virtualenv to perform sanity operation
function prepare_workspace {
SANITY_DIR=$(pwd)
- virtualenv -p python3 --clear "$SANITY_DIR"/.venv
+ python3 -m venv "$SANITY_DIR"/.venv
export TVENV="$SANITY_DIR/tools/with_venv.sh"
cd "$SANITY_DIR"