Merge "Update volume and volume transfer schema"

This commit is contained in:
Zuul 2022-08-26 20:51:46 +00:00 committed by Gerrit Code Review
commit ee6eebea9b
11 changed files with 279 additions and 5 deletions

View File

@ -110,9 +110,7 @@ class VolumesTransfersV355Test(VolumesTransfersTest):
"""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 @@ class VolumesTransfersV355Test(VolumesTransfersTest):
"""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()

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -18,12 +18,23 @@ from urllib import parse as urllib
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 @@ class TransfersClient(rest_client.RestClient):
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 @@ class TransfersClient(rest_client.RestClient):
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 @@ class TransfersClient(rest_client.RestClient):
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 @@ class TransfersClient(rest_client.RestClient):
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 @@ class TransfersClient(rest_client.RestClient):
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)

View File

@ -20,6 +20,8 @@ from oslo_serialization import jsonutils as json
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 @@ class VolumesClient(base_client.BaseClient):
{'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):