Fix soft deleting vm fails after "nova resize" vm
Problem description:
When trying to soft-delete an instance that is just resized but the resize
action is not yet confirmed, the soft-delete call will first attempt to
confirm_resize the instance, then an error will occur since confirm_resize
method does not expect a SOFT_DELETING task_state currently.
https://github.com/openstack/nova/blob/8e052c7/nova/compute/manager.py#L3911
Fix steps:
1 Add SOFT_DELETING to the expected_task_state of confirm_resize method.
2 Since confirm_resize method sets instance.task_state to None, set
instance.task_state to back to SOFT_DELETING after confirm_resize is
executed, so the rest workflow should finish as normal situations.
Co-Authored-By: Chen <dstbtgagt@foxmail.com>
Change-Id: Ia4592adc93960625148ffa6e9f7d1cfa0c6046aa
Closes-Bug: #1712480
(cherry picked from commit 018522f4d0
)
This commit is contained in:
parent
e19d6f06e3
commit
7871204988
|
@ -1921,6 +1921,18 @@ class API(base.Base):
|
|||
|
||||
if instance.vm_state == vm_states.RESIZED:
|
||||
self._confirm_resize_on_deleting(context, instance)
|
||||
# NOTE(neha_alhat): After confirm resize vm_state will become
|
||||
# 'active' and task_state will be set to 'None'. But for soft
|
||||
# deleting a vm, the _do_soft_delete callback requires
|
||||
# task_state in 'SOFT_DELETING' status. So, we need to set
|
||||
# task_state as 'SOFT_DELETING' again for soft_delete case.
|
||||
# After confirm resize and before saving the task_state to
|
||||
# "SOFT_DELETING", during the short window, user can submit
|
||||
# soft delete vm request again and system will accept and
|
||||
# process it without any errors.
|
||||
if delete_type == 'soft_delete':
|
||||
instance.task_state = instance_attrs['task_state']
|
||||
instance.save()
|
||||
|
||||
is_local_delete = True
|
||||
try:
|
||||
|
|
|
@ -3772,7 +3772,8 @@ class ComputeManager(manager.Manager):
|
|||
|
||||
instance.vm_state = vm_state
|
||||
instance.task_state = None
|
||||
instance.save(expected_task_state=[None, task_states.DELETING])
|
||||
instance.save(expected_task_state=[None, task_states.DELETING,
|
||||
task_states.SOFT_DELETING])
|
||||
|
||||
self._notify_about_instance_usage(
|
||||
context, instance, "resize.confirm.end",
|
||||
|
|
|
@ -983,9 +983,16 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
self.context, inst.uuid, 'finished').AndReturn(migration)
|
||||
self.compute_api._record_action_start(
|
||||
self.context, inst, instance_actions.CONFIRM_RESIZE)
|
||||
|
||||
def _reset_task_state(context, instance, migration, src_host,
|
||||
cast=False):
|
||||
inst.update({'task_state': None})
|
||||
|
||||
# After confirm resize action, instance task_state is reset to None
|
||||
self.compute_api.compute_rpcapi.confirm_resize(
|
||||
self.context, inst, migration,
|
||||
migration['source_compute'], cast=False)
|
||||
migration['source_compute'], cast=False).WithSideEffects(
|
||||
_reset_task_state)
|
||||
|
||||
def _test_delete_shelved_part(self, inst):
|
||||
image_api = self.compute_api.image_api
|
||||
|
@ -1115,6 +1122,17 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
if self.cell_type != 'api':
|
||||
if inst.vm_state == vm_states.RESIZED:
|
||||
self._test_delete_resized_part(inst)
|
||||
|
||||
# After confirm resize action, instance task_state
|
||||
# is reset to None, so is the expected value. But
|
||||
# for soft delete, task_state will be again reset
|
||||
# back to soft-deleting in the code to avoid status
|
||||
# checking failure.
|
||||
updates['task_state'] = None
|
||||
if delete_type == 'soft_delete':
|
||||
inst.save()
|
||||
updates['task_state'] = 'soft-deleting'
|
||||
|
||||
if inst.host is not None:
|
||||
self.context.elevated().AndReturn(self.context)
|
||||
objects.Service.get_by_compute_host(self.context,
|
||||
|
@ -1201,6 +1219,9 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
def test_delete_soft_with_down_host(self):
|
||||
self._test_delete('soft_delete', host='down-host')
|
||||
|
||||
def test_delete_soft_in_resized(self):
|
||||
self._test_delete('soft_delete', vm_state=vm_states.RESIZED)
|
||||
|
||||
def test_delete_soft(self):
|
||||
self._test_delete('soft_delete')
|
||||
|
||||
|
|
|
@ -6573,6 +6573,9 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
|||
self.migration,
|
||||
self.instance.old_flavor,
|
||||
self.migration.source_node)
|
||||
mock_save.assert_called_with(expected_task_state=
|
||||
[None, task_states.DELETING,
|
||||
task_states.SOFT_DELETING])
|
||||
|
||||
do_confirm_resize()
|
||||
|
||||
|
|
Loading…
Reference in New Issue