Add wait to check the import task status
Once Glance finish the import operation(change image status
to active), it move the task to 'success' state but in between of
image become active and task is transitioning to 'success', tempest
try to check the task status and race condition happen.
Adding waiter method in test for task status check.
Closes-Bug: #1926671
Change-Id: I960b80314f1b0926eca33af830bc827f31cbeda6
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index efa23bb..d283ab3 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -105,12 +105,10 @@
'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'])
+ tasks = waiters.wait_for_image_tasks_status(
+ self.client, image_id, 'success')
+ self.assertEqual(1, len(tasks))
+ task = tasks[0]
self.assertEqual(resp.response['x-openstack-request-id'],
task['request_id'])
self.assertEqual('glance-direct',
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index eaac05e..3750b11 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -193,6 +193,30 @@
raise lib_exc.TimeoutException(message)
+def wait_for_image_tasks_status(client, image_id, status):
+ """Waits for an image tasks to reach a given status."""
+ pending_tasks = []
+ start = int(time.time())
+ while int(time.time()) - start < client.build_timeout:
+ tasks = client.show_image_tasks(image_id)['tasks']
+
+ pending_tasks = [task for task in tasks if task['status'] != status]
+ if not pending_tasks:
+ return tasks
+ time.sleep(client.build_interval)
+
+ message = ('Image %(image_id)s tasks: %(pending_tasks)s '
+ 'failed to reach %(status)s state within the required '
+ 'time (%(timeout)s s).' % {'image_id': image_id,
+ 'pending_tasks': pending_tasks,
+ 'status': status,
+ 'timeout': client.build_timeout})
+ caller = test_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ raise lib_exc.TimeoutException(message)
+
+
def wait_for_image_imported_to_stores(client, image_id, stores=None):
"""Waits for an image to be imported to all requested stores.
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index d64d7b0..f801243 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -120,6 +120,29 @@
waiters.wait_for_image_copied_to_stores,
self.client, 'fake_image_id')
+ def test_wait_for_image_tasks_status(self):
+ self.client.show_image_tasks.return_value = ({
+ 'tasks': [{'status': 'success'}]})
+ start_time = int(time.time())
+ waiters.wait_for_image_tasks_status(
+ self.client, 'fake_image_id', 'success')
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout
+ self.assertLess((end_time - start_time), 10)
+
+ def test_wait_for_image_tasks_status_timeout(self):
+ time_mock = self.patch('time.time')
+ self.patch('time.time', side_effect=[0., 1.])
+ time_mock.side_effect = utils.generate_timeout_series(1)
+
+ self.client.show_image_tasks.return_value = ({
+ 'tasks': [
+ {'status': 'success'},
+ {'status': 'processing'}]})
+ self.assertRaises(lib_exc.TimeoutException,
+ waiters.wait_for_image_tasks_status,
+ self.client, 'fake_image_id', 'success')
+
class TestInterfaceWaiters(base.TestCase):