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