Skip to content

Commit c41f5f6

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Fix image-create --poll race-condition."
2 parents 85d591b + 7ef0786 commit c41f5f6

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

novaclient/v1_1/shell.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ def do_cloudpipe_create(cs, args):
248248

249249

250250
def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
251-
poll_period=5, show_progress=True):
251+
poll_period=5, show_progress=True,
252+
status_field="status", silent=False):
252253
"""Block while an action is being performed, periodically printing
253254
progress.
254255
"""
@@ -262,21 +263,32 @@ def print_progress(progress):
262263
sys.stdout.write(msg)
263264
sys.stdout.flush()
264265

265-
print
266+
if not silent:
267+
print
268+
266269
while True:
267270
obj = poll_fn(obj_id)
268-
status = obj.status.lower()
271+
272+
status = getattr(obj, status_field)
273+
274+
if status:
275+
status = status.lower()
276+
269277
progress = getattr(obj, 'progress', None) or 0
270278
if status in final_ok_states:
271-
print_progress(100)
272-
print "\nFinished"
279+
if not silent:
280+
print_progress(100)
281+
print "\nFinished"
273282
break
274283
elif status == "error":
275-
print "\nError %(action)s instance" % locals()
284+
if not silent:
285+
print "\nError %(action)s instance" % locals()
276286
break
277-
else:
287+
288+
if not silent:
278289
print_progress(progress)
279-
time.sleep(poll_period)
290+
291+
time.sleep(poll_period)
280292

281293

282294
def _translate_flavor_keys(collection):
@@ -753,6 +765,21 @@ def do_image_create(cs, args):
753765
_poll_for_status(cs.images.get, image_uuid, 'snapshotting',
754766
['active'])
755767

768+
# NOTE(sirp): A race-condition exists between when the image finishes
769+
# uploading and when the servers's `task_state` is cleared. To account
770+
# for this, we need to poll a second time to ensure the `task_state` is
771+
# cleared before returning, ensuring that a snapshot taken immediately
772+
# after this function returns will succeed.
773+
#
774+
# A better long-term solution will be to separate 'snapshotting' and
775+
# 'image-uploading' in Nova and clear the task-state once the VM
776+
# snapshot is complete but before the upload begins.
777+
task_state_field = "OS-EXT-STS:task_state"
778+
if hasattr(server, task_state_field):
779+
_poll_for_status(cs.servers.get, server.id, 'image_snapshot',
780+
[None], status_field=task_state_field,
781+
show_progress=False, silent=True)
782+
756783

757784
@utils.arg('server',
758785
metavar='<server>',

0 commit comments

Comments
 (0)