All the errors during an opcode execution are reported via exceptions.
Except all the exceptions and execute POST global hooks with FAILED
status.

Signed-off-by: Oleg Ponomarev <[email protected]>
---
 lib/hooksmaster.py |  4 +--
 lib/mcpu.py        | 73 +++++++++++++++++++++++++++++++-----------------------
 2 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/lib/hooksmaster.py b/lib/hooksmaster.py
index 221e589..d3f18c0 100644
--- a/lib/hooksmaster.py
+++ b/lib/hooksmaster.py
@@ -39,7 +39,7 @@ from ganeti import compat
 from ganeti import pathutils
 
 
-def _RpcResultsToHooksResults(rpc_results):
+def RpcResultsToHooksResults(rpc_results):
   """Function to convert RPC results to the format expected by HooksMaster.
 
   @type rpc_results: dict(node: L{rpc.RpcResult})
@@ -300,6 +300,6 @@ class HooksMaster(object):
       cluster_name = lu.cfg.GetClusterName()
 
     return HooksMaster(lu.op.OP_ID, lu.HPATH, nodes, hooks_execution_fn,
-                       _RpcResultsToHooksResults, lu.BuildHooksEnv,
+                       RpcResultsToHooksResults, lu.BuildHooksEnv,
                        lu.PreparePostHookNodes, lu.LogWarning, lu.HTYPE,
                        cluster_name, master_name, job_id)
diff --git a/lib/mcpu.py b/lib/mcpu.py
index 9be8d46..30983ea 100644
--- a/lib/mcpu.py
+++ b/lib/mcpu.py
@@ -688,39 +688,50 @@ class Processor(object):
 
     self._cbs = cbs
     try:
-      if self._enable_locks:
-        # Acquire the Big Ganeti Lock exclusively if this LU requires it,
-        # and in a shared fashion otherwise (to prevent concurrent run with
-        # an exclusive LU.
-        self._AcquireLocks(locking.LEVEL_CLUSTER, locking.BGL,
-                            not lu_class.REQ_BGL, False, calc_timeout())
-      elif lu_class.REQ_BGL:
-        raise errors.ProgrammerError("Opcode '%s' requires BGL, but locks are"
-                                     " disabled" % op.OP_ID)
-
-      lu = lu_class(self, op, self.cfg, self.rpc,
-                    self._wconfdcontext, self.wconfd)
-      lu.wconfdlocks = self.wconfd.Client().ListLocks(self._wconfdcontext)
-      _CheckSecretParameters(op)
-      lu.ExpandNames()
-      assert lu.needed_locks is not None, "needed_locks not set by LU"
-
       try:
-        result = self._LockAndExecLU(lu, locking.LEVEL_CLUSTER + 1,
-                                     calc_timeout)
-      finally:
-        if self._ec_id:
-          self.cfg.DropECReservations(self._ec_id)
-    finally:
-      self.wconfd.Client().FreeLocksLevel(
-        self._wconfdcontext, locking.LEVEL_NAMES[locking.LEVEL_CLUSTER])
-      self._cbs = None
-
-    self._CheckLUResult(op, result)
+        if self._enable_locks:
+          # Acquire the Big Ganeti Lock exclusively if this LU requires it,
+          # and in a shared fashion otherwise (to prevent concurrent run with
+          # an exclusive LU.
+          self._AcquireLocks(locking.LEVEL_CLUSTER, locking.BGL,
+                              not lu_class.REQ_BGL, False, calc_timeout())
+        elif lu_class.REQ_BGL:
+          raise errors.ProgrammerError("Opcode '%s' requires BGL, but locks 
are"
+                                       " disabled" % op.OP_ID)
+
+        lu = lu_class(self, op, self.cfg, self.rpc,
+                      self._wconfdcontext, self.wconfd)
+        lu.wconfdlocks = self.wconfd.Client().ListLocks(self._wconfdcontext)
+        _CheckSecretParameters(op)
+        lu.ExpandNames()
+        assert lu.needed_locks is not None, "needed_locks not set by LU"
 
-    if self._hm is not None:
-      self._hm.RunPhase(constants.HOOKS_PHASE_POST, None, True,
-                        constants.POST_HOOKS_STATUS_SUCCEEDED)
+        try:
+          result = self._LockAndExecLU(lu, locking.LEVEL_CLUSTER + 1,
+                                       calc_timeout)
+        finally:
+          if self._ec_id:
+            self.cfg.DropECReservations(self._ec_id)
+      finally:
+        self.wconfd.Client().FreeLocksLevel(
+          self._wconfdcontext, locking.LEVEL_NAMES[locking.LEVEL_CLUSTER])
+        self._cbs = None
+
+      self._CheckLUResult(op, result)
+
+      if self._hm is not None:
+        self._hm.RunPhase(constants.HOOKS_PHASE_POST, None, True,
+                          constants.POST_HOOKS_STATUS_SUCCEEDED)
+    except:
+      # execute global post hooks with the failed status on any exception
+      hm = self.hmclass(op.OP_ID, None, ([], [self.cfg.GetMasterNodeName()]),
+                        self.rpc.call_hooks_runner,
+                        hooksmaster.RpcResultsToHooksResults, None, None,
+                        logging.warning, self.cfg.GetClusterName(),
+                        self.cfg.GetMasterNodeName(), self.GetECId())
+      hm.RunPhase(phase=constants.HOOKS_PHASE_POST, glob=True,
+                  post_status=constants.POST_HOOKS_STATUS_FAILED)
+      raise
 
     return result
 
-- 
2.6.0.rc2.230.g3dd15c0

Reply via email to