Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.mcpu_unittest.py @ d01e51a5

History | View | Annotate | Download (8.9 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2009, 2011 Google Inc.
5
#
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.
10
#
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.
15
#
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
19
# 02110-1301, USA.
20

    
21

    
22
"""Script for unittesting the mcpu module"""
23

    
24

    
25
import unittest
26
import itertools
27

    
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, \
37
    LOCK_ATTEMPTS_MINWAIT
38

    
39
import testutils
40

    
41

    
42
REQ_BGL_WHITELIST = compat.UniqueFrozenset([
43
  opcodes.OpClusterActivateMasterIp,
44
  opcodes.OpClusterDeactivateMasterIp,
45
  opcodes.OpClusterDestroy,
46
  opcodes.OpClusterPostInit,
47
  opcodes.OpClusterRename,
48
  opcodes.OpInstanceRename,
49
  opcodes.OpNodeAdd,
50
  opcodes.OpNodeRemove,
51
  opcodes.OpTestAllocator,
52
  ])
53

    
54

    
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)
60

    
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")
65

    
66
  def testSimple(self):
67
    strat = mcpu.LockAttemptTimeoutStrategy(_random_fn=lambda: 0.5,
68
                                            _time_fn=lambda: 0.0)
69

    
70
    prev = None
71
    for i in range(len(strat._TIMEOUT_PER_ATTEMPT)):
72
      timeout = strat.NextAttempt()
73
      self.assert_(timeout is not None)
74

    
75
      self.assert_(timeout <= LOCK_ATTEMPTS_MAXWAIT)
76
      self.assert_(timeout >= LOCK_ATTEMPTS_MINWAIT)
77
      self.assert_(prev is None or timeout >= prev)
78

    
79
      prev = timeout
80

    
81
    for _ in range(10):
82
      self.assert_(strat.NextAttempt() is None)
83

    
84

    
85
class TestDispatchTable(unittest.TestCase):
86
  def test(self):
87
    for opcls in opcodes.OP_MAPPING.values():
88
      if not opcls.WITH_LU:
89
        continue
90
      self.assertTrue(opcls in mcpu.Processor.DISPATCH_TABLE,
91
                      msg="%s missing handler class" % opcls)
92

    
93
      # Check against BGL whitelist
94
      lucls = mcpu.Processor.DISPATCH_TABLE[opcls]
95
      if lucls.REQ_BGL:
96
        self.assertTrue(opcls in REQ_BGL_WHITELIST,
97
                        msg=("%s not whitelisted for BGL" % opcls.OP_ID))
98
      else:
99
        self.assertFalse(opcls in REQ_BGL_WHITELIST,
100
                         msg=("%s whitelisted for BGL, but doesn't use it" %
101
                              opcls.OP_ID))
102

    
103

    
104
class TestProcessResult(unittest.TestCase):
105
  def setUp(self):
106
    self._submitted = []
107
    self._count = itertools.count(200)
108

    
109
  def _Submit(self, jobs):
110
    job_ids = [self._count.next() for _ in jobs]
111
    self._submitted.extend(zip(job_ids, jobs))
112
    return job_ids
113

    
114
  def testNoJobs(self):
115
    for i in [object(), [], False, True, None, 1, 929, {}]:
116
      self.assertEqual(mcpu._ProcessResult(NotImplemented, NotImplemented, i),
117
                       i)
118

    
119
  def testDefaults(self):
120
    src = opcodes.OpTestDummy()
121

    
122
    res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
123
      opcodes.OpTestDelay(),
124
      opcodes.OpTestDelay(),
125
      ], [
126
      opcodes.OpTestDelay(),
127
      ]]))
128

    
129
    self.assertEqual(res, {
130
      constants.JOB_IDS_KEY: [200, 201],
131
      })
132

    
133
    (_, (op1, op2)) = self._submitted.pop(0)
134
    (_, (op3, )) = self._submitted.pop(0)
135
    self.assertRaises(IndexError, self._submitted.pop)
136

    
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"))
141

    
142
  def testParams(self):
143
    src = opcodes.OpTestDummy(priority=constants.OP_PRIO_HIGH,
144
                              debug_level=3)
145

    
146
    res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
147
      opcodes.OpTestDelay(priority=constants.OP_PRIO_LOW),
148
      ], [
149
      opcodes.OpTestDelay(comment="foobar", debug_level=10),
150
      ]], other=True, value=range(10)))
151

    
152
    self.assertEqual(res, {
153
      constants.JOB_IDS_KEY: [200, 201],
154
      "other": True,
155
      "value": range(10),
156
      })
157

    
158
    (_, (op1, )) = self._submitted.pop(0)
159
    (_, (op2, )) = self._submitted.pop(0)
160
    self.assertRaises(IndexError, self._submitted.pop)
161

    
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)
165

    
166
    self.assertEqual(op2.priority, constants.OP_PRIO_HIGH)
167
    self.assertEqual(op2.comment, "foobar")
168
    self.assertEqual(op2.debug_level, 3)
169

    
170

    
171
class _FakeLuWithLocks:
172
  def __init__(self, needed_locks, share_locks):
173
    self.needed_locks = needed_locks
174
    self.share_locks = share_locks
175

    
176

    
177
class _FakeGlm:
178
  def __init__(self, owning_nal):
179
    self._owning_nal = owning_nal
180

    
181
  def check_owned(self, level, names):
182
    assert level == locking.LEVEL_NODE_ALLOC
183
    assert names == locking.NAL
184
    return self._owning_nal
185

    
186
  def owning_all(self, level):
187
    return False
188

    
189

    
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)
197

    
198
  def testNotAllSameMode(self):
199
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
200
      lu = _FakeLuWithLocks({
201
        level: ["foo"],
202
        }, {
203
        level: 0,
204
        locking.LEVEL_NODE_ALLOC: 0,
205
        })
206
      glm = _FakeGlm(False)
207
      mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
208

    
209
  def testDifferentMode(self):
210
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
211
      lu = _FakeLuWithLocks({
212
        level: ["foo"],
213
        }, {
214
        level: 0,
215
        locking.LEVEL_NODE_ALLOC: 1,
216
        })
217
      glm = _FakeGlm(False)
218
      try:
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))
222
      else:
223
        self.fail("Exception not raised")
224

    
225
      # Once more with the whitelist
226
      mcpu._VerifyLocks(lu, glm, _mode_whitelist=[_FakeLuWithLocks],
227
                        _nal_whitelist=[])
228

    
229
  def testSameMode(self):
230
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
231
      lu = _FakeLuWithLocks({
232
        level: ["foo"],
233
        locking.LEVEL_NODE_ALLOC: locking.ALL_SET,
234
        }, {
235
        level: 1,
236
        locking.LEVEL_NODE_ALLOC: 1,
237
        })
238
      glm = _FakeGlm(True)
239

    
240
      try:
241
        mcpu._VerifyLocks(lu, glm, _mode_whitelist=[_FakeLuWithLocks],
242
                          _nal_whitelist=[])
243
      except AssertionError, err:
244
        self.assertTrue("whitelisted to use different modes" in str(err))
245
      else:
246
        self.fail("Exception not raised")
247

    
248
      # Once more without the whitelist
249
      mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
250

    
251
  def testAllWithoutAllocLock(self):
252
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
253
      lu = _FakeLuWithLocks({
254
        level: locking.ALL_SET,
255
        }, {
256
        level: 0,
257
        locking.LEVEL_NODE_ALLOC: 0,
258
        })
259
      glm = _FakeGlm(False)
260
      try:
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))
264
      else:
265
        self.fail("Exception not raised")
266

    
267
      # Once more with the whitelist
268
      mcpu._VerifyLocks(lu, glm, _mode_whitelist=[],
269
                        _nal_whitelist=[_FakeLuWithLocks])
270

    
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,
276
        }, {
277
        level: 0,
278
        locking.LEVEL_NODE_ALLOC: 0,
279
        })
280
      glm = _FakeGlm(True)
281

    
282
      try:
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))
287
      else:
288
        self.fail("Exception not raised")
289

    
290
      # Once more without the whitelist
291
      mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
292

    
293

    
294
if __name__ == "__main__":
295
  testutils.GanetiTestProgram()