diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py index efa23bb83a..d283ab3c1f 100644 --- a/tempest/api/image/v2/test_images.py +++ b/tempest/api/image/v2/test_images.py @@ -105,12 +105,10 @@ class ImportImagesTest(base.BaseV2ImageTest): '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 eaac05e6dd..3750b113f8 100644 --- a/tempest/common/waiters.py +++ b/tempest/common/waiters.py @@ -193,6 +193,30 @@ def wait_for_image_status(client, image_id, status): 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 d64d7b020f..f801243011 100755 --- a/tempest/tests/common/test_waiters.py +++ b/tempest/tests/common/test_waiters.py @@ -120,6 +120,29 @@ class TestImageWaiters(base.TestCase): 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):