Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hooks_unittest.py @ 5470b894

History | View | Annotate | Download (18.7 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Script for unittesting the hooks module"""
23 a8083063 Iustin Pop
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
import unittest
26 a8083063 Iustin Pop
import os
27 a8083063 Iustin Pop
import time
28 a8083063 Iustin Pop
import tempfile
29 a8083063 Iustin Pop
import os.path
30 a8083063 Iustin Pop
31 a8083063 Iustin Pop
from ganeti import errors
32 a8083063 Iustin Pop
from ganeti import opcodes
33 68d95757 Guido Trotter
from ganeti import hooksmaster
34 a8083063 Iustin Pop
from ganeti import backend
35 a8083063 Iustin Pop
from ganeti import constants
36 a8083063 Iustin Pop
from ganeti import cmdlib
37 4869595d Petr Pudlak
from ganeti.rpc import node as rpc
38 dd7f6776 Michael Hanselmann
from ganeti import compat
39 a56625a2 Michael Hanselmann
from ganeti import pathutils
40 a8083063 Iustin Pop
from ganeti.constants import HKR_SUCCESS, HKR_FAIL, HKR_SKIP
41 a8083063 Iustin Pop
42 c259ce64 Michael Hanselmann
from mocks import FakeConfig, FakeProc, FakeContext
43 a8083063 Iustin Pop
44 25231ec5 Michael Hanselmann
import testutils
45 25231ec5 Michael Hanselmann
46 25231ec5 Michael Hanselmann
47 a8083063 Iustin Pop
class FakeLU(cmdlib.LogicalUnit):
48 a8083063 Iustin Pop
  HPATH = "test"
49 07e0896f Michael Hanselmann
50 a8083063 Iustin Pop
  def BuildHooksEnv(self):
51 07e0896f Michael Hanselmann
    return {}
52 07e0896f Michael Hanselmann
53 07e0896f Michael Hanselmann
  def BuildHooksNodes(self):
54 1c3231aa Thomas Thrainer
    return ["a"], ["a"]
55 a8083063 Iustin Pop
56 25231ec5 Michael Hanselmann
57 a8083063 Iustin Pop
class TestHooksRunner(unittest.TestCase):
58 a8083063 Iustin Pop
  """Testing case for HooksRunner"""
59 a8083063 Iustin Pop
  def setUp(self):
60 a8083063 Iustin Pop
    self.torm = []
61 a8083063 Iustin Pop
    self.tmpdir = tempfile.mkdtemp()
62 a8083063 Iustin Pop
    self.torm.append((self.tmpdir, True))
63 a8083063 Iustin Pop
    self.logdir = tempfile.mkdtemp()
64 a8083063 Iustin Pop
    self.torm.append((self.logdir, True))
65 a8083063 Iustin Pop
    self.hpath = "fake"
66 a8083063 Iustin Pop
    self.ph_dirs = {}
67 a8083063 Iustin Pop
    for i in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
68 a8083063 Iustin Pop
      dname = "%s/%s-%s.d" % (self.tmpdir, self.hpath, i)
69 a8083063 Iustin Pop
      os.mkdir(dname)
70 a8083063 Iustin Pop
      self.torm.append((dname, True))
71 a8083063 Iustin Pop
      self.ph_dirs[i] = dname
72 a8083063 Iustin Pop
    self.hr = backend.HooksRunner(hooks_base_dir=self.tmpdir)
73 a8083063 Iustin Pop
74 a8083063 Iustin Pop
  def tearDown(self):
75 a8083063 Iustin Pop
    self.torm.reverse()
76 a8083063 Iustin Pop
    for path, kind in self.torm:
77 a8083063 Iustin Pop
      if kind:
78 a8083063 Iustin Pop
        os.rmdir(path)
79 a8083063 Iustin Pop
      else:
80 a8083063 Iustin Pop
        os.unlink(path)
81 a8083063 Iustin Pop
82 a8083063 Iustin Pop
  def _rname(self, fname):
83 a8083063 Iustin Pop
    return "/".join(fname.split("/")[-2:])
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  def testEmpty(self):
86 a8083063 Iustin Pop
    """Test no hooks"""
87 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
88 d019f8bd Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}), [])
89 a8083063 Iustin Pop
90 a8083063 Iustin Pop
  def testSkipNonExec(self):
91 a8083063 Iustin Pop
    """Test skip non-exec file"""
92 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
93 a8083063 Iustin Pop
      fname = "%s/test" % self.ph_dirs[phase]
94 a8083063 Iustin Pop
      f = open(fname, "w")
95 a8083063 Iustin Pop
      f.close()
96 a8083063 Iustin Pop
      self.torm.append((fname, False))
97 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
98 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SKIP, "")])
99 a8083063 Iustin Pop
100 a8083063 Iustin Pop
  def testSkipInvalidName(self):
101 a8083063 Iustin Pop
    """Test skip script with invalid name"""
102 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
103 a8083063 Iustin Pop
      fname = "%s/a.off" % self.ph_dirs[phase]
104 a8083063 Iustin Pop
      f = open(fname, "w")
105 a8083063 Iustin Pop
      f.write("#!/bin/sh\nexit 0\n")
106 a8083063 Iustin Pop
      f.close()
107 a8083063 Iustin Pop
      os.chmod(fname, 0700)
108 a8083063 Iustin Pop
      self.torm.append((fname, False))
109 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
110 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SKIP, "")])
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
  def testSkipDir(self):
113 a8083063 Iustin Pop
    """Test skip directory"""
114 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
115 a8083063 Iustin Pop
      fname = "%s/testdir" % self.ph_dirs[phase]
116 a8083063 Iustin Pop
      os.mkdir(fname)
117 a8083063 Iustin Pop
      self.torm.append((fname, True))
118 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
119 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SKIP, "")])
120 a8083063 Iustin Pop
121 a8083063 Iustin Pop
  def testSuccess(self):
122 a8083063 Iustin Pop
    """Test success execution"""
123 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
124 a8083063 Iustin Pop
      fname = "%s/success" % self.ph_dirs[phase]
125 a8083063 Iustin Pop
      f = open(fname, "w")
126 a8083063 Iustin Pop
      f.write("#!/bin/sh\nexit 0\n")
127 a8083063 Iustin Pop
      f.close()
128 a8083063 Iustin Pop
      self.torm.append((fname, False))
129 a8083063 Iustin Pop
      os.chmod(fname, 0700)
130 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
131 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SUCCESS, "")])
132 a8083063 Iustin Pop
133 a8083063 Iustin Pop
  def testSymlink(self):
134 a8083063 Iustin Pop
    """Test running a symlink"""
135 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
136 a8083063 Iustin Pop
      fname = "%s/success" % self.ph_dirs[phase]
137 a8083063 Iustin Pop
      os.symlink("/bin/true", fname)
138 a8083063 Iustin Pop
      self.torm.append((fname, False))
139 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
140 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SUCCESS, "")])
141 a8083063 Iustin Pop
142 a8083063 Iustin Pop
  def testFail(self):
143 a8083063 Iustin Pop
    """Test success execution"""
144 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
145 a8083063 Iustin Pop
      fname = "%s/success" % self.ph_dirs[phase]
146 a8083063 Iustin Pop
      f = open(fname, "w")
147 a8083063 Iustin Pop
      f.write("#!/bin/sh\nexit 1\n")
148 a8083063 Iustin Pop
      f.close()
149 a8083063 Iustin Pop
      self.torm.append((fname, False))
150 a8083063 Iustin Pop
      os.chmod(fname, 0700)
151 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}),
152 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_FAIL, "")])
153 a8083063 Iustin Pop
154 a8083063 Iustin Pop
  def testCombined(self):
155 a8083063 Iustin Pop
    """Test success, failure and skip all in one test"""
156 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
157 a8083063 Iustin Pop
      expect = []
158 a8083063 Iustin Pop
      for fbase, ecode, rs in [("00succ", 0, HKR_SUCCESS),
159 a8083063 Iustin Pop
                               ("10fail", 1, HKR_FAIL),
160 a8083063 Iustin Pop
                               ("20inv.", 0, HKR_SKIP),
161 a8083063 Iustin Pop
                               ]:
162 a8083063 Iustin Pop
        fname = "%s/%s" % (self.ph_dirs[phase], fbase)
163 a8083063 Iustin Pop
        f = open(fname, "w")
164 a8083063 Iustin Pop
        f.write("#!/bin/sh\nexit %d\n" % ecode)
165 a8083063 Iustin Pop
        f.close()
166 a8083063 Iustin Pop
        self.torm.append((fname, False))
167 a8083063 Iustin Pop
        os.chmod(fname, 0700)
168 a8083063 Iustin Pop
        expect.append((self._rname(fname), rs, ""))
169 d019f8bd Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}), expect)
170 a8083063 Iustin Pop
171 a8083063 Iustin Pop
  def testOrdering(self):
172 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
173 a8083063 Iustin Pop
      expect = []
174 a8083063 Iustin Pop
      for fbase in ["10s1",
175 a8083063 Iustin Pop
                    "00s0",
176 a8083063 Iustin Pop
                    "10sa",
177 a8083063 Iustin Pop
                    "80sc",
178 a8083063 Iustin Pop
                    "60sd",
179 a8083063 Iustin Pop
                    ]:
180 a8083063 Iustin Pop
        fname = "%s/%s" % (self.ph_dirs[phase], fbase)
181 a8083063 Iustin Pop
        os.symlink("/bin/true", fname)
182 a8083063 Iustin Pop
        self.torm.append((fname, False))
183 a8083063 Iustin Pop
        expect.append((self._rname(fname), HKR_SUCCESS, ""))
184 a8083063 Iustin Pop
      expect.sort()
185 d019f8bd Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, {}), expect)
186 a8083063 Iustin Pop
187 a8083063 Iustin Pop
  def testEnv(self):
188 a8083063 Iustin Pop
    """Test environment execution"""
189 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
190 a8083063 Iustin Pop
      fbase = "success"
191 a8083063 Iustin Pop
      fname = "%s/%s" % (self.ph_dirs[phase], fbase)
192 a8083063 Iustin Pop
      os.symlink("/usr/bin/env", fname)
193 a8083063 Iustin Pop
      self.torm.append((fname, False))
194 a8083063 Iustin Pop
      env_snt = {"PHASE": phase}
195 7b80424f Iustin Pop
      env_exp = "PHASE=%s" % phase
196 a8083063 Iustin Pop
      self.failUnlessEqual(self.hr.RunHooks(self.hpath, phase, env_snt),
197 d019f8bd Iustin Pop
                           [(self._rname(fname), HKR_SUCCESS, env_exp)])
198 a8083063 Iustin Pop
199 a8083063 Iustin Pop
200 dd7f6776 Michael Hanselmann
def FakeHooksRpcSuccess(node_list, hpath, phase, env):
201 dd7f6776 Michael Hanselmann
  """Fake call_hooks_runner function.
202 dd7f6776 Michael Hanselmann

203 dd7f6776 Michael Hanselmann
  @rtype: dict of node -> L{rpc.RpcResult} with a successful script result
204 dd7f6776 Michael Hanselmann
  @return: script execution from all nodes
205 dd7f6776 Michael Hanselmann

206 dd7f6776 Michael Hanselmann
  """
207 dd7f6776 Michael Hanselmann
  rr = rpc.RpcResult
208 3fc210de Andrea Spadaccini
  return dict([(node, rr((True, [("utest", constants.HKR_SUCCESS, "ok")]),
209 8c114acd Michael Hanselmann
                         node=node, call="FakeScriptOk"))
210 dd7f6776 Michael Hanselmann
               for node in node_list])
211 dd7f6776 Michael Hanselmann
212 dd7f6776 Michael Hanselmann
213 a8083063 Iustin Pop
class TestHooksMaster(unittest.TestCase):
214 a8083063 Iustin Pop
  """Testing case for HooksMaster"""
215 a8083063 Iustin Pop
216 a8083063 Iustin Pop
  def _call_false(*args):
217 a8083063 Iustin Pop
    """Fake call_hooks_runner function which returns False."""
218 a8083063 Iustin Pop
    return False
219 a8083063 Iustin Pop
220 a8083063 Iustin Pop
  @staticmethod
221 a8083063 Iustin Pop
  def _call_nodes_false(node_list, hpath, phase, env):
222 a8083063 Iustin Pop
    """Fake call_hooks_runner function.
223 a8083063 Iustin Pop

224 7ccb3074 Guido Trotter
    @rtype: dict of node -> L{rpc.RpcResult} with an rpc error
225 7ccb3074 Guido Trotter
    @return: rpc failure from all nodes
226 a8083063 Iustin Pop

227 a8083063 Iustin Pop
    """
228 8c114acd Michael Hanselmann
    return dict([(node, rpc.RpcResult("error", failed=True,
229 8c114acd Michael Hanselmann
                  node=node, call="FakeError")) for node in node_list])
230 a8083063 Iustin Pop
231 a8083063 Iustin Pop
  @staticmethod
232 a8083063 Iustin Pop
  def _call_script_fail(node_list, hpath, phase, env):
233 a8083063 Iustin Pop
    """Fake call_hooks_runner function.
234 a8083063 Iustin Pop

235 7ccb3074 Guido Trotter
    @rtype: dict of node -> L{rpc.RpcResult} with a failed script result
236 7ccb3074 Guido Trotter
    @return: script execution failure from all nodes
237 a8083063 Iustin Pop

238 a8083063 Iustin Pop
    """
239 3fb4f740 Iustin Pop
    rr = rpc.RpcResult
240 3fb4f740 Iustin Pop
    return dict([(node, rr((True, [("utest", constants.HKR_FAIL, "err")]),
241 8c114acd Michael Hanselmann
                           node=node, call="FakeScriptFail"))
242 3fb4f740 Iustin Pop
                  for node in node_list])
243 a8083063 Iustin Pop
244 d2525573 Guido Trotter
  def setUp(self):
245 d2525573 Guido Trotter
    self.op = opcodes.OpCode()
246 77b657a3 Guido Trotter
    self.context = FakeContext()
247 72737a7f Iustin Pop
    # WARNING: here we pass None as RpcRunner instance since we know
248 72737a7f Iustin Pop
    # our usage via HooksMaster will not use lu.rpc
249 87ed6b79 Klaus Aehlig
    self.lu = FakeLU(FakeProc(), self.op, self.context, None, (123, "/foo/bar"),
250 87ed6b79 Klaus Aehlig
                     None)
251 d2525573 Guido Trotter
252 a8083063 Iustin Pop
  def testTotalFalse(self):
253 a8083063 Iustin Pop
    """Test complete rpc failure"""
254 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._call_false, self.lu)
255 a8083063 Iustin Pop
    self.failUnlessRaises(errors.HooksFailure,
256 a8083063 Iustin Pop
                          hm.RunPhase, constants.HOOKS_PHASE_PRE)
257 a8083063 Iustin Pop
    hm.RunPhase(constants.HOOKS_PHASE_POST)
258 a8083063 Iustin Pop
259 a8083063 Iustin Pop
  def testIndividualFalse(self):
260 2395c322 Iustin Pop
    """Test individual node failure"""
261 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._call_nodes_false, self.lu)
262 2395c322 Iustin Pop
    hm.RunPhase(constants.HOOKS_PHASE_PRE)
263 2395c322 Iustin Pop
    #self.failUnlessRaises(errors.HooksFailure,
264 2395c322 Iustin Pop
    #                      hm.RunPhase, constants.HOOKS_PHASE_PRE)
265 a8083063 Iustin Pop
    hm.RunPhase(constants.HOOKS_PHASE_POST)
266 a8083063 Iustin Pop
267 a8083063 Iustin Pop
  def testScriptFalse(self):
268 a8083063 Iustin Pop
    """Test individual rpc failure"""
269 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._call_script_fail, self.lu)
270 a8083063 Iustin Pop
    self.failUnlessRaises(errors.HooksAbort,
271 a8083063 Iustin Pop
                          hm.RunPhase, constants.HOOKS_PHASE_PRE)
272 a8083063 Iustin Pop
    hm.RunPhase(constants.HOOKS_PHASE_POST)
273 a8083063 Iustin Pop
274 a8083063 Iustin Pop
  def testScriptSucceed(self):
275 a8083063 Iustin Pop
    """Test individual rpc failure"""
276 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(FakeHooksRpcSuccess, self.lu)
277 a8083063 Iustin Pop
    for phase in (constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST):
278 a8083063 Iustin Pop
      hm.RunPhase(phase)
279 a8083063 Iustin Pop
280 25231ec5 Michael Hanselmann
281 dd7f6776 Michael Hanselmann
class FakeEnvLU(cmdlib.LogicalUnit):
282 dd7f6776 Michael Hanselmann
  HPATH = "env_test_lu"
283 dd7f6776 Michael Hanselmann
  HTYPE = constants.HTYPE_GROUP
284 dd7f6776 Michael Hanselmann
285 dd7f6776 Michael Hanselmann
  def __init__(self, *args):
286 dd7f6776 Michael Hanselmann
    cmdlib.LogicalUnit.__init__(self, *args)
287 dd7f6776 Michael Hanselmann
    self.hook_env = None
288 dd7f6776 Michael Hanselmann
289 dd7f6776 Michael Hanselmann
  def BuildHooksEnv(self):
290 dd7f6776 Michael Hanselmann
    assert self.hook_env is not None
291 07e0896f Michael Hanselmann
    return self.hook_env
292 07e0896f Michael Hanselmann
293 07e0896f Michael Hanselmann
  def BuildHooksNodes(self):
294 1c3231aa Thomas Thrainer
    return (["a"], ["a"])
295 07e0896f Michael Hanselmann
296 dd7f6776 Michael Hanselmann
297 07e0896f Michael Hanselmann
class FakeNoHooksLU(cmdlib.NoHooksLU):
298 07e0896f Michael Hanselmann
  pass
299 dd7f6776 Michael Hanselmann
300 dd7f6776 Michael Hanselmann
301 dd7f6776 Michael Hanselmann
class TestHooksRunnerEnv(unittest.TestCase):
302 dd7f6776 Michael Hanselmann
  def setUp(self):
303 dd7f6776 Michael Hanselmann
    self._rpcs = []
304 dd7f6776 Michael Hanselmann
305 dd7f6776 Michael Hanselmann
    self.op = opcodes.OpTestDummy(result=False, messages=[], fail=False)
306 dd7f6776 Michael Hanselmann
    self.lu = FakeEnvLU(FakeProc(), self.op, FakeContext(), None)
307 dd7f6776 Michael Hanselmann
308 dd7f6776 Michael Hanselmann
  def _HooksRpc(self, *args):
309 dd7f6776 Michael Hanselmann
    self._rpcs.append(args)
310 dd7f6776 Michael Hanselmann
    return FakeHooksRpcSuccess(*args)
311 dd7f6776 Michael Hanselmann
312 dd7f6776 Michael Hanselmann
  def _CheckEnv(self, env, phase, hpath):
313 dd7f6776 Michael Hanselmann
    self.assertTrue(env["PATH"].startswith("/sbin"))
314 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_HOOKS_PHASE"], phase)
315 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_HOOKS_PATH"], hpath)
316 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_OP_CODE"], self.op.OP_ID)
317 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_HOOKS_VERSION"], str(constants.HOOKS_VERSION))
318 a56625a2 Michael Hanselmann
    self.assertEqual(env["GANETI_DATA_DIR"], pathutils.DATA_DIR)
319 07e0896f Michael Hanselmann
    if "GANETI_OBJECT_TYPE" in env:
320 07e0896f Michael Hanselmann
      self.assertEqual(env["GANETI_OBJECT_TYPE"], constants.HTYPE_GROUP)
321 07e0896f Michael Hanselmann
    else:
322 07e0896f Michael Hanselmann
      self.assertTrue(self.lu.HTYPE is None)
323 dd7f6776 Michael Hanselmann
324 dd7f6776 Michael Hanselmann
  def testEmptyEnv(self):
325 dd7f6776 Michael Hanselmann
    # Check pre-phase hook
326 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {}
327 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
328 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_PRE)
329 dd7f6776 Michael Hanselmann
330 dd7f6776 Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
331 1c3231aa Thomas Thrainer
    self.assertEqual(node_list, set(["node_a.example.com"]))
332 dd7f6776 Michael Hanselmann
    self.assertEqual(hpath, self.lu.HPATH)
333 dd7f6776 Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_PRE)
334 dd7f6776 Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_PRE, self.lu.HPATH)
335 dd7f6776 Michael Hanselmann
336 dd7f6776 Michael Hanselmann
    # Check post-phase hook
337 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {}
338 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_POST)
339 dd7f6776 Michael Hanselmann
340 dd7f6776 Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
341 1c3231aa Thomas Thrainer
    self.assertEqual(node_list, set(["node_a.example.com"]))
342 dd7f6776 Michael Hanselmann
    self.assertEqual(hpath, self.lu.HPATH)
343 dd7f6776 Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
344 dd7f6776 Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST, self.lu.HPATH)
345 dd7f6776 Michael Hanselmann
346 dd7f6776 Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
347 dd7f6776 Michael Hanselmann
348 dd7f6776 Michael Hanselmann
  def testEnv(self):
349 dd7f6776 Michael Hanselmann
    # Check pre-phase hook
350 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {
351 dd7f6776 Michael Hanselmann
      "FOO": "pre-foo-value",
352 dd7f6776 Michael Hanselmann
      }
353 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
354 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_PRE)
355 dd7f6776 Michael Hanselmann
356 dd7f6776 Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
357 1c3231aa Thomas Thrainer
    self.assertEqual(node_list, set(["node_a.example.com"]))
358 dd7f6776 Michael Hanselmann
    self.assertEqual(hpath, self.lu.HPATH)
359 dd7f6776 Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_PRE)
360 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_FOO"], "pre-foo-value")
361 dd7f6776 Michael Hanselmann
    self.assertFalse(compat.any(key.startswith("GANETI_POST") for key in env))
362 dd7f6776 Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_PRE, self.lu.HPATH)
363 dd7f6776 Michael Hanselmann
364 dd7f6776 Michael Hanselmann
    # Check post-phase hook
365 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {
366 dd7f6776 Michael Hanselmann
      "FOO": "post-value",
367 dd7f6776 Michael Hanselmann
      "BAR": 123,
368 dd7f6776 Michael Hanselmann
      }
369 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_POST)
370 dd7f6776 Michael Hanselmann
371 dd7f6776 Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
372 1c3231aa Thomas Thrainer
    self.assertEqual(node_list, set(["node_a.example.com"]))
373 dd7f6776 Michael Hanselmann
    self.assertEqual(hpath, self.lu.HPATH)
374 dd7f6776 Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
375 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_FOO"], "pre-foo-value")
376 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_POST_FOO"], "post-value")
377 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_POST_BAR"], "123")
378 dd7f6776 Michael Hanselmann
    self.assertFalse("GANETI_BAR" in env)
379 dd7f6776 Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST, self.lu.HPATH)
380 dd7f6776 Michael Hanselmann
381 dd7f6776 Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
382 dd7f6776 Michael Hanselmann
383 dd7f6776 Michael Hanselmann
    # Check configuration update hook
384 07e0896f Michael Hanselmann
    hm.RunConfigUpdate()
385 dd7f6776 Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
386 1c3231aa Thomas Thrainer
    self.assertEqual(set(node_list), set([self.lu.cfg.GetMasterNodeName()]))
387 dd7f6776 Michael Hanselmann
    self.assertEqual(hpath, constants.HOOKS_NAME_CFGUPDATE)
388 dd7f6776 Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
389 dd7f6776 Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST,
390 dd7f6776 Michael Hanselmann
                   constants.HOOKS_NAME_CFGUPDATE)
391 dd7f6776 Michael Hanselmann
    self.assertFalse(compat.any(key.startswith("GANETI_POST") for key in env))
392 dd7f6776 Michael Hanselmann
    self.assertEqual(env["GANETI_FOO"], "pre-foo-value")
393 dd7f6776 Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
394 dd7f6776 Michael Hanselmann
395 dd7f6776 Michael Hanselmann
  def testConflict(self):
396 dd7f6776 Michael Hanselmann
    for name in ["DATA_DIR", "OP_CODE"]:
397 dd7f6776 Michael Hanselmann
      self.lu.hook_env = { name: "value" }
398 b423c513 Michael Hanselmann
399 b423c513 Michael Hanselmann
      # Test using a clean HooksMaster instance
400 68d95757 Guido Trotter
      hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
401 b423c513 Michael Hanselmann
402 dd7f6776 Michael Hanselmann
      for phase in [constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST]:
403 b423c513 Michael Hanselmann
        self.assertRaises(AssertionError, hm.RunPhase, phase)
404 dd7f6776 Michael Hanselmann
        self.assertRaises(IndexError, self._rpcs.pop)
405 dd7f6776 Michael Hanselmann
406 dd7f6776 Michael Hanselmann
  def testNoNodes(self):
407 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {}
408 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
409 1c3231aa Thomas Thrainer
    hm.RunPhase(constants.HOOKS_PHASE_PRE, node_names=[])
410 dd7f6776 Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
411 dd7f6776 Michael Hanselmann
412 dd7f6776 Michael Hanselmann
  def testSpecificNodes(self):
413 dd7f6776 Michael Hanselmann
    self.lu.hook_env = {}
414 dd7f6776 Michael Hanselmann
415 dd7f6776 Michael Hanselmann
    nodes = [
416 dd7f6776 Michael Hanselmann
      "node1.example.com",
417 dd7f6776 Michael Hanselmann
      "node93782.example.net",
418 dd7f6776 Michael Hanselmann
      ]
419 dd7f6776 Michael Hanselmann
420 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
421 07e0896f Michael Hanselmann
422 dd7f6776 Michael Hanselmann
    for phase in [constants.HOOKS_PHASE_PRE, constants.HOOKS_PHASE_POST]:
423 1c3231aa Thomas Thrainer
      hm.RunPhase(phase, node_names=nodes)
424 dd7f6776 Michael Hanselmann
425 dd7f6776 Michael Hanselmann
      (node_list, hpath, rpc_phase, env) = self._rpcs.pop(0)
426 dd7f6776 Michael Hanselmann
      self.assertEqual(set(node_list), set(nodes))
427 dd7f6776 Michael Hanselmann
      self.assertEqual(hpath, self.lu.HPATH)
428 dd7f6776 Michael Hanselmann
      self.assertEqual(rpc_phase, phase)
429 dd7f6776 Michael Hanselmann
      self._CheckEnv(env, phase, self.lu.HPATH)
430 dd7f6776 Michael Hanselmann
431 dd7f6776 Michael Hanselmann
      self.assertRaises(IndexError, self._rpcs.pop)
432 dd7f6776 Michael Hanselmann
433 dd7f6776 Michael Hanselmann
  def testRunConfigUpdateNoPre(self):
434 07e0896f Michael Hanselmann
    self.lu.hook_env = {
435 07e0896f Michael Hanselmann
      "FOO": "value",
436 07e0896f Michael Hanselmann
      }
437 07e0896f Michael Hanselmann
438 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
439 07e0896f Michael Hanselmann
    hm.RunConfigUpdate()
440 07e0896f Michael Hanselmann
441 07e0896f Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
442 1c3231aa Thomas Thrainer
    self.assertEqual(set(node_list), set([self.lu.cfg.GetMasterNodeName()]))
443 07e0896f Michael Hanselmann
    self.assertEqual(hpath, constants.HOOKS_NAME_CFGUPDATE)
444 07e0896f Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
445 07e0896f Michael Hanselmann
    self.assertEqual(env["GANETI_FOO"], "value")
446 07e0896f Michael Hanselmann
    self.assertFalse(compat.any(key.startswith("GANETI_POST") for key in env))
447 07e0896f Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST,
448 07e0896f Michael Hanselmann
                   constants.HOOKS_NAME_CFGUPDATE)
449 07e0896f Michael Hanselmann
450 dd7f6776 Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
451 dd7f6776 Michael Hanselmann
452 b423c513 Michael Hanselmann
  def testNoPreBeforePost(self):
453 07e0896f Michael Hanselmann
    self.lu.hook_env = {
454 07e0896f Michael Hanselmann
      "FOO": "value",
455 07e0896f Michael Hanselmann
      }
456 07e0896f Michael Hanselmann
457 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
458 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_POST)
459 07e0896f Michael Hanselmann
460 07e0896f Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
461 1c3231aa Thomas Thrainer
    self.assertEqual(node_list, set(["node_a.example.com"]))
462 07e0896f Michael Hanselmann
    self.assertEqual(hpath, self.lu.HPATH)
463 07e0896f Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
464 07e0896f Michael Hanselmann
    self.assertEqual(env["GANETI_FOO"], "value")
465 07e0896f Michael Hanselmann
    self.assertEqual(env["GANETI_POST_FOO"], "value")
466 07e0896f Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST, self.lu.HPATH)
467 07e0896f Michael Hanselmann
468 07e0896f Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
469 07e0896f Michael Hanselmann
470 07e0896f Michael Hanselmann
  def testNoHooksLU(self):
471 07e0896f Michael Hanselmann
    self.lu = FakeNoHooksLU(FakeProc(), self.op, FakeContext(), None)
472 07e0896f Michael Hanselmann
    self.assertRaises(AssertionError, self.lu.BuildHooksEnv)
473 07e0896f Michael Hanselmann
    self.assertRaises(AssertionError, self.lu.BuildHooksNodes)
474 07e0896f Michael Hanselmann
475 68d95757 Guido Trotter
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
476 07e0896f Michael Hanselmann
    self.assertEqual(hm.pre_env, {})
477 07e0896f Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
478 07e0896f Michael Hanselmann
479 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_PRE)
480 07e0896f Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
481 07e0896f Michael Hanselmann
482 07e0896f Michael Hanselmann
    hm.RunPhase(constants.HOOKS_PHASE_POST)
483 07e0896f Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
484 07e0896f Michael Hanselmann
485 07e0896f Michael Hanselmann
    hm.RunConfigUpdate()
486 07e0896f Michael Hanselmann
487 07e0896f Michael Hanselmann
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
488 1c3231aa Thomas Thrainer
    self.assertEqual(set(node_list), set([self.lu.cfg.GetMasterNodeName()]))
489 07e0896f Michael Hanselmann
    self.assertEqual(hpath, constants.HOOKS_NAME_CFGUPDATE)
490 07e0896f Michael Hanselmann
    self.assertEqual(phase, constants.HOOKS_PHASE_POST)
491 07e0896f Michael Hanselmann
    self.assertFalse(compat.any(key.startswith("GANETI_POST") for key in env))
492 07e0896f Michael Hanselmann
    self._CheckEnv(env, constants.HOOKS_PHASE_POST,
493 07e0896f Michael Hanselmann
                   constants.HOOKS_NAME_CFGUPDATE)
494 07e0896f Michael Hanselmann
    self.assertRaises(IndexError, self._rpcs.pop)
495 07e0896f Michael Hanselmann
496 07e0896f Michael Hanselmann
    assert isinstance(self.lu, FakeNoHooksLU), "LU was replaced"
497 b423c513 Michael Hanselmann
498 dd7f6776 Michael Hanselmann
499 ff1c051b Thomas Thrainer
class FakeEnvWithCustomPostHookNodesLU(cmdlib.LogicalUnit):
500 1c3231aa Thomas Thrainer
  HPATH = "env_test_lu"
501 1c3231aa Thomas Thrainer
  HTYPE = constants.HTYPE_GROUP
502 1c3231aa Thomas Thrainer
503 1c3231aa Thomas Thrainer
  def __init__(self, *args):
504 1c3231aa Thomas Thrainer
    cmdlib.LogicalUnit.__init__(self, *args)
505 1c3231aa Thomas Thrainer
506 1c3231aa Thomas Thrainer
  def BuildHooksEnv(self):
507 1c3231aa Thomas Thrainer
    return {}
508 1c3231aa Thomas Thrainer
509 1c3231aa Thomas Thrainer
  def BuildHooksNodes(self):
510 ff1c051b Thomas Thrainer
    return (["a"], ["a"])
511 ff1c051b Thomas Thrainer
512 ff1c051b Thomas Thrainer
  def PreparePostHookNodes(self, post_hook_node_uuids):
513 ff1c051b Thomas Thrainer
    return post_hook_node_uuids + ["b"]
514 1c3231aa Thomas Thrainer
515 1c3231aa Thomas Thrainer
516 1c3231aa Thomas Thrainer
class TestHooksRunnerEnv(unittest.TestCase):
517 1c3231aa Thomas Thrainer
  def setUp(self):
518 1c3231aa Thomas Thrainer
    self._rpcs = []
519 1c3231aa Thomas Thrainer
520 1c3231aa Thomas Thrainer
    self.op = opcodes.OpTestDummy(result=False, messages=[], fail=False)
521 ff1c051b Thomas Thrainer
    self.lu = FakeEnvWithCustomPostHookNodesLU(FakeProc(), self.op,
522 87ed6b79 Klaus Aehlig
                                               FakeContext(), None,
523 87ed6b79 Klaus Aehlig
                                               (123, "/foo/bar"),
524 87ed6b79 Klaus Aehlig
                                               None)
525 1c3231aa Thomas Thrainer
526 1c3231aa Thomas Thrainer
  def _HooksRpc(self, *args):
527 1c3231aa Thomas Thrainer
    self._rpcs.append(args)
528 1c3231aa Thomas Thrainer
    return FakeHooksRpcSuccess(*args)
529 1c3231aa Thomas Thrainer
530 1c3231aa Thomas Thrainer
  def testEmptyEnv(self):
531 1c3231aa Thomas Thrainer
    # Check pre-phase hook
532 1c3231aa Thomas Thrainer
    hm = hooksmaster.HooksMaster.BuildFromLu(self._HooksRpc, self.lu)
533 1c3231aa Thomas Thrainer
    hm.RunPhase(constants.HOOKS_PHASE_PRE)
534 1c3231aa Thomas Thrainer
535 1c3231aa Thomas Thrainer
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
536 ff1c051b Thomas Thrainer
    self.assertEqual(node_list, set(["a"]))
537 1c3231aa Thomas Thrainer
538 1c3231aa Thomas Thrainer
    # Check post-phase hook
539 1c3231aa Thomas Thrainer
    hm.RunPhase(constants.HOOKS_PHASE_POST)
540 1c3231aa Thomas Thrainer
541 1c3231aa Thomas Thrainer
    (node_list, hpath, phase, env) = self._rpcs.pop(0)
542 ff1c051b Thomas Thrainer
    self.assertEqual(node_list, set(["a", "b"]))
543 1c3231aa Thomas Thrainer
544 1c3231aa Thomas Thrainer
    self.assertRaises(IndexError, self._rpcs.pop)
545 1c3231aa Thomas Thrainer
546 1c3231aa Thomas Thrainer
547 2f96c43c Michael Hanselmann
if __name__ == "__main__":
548 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()