Raise exception when poll returns error state

When running nova boot --poll, any error states that occur will be
seen but, an exit code of 0 will be returned indicating success.
This would be problematic for scripts looking to see if an
operation completed successfully.

To fix this, an exception is raised after the nova api indicates to the
poll code that the vm is in an error state. The exceptions signals the shell
main function to exit with code 1.

Change-Id: I48f6b1c82e2f8b221dda898dcb804b0196018505
Fixes-Bug: #1292669
This commit is contained in:
Ryan Hallisey 2014-03-14 15:32:10 -04:00
parent 14deb0194e
commit d01b3abdb0
7 changed files with 30 additions and 4 deletions

View File

@ -77,6 +77,11 @@ class ConnectionRefused(Exception):
return "ConnectionRefused: %s" % repr(self.response)
class InstanceInErrorState(Exception):
"""Instance is in the error state."""
pass
class ClientException(Exception):
"""
The base exception class for all exceptions this library raises.

View File

@ -369,7 +369,10 @@ class FakeHTTPClient(base_client.HTTPClient):
if 'personality' in body['server']:
for pfile in body['server']['personality']:
fakes.assert_has_keys(pfile, required=['path', 'contents'])
return (202, {}, self.get_servers_1234()[2])
if body['server']['name'] == 'some-bad-server':
return (202, {}, self.get_servers_1235()[2])
else:
return (202, {}, self.get_servers_1234()[2])
def post_os_volumes_boot(self, body, **kw):
assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
@ -392,6 +395,13 @@ class FakeHTTPClient(base_client.HTTPClient):
r = {'server': self.get_servers_detail()[2]['servers'][0]}
return (200, {}, r)
def get_servers_1235(self, **kw):
r = {'server': self.get_servers_detail()[2]['servers'][0]}
r['server']['id'] = 1235
r['server']['status'] = 'error'
r['server']['fault'] = {'message': 'something went wrong!'}
return (200, {}, r)
def get_servers_5678(self, **kw):
r = {'server': self.get_servers_detail()[2]['servers'][1]}
return (200, {}, r)

View File

@ -581,6 +581,10 @@ class ShellTest(utils.TestCase):
[mock.call(self.shell.cs.servers.get, 1234, 'building',
['active'])])
def test_boot_with_poll_to_check_VM_state_error(self):
self.assertRaises(exceptions.InstanceInErrorState, self.run_command,
'boot --flavor 1 --image 1 some-bad-server --poll')
def test_flavor_list(self):
self.run_command('flavor-list')
self.assert_called_anytime('GET', '/flavors/detail')

View File

@ -170,7 +170,10 @@ class FakeHTTPClient(fakes_v1_1.FakeHTTPClient):
required=['name', 'image_ref', 'flavor_ref'],
optional=['metadata', 'personality',
'os-scheduler-hints:scheduler_hints'])
return (202, {}, self.get_servers_1234()[2])
if body['server']['name'] == 'some-bad-server':
return (202, {}, self.get_servers_1235()[2])
else:
return (202, {}, self.get_servers_1234()[2])
#
# Server Actions

View File

@ -480,3 +480,7 @@ class ShellTest(utils.TestCase):
poll_method.assert_has_calls(
[mock.call(self.shell.cs.servers.get, 1234, 'building',
['active'])])
def test_boot_with_poll_to_check_VM_state_error(self):
self.assertRaises(exceptions.InstanceInErrorState, self.run_command,
'boot --flavor 1 --image 1 some-bad-server --poll')

View File

@ -494,7 +494,7 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
elif status == "error":
if not silent:
print(_("\nError %s server") % action)
break
raise exceptions.InstanceInErrorState(obj.fault['message'])
if not silent:
print_progress(progress)

View File

@ -349,7 +349,7 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
elif status == "error":
if not silent:
print("\nError %s server" % action)
break
raise exceptions.InstanceInErrorState(obj.fault['message'])
if not silent:
print_progress(progress)