Revision 2395c322
b/doc/hooks.sgml | ||
---|---|---|
60 | 60 |
the script(s) run again with exactly the same |
61 | 61 |
parameters.</para> |
62 | 62 |
|
63 |
<para> |
|
64 |
Note that if a node is unreachable at the time a hooks is run, |
|
65 |
this will not be interpreted as a deny for the execution. In |
|
66 |
other words, only an actual error returned from a script will |
|
67 |
cause abort, and not an unreachable node. |
|
68 |
</para> |
|
69 |
|
|
70 |
<para> |
|
71 |
Therefore, if you want to guarantee that a hook script is run |
|
72 |
and denies an action, it's best to put it on the master node. |
|
73 |
</para> |
|
74 |
|
|
63 | 75 |
</section> |
64 | 76 |
|
65 | 77 |
<section> |
b/lib/mcpu.py | ||
---|---|---|
122 | 122 |
write_count = 0 |
123 | 123 |
lu = lu_class(self, op, self.cfg, self.sstore) |
124 | 124 |
lu.CheckPrereq() |
125 |
hm = HooksMaster(rpc.call_hooks_runner, lu) |
|
125 |
hm = HooksMaster(rpc.call_hooks_runner, self, lu)
|
|
126 | 126 |
hm.RunPhase(constants.HOOKS_PHASE_PRE) |
127 | 127 |
result = lu.Exec(self._feedback_fn) |
128 | 128 |
hm.RunPhase(constants.HOOKS_PHASE_POST) |
... | ... | |
159 | 159 |
lu = lu_class(self, op, self.cfg, self.sstore) |
160 | 160 |
lu.CheckPrereq() |
161 | 161 |
#if do_hooks: |
162 |
# hm = HooksMaster(rpc.call_hooks_runner, lu) |
|
162 |
# hm = HooksMaster(rpc.call_hooks_runner, self, lu)
|
|
163 | 163 |
# hm.RunPhase(constants.HOOKS_PHASE_PRE) |
164 | 164 |
result = lu.Exec(self._feedback_fn) |
165 | 165 |
#if do_hooks: |
... | ... | |
202 | 202 |
which behaves the same works. |
203 | 203 |
|
204 | 204 |
""" |
205 |
def __init__(self, callfn, lu): |
|
205 |
def __init__(self, callfn, proc, lu):
|
|
206 | 206 |
self.callfn = callfn |
207 |
self.proc = proc |
|
207 | 208 |
self.lu = lu |
208 | 209 |
self.op = lu.op |
209 | 210 |
self.env, node_list_pre, node_list_post = self._BuildEnv() |
... | ... | |
272 | 273 |
for node_name in results: |
273 | 274 |
res = results[node_name] |
274 | 275 |
if res is False or not isinstance(res, list): |
275 |
raise errors.HooksFailure("Communication failure to node %s" %
|
|
276 |
node_name)
|
|
276 |
self.proc.LogWarning("Communication failure to node %s" % node_name)
|
|
277 |
continue
|
|
277 | 278 |
for script, hkr, output in res: |
278 | 279 |
if hkr == constants.HKR_FAIL: |
279 | 280 |
output = output.strip().encode("string_escape") |
b/test/ganeti.hooks_unittest.py | ||
---|---|---|
36 | 36 |
from ganeti import cmdlib |
37 | 37 |
from ganeti.constants import HKR_SUCCESS, HKR_FAIL, HKR_SKIP |
38 | 38 |
|
39 |
from mocks import FakeConfig, FakeSStore |
|
39 |
from mocks import FakeConfig, FakeSStore, FakeProc
|
|
40 | 40 |
|
41 | 41 |
class FakeLU(cmdlib.LogicalUnit): |
42 | 42 |
HPATH = "test" |
... | ... | |
231 | 231 |
sstore = FakeSStore() |
232 | 232 |
op = opcodes.OpCode() |
233 | 233 |
lu = FakeLU(None, op, cfg, sstore) |
234 |
hm = mcpu.HooksMaster(self._call_false, lu) |
|
234 |
hm = mcpu.HooksMaster(self._call_false, FakeProc(), lu)
|
|
235 | 235 |
self.failUnlessRaises(errors.HooksFailure, |
236 | 236 |
hm.RunPhase, constants.HOOKS_PHASE_PRE) |
237 | 237 |
hm.RunPhase(constants.HOOKS_PHASE_POST) |
238 | 238 |
|
239 | 239 |
def testIndividualFalse(self): |
240 |
"""Test individual rpc failure"""
|
|
240 |
"""Test individual node failure"""
|
|
241 | 241 |
cfg = FakeConfig() |
242 | 242 |
sstore = FakeSStore() |
243 | 243 |
op = opcodes.OpCode() |
244 | 244 |
lu = FakeLU(None, op, cfg, sstore) |
245 |
hm = mcpu.HooksMaster(self._call_nodes_false, lu) |
|
246 |
self.failUnlessRaises(errors.HooksFailure, |
|
247 |
hm.RunPhase, constants.HOOKS_PHASE_PRE) |
|
245 |
hm = mcpu.HooksMaster(self._call_nodes_false, FakeProc(), lu) |
|
246 |
hm.RunPhase(constants.HOOKS_PHASE_PRE) |
|
247 |
#self.failUnlessRaises(errors.HooksFailure, |
|
248 |
# hm.RunPhase, constants.HOOKS_PHASE_PRE) |
|
248 | 249 |
hm.RunPhase(constants.HOOKS_PHASE_POST) |
249 | 250 |
|
250 | 251 |
def testScriptFalse(self): |
... | ... | |
253 | 254 |
op = opcodes.OpCode() |
254 | 255 |
sstore = FakeSStore() |
255 | 256 |
lu = FakeLU(None, op, cfg, sstore) |
256 |
hm = mcpu.HooksMaster(self._call_script_fail, lu) |
|
257 |
hm = mcpu.HooksMaster(self._call_script_fail, FakeProc(), lu)
|
|
257 | 258 |
self.failUnlessRaises(errors.HooksAbort, |
258 | 259 |
hm.RunPhase, constants.HOOKS_PHASE_PRE) |
259 | 260 |
hm.RunPhase(constants.HOOKS_PHASE_POST) |
... | ... | |
264 | 265 |
op = opcodes.OpCode() |
265 | 266 |
sstore = FakeSStore() |
266 | 267 |
lu = FakeLU(None, op, cfg, sstore) |
267 |
hm = mcpu.HooksMaster(self._call_script_succeed, lu) |
|
268 |
hm = mcpu.HooksMaster(self._call_script_succeed, FakeProc(), lu)
|
|
268 | 269 |
for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST): |
269 | 270 |
hm.RunPhase(phase) |
270 | 271 |
|
b/test/mocks.py | ||
---|---|---|
45 | 45 |
|
46 | 46 |
def GetMasterNode(self): |
47 | 47 |
return utils.HostInfo().name |
48 |
|
|
49 |
|
|
50 |
class FakeProc: |
|
51 |
"""Fake processor object""" |
|
52 |
|
|
53 |
def LogWarning(self, msg): |
|
54 |
pass |
|
55 |
|
|
56 |
def LogInfo(self, msg): |
|
57 |
pass |
Also available in: Unified diff