Introduce HooksAbortCallBack
authorHelga Velroyen <helgav@google.com>
Tue, 12 Jan 2016 12:49:59 +0000 (13:49 +0100)
committerHelga Velroyen <helgav@google.com>
Tue, 12 Jan 2016 15:53:00 +0000 (16:53 +0100)
There is currently no way to clean up anything after (pre)
hooks failed. LUs have a hook that is called after the hooks
finish successfully, but any exception that aborts the hook
execution is bubbled up till mcpu and then ignored.

This patch introduces another callback called
'HooksAbortCallBack'. Similar to 'HooksCallBack', this
callback is called after the hook execution, but in this
case only if the execution fails with an exception.

After the hook is called, the exception is rethrown in
order to maintain the control flow as it was before.

Signed-off-by: Helga Velroyen <helgav@google.com>
Reviewed-by: Klaus Aehlig <aehlig@google.com>

lib/cmdlib/base.py
lib/mcpu.py

index 57eb8d5..1e8b2d9 100644 (file)
@@ -438,6 +438,30 @@ class LogicalUnit(object): # pylint: disable=R0902
     # pylint: disable=W0613,R0201
     return lu_result
 
+  def HooksAbortCallBack(self, phase, feedback_fn, exception):
+    """Called when the hooks get aborted by an exception.
+
+    This method is called everytime a hooks phase is aborted by an exception.
+    This exception is most likely of type C{errors.HooksAbort}. However, we
+    keep the design of this function broad enough to handle any kind of
+    exception.
+
+    The intended purpose of this call back is to run any action that is
+    necessary to bring the cluster back to a clean state from the point
+    in time before calling the hook.
+
+    @type phase: string
+    @param phase: one of L{constants.HOOKS_PHASE_POST} or
+        L{constants.HOOKS_PHASE_PRE}; it denotes the hooks phase
+    @type feedback_fn: callable
+    @param feedback_fn: function used send feedback back to the caller
+    @type exception: Exception
+    @param exception: The exception that was raised during the execution of
+    hooks.
+
+    """
+    pass
+
   def _ExpandAndLockInstance(self, allow_forthcoming=False):
     """Helper function to expand and lock an instance.
 
index 1da0766..b3d4966 100644 (file)
@@ -484,7 +484,16 @@ class Processor(object):
     lu.CheckPrereq()
 
     hm = self.BuildHooksManager(lu)
-    h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE)
+    try:
+      h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE)
+    except Exception, err:  # pylint: disable=W0703
+      # This gives the LU a chance of cleaning up in case of an hooks failure.
+      # The type of exception is deliberately broad to be able to react to
+      # any kind of failure.
+      lu.HooksAbortCallBack(constants.HOOKS_PHASE_PRE, self.Log, err)
+      # We re-raise the exception to not alter the behavior of LU handling
+      # otherwise.
+      raise err
     lu.HooksCallBack(constants.HOOKS_PHASE_PRE, h_results,
                      self.Log, None)