Allow wait_for_image_status() to have multiple

This lets us wait for one of multiple target states so we can more
effectively avoid race conditions where we miss an intermediate state
and first poll the final one.

Change-Id: If12c35d38c03fa329ebbf536e2fcd3ff2bd136de
This commit is contained in:
Dan Smith 2024-11-13 07:21:46 -08:00
parent 2ba7ed8e39
commit aa8d42c51d
2 changed files with 18 additions and 4 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
The wait_for_image_status() waiter now allows a list of status values
instead of just a string, and returns the state the image was in when we
stopped waiting.

View File

@ -154,13 +154,21 @@ def wait_for_server_termination(client, server_id, ignore_error=False,
def wait_for_image_status(client, image_id, status): def wait_for_image_status(client, image_id, status):
"""Waits for an image to reach a given status. """Waits for an image to reach a given status (or list of them).
The client should have a show_image(image_id) method to get the image. The client should have a show_image(image_id) method to get the image.
The client should also have build_interval and build_timeout attributes. The client should also have build_interval and build_timeout attributes.
status can be either a string or a list of strings that constitute a
terminal state that we will return.
""" """
show_image = client.show_image show_image = client.show_image
if isinstance(status, str):
terminal_status = [status]
else:
terminal_status = status
current_status = 'An unknown status' current_status = 'An unknown status'
start = int(time.time()) start = int(time.time())
while int(time.time()) - start < client.build_timeout: while int(time.time()) - start < client.build_timeout:
@ -171,8 +179,8 @@ def wait_for_image_status(client, image_id, status):
image = image['image'] image = image['image']
current_status = image['status'] current_status = image['status']
if current_status == status: if current_status in terminal_status:
return return current_status
if current_status.lower() == 'killed': if current_status.lower() == 'killed':
raise exceptions.ImageKilledException(image_id=image_id, raise exceptions.ImageKilledException(image_id=image_id,
status=status) status=status)
@ -184,7 +192,7 @@ def wait_for_image_status(client, image_id, status):
message = ('Image %(image_id)s failed to reach %(status)s state ' message = ('Image %(image_id)s failed to reach %(status)s state '
'(current state %(current_status)s) within the required ' '(current state %(current_status)s) within the required '
'time (%(timeout)s s).' % {'image_id': image_id, 'time (%(timeout)s s).' % {'image_id': image_id,
'status': status, 'status': ','.join(terminal_status),
'current_status': current_status, 'current_status': current_status,
'timeout': client.build_timeout}) 'timeout': client.build_timeout})
caller = test_utils.find_test_caller() caller = test_utils.find_test_caller()