Fix rebuild of baremetal instance when vm_state is ERROR
Nova allows rebuild of instance when vm_state is ERROR. [1] The vm_state is restored to ACTIVE only after a successful build. This means rebuilding a baremetal instance using the Ironic driver is impossible because wait_for_active fails if vm_state=ERROR is found. This is a regression introduced in a previous change which added the ability to delete an instance in spawning state. [2] This present change will skip the abort installation logic if task_state is REBUILD_SPAWNING while preserving the previous logic. [1] https://bugs.launchpad.net/nova/+bug/1183946 [2] https://bugs.launchpad.net/nova/+bug/1455000 Change-Id: I857ad7264f1a7ef1263d8a9d4eca491d6c8dce0f Closes-bug: #1735009
This commit is contained in:
parent
af40e3d1a6
commit
1819718e79
|
@ -201,6 +201,23 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
|||
fake_validate.assert_called_once_with(instance)
|
||||
fake_refresh.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(objects.Instance, 'refresh')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
def test__wait_for_active_from_error(self, fake_validate, fake_refresh):
|
||||
instance = fake_instance.fake_instance_obj(self.ctx,
|
||||
uuid=uuidutils.generate_uuid(),
|
||||
vm_state=vm_states.ERROR,
|
||||
task_state=task_states.REBUILD_SPAWNING)
|
||||
node = ironic_utils.get_test_node(
|
||||
provision_state=ironic_states.ACTIVE)
|
||||
|
||||
fake_validate.return_value = node
|
||||
self.assertRaises(loopingcall.LoopingCallDone,
|
||||
self.driver._wait_for_active, instance)
|
||||
fake_validate.assert_called_once_with(instance)
|
||||
fake_refresh.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(objects.Instance, 'refresh')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
|
@ -236,7 +253,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
|||
self._wait_for_active_abort({'vm_state': vm_states.DELETED})
|
||||
|
||||
def test__wait_for_active_abort_error(self):
|
||||
self._wait_for_active_abort({'vm_state': vm_states.ERROR})
|
||||
self._wait_for_active_abort({'task_state': task_states.SPAWNING,
|
||||
'vm_state': vm_states.ERROR})
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
|
|
|
@ -497,8 +497,10 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||
def _wait_for_active(self, instance):
|
||||
"""Wait for the node to be marked as ACTIVE in Ironic."""
|
||||
instance.refresh()
|
||||
if (instance.task_state == task_states.DELETING or
|
||||
instance.vm_state in (vm_states.ERROR, vm_states.DELETED)):
|
||||
# Ignore REBUILD_SPAWNING when rebuilding from ERROR state.
|
||||
if (instance.task_state != task_states.REBUILD_SPAWNING and
|
||||
(instance.task_state == task_states.DELETING or
|
||||
instance.vm_state in (vm_states.ERROR, vm_states.DELETED))):
|
||||
raise exception.InstanceDeployFailure(
|
||||
_("Instance %s provisioning was aborted") % instance.uuid)
|
||||
|
||||
|
|
Loading…
Reference in New Issue