diff options
author | Jenkins <jenkins@review.openstack.org> | 2012-07-24 15:23:21 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2012-07-24 15:23:21 +0000 |
commit | c41f5f643af136ccb9cdc40902a6cebfdebaa518 (patch) | |
tree | a3af13d3e18616b00d74c9063a8ed344ad5a626f | |
parent | 85d591b1d88b7e6d174c8eabd41dda14162a8bbc (diff) | |
parent | 7ef0786d9e6172a9df0d33a1113f27569bd7f522 (diff) | |
download | python-novaclient-2.7.0.tar.gz |
Merge "Fix image-create --poll race-condition."2.7.0
-rw-r--r-- | novaclient/v1_1/shell.py | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index daad9b4d..99991c2c 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -248,7 +248,8 @@ def do_cloudpipe_create(cs, args): def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True): + poll_period=5, show_progress=True, + status_field="status", silent=False): """Block while an action is being performed, periodically printing progress. """ @@ -262,21 +263,32 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states, sys.stdout.write(msg) sys.stdout.flush() - print + if not silent: + print + while True: obj = poll_fn(obj_id) - status = obj.status.lower() + + status = getattr(obj, status_field) + + if status: + status = status.lower() + progress = getattr(obj, 'progress', None) or 0 if status in final_ok_states: - print_progress(100) - print "\nFinished" + if not silent: + print_progress(100) + print "\nFinished" break elif status == "error": - print "\nError %(action)s instance" % locals() + if not silent: + print "\nError %(action)s instance" % locals() break - else: + + if not silent: print_progress(progress) - time.sleep(poll_period) + + time.sleep(poll_period) def _translate_flavor_keys(collection): @@ -753,6 +765,21 @@ def do_image_create(cs, args): _poll_for_status(cs.images.get, image_uuid, 'snapshotting', ['active']) + # NOTE(sirp): A race-condition exists between when the image finishes + # uploading and when the servers's `task_state` is cleared. To account + # for this, we need to poll a second time to ensure the `task_state` is + # cleared before returning, ensuring that a snapshot taken immediately + # after this function returns will succeed. + # + # A better long-term solution will be to separate 'snapshotting' and + # 'image-uploading' in Nova and clear the task-state once the VM + # snapshot is complete but before the upload begins. + task_state_field = "OS-EXT-STS:task_state" + if hasattr(server, task_state_field): + _poll_for_status(cs.servers.get, server.id, 'image_snapshot', + [None], status_field=task_state_field, + show_progress=False, silent=True) + @utils.arg('server', metavar='<server>', |