Enable hard-reboot on more states

Instance may stuck at some status, so enable hard-reboot on more
status to enable user to reset instance when it gets in some sort
of bad state.

Change-Id: I99200d44a179705d89c9912a7261fe40100b535b
Closes-Bug: #1376384
This commit is contained in:
He Jie Xu 2014-11-06 13:42:51 +08:00
parent 89cd6a0c49
commit 4b033f8fa2
4 changed files with 53 additions and 20 deletions

View File

@ -2229,23 +2229,25 @@ class API(base.Base):
instance_uuid=instance['uuid'],
state=instance['vm_state'],
method='soft reboot')
if ((reboot_type == 'SOFT' and
instance['task_state'] in
(task_states.REBOOTING, task_states.REBOOTING_HARD,
task_states.REBOOT_PENDING, task_states.REBOOT_STARTED)) or
(reboot_type == 'HARD' and
instance['task_state'] == task_states.REBOOTING_HARD)):
if reboot_type == 'SOFT' and instance['task_state'] is not None:
raise exception.InstanceInvalidState(
attr='task_state',
instance_uuid=instance['uuid'],
state=instance['task_state'],
method='reboot')
expected_task_state = [None]
if reboot_type == 'HARD':
expected_task_state.extend([task_states.REBOOTING,
task_states.REBOOT_PENDING,
task_states.REBOOT_STARTED,
task_states.REBOOTING_HARD,
task_states.RESUMING,
task_states.UNPAUSING,
task_states.SUSPENDING])
state = {'SOFT': task_states.REBOOTING,
'HARD': task_states.REBOOTING_HARD}[reboot_type]
instance.task_state = state
instance.save(expected_task_state=[None, task_states.REBOOTING,
task_states.REBOOT_PENDING,
task_states.REBOOT_STARTED])
instance.save(expected_task_state=expected_task_state)
self._record_action_start(context, instance, instance_actions.REBOOT)

View File

@ -246,15 +246,13 @@ class ServerActionsControllerTest(test.TestCase):
task_state=task_states.REBOOTING))
self.controller._action_reboot(req, FAKE_UUID, body)
def test_reboot_hard_with_hard_in_progress_raises_conflict(self):
def test_reboot_hard_with_hard_in_progress(self):
body = dict(reboot=dict(type="HARD"))
req = fakes.HTTPRequestV3.blank(self.url)
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE,
task_state=task_states.REBOOTING_HARD))
self.assertRaises(webob.exc.HTTPConflict,
self.controller._action_reboot,
req, FAKE_UUID, body)
self.controller._action_reboot(req, FAKE_UUID, body)
def test_rebuild_accepted_minimum(self):
return_server = fakes.fake_instance_get(image_ref='2',

View File

@ -310,15 +310,13 @@ class ServerActionsControllerTest(test.TestCase):
task_state=task_states.REBOOTING))
self.controller._action_reboot(req, FAKE_UUID, body)
def test_reboot_hard_with_hard_in_progress_raises_conflict(self):
def test_reboot_hard_with_hard_in_progress(self):
body = dict(reboot=dict(type="HARD"))
req = fakes.HTTPRequest.blank(self.url)
self.stubs.Set(db, 'instance_get_by_uuid',
fakes.fake_instance_get(vm_state=vm_states.ACTIVE,
task_state=task_states.REBOOTING_HARD))
self.assertRaises(webob.exc.HTTPConflict,
self.controller._action_reboot,
req, FAKE_UUID, body)
self.controller._action_reboot(req, FAKE_UUID, body)
def test_rebuild_preserve_ephemeral_is_ignored_when_ext_not_loaded(self):
return_server = fakes.fake_instance_get(image_ref='2',

View File

@ -421,9 +421,16 @@ class _ComputeAPIUnitTestMixIn(object):
self.mox.StubOutWithMock(self.compute_api, '_record_action_start')
self.mox.StubOutWithMock(self.compute_api, 'update')
self.mox.StubOutWithMock(inst, 'save')
inst.save(expected_task_state=[None, task_states.REBOOTING,
task_states.REBOOT_PENDING,
task_states.REBOOT_STARTED])
expected_task_state = [None]
if reboot_type == 'HARD':
expected_task_state.extend([task_states.REBOOTING,
task_states.REBOOT_PENDING,
task_states.REBOOT_STARTED,
task_states.REBOOTING_HARD,
task_states.RESUMING,
task_states.UNPAUSING,
task_states.SUSPENDING])
inst.save(expected_task_state=expected_task_state)
self.compute_api._record_action_start(self.context, inst,
instance_actions.REBOOT)
@ -469,6 +476,22 @@ class _ComputeAPIUnitTestMixIn(object):
def test_reboot_hard_rescued(self):
self._test_reboot_type_fails('HARD', vm_state=vm_states.RESCUED)
def test_reboot_hard_resuming(self):
self._test_reboot_type(vm_states.ACTIVE,
'HARD', task_state=task_states.RESUMING)
def test_reboot_hard_pausing(self):
self._test_reboot_type(vm_states.ACTIVE,
'HARD', task_state=task_states.PAUSING)
def test_reboot_hard_unpausing(self):
self._test_reboot_type(vm_states.ACTIVE,
'HARD', task_state=task_states.UNPAUSING)
def test_reboot_hard_suspending(self):
self._test_reboot_type(vm_states.ACTIVE,
'HARD', task_state=task_states.SUSPENDING)
def test_reboot_hard_error_not_launched(self):
self._test_reboot_type_fails('HARD', vm_state=vm_states.ERROR,
launched_at=None)
@ -510,6 +533,18 @@ class _ComputeAPIUnitTestMixIn(object):
self._test_reboot_type_fails('SOFT', vm_state=vm_states.ERROR,
launched_at=None)
def test_reboot_soft_resuming(self):
self._test_reboot_type_fails('SOFT', task_state=task_states.RESUMING)
def test_reboot_soft_pausing(self):
self._test_reboot_type_fails('SOFT', task_state=task_states.PAUSING)
def test_reboot_soft_unpausing(self):
self._test_reboot_type_fails('SOFT', task_state=task_states.UNPAUSING)
def test_reboot_soft_suspending(self):
self._test_reboot_type_fails('SOFT', task_state=task_states.SUSPENDING)
def _test_delete_resizing_part(self, inst, deltas):
fake_db_migration = test_migration.fake_db_migration()
migration = objects.Migration._from_db_object(