Allow evacuate from vm_state=Error

We currently allow reboot/rebuild/rescue for an instance in the Error state.
This commit allows "evacuate" as well, since it is essentially a "rebuild"
on a different compute node.

This is useful in a number of cases, in particular if an initial evacuation
attempt fails.

Change-Id: I3f513eb738c91fe71767308f57251629639efd6a
Closes-Bug: 1298061
This commit is contained in:
Chris Friesen 2014-03-14 11:37:55 -06:00
parent d239e93858
commit 2f8dfc0da2
3 changed files with 14 additions and 6 deletions

View File

@ -3015,7 +3015,8 @@ class API(base.Base):
host_name, block_migration=block_migration,
disk_over_commit=disk_over_commit)
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED])
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
vm_states.ERROR])
def evacuate(self, context, instance, host, on_shared_storage,
admin_password=None):
"""Running evacuate to target host.

View File

@ -9080,9 +9080,9 @@ class ComputeAPITestCase(BaseTestCase):
instance.refresh()
self.assertEqual(instance['task_state'], task_states.MIGRATING)
def test_evacuate(self):
def _check_evacuate(self, instance_params=None):
instance = jsonutils.to_primitive(self._create_fake_instance(
services=True))
instance_params, services=True))
instance_uuid = instance['uuid']
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertIsNone(instance['task_state'])
@ -9111,6 +9111,12 @@ class ComputeAPITestCase(BaseTestCase):
db.instance_destroy(self.context, instance['uuid'])
def test_evacuate(self):
self._check_evacuate()
def test_error_evacuate(self):
self._check_evacuate({'vm_state': vm_states.ERROR})
def test_fail_evacuate_from_non_existing_host(self):
inst = {}
inst['vm_state'] = vm_states.ACTIVE
@ -9179,9 +9185,7 @@ class ComputeAPITestCase(BaseTestCase):
jsonutils.to_primitive(self._create_fake_instance(
{'vm_state': vm_states.SOFT_DELETED})),
jsonutils.to_primitive(self._create_fake_instance(
{'vm_state': vm_states.DELETED})),
jsonutils.to_primitive(self._create_fake_instance(
{'vm_state': vm_states.ERROR}))
{'vm_state': vm_states.DELETED}))
]
for instance in instances:

View File

@ -130,6 +130,9 @@ class CellsComputeAPITestCase(test_compute.ComputeAPITestCase):
def test_evacuate(self):
self.skipTest("Test is incompatible with cells.")
def test_error_evacuate(self):
self.skipTest("Test is incompatible with cells.")
def test_delete_instance_no_cell(self):
cells_rpcapi = self.compute_api.cells_rpcapi
self.mox.StubOutWithMock(cells_rpcapi,