4 # Copyright (C) 2009, 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script for unittesting the mcpu module"""
28 from ganeti import compat
29 from ganeti import mcpu
30 from ganeti import opcodes
31 from ganeti import cmdlib
32 from ganeti import locking
33 from ganeti import constants
34 from ganeti.constants import \
35 LOCK_ATTEMPTS_TIMEOUT, \
36 LOCK_ATTEMPTS_MAXWAIT, \
42 REQ_BGL_WHITELIST = compat.UniqueFrozenset([
43 opcodes.OpClusterActivateMasterIp,
44 opcodes.OpClusterDeactivateMasterIp,
45 opcodes.OpClusterDestroy,
46 opcodes.OpClusterPostInit,
47 opcodes.OpClusterRename,
48 opcodes.OpInstanceRename,
51 opcodes.OpTestAllocator,
55 class TestLockAttemptTimeoutStrategy(unittest.TestCase):
56 def testConstants(self):
57 tpa = mcpu.LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT
58 self.assert_(len(tpa) > LOCK_ATTEMPTS_TIMEOUT / LOCK_ATTEMPTS_MAXWAIT)
59 self.assert_(sum(tpa) >= LOCK_ATTEMPTS_TIMEOUT)
61 self.assertTrue(LOCK_ATTEMPTS_TIMEOUT >= 1800,
62 msg="Waiting less than half an hour per priority")
63 self.assertTrue(LOCK_ATTEMPTS_TIMEOUT <= 3600,
64 msg="Waiting more than an hour per priority")
67 strat = mcpu.LockAttemptTimeoutStrategy(_random_fn=lambda: 0.5,
71 for i in range(len(strat._TIMEOUT_PER_ATTEMPT)):
72 timeout = strat.NextAttempt()
73 self.assert_(timeout is not None)
75 self.assert_(timeout <= LOCK_ATTEMPTS_MAXWAIT)
76 self.assert_(timeout >= LOCK_ATTEMPTS_MINWAIT)
77 self.assert_(prev is None or timeout >= prev)
82 self.assert_(strat.NextAttempt() is None)
85 class TestDispatchTable(unittest.TestCase):
87 for opcls in opcodes.OP_MAPPING.values():
90 self.assertTrue(opcls in mcpu.Processor.DISPATCH_TABLE,
91 msg="%s missing handler class" % opcls)
93 # Check against BGL whitelist
94 lucls = mcpu.Processor.DISPATCH_TABLE[opcls]
96 self.assertTrue(opcls in REQ_BGL_WHITELIST,
97 msg=("%s not whitelisted for BGL" % opcls.OP_ID))
99 self.assertFalse(opcls in REQ_BGL_WHITELIST,
100 msg=("%s whitelisted for BGL, but doesn't use it" %
104 class TestProcessResult(unittest.TestCase):
107 self._count = itertools.count(200)
109 def _Submit(self, jobs):
110 job_ids = [self._count.next() for _ in jobs]
111 self._submitted.extend(zip(job_ids, jobs))
114 def testNoJobs(self):
115 for i in [object(), [], False, True, None, 1, 929, {}]:
116 self.assertEqual(mcpu._ProcessResult(NotImplemented, NotImplemented, i),
119 def testDefaults(self):
120 src = opcodes.OpTestDummy()
122 res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
123 opcodes.OpTestDelay(),
124 opcodes.OpTestDelay(),
126 opcodes.OpTestDelay(),
129 self.assertEqual(res, {
130 constants.JOB_IDS_KEY: [200, 201],
133 (_, (op1, op2)) = self._submitted.pop(0)
134 (_, (op3, )) = self._submitted.pop(0)
135 self.assertRaises(IndexError, self._submitted.pop)
137 for op in [op1, op2, op3]:
138 self.assertTrue("OP_TEST_DUMMY" in op.comment)
139 self.assertFalse(hasattr(op, "priority"))
140 self.assertFalse(hasattr(op, "debug_level"))
142 def testParams(self):
143 src = opcodes.OpTestDummy(priority=constants.OP_PRIO_HIGH,
146 res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
147 opcodes.OpTestDelay(priority=constants.OP_PRIO_LOW),
149 opcodes.OpTestDelay(comment="foobar", debug_level=10),
150 ]], other=True, value=range(10)))
152 self.assertEqual(res, {
153 constants.JOB_IDS_KEY: [200, 201],
158 (_, (op1, )) = self._submitted.pop(0)
159 (_, (op2, )) = self._submitted.pop(0)
160 self.assertRaises(IndexError, self._submitted.pop)
162 self.assertEqual(op1.priority, constants.OP_PRIO_LOW)
163 self.assertTrue("OP_TEST_DUMMY" in op1.comment)
164 self.assertEqual(op1.debug_level, 3)
166 self.assertEqual(op2.priority, constants.OP_PRIO_HIGH)
167 self.assertEqual(op2.comment, "foobar")
168 self.assertEqual(op2.debug_level, 3)
171 class _FakeLuWithLocks:
172 def __init__(self, needed_locks, share_locks):
173 self.needed_locks = needed_locks
174 self.share_locks = share_locks
178 def __init__(self, owning_nal):
179 self._owning_nal = owning_nal
181 def check_owned(self, level, names):
182 assert level == locking.LEVEL_NODE_ALLOC
183 assert names == locking.NAL
184 return self._owning_nal
186 def owning_all(self, level):
190 class TestVerifyLocks(unittest.TestCase):
191 def testNoLocks(self):
192 lu = _FakeLuWithLocks({}, {})
193 glm = _FakeGlm(False)
194 mcpu._VerifyLocks(lu, glm,
195 _mode_whitelist=NotImplemented,
196 _nal_whitelist=NotImplemented)
198 def testNotAllSameMode(self):
199 for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
200 lu = _FakeLuWithLocks({
204 locking.LEVEL_NODE_ALLOC: 0,
206 glm = _FakeGlm(False)
207 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
209 def testDifferentMode(self):
210 for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
211 lu = _FakeLuWithLocks({
215 locking.LEVEL_NODE_ALLOC: 1,
217 glm = _FakeGlm(False)
219 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
220 except AssertionError, err:
221 self.assertTrue("using the same mode as nodes" in str(err))
223 self.fail("Exception not raised")
225 # Once more with the whitelist
226 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[_FakeLuWithLocks],
229 def testSameMode(self):
230 for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
231 lu = _FakeLuWithLocks({
233 locking.LEVEL_NODE_ALLOC: locking.ALL_SET,
236 locking.LEVEL_NODE_ALLOC: 1,
241 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[_FakeLuWithLocks],
243 except AssertionError, err:
244 self.assertTrue("whitelisted to use different modes" in str(err))
246 self.fail("Exception not raised")
248 # Once more without the whitelist
249 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
251 def testAllWithoutAllocLock(self):
252 for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
253 lu = _FakeLuWithLocks({
254 level: locking.ALL_SET,
257 locking.LEVEL_NODE_ALLOC: 0,
259 glm = _FakeGlm(False)
261 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
262 except AssertionError, err:
263 self.assertTrue("allocation lock must be used if" in str(err))
265 self.fail("Exception not raised")
267 # Once more with the whitelist
268 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[],
269 _nal_whitelist=[_FakeLuWithLocks])
271 def testAllWithAllocLock(self):
272 for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
273 lu = _FakeLuWithLocks({
274 level: locking.ALL_SET,
275 locking.LEVEL_NODE_ALLOC: locking.ALL_SET,
278 locking.LEVEL_NODE_ALLOC: 0,
283 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[],
284 _nal_whitelist=[_FakeLuWithLocks])
285 except AssertionError, err:
286 self.assertTrue("whitelisted for not acquiring" in str(err))
288 self.fail("Exception not raised")
290 # Once more without the whitelist
291 mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
294 if __name__ == "__main__":
295 testutils.GanetiTestProgram()