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 <[email protected]> --- lib/cmdlib/base.py | 24 ++++++++++++++++++++++++ lib/mcpu.py | 11 ++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/cmdlib/base.py b/lib/cmdlib/base.py index 57eb8d5..1e8b2d9 100644 --- a/lib/cmdlib/base.py +++ b/lib/cmdlib/base.py @@ -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. diff --git a/lib/mcpu.py b/lib/mcpu.py index 1da0766..b3d4966 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -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) -- 2.6.0.rc2.230.g3dd15c0
