Add the *glob* argument to the RunPhase function. With *glob* set to
True, HooksMaster runs global hooks instead of per-opcode's hooks. The
global hooks should be placed in the "global" subdirectory of the hooks
directory.

Signed-off-by: Oleg Ponomarev <[email protected]>
---
 lib/hooksmaster.py      | 24 ++++++++++++++++++------
 src/Ganeti/Constants.hs |  5 +++++
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/lib/hooksmaster.py b/lib/hooksmaster.py
index c23d857..221e589 100644
--- a/lib/hooksmaster.py
+++ b/lib/hooksmaster.py
@@ -56,7 +56,8 @@ def _RpcResultsToHooksResults(rpc_results):
 class HooksMaster(object):
   def __init__(self, opcode, hooks_path, nodes, hooks_execution_fn,
                hooks_results_adapt_fn, build_env_fn, prepare_post_nodes_fn,
-               log_fn, htype=None, cluster_name=None, master_name=None):
+               log_fn, htype=None, cluster_name=None, master_name=None,
+               job_id=None):
     """Base class for hooks masters.
 
     This class invokes the execution of hooks according to the behaviour
@@ -105,6 +106,7 @@ class HooksMaster(object):
     self.htype = htype
     self.cluster_name = cluster_name
     self.master_name = master_name
+    self.job_id = job_id
 
     self.pre_env = self._BuildEnv(constants.HOOKS_PHASE_PRE)
     (self.pre_nodes, self.post_nodes) = nodes
@@ -151,7 +153,8 @@ class HooksMaster(object):
 
     return env
 
-  def _RunWrapper(self, node_list, hpath, phase, phase_env):
+  def _RunWrapper(self, node_list, hpath, phase, phase_env, glob=False,
+                  post_status=None):
     """Simple wrapper over self.callfn.
 
     This method fixes the environment before executing the hooks.
@@ -175,6 +178,12 @@ class HooksMaster(object):
     if self.master_name is not None:
       env["GANETI_MASTER"] = self.master_name
 
+    if self.job_id and glob:
+      env["GANETI_JOB_ID"] = self.job_id
+    if phase == constants.HOOKS_PHASE_POST and glob:
+      assert post_status is not None
+      env["GANETI_POST_STATUS"] = post_status
+
     if phase_env:
       env = utils.algo.JoinDisjointDicts(env, phase_env)
 
@@ -186,7 +195,7 @@ class HooksMaster(object):
 
     return self.hooks_execution_fn(node_list, hpath, phase, env)
 
-  def RunPhase(self, phase, node_names=None):
+  def RunPhase(self, phase, node_names=None, glob=False, post_status=None):
     """Run all the scripts for a phase.
 
     This is the main function of the HookMaster.
@@ -198,6 +207,7 @@ class HooksMaster(object):
         L{constants.HOOKS_PHASE_PRE}; it denotes the hooks phase
     @param node_names: overrides the predefined list of nodes for the given
         phase
+    @param glob: whether global or per-opcode hooks should be executed
     @return: the processed results of the hooks multi-node rpc call
     @raise errors.HooksFailure: on communication failure to the nodes
     @raise errors.HooksAbort: on failure of one of the hooks
@@ -222,7 +232,9 @@ class HooksMaster(object):
       # even attempt to run, or this LU doesn't do hooks at all
       return
 
-    results = self._RunWrapper(node_names, self.hooks_path, phase, env)
+    hooks_path = constants.GLOBAL_HOOKS_DIR if glob else self.hooks_path
+    results = self._RunWrapper(node_names, hooks_path, phase, env, glob,
+                               post_status)
     if not results:
       msg = "Communication Failure"
       if phase == constants.HOOKS_PHASE_PRE:
@@ -272,7 +284,7 @@ class HooksMaster(object):
     self._RunWrapper(nodes, hpath, phase, self.pre_env)
 
   @staticmethod
-  def BuildFromLu(hooks_execution_fn, lu):
+  def BuildFromLu(hooks_execution_fn, lu, job_id=None):
     if lu.HPATH is None:
       nodes = (None, None)
     else:
@@ -290,4 +302,4 @@ class HooksMaster(object):
     return HooksMaster(lu.op.OP_ID, lu.HPATH, nodes, hooks_execution_fn,
                        _RpcResultsToHooksResults, lu.BuildHooksEnv,
                        lu.PreparePostHookNodes, lu.LogWarning, lu.HTYPE,
-                       cluster_name, master_name)
+                       cluster_name, master_name, job_id)
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index 86c8c95..180ff4d 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -724,6 +724,11 @@ hooksPhasePre = "pre"
 hooksVersion :: Int
 hooksVersion = 2
 
+-- * Global hooks related constants
+
+globalHooksDir :: String
+globalHooksDir = "global"
+
 -- * Hooks subject type (what object type does the LU deal with)
 
 htypeCluster :: String
-- 
2.6.0.rc2.230.g3dd15c0

Reply via email to