Add 'deleted' status check in _poll_for_status
When use command '--poll' to show progress, if the object's staus change into 'deleted' for some reason, it will lead a endless loop.Becasue there is no check about 'deleted' status. For example, when use 'image-create --poll' to create a vm's snapshoot, if glance's quota is small than the snapshoot, the image will be deleted. Change-Id: I028e3064b3371f87873d74494c39255775a2c818 Closes-bug:#1470047
This commit is contained in:
parent
40a4070f28
commit
ba79073d7b
@ -93,6 +93,11 @@ class VersionNotFoundForAPIMethod(Exception):
|
|||||||
return self.msg_fmt % {"vers": self.version, "method": self.method}
|
return self.msg_fmt % {"vers": self.version, "method": self.method}
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceInDeletedState(Exception):
|
||||||
|
"""Instance is in the deleted state."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ClientException(Exception):
|
class ClientException(Exception):
|
||||||
"""
|
"""
|
||||||
The base exception class for all exceptions this library raises.
|
The base exception class for all exceptions this library raises.
|
||||||
|
@ -665,6 +665,8 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
elif action == 'createImage':
|
elif action == 'createImage':
|
||||||
assert set(body[action].keys()) == set(['name', 'metadata'])
|
assert set(body[action].keys()) == set(['name', 'metadata'])
|
||||||
_headers = dict(location="http://blah/images/456")
|
_headers = dict(location="http://blah/images/456")
|
||||||
|
if body[action]['name'] == 'mysnapshot_deleted':
|
||||||
|
_headers = dict(location="http://blah/images/457")
|
||||||
elif action == 'os-getConsoleOutput':
|
elif action == 'os-getConsoleOutput':
|
||||||
assert list(body[action]) == ['length']
|
assert list(body[action]) == ['length']
|
||||||
return (202, {}, {'output': 'foo'})
|
return (202, {}, {'output': 'foo'})
|
||||||
@ -1035,6 +1037,16 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
"status": "SAVING",
|
"status": "SAVING",
|
||||||
"progress": 80,
|
"progress": 80,
|
||||||
"links": {},
|
"links": {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "My Server Backup Deleted",
|
||||||
|
"serverId": 1234,
|
||||||
|
"updated": "2010-10-10T12:00:00Z",
|
||||||
|
"created": "2010-08-10T12:00:00Z",
|
||||||
|
"status": "DELETED",
|
||||||
|
"fault": {'message': 'Image has been deleted.'},
|
||||||
|
"links": {},
|
||||||
}
|
}
|
||||||
]})
|
]})
|
||||||
|
|
||||||
@ -1047,6 +1059,9 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
def get_images_456(self, **kw):
|
def get_images_456(self, **kw):
|
||||||
return (200, {}, {'image': self.get_images_detail()[2]['images'][1]})
|
return (200, {}, {'image': self.get_images_detail()[2]['images'][1]})
|
||||||
|
|
||||||
|
def get_images_457(self, **kw):
|
||||||
|
return (200, {}, {'image': self.get_images_detail()[2]['images'][2]})
|
||||||
|
|
||||||
def get_images_3e861307_73a6_4d1f_8d68_f68b03223032(self):
|
def get_images_3e861307_73a6_4d1f_8d68_f68b03223032(self):
|
||||||
raise exceptions.NotFound('404')
|
raise exceptions.NotFound('404')
|
||||||
|
|
||||||
|
@ -813,6 +813,24 @@ class ShellTest(utils.TestCase):
|
|||||||
self.assertIn('My Server Backup', output)
|
self.assertIn('My Server Backup', output)
|
||||||
self.assertIn('SAVING', output)
|
self.assertIn('SAVING', output)
|
||||||
|
|
||||||
|
@mock.patch('novaclient.v2.shell._poll_for_status')
|
||||||
|
def test_create_image_with_poll(self, poll_method):
|
||||||
|
self.run_command(
|
||||||
|
'image-create sample-server mysnapshot --poll')
|
||||||
|
self.assert_called_anytime(
|
||||||
|
'POST', '/servers/1234/action',
|
||||||
|
{'createImage': {'name': 'mysnapshot', 'metadata': {}}},
|
||||||
|
)
|
||||||
|
self.assertEqual(1, poll_method.call_count)
|
||||||
|
poll_method.assert_has_calls(
|
||||||
|
[mock.call(self.shell.cs.images.get, '456', 'snapshotting',
|
||||||
|
['active'])])
|
||||||
|
|
||||||
|
def test_create_image_with_poll_to_check_image_state_deleted(self):
|
||||||
|
self.assertRaises(
|
||||||
|
exceptions.InstanceInDeletedState, self.run_command,
|
||||||
|
'image-create sample-server mysnapshot_deleted --poll')
|
||||||
|
|
||||||
def test_image_delete(self):
|
def test_image_delete(self):
|
||||||
self.run_command('image-delete 1')
|
self.run_command('image-delete 1')
|
||||||
self.assert_called('DELETE', '/images/1')
|
self.assert_called('DELETE', '/images/1')
|
||||||
|
@ -583,6 +583,10 @@ def _poll_for_status(poll_fn, obj_id, action, final_ok_states,
|
|||||||
if not silent:
|
if not silent:
|
||||||
print(_("\nError %s server") % action)
|
print(_("\nError %s server") % action)
|
||||||
raise exceptions.InstanceInErrorState(obj.fault['message'])
|
raise exceptions.InstanceInErrorState(obj.fault['message'])
|
||||||
|
elif status == "deleted":
|
||||||
|
if not silent:
|
||||||
|
print(_("\nDeleted %s server") % action)
|
||||||
|
raise exceptions.InstanceInDeletedState(obj.fault['message'])
|
||||||
|
|
||||||
if not silent:
|
if not silent:
|
||||||
print_progress(progress)
|
print_progress(progress)
|
||||||
|
Loading…
Reference in New Issue
Block a user