@@ -8257,29 +8257,60 @@ def _deleted_old_enough(self, instance, timeout):
8257
8257
@contextlib .contextmanager
8258
8258
def _error_out_instance_on_exception (self , context , instance ,
8259
8259
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.
8260
8291
instance_uuid = instance .uuid
8261
8292
try :
8262
8293
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" ,
8267
8299
{'state' : instance_state , 'error' : error },
8268
8300
instance_uuid = instance_uuid )
8269
8301
self ._instance_update (context , instance ,
8270
8302
vm_state = instance_state ,
8271
8303
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
8279
8309
except Exception :
8280
8310
LOG .exception ('Setting instance vm_state to ERROR' ,
8281
8311
instance_uuid = instance_uuid )
8282
8312
with excutils .save_and_reraise_exception ():
8313
+ # NOTE(mriedem): Why don't we pass clean_task_state=True here?
8283
8314
self ._set_instance_obj_error_state (context , instance )
8284
8315
8285
8316
@wrap_exception ()
0 commit comments