diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-02-09 15:04:07 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-02-09 15:04:08 +0000 |
commit | 3da2728ce61aea60a6e8b4a50f10ba861d8e6673 (patch) | |
tree | cd346c665e9db17eac06893c54815cc00192415c | |
parent | b0fcc4efdd360dfb5705f3601d2195cf64bc28ab (diff) | |
parent | 0d0749d39ffd122387fde6ee5e9b029f93e53459 (diff) | |
download | python-novaclient-3da2728ce61aea60a6e8b4a50f10ba861d8e6673.tar.gz |
Merge "Make _poll_for_status more user-friendly"
-rw-r--r-- | novaclient/exceptions.py | 12 | ||||
-rw-r--r-- | novaclient/tests/unit/v2/test_shell.py | 90 | ||||
-rw-r--r-- | novaclient/v2/shell.py | 4 |
3 files changed, 100 insertions, 6 deletions
diff --git a/novaclient/exceptions.py b/novaclient/exceptions.py index 94591f26..b9bdf114 100644 --- a/novaclient/exceptions.py +++ b/novaclient/exceptions.py @@ -77,9 +77,15 @@ class ConnectionRefused(Exception): return "ConnectionRefused: %s" % repr(self.response) -class InstanceInErrorState(Exception): - """Instance is in the error state.""" - pass +class ResourceInErrorState(Exception): + """Resource is in the error state.""" + + def __init__(self, obj): + msg = "`%s` resource is in the error state" % obj.__class__.__name__ + fault_msg = getattr(obj, "fault", {}).get("message") + if fault_msg: + msg += "due to '%s'" % fault_msg + self.message = "%s." % msg class VersionNotFoundForAPIMethod(Exception): diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index c079d9c6..0869a110 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -29,6 +29,7 @@ from six.moves import builtins import novaclient from novaclient import api_versions +from novaclient import base import novaclient.client from novaclient import exceptions import novaclient.shell @@ -758,7 +759,7 @@ class ShellTest(utils.TestCase): ['active'])]) def test_boot_with_poll_to_check_VM_state_error(self): - self.assertRaises(exceptions.InstanceInErrorState, self.run_command, + self.assertRaises(exceptions.ResourceInErrorState, self.run_command, 'boot --flavor 1 --image 1 some-bad-server --poll') def test_boot_named_flavor(self): @@ -2789,3 +2790,90 @@ class GetFirstEndpointTest(utils.TestCase): self.assertRaises(LookupError, novaclient.v2.shell._get_first_endpoint, [], "ORD") + + +class PollForStatusTestCase(utils.TestCase): + @mock.patch("novaclient.v2.shell.time") + def test_simple_usage(self, mock_time): + poll_period = 3 + some_id = "uuuuuuuuuuuiiiiiiiii" + updated_objects = ( + base.Resource(None, info={"not_default_field": "INPROGRESS"}), + base.Resource(None, info={"not_default_field": "OK"})) + poll_fn = mock.MagicMock(side_effect=updated_objects) + + novaclient.v2.shell._poll_for_status( + poll_fn=poll_fn, + obj_id=some_id, + status_field="not_default_field", + final_ok_states=["ok"], + poll_period=poll_period, + # just want to test printing in separate tests + action="some", + silent=True, + show_progress=False + ) + self.assertEqual([mock.call(poll_period)], + mock_time.sleep.call_args_list) + self.assertEqual([mock.call(some_id)] * 2, poll_fn.call_args_list) + + @mock.patch("novaclient.v2.shell.sys.stdout") + @mock.patch("novaclient.v2.shell.time") + def test_print_progress(self, mock_time, mock_stdout): + updated_objects = ( + base.Resource(None, info={"status": "INPROGRESS", "progress": 0}), + base.Resource(None, info={"status": "INPROGRESS", "progress": 50}), + base.Resource(None, info={"status": "OK", "progress": 100})) + poll_fn = mock.MagicMock(side_effect=updated_objects) + action = "some" + + novaclient.v2.shell._poll_for_status( + poll_fn=poll_fn, + obj_id="uuuuuuuuuuuiiiiiiiii", + final_ok_states=["ok"], + poll_period="3", + action=action, + show_progress=True, + silent=False) + + stdout_arg_list = [ + mock.call("\n"), + mock.call("\rServer %s... 0%% complete" % action), + mock.call("\rServer %s... 50%% complete" % action), + mock.call("\rServer %s... 100%% complete" % action), + mock.call("\nFinished"), + mock.call("\n")] + self.assertEqual( + stdout_arg_list, + mock_stdout.write.call_args_list + ) + + @mock.patch("novaclient.v2.shell.time") + def test_error_state(self, mock_time): + fault_msg = "Oops" + updated_objects = ( + base.Resource(None, info={"status": "error", + "fault": {"message": fault_msg}}), + base.Resource(None, info={"status": "error"})) + poll_fn = mock.MagicMock(side_effect=updated_objects) + action = "some" + + self.assertRaises(exceptions.ResourceInErrorState, + novaclient.v2.shell._poll_for_status, + poll_fn=poll_fn, + obj_id="uuuuuuuuuuuiiiiiiiii", + final_ok_states=["ok"], + poll_period="3", + action=action, + show_progress=True, + silent=False) + + self.assertRaises(exceptions.ResourceInErrorState, + novaclient.v2.shell._poll_for_status, + poll_fn=poll_fn, + obj_id="uuuuuuuuuuuiiiiiiiii", + final_ok_states=["ok"], + poll_period="3", + action=action, + show_progress=True, + silent=False) diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index 9ff95a51..f16d5903 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -642,11 +642,11 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states, elif status == "error": if not silent: print(_("\nError %s server") % action) - raise exceptions.InstanceInErrorState(obj.fault['message']) + raise exceptions.ResourceInErrorState(obj) elif status == "deleted": if not silent: print(_("\nDeleted %s server") % action) - raise exceptions.InstanceInDeletedState(obj.fault['message']) + raise exceptions.InstanceInDeletedState(obj.fault["message"]) if not silent: print_progress(progress) |