Handle creating an image from a server with microversion > 2.35
The compute 2.35 API deprecates the compute image proxy APIs for showing/listing/deleting images. The compute 2.45 API removes the 'location' header from the createImage server action response and in that same version, adds a response body with a single "image_id" key. This change updates the BaseV2ComputeTest.create_image_from_server helper method to be aware of the microversion that the test running this code is using, and adjust the client to use appropriately. As a result, the compute images client needs to be aware of the changed createImage response schema so that is added for compute API version 2.45. Change-Id: I5551af0064f9cca594ae533379d0b0ae14444f88
This commit is contained in:
parent
039740add6
commit
f110a4ba1f
|
@ -99,6 +99,15 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
|||
cls.versions_client = cls.os_primary.compute_versions_client
|
||||
if CONF.service_available.cinder:
|
||||
cls.volumes_client = cls.os_primary.volumes_client_latest
|
||||
if CONF.service_available.glance:
|
||||
if CONF.image_feature_enabled.api_v1:
|
||||
cls.images_client = cls.os_primary.image_client
|
||||
elif CONF.image_feature_enabled.api_v2:
|
||||
cls.images_client = cls.os_primary.image_client_v2
|
||||
else:
|
||||
raise lib_exc.InvalidConfiguration(
|
||||
'Either api_v1 or api_v2 must be True in '
|
||||
'[image-feature-enabled].')
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
|
@ -254,7 +263,11 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
|||
|
||||
@classmethod
|
||||
def create_image_from_server(cls, server_id, **kwargs):
|
||||
"""Wrapper utility that returns an image created from the server."""
|
||||
"""Wrapper utility that returns an image created from the server.
|
||||
|
||||
If compute microversion >= 2.36, the returned image response will
|
||||
be from the image service API rather than the compute image proxy API.
|
||||
"""
|
||||
name = kwargs.pop('name',
|
||||
data_utils.rand_name(cls.__name__ + "-image"))
|
||||
wait_until = kwargs.pop('wait_until', None)
|
||||
|
@ -267,14 +280,21 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
|||
image_id = image['image_id']
|
||||
else:
|
||||
image_id = data_utils.parse_image_id(image.response['location'])
|
||||
|
||||
# The compute image proxy APIs were deprecated in 2.35 so
|
||||
# use the images client directly if the API microversion being
|
||||
# used is >=2.36.
|
||||
if api_version_utils.compare_version_header_to_response(
|
||||
"OpenStack-API-Version", "compute 2.36", image.response, "lt"):
|
||||
client = cls.images_client
|
||||
else:
|
||||
client = cls.compute_images_client
|
||||
cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
cls.compute_images_client.delete_image,
|
||||
image_id)
|
||||
client.delete_image, image_id)
|
||||
|
||||
if wait_until is not None:
|
||||
try:
|
||||
waiters.wait_for_image_status(cls.compute_images_client,
|
||||
image_id, wait_until)
|
||||
waiters.wait_for_image_status(client, image_id, wait_until)
|
||||
except lib_exc.NotFound:
|
||||
if wait_until.upper() == 'ACTIVE':
|
||||
# If the image is not found after create_image returned
|
||||
|
@ -292,7 +312,11 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
|||
image_id=image_id)
|
||||
else:
|
||||
raise
|
||||
image = cls.compute_images_client.show_image(image_id)['image']
|
||||
image = client.show_image(image_id)
|
||||
# Compute image client returns response wrapped in 'image' element
|
||||
# which is not the case with Glance image client.
|
||||
if 'image' in image:
|
||||
image = image['image']
|
||||
|
||||
if wait_until.upper() == 'ACTIVE':
|
||||
if wait_for_server:
|
||||
|
|
|
@ -30,18 +30,6 @@ CONF = config.CONF
|
|||
|
||||
class FlavorsV2NegativeTest(base.BaseV2ComputeTest):
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(FlavorsV2NegativeTest, cls).setup_clients()
|
||||
if CONF.image_feature_enabled.api_v1:
|
||||
cls.images_client = cls.os_primary.image_client
|
||||
elif CONF.image_feature_enabled.api_v2:
|
||||
cls.images_client = cls.os_primary.image_client_v2
|
||||
else:
|
||||
raise lib_exc.InvalidConfiguration(
|
||||
'Either api_v1 or api_v2 must be True in '
|
||||
'[image-feature-enabled].')
|
||||
|
||||
@decorators.attr(type=['negative'])
|
||||
@utils.services('image')
|
||||
@decorators.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# 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.
|
||||
|
||||
# The 2.45 microversion removes the "location" header and adds "image_id"
|
||||
# to the response body.
|
||||
create_image = {
|
||||
'status_code': [202],
|
||||
'response_body': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'image_id': {'type': 'string'}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
'required': ['image_id']
|
||||
}
|
||||
}
|
||||
|
||||
# NOTE(mriedem): The compute proxy APIs for showing/listing and deleting
|
||||
# images were deprecated in microversion 2.35, and the compute proxy APIs for
|
||||
# working with image metadata were deprecated in microversion 2.39. Therefore,
|
||||
# client-side code shouldn't rely on those APIs in the compute images client
|
||||
# past those microversions and should instead use the Glance images client
|
||||
# directly.
|
|
@ -17,6 +17,7 @@ from oslo_serialization import jsonutils as json
|
|||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.api_schema.response.compute.v2_1 import images as schema
|
||||
from tempest.lib.api_schema.response.compute.v2_45 import images as schemav245
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from tempest.lib.services.compute import base_compute_client
|
||||
|
@ -24,6 +25,10 @@ from tempest.lib.services.compute import base_compute_client
|
|||
|
||||
class ImagesClient(base_compute_client.BaseComputeClient):
|
||||
|
||||
schema_versions_info = [
|
||||
{'min': None, 'max': '2.44', 'schema': schema},
|
||||
{'min': '2.45', 'max': None, 'schema': schemav245}]
|
||||
|
||||
def create_image(self, server_id, **kwargs):
|
||||
"""Create an image of the original server.
|
||||
|
||||
|
@ -36,7 +41,10 @@ class ImagesClient(base_compute_client.BaseComputeClient):
|
|||
post_body = json.dumps(post_body)
|
||||
resp, body = self.post('servers/%s/action' % server_id,
|
||||
post_body)
|
||||
self.validate_response(schema.create_image, resp, body)
|
||||
_schema = self.get_schema(self.schema_versions_info)
|
||||
if body:
|
||||
body = json.loads(body)
|
||||
self.validate_response(_schema.create_image, resp, body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def list_images(self, detail=False, **params):
|
||||
|
|
Loading…
Reference in New Issue