Add image task validation

Glance is adding a /image/$image/tasks API to make it easier to
consume the import API. This fetches the tasks after glance-direct
import, and validates that they look like we expect.

Because this is only supported after v2.12, we check for that before
doing the validation. To make that easier, this adds a has_version()
helper to the VersionsClient.

Change-Id: I2850f0659e82bf5c5a1005de0a063e7fcacadb51
This commit is contained in:
Dan Smith 2021-02-15 08:44:47 -08:00
parent 08b38f5dc9
commit 7bde7bf537
6 changed files with 100 additions and 1 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
Adds a method to images_client to get tasks relevant to a given image. Also adds
has_version() method to image versions_client to probe for availability of a given
API version.

View File

@ -96,9 +96,26 @@ class ImportImagesTest(base.BaseV2ImageTest):
image_id = self._stage_and_check()
# import image from staging to backend
self.client.image_import(image_id, method='glance-direct')
resp = self.client.image_import(image_id, method='glance-direct')
waiters.wait_for_image_imported_to_stores(self.client, image_id)
if not self.versions_client.has_version('2.12'):
# API is not new enough to support image/tasks API
LOG.info('Glance does not support v2.12, so I am unable to '
'validate the image/tasks API.')
return
# Make sure we can access the task and that some of the key
# fields look legit.
tasks = self.client.show_image_tasks(image_id)
self.assertEqual(1, len(tasks['tasks']))
task = tasks['tasks'][0]
self.assertEqual('success', task['status'])
self.assertEqual(resp.response['x-openstack-request-id'],
task['request_id'])
self.assertEqual('glance-direct',
task['input']['import_req']['method']['name'])
@decorators.idempotent_id('f6feb7a4-b04f-4706-a011-206129f83e62')
def test_image_web_download_import(self):
"""Test 'web-download' import functionalities

View File

@ -121,6 +121,14 @@ class ImagesClient(rest_client.RestClient):
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_image_tasks(self, image_id):
"""Show image tasks."""
url = 'images/%s/tasks' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
try:
self.show_image(id)

View File

@ -30,3 +30,13 @@ class VersionsClient(rest_client.RestClient):
self.expected_success(300, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def has_version(self, version):
"""Return True if a version is supported."""
version = 'v%s' % version
supported = ['SUPPORTED', 'CURRENT']
versions = self.list_versions()
for version_struct in versions['versions']:
if version_struct['id'] == version:
return version_struct['status'] in supported
return False

View File

@ -105,6 +105,44 @@ class TestImagesClient(base.BaseServiceTest):
"first": "/v2/images"
}
FAKE_SHOW_IMAGE_TASKS = {
"tasks": [
{
"id": "ee22890e-8948-4ea6-9668-831f973c84f5",
"image_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
"request-id": "rrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr",
"user": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu",
"type": "api_image_import",
"status": "processing",
"owner": "64f0efc9955145aeb06f297a8a6fe402",
"expires_at": None,
"created_at": "2020-12-18T05:20:38.000000",
"updated_at": "2020-12-18T05:25:39.000000",
"deleted_at": None,
"deleted": False,
"input": {
"image_id": "829c729b-ebc4-4cc7-a164-6f43f1149b17",
"import_req": {
"method": {
"name": "copy-image",
},
"all_stores": True,
"all_stores_must_succeed": False,
},
"backend": [
"fast",
"cheap",
"slow",
"reliable",
"common",
]
},
"result": None,
"message": "Copied 15 MiB",
}
]
}
FAKE_TAG_NAME = "fake tag"
def setUp(self):
@ -230,3 +268,11 @@ class TestImagesClient(base.BaseServiceTest):
def test_list_images_with_bytes_body(self):
self._test_list_images(bytes_body=True)
def test_show_image_tasks(self):
self.check_service_client_function(
self.client.show_image_tasks,
'tempest.lib.common.rest_client.RestClient.get',
self.FAKE_SHOW_IMAGE_TASKS,
True,
image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8")

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import fixtures
from tempest.lib.services.image.v2 import versions_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
@ -92,3 +94,13 @@ class TestVersionsClient(base.BaseServiceTest):
def test_list_versions_with_bytes_body(self):
self._test_list_versions(bytes_body=True)
def test_has_version(self):
mocked_r = self.create_response(self.FAKE_VERSIONS_INFO, False,
300, None)
self.useFixture(fixtures.MockPatch(
'tempest.lib.common.rest_client.RestClient.raw_request',
return_value=mocked_r))
self.assertTrue(self.client.has_version('2.1'))
self.assertFalse(self.client.has_version('9.9'))