Skip to content

Commit 9d7003c

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Change InstanceFaultRollback handling in _error_out_instance_on_exception" into stable/stein
2 parents 54d6ca6 + cdaa800 commit 9d7003c

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

nova/compute/manager.py

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8257,29 +8257,60 @@ def _deleted_old_enough(self, instance, timeout):
82578257
@contextlib.contextmanager
82588258
def _error_out_instance_on_exception(self, context, instance,
82598259
instance_state=vm_states.ACTIVE):
8260+
"""Context manager to set instance.vm_state after some operation raises
8261+
8262+
Used to handle NotImplementedError and InstanceFaultRollback errors
8263+
and reset the instance vm_state and task_state. The vm_state is set
8264+
to the $instance_state parameter and task_state is set to None.
8265+
For all other types of exceptions, the vm_state is set to ERROR and
8266+
the task_state is left unchanged (although most callers will have the
8267+
@reverts_task_state decorator which will set the task_state to None).
8268+
8269+
Re-raises the original exception *except* in the case of
8270+
InstanceFaultRollback in which case the wrapped `inner_exception` is
8271+
re-raised.
8272+
8273+
:param context: The nova auth request context for the operation.
8274+
:param instance: The instance to update. The vm_state will be set by
8275+
this context manager when an exception is raised.
8276+
:param instance_state: For NotImplementedError and
8277+
InstanceFaultRollback this is the vm_state to set the instance to
8278+
when handling one of those types of exceptions. By default the
8279+
instance will be set to ACTIVE, but the caller should control this
8280+
in case there have been no changes to the running state of the
8281+
instance. For example, resizing a stopped server where prep_resize
8282+
fails early and does not change the power state of the guest should
8283+
not set the instance status to ACTIVE but remain STOPPED.
8284+
This parameter is ignored for all other types of exceptions and the
8285+
instance vm_state is set to ERROR.
8286+
"""
8287+
# NOTE(mriedem): Why doesn't this method just save off the
8288+
# original instance.vm_state here rather than use a parameter? Or use
8289+
# instance_state=None as an override but default to the current
8290+
# vm_state when rolling back.
82608291
instance_uuid = instance.uuid
82618292
try:
82628293
yield
8263-
except NotImplementedError as error:
8264-
with excutils.save_and_reraise_exception():
8265-
LOG.info("Setting instance back to %(state)s after: "
8266-
"%(error)s",
8294+
except (NotImplementedError, exception.InstanceFaultRollback) as error:
8295+
# Use reraise=False to determine if we want to raise the original
8296+
# exception or something else.
8297+
with excutils.save_and_reraise_exception(reraise=False) as ctxt:
8298+
LOG.info("Setting instance back to %(state)s after: %(error)s",
82678299
{'state': instance_state, 'error': error},
82688300
instance_uuid=instance_uuid)
82698301
self._instance_update(context, instance,
82708302
vm_state=instance_state,
82718303
task_state=None)
8272-
except exception.InstanceFaultRollback as error:
8273-
LOG.info("Setting instance back to ACTIVE after: %s",
8274-
error, instance_uuid=instance_uuid)
8275-
self._instance_update(context, instance,
8276-
vm_state=vm_states.ACTIVE,
8277-
task_state=None)
8278-
raise error.inner_exception
8304+
if isinstance(error, exception.InstanceFaultRollback):
8305+
# Raise the wrapped exception.
8306+
raise error.inner_exception
8307+
# Else re-raise the NotImplementedError.
8308+
ctxt.reraise = True
82798309
except Exception:
82808310
LOG.exception('Setting instance vm_state to ERROR',
82818311
instance_uuid=instance_uuid)
82828312
with excutils.save_and_reraise_exception():
8313+
# NOTE(mriedem): Why don't we pass clean_task_state=True here?
82838314
self._set_instance_obj_error_state(context, instance)
82848315

82858316
@wrap_exception()

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4058,15 +4058,16 @@ def test_error_out_instance_on_exception_inst_fault_rollback(self,
40584058
instance = fake_instance.fake_instance_obj(self.context)
40594059

40604060
def do_test():
4061-
with self.compute._error_out_instance_on_exception(self.context,
4062-
instance):
4061+
with self.compute._error_out_instance_on_exception(
4062+
self.context, instance, instance_state=vm_states.STOPPED):
40634063
raise exception.InstanceFaultRollback(
40644064
inner_exception=test.TestingException('test'))
40654065

40664066
self.assertRaises(test.TestingException, do_test)
4067+
# The vm_state should be set to the instance_state parameter.
40674068
inst_update_mock.assert_called_once_with(
40684069
self.context, instance,
4069-
vm_state=vm_states.ACTIVE, task_state=None)
4070+
vm_state=vm_states.STOPPED, task_state=None)
40704071

40714072
@mock.patch('nova.compute.manager.ComputeManager.'
40724073
'_set_instance_obj_error_state')

0 commit comments

Comments
 (0)