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
