Merge "Tempest test for checking unshelve to host"
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 0ed73a8..a69dbb3 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -43,7 +43,7 @@
super(ServerActionsTestJSON, self).setUp()
# Check if the server is in a clean state after test
try:
- validation_resources = self.get_class_validation_resources(
+ self.validation_resources = self.get_class_validation_resources(
self.os_primary)
# _test_rebuild_server test compares ip address attached to the
# server before and after the rebuild, in order to avoid
@@ -53,18 +53,18 @@
waiters.wait_for_server_floating_ip(
self.client,
self.client.show_server(self.server_id)['server'],
- validation_resources['floating_ip'])
+ self.validation_resources['floating_ip'])
waiters.wait_for_server_status(self.client,
self.server_id, 'ACTIVE')
except lib_exc.NotFound:
# The server was deleted by previous test, create a new one
# Use class level validation resources to avoid them being
# deleted once a test is over
- validation_resources = self.get_class_validation_resources(
+ self.validation_resources = self.get_class_validation_resources(
self.os_primary)
server = self.create_test_server(
validatable=True,
- validation_resources=validation_resources,
+ validation_resources=self.validation_resources,
wait_until='SSHABLE')
self.__class__.server_id = server['id']
except Exception:
@@ -106,11 +106,9 @@
"""
# Since this test messes with the password and makes the
# server unreachable, it should create its own server
- validation_resources = self.get_test_validation_resources(
- self.os_primary)
newserver = self.create_test_server(
validatable=True,
- validation_resources=validation_resources,
+ validation_resources=self.validation_resources,
wait_until='ACTIVE')
self.addCleanup(self.delete_server, newserver['id'])
# The server's password should be set to the provided password
@@ -122,7 +120,7 @@
# Verify that the user can authenticate with the new password
server = self.client.show_server(newserver['id'])['server']
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_user,
new_password,
server=server,
@@ -131,15 +129,13 @@
def _test_reboot_server(self, reboot_type):
if CONF.validation.run_validation:
- validation_resources = self.get_class_validation_resources(
- self.os_primary)
# Get the time the server was last rebooted,
server = self.client.show_server(self.server_id)['server']
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_user,
self.password,
- validation_resources['keypair']['private_key'],
+ self.validation_resources['keypair']['private_key'],
server=server,
servers_client=self.client)
boot_time = linux_client.get_boot_time()
@@ -153,10 +149,10 @@
if CONF.validation.run_validation:
# Log in and verify the boot time has changed
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_user,
self.password,
- validation_resources['keypair']['private_key'],
+ self.validation_resources['keypair']['private_key'],
server=server,
servers_client=self.client)
new_boot_time = linux_client.get_boot_time()
@@ -185,10 +181,18 @@
server = self.client.show_server(server['id'])['server']
self.assertNotIn('security_groups', server)
- def _rebuild_server_and_check(self, image_ref):
- rebuilt_server = (self.client.rebuild_server(self.server_id, image_ref)
+ def _rebuild_server_and_check(self, image_ref, server):
+ rebuilt_server = (self.client.rebuild_server(server['id'], image_ref)
['server'])
- waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
+ if CONF.validation.run_validation:
+ tenant_network = self.get_tenant_network()
+ compute.wait_for_ssh_or_ping(
+ server, self.os_primary, tenant_network,
+ True, self.validation_resources, "SSHABLE", True)
+ else:
+ waiters.wait_for_server_status(self.client, self.server['id'],
+ 'ACTIVE')
+
msg = ('Server was not rebuilt to the original image. '
'The original image: {0}. The current image: {1}'
.format(image_ref, rebuilt_server['image']['id']))
@@ -212,7 +216,8 @@
# If the server was rebuilt on a different image, restore it to the
# original image once the test ends
if self.image_ref_alt != self.image_ref:
- self.addCleanup(self._rebuild_server_and_check, self.image_ref)
+ self.addCleanup(self._rebuild_server_and_check, self.image_ref,
+ rebuilt_server)
# Verify the properties in the initial response are correct
self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -230,8 +235,6 @@
self.assertEqual(original_addresses, server['addresses'])
if CONF.validation.run_validation:
- validation_resources = self.get_class_validation_resources(
- self.os_primary)
# Authentication is attempted in the following order of priority:
# 1.The key passed in, if one was passed in.
# 2.Any key we can find through an SSH agent (if allowed).
@@ -239,10 +242,10 @@
# ~/.ssh/ (if allowed).
# 4.Plain username/password auth, if a password was given.
linux_client = remote_client.RemoteClient(
- self.get_server_ip(rebuilt_server, validation_resources),
+ self.get_server_ip(rebuilt_server, self.validation_resources),
self.ssh_alt_user,
password,
- validation_resources['keypair']['private_key'],
+ self.validation_resources['keypair']['private_key'],
server=rebuilt_server,
servers_client=self.client)
linux_client.validate_authentication()
@@ -273,7 +276,7 @@
# If the server was rebuilt on a different image, restore it to the
# original image once the test ends
if self.image_ref_alt != self.image_ref:
- self.addCleanup(self._rebuild_server_and_check, old_image)
+ self.addCleanup(self._rebuild_server_and_check, old_image, server)
# Verify the properties in the initial response are correct
self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -318,13 +321,11 @@
self.assertEqual(self.server_id,
vol_after_rebuild['attachments'][0]['server_id'])
if CONF.validation.run_validation:
- validation_resources = self.get_class_validation_resources(
- self.os_primary)
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_alt_user,
password=None,
- pkey=validation_resources['keypair']['private_key'],
+ pkey=self.validation_resources['keypair']['private_key'],
server=server,
servers_client=self.client)
linux_client.validate_authentication()
@@ -376,10 +377,8 @@
kwargs = {'volume_backed': True,
'wait_until': 'ACTIVE'}
if CONF.validation.run_validation:
- validation_resources = self.get_test_validation_resources(
- self.os_primary)
kwargs.update({'validatable': True,
- 'validation_resources': validation_resources})
+ 'validation_resources': self.validation_resources})
server = self.create_test_server(**kwargs)
# NOTE(mgoddard): Get detailed server to ensure addresses are present
@@ -395,10 +394,10 @@
self.client.get_console_output(server['id'])
if CONF.validation.run_validation:
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_user,
password=None,
- pkey=validation_resources['keypair']['private_key'],
+ pkey=self.validation_resources['keypair']['private_key'],
server=server,
servers_client=self.client)
linux_client.validate_authentication()
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index d283ab3..96031ac 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -131,7 +131,7 @@
# import image from web to backend
image_uri = CONF.image.http_image
self.client.image_import(image['id'], method='web-download',
- image_uri=image_uri)
+ import_params={'uri': image_uri})
waiters.wait_for_image_imported_to_stores(self.client, image['id'])
@decorators.idempotent_id('e04761a1-22af-42c2-b8bc-a34a3f12b585')
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index a3802a9..80c01a5 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -206,7 +206,7 @@
# import image from web to backend
image_uri = 'http://does-not.exist/no/possible/way'
self.client.image_import(image['id'], method='web-download',
- image_uri=image_uri,
+ import_params={'uri': image_uri},
stores=[stores[0]['id']])
start_time = int(time.time())
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index f1dec06..62cb203 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -110,9 +110,7 @@
"""Test volume transfer for the "new" Transfers API mv 3.55"""
volume_min_microversion = '3.55'
- volume_max_microversion = 'latest'
-
- credentials = ['primary', 'alt', 'admin']
+ volume_max_microversion = '3.56'
@classmethod
def setup_clients(cls):
@@ -131,3 +129,22 @@
"""Test create, list, delete with volume-transfers API mv 3.55"""
super(VolumesTransfersV355Test, self). \
test_create_list_delete_volume_transfer()
+
+
+class VolumesTransfersV357Test(VolumesTransfersV355Test):
+ """Test volume transfer for the "new" Transfers API mv 3.57"""
+
+ volume_min_microversion = '3.57'
+ volume_max_microversion = 'latest'
+
+ @decorators.idempotent_id('d746bd69-bb30-4414-9a1c-577959fac6a1')
+ def test_create_get_list_accept_volume_transfer(self):
+ """Test create, get, list, accept with volume-transfers API mv 3.57"""
+ super(VolumesTransfersV357Test, self). \
+ test_create_get_list_accept_volume_transfer()
+
+ @decorators.idempotent_id('d4b20ec2-e1bb-4068-adcf-6c20020a8e05')
+ def test_create_list_delete_volume_transfer(self):
+ """Test create, list, delete with volume-transfers API mv 3.57"""
+ super(VolumesTransfersV357Test, self). \
+ test_create_list_delete_volume_transfer()
diff --git a/tempest/lib/api_schema/response/volume/v3_55/__init__.py b/tempest/lib/api_schema/response/volume/v3_55/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_55/__init__.py
diff --git a/tempest/lib/api_schema/response/volume/v3_55/transfers.py b/tempest/lib/api_schema/response/volume/v3_55/transfers.py
new file mode 100644
index 0000000..683c62f
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_55/transfers.py
@@ -0,0 +1,46 @@
+# Copyright 2022 Red Hat, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+from tempest.lib.api_schema.response.volume import transfers
+
+# Volume microversion 3.55:
+# Add 'no_snapshots' attribute in 'transfer' responses.
+
+create_volume_transfer = copy.deepcopy(transfers.create_volume_transfer)
+create_volume_transfer['response_body']['properties']['transfer'][
+ 'properties'].update({'no_snapshots': {'type': 'boolean'}})
+
+common_show_volume_transfer = copy.deepcopy(
+ transfers.common_show_volume_transfer)
+common_show_volume_transfer['properties'].update(
+ {'no_snapshots': {'type': 'boolean'}})
+
+show_volume_transfer = copy.deepcopy(transfers.show_volume_transfer)
+show_volume_transfer['response_body']['properties'][
+ 'transfer'] = common_show_volume_transfer
+
+list_volume_transfers_no_detail = copy.deepcopy(
+ transfers.list_volume_transfers_no_detail)
+
+list_volume_transfers_with_detail = copy.deepcopy(
+ transfers.list_volume_transfers_with_detail)
+list_volume_transfers_with_detail['response_body']['properties']['transfers'][
+ 'items'] = common_show_volume_transfer
+
+delete_volume_transfer = copy.deepcopy(transfers.delete_volume_transfer)
+
+accept_volume_transfer = copy.deepcopy(transfers.accept_volume_transfer)
diff --git a/tempest/lib/api_schema/response/volume/v3_57/__init__.py b/tempest/lib/api_schema/response/volume/v3_57/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_57/__init__.py
diff --git a/tempest/lib/api_schema/response/volume/v3_57/transfers.py b/tempest/lib/api_schema/response/volume/v3_57/transfers.py
new file mode 100644
index 0000000..2fcf0aa
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_57/transfers.py
@@ -0,0 +1,61 @@
+# Copyright 2022 Red Hat, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+from tempest.lib.api_schema.response.volume.v3_55 import transfers
+
+# Volume microversion 3.57:
+# Add these attributes in 'transfer' responses.
+# 'destination_project_id'
+# 'source_project_id'
+# 'accepted'
+
+create_volume_transfer = copy.deepcopy(transfers.create_volume_transfer)
+create_volume_transfer['response_body']['properties']['transfer'][
+ 'properties'].update(
+ {'destination_project_id': parameter_types.uuid_or_null})
+create_volume_transfer['response_body']['properties']['transfer'][
+ 'properties'].update(
+ {'source_project_id': {'type': 'string', 'format': 'uuid'}})
+create_volume_transfer['response_body']['properties']['transfer'][
+ 'properties'].update(
+ {'accepted': {'type': 'boolean'}})
+
+common_show_volume_transfer = copy.deepcopy(
+ transfers.common_show_volume_transfer)
+common_show_volume_transfer['properties'].update(
+ {'destination_project_id': parameter_types.uuid_or_null})
+common_show_volume_transfer['properties'].update(
+ {'source_project_id': {'type': 'string', 'format': 'uuid'}})
+common_show_volume_transfer['properties'].update(
+ {'accepted': {'type': 'boolean'}})
+
+show_volume_transfer = copy.deepcopy(transfers.show_volume_transfer)
+show_volume_transfer['response_body']['properties'][
+ 'transfer'] = common_show_volume_transfer
+
+list_volume_transfers_no_detail = copy.deepcopy(
+ transfers.list_volume_transfers_no_detail)
+
+list_volume_transfers_with_detail = copy.deepcopy(
+ transfers.list_volume_transfers_with_detail)
+list_volume_transfers_with_detail['response_body']['properties']['transfers'][
+ 'items'] = common_show_volume_transfer
+
+delete_volume_transfer = copy.deepcopy(transfers.delete_volume_transfer)
+
+accept_volume_transfer = copy.deepcopy(transfers.accept_volume_transfer)
diff --git a/tempest/lib/api_schema/response/volume/v3_65/__init__.py b/tempest/lib/api_schema/response/volume/v3_65/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_65/__init__.py
diff --git a/tempest/lib/api_schema/response/volume/v3_65/volumes.py b/tempest/lib/api_schema/response/volume/v3_65/volumes.py
new file mode 100644
index 0000000..f7d9e1b
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_65/volumes.py
@@ -0,0 +1,65 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+from tempest.lib.api_schema.response.volume.v3_64 import volumes
+
+# Volume microversion 3.65:
+# Add 'consumes_quota' attribute in volume details.
+
+common_show_volume = copy.deepcopy(volumes.common_show_volume)
+common_show_volume['properties'].update(
+ {'consumes_quota': {'type': 'boolean'}})
+
+create_volume = copy.deepcopy(volumes.create_volume)
+create_volume['response_body']['properties']['volume']['properties'].update(
+ {'consumes_quota': {'type': 'boolean'}})
+
+# copy unchanged volumes schema
+attachments = copy.deepcopy(volumes.attachments)
+list_volumes_no_detail = copy.deepcopy(volumes.list_volumes_no_detail)
+# show_volume refers to common_show_volume
+show_volume = copy.deepcopy(volumes.show_volume)
+show_volume['response_body']['properties']['volume'] = common_show_volume
+# list_volumes_detail refers to latest common_show_volume
+list_volumes_detail = copy.deepcopy(common_show_volume)
+list_volumes_with_detail = copy.deepcopy(volumes.list_volumes_with_detail)
+list_volumes_with_detail['response_body']['properties']['volumes']['items'] \
+ = list_volumes_detail
+update_volume = copy.deepcopy(volumes.update_volume)
+delete_volume = copy.deepcopy(volumes.delete_volume)
+show_volume_summary = copy.deepcopy(volumes.show_volume_summary)
+attach_volume = copy.deepcopy(volumes.attach_volume)
+set_bootable_volume = copy.deepcopy(volumes.set_bootable_volume)
+detach_volume = copy.deepcopy(volumes.detach_volume)
+reserve_volume = copy.deepcopy(volumes.reserve_volume)
+unreserve_volume = copy.deepcopy(volumes.unreserve_volume)
+extend_volume = copy.deepcopy(volumes.extend_volume)
+reset_volume_status = copy.deepcopy(volumes.reset_volume_status)
+update_volume_readonly = copy.deepcopy(volumes.update_volume_readonly)
+force_delete_volume = copy.deepcopy(volumes.force_delete_volume)
+retype_volume = copy.deepcopy(volumes.retype_volume)
+force_detach_volume = copy.deepcopy(volumes.force_detach_volume)
+create_volume_metadata = copy.deepcopy(volumes.create_volume_metadata)
+show_volume_metadata = copy.deepcopy(volumes.show_volume_metadata)
+update_volume_metadata = copy.deepcopy(volumes.update_volume_metadata)
+update_volume_metadata_item = copy.deepcopy(
+ volumes.update_volume_metadata_item)
+update_volume_image_metadata = copy.deepcopy(
+ volumes.update_volume_image_metadata)
+delete_volume_image_metadata = copy.deepcopy(
+ volumes.delete_volume_image_metadata)
+unmanage_volume = copy.deepcopy(volumes.unmanage_volume)
diff --git a/tempest/lib/api_schema/response/volume/v3_69/__init__.py b/tempest/lib/api_schema/response/volume/v3_69/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_69/__init__.py
diff --git a/tempest/lib/api_schema/response/volume/v3_69/volumes.py b/tempest/lib/api_schema/response/volume/v3_69/volumes.py
new file mode 100644
index 0000000..e83ef46
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/v3_69/volumes.py
@@ -0,0 +1,65 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+from tempest.lib.api_schema.response.volume.v3_65 import volumes
+
+# Volume microversion 3.69:
+# The 'shared_targets' attribute is now a tristate boolean.
+
+common_show_volume = copy.deepcopy(volumes.common_show_volume)
+common_show_volume['properties'].update(
+ {'shared_targets': {'type': ['boolean', 'null']}})
+
+create_volume = copy.deepcopy(volumes.create_volume)
+create_volume['response_body']['properties']['volume']['properties'].update(
+ {'shared_targets': {'type': ['boolean', 'null']}})
+
+# copy unchanged volumes schema
+attachments = copy.deepcopy(volumes.attachments)
+list_volumes_no_detail = copy.deepcopy(volumes.list_volumes_no_detail)
+# show_volume refers to common_show_volume
+show_volume = copy.deepcopy(volumes.show_volume)
+show_volume['response_body']['properties']['volume'] = common_show_volume
+# list_volumes_detail refers to latest common_show_volume
+list_volumes_detail = copy.deepcopy(common_show_volume)
+list_volumes_with_detail = copy.deepcopy(volumes.list_volumes_with_detail)
+list_volumes_with_detail['response_body']['properties']['volumes']['items'] \
+ = list_volumes_detail
+update_volume = copy.deepcopy(volumes.update_volume)
+delete_volume = copy.deepcopy(volumes.delete_volume)
+show_volume_summary = copy.deepcopy(volumes.show_volume_summary)
+attach_volume = copy.deepcopy(volumes.attach_volume)
+set_bootable_volume = copy.deepcopy(volumes.set_bootable_volume)
+detach_volume = copy.deepcopy(volumes.detach_volume)
+reserve_volume = copy.deepcopy(volumes.reserve_volume)
+unreserve_volume = copy.deepcopy(volumes.unreserve_volume)
+extend_volume = copy.deepcopy(volumes.extend_volume)
+reset_volume_status = copy.deepcopy(volumes.reset_volume_status)
+update_volume_readonly = copy.deepcopy(volumes.update_volume_readonly)
+force_delete_volume = copy.deepcopy(volumes.force_delete_volume)
+retype_volume = copy.deepcopy(volumes.retype_volume)
+force_detach_volume = copy.deepcopy(volumes.force_detach_volume)
+create_volume_metadata = copy.deepcopy(volumes.create_volume_metadata)
+show_volume_metadata = copy.deepcopy(volumes.show_volume_metadata)
+update_volume_metadata = copy.deepcopy(volumes.update_volume_metadata)
+update_volume_metadata_item = copy.deepcopy(
+ volumes.update_volume_metadata_item)
+update_volume_image_metadata = copy.deepcopy(
+ volumes.update_volume_image_metadata)
+delete_volume_image_metadata = copy.deepcopy(
+ volumes.delete_volume_image_metadata)
+unmanage_volume = copy.deepcopy(volumes.unmanage_volume)
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index be8c0e8..d687eb5 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -559,23 +559,24 @@
except lib_exc.NotFound:
LOG.warning("user with name: %s not found for delete",
creds.username)
- # NOTE(zhufl): Only when neutron's security_group ext is
- # enabled, cleanup_default_secgroup will not raise error. But
- # here cannot use test_utils.is_extension_enabled for it will cause
- # "circular dependency". So here just use try...except to
- # ensure tenant deletion without big changes.
- try:
- if self.neutron_available:
- self.cleanup_default_secgroup(
- self.security_groups_admin_client, creds.tenant_id)
- except lib_exc.NotFound:
- LOG.warning("failed to cleanup tenant %s's secgroup",
- creds.tenant_name)
- try:
- self.creds_client.delete_project(creds.tenant_id)
- except lib_exc.NotFound:
- LOG.warning("tenant with name: %s not found for delete",
- creds.tenant_name)
+ if creds.tenant_id:
+ # NOTE(zhufl): Only when neutron's security_group ext is
+ # enabled, cleanup_default_secgroup will not raise error. But
+ # here cannot use test_utils.is_extension_enabled for it will
+ # cause "circular dependency". So here just use try...except to
+ # ensure tenant deletion without big changes.
+ try:
+ if self.neutron_available:
+ self.cleanup_default_secgroup(
+ self.security_groups_admin_client, creds.tenant_id)
+ except lib_exc.NotFound:
+ LOG.warning("failed to cleanup tenant %s's secgroup",
+ creds.tenant_name)
+ try:
+ self.creds_client.delete_project(creds.tenant_id)
+ except lib_exc.NotFound:
+ LOG.warning("tenant with name: %s not found for delete",
+ creds.tenant_name)
# if cred is domain scoped, delete ephemeral domain
# do not delete default domain
diff --git a/tempest/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index abf427c..ae6ce25 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -206,7 +206,7 @@
def image_import(self, image_id, method='glance-direct',
all_stores_must_succeed=None, all_stores=True,
- stores=None, image_uri=None):
+ stores=None, import_params=None):
"""Import data from staging area to glance store.
For a full list of available parameters, please refer to the official
@@ -222,9 +222,11 @@
all available stores (incompatible with stores)
:param stores: A list of destination store names for the import. Must
be None if server does not support multistore.
- :param image_uri: A URL to be used with the web-download method
+ :param import_params: A dict of import method parameters
"""
url = 'images/%s/import' % image_id
+ if import_params is None:
+ import_params = {}
data = {
"method": {
"name": method
@@ -237,8 +239,8 @@
if all_stores_must_succeed is not None:
data['all_stores_must_succeed'] = all_stores_must_succeed
- if image_uri:
- data['method']['uri'] = image_uri
+ if import_params:
+ data['method'].update(import_params)
data = json.dumps(data)
headers = {'Content-Type': 'application/json'}
resp, _ = self.post(url, data, headers=headers)
diff --git a/tempest/lib/services/volume/v3/transfers_client.py b/tempest/lib/services/volume/v3/transfers_client.py
index cc4e1b2..f85bf21 100644
--- a/tempest/lib/services/volume/v3/transfers_client.py
+++ b/tempest/lib/services/volume/v3/transfers_client.py
@@ -18,12 +18,23 @@
from oslo_serialization import jsonutils as json
from tempest.lib.api_schema.response.volume import transfers as schema
+from tempest.lib.api_schema.response.volume.v3_55 \
+ import transfers as schemav355
+from tempest.lib.api_schema.response.volume.v3_57 \
+ import transfers as schemav357
from tempest.lib.common import rest_client
+from tempest.lib.services.volume import base_client
-class TransfersClient(rest_client.RestClient):
+class TransfersClient(base_client.BaseClient):
"""Client class to send CRUD Volume Transfer API requests"""
+ schema_versions_info = [
+ {'min': None, 'max': '3.54', 'schema': schema},
+ {'min': '3.55', 'max': '3.56', 'schema': schemav355},
+ {'min': '3.57', 'max': None, 'schema': schemav357}
+ ]
+
resource_path = 'os-volume-transfer'
def create_volume_transfer(self, **kwargs):
@@ -36,6 +47,7 @@
post_body = json.dumps({'transfer': kwargs})
resp, body = self.post(self.resource_path, post_body)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.create_volume_transfer, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -44,6 +56,7 @@
url = "%s/%s" % (self.resource_path, transfer_id)
resp, body = self.get(url)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.show_volume_transfer, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -56,6 +69,7 @@
https://docs.openstack.org/api-ref/block-storage/v3/index.html#list-volume-transfers-and-details
"""
url = self.resource_path
+ schema = self.get_schema(self.schema_versions_info)
schema_list_transfers = schema.list_volume_transfers_no_detail
if detail:
url += '/detail'
@@ -70,6 +84,7 @@
def delete_volume_transfer(self, transfer_id):
"""Delete a volume transfer."""
resp, body = self.delete("%s/%s" % (self.resource_path, transfer_id))
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.delete_volume_transfer, resp, body)
return rest_client.ResponseBody(resp, body)
@@ -84,6 +99,7 @@
post_body = json.dumps({'accept': kwargs})
resp, body = self.post(url, post_body)
body = json.loads(body)
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.accept_volume_transfer, resp, body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v3/volumes_client.py b/tempest/lib/services/volume/v3/volumes_client.py
index 9934e47..ad8bd71 100644
--- a/tempest/lib/services/volume/v3/volumes_client.py
+++ b/tempest/lib/services/volume/v3/volumes_client.py
@@ -20,6 +20,8 @@
from tempest.lib.api_schema.response.volume.v3_61 import volumes as schemav361
from tempest.lib.api_schema.response.volume.v3_63 import volumes as schemav363
from tempest.lib.api_schema.response.volume.v3_64 import volumes as schemav364
+from tempest.lib.api_schema.response.volume.v3_65 import volumes as schemav365
+from tempest.lib.api_schema.response.volume.v3_69 import volumes as schemav369
from tempest.lib.api_schema.response.volume import volumes as schema
from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
@@ -33,7 +35,9 @@
{'min': None, 'max': '3.60', 'schema': schema},
{'min': '3.61', 'max': '3.62', 'schema': schemav361},
{'min': '3.63', 'max': '3.63', 'schema': schemav363},
- {'min': '3.64', 'max': None, 'schema': schemav364}
+ {'min': '3.64', 'max': '3.64', 'schema': schemav364},
+ {'min': '3.65', 'max': '3.68', 'schema': schemav365},
+ {'min': '3.69', 'max': None, 'schema': schemav369}
]
def _prepare_params(self, params):