Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.mcpu_unittest.py @ e9a81214

History | View | Annotate | Download (8.8 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 mcpu
29
from ganeti import opcodes
30
from ganeti import cmdlib
31
from ganeti import locking
32
from ganeti import constants
33
from ganeti.constants import \
34
    LOCK_ATTEMPTS_TIMEOUT, \
35
    LOCK_ATTEMPTS_MAXWAIT, \
36
    LOCK_ATTEMPTS_MINWAIT
37

    
38
import testutils
39

    
40

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

    
53

    
54
class TestLockAttemptTimeoutStrategy(unittest.TestCase):
55
  def testConstants(self):
56
    tpa = mcpu.LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT
57
    self.assert_(len(tpa) > LOCK_ATTEMPTS_TIMEOUT / LOCK_ATTEMPTS_MAXWAIT)
58
    self.assert_(sum(tpa) >= LOCK_ATTEMPTS_TIMEOUT)
59

    
60
    self.assertTrue(LOCK_ATTEMPTS_TIMEOUT >= 1800,
61
                    msg="Waiting less than half an hour per priority")
62
    self.assertTrue(LOCK_ATTEMPTS_TIMEOUT <= 3600,
63
                    msg="Waiting more than an hour per priority")
64

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

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

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

    
78
      prev = timeout
79

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

    
83

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

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

    
102

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

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

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

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

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

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

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

    
136
    for op in [op1, op2, op3]:
137
      self.assertTrue("OP_TEST_DUMMY" in op.comment)
138
      self.assertFalse(hasattr(op, "priority"))
139
      self.assertFalse(hasattr(op, "debug_level"))
140

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

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

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

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

    
161
    self.assertEqual(op1.priority, constants.OP_PRIO_LOW)
162
    self.assertTrue("OP_TEST_DUMMY" in op1.comment)
163
    self.assertEqual(op1.debug_level, 3)
164

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

    
169

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

    
175

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

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

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

    
188

    
189
class TestVerifyLocks(unittest.TestCase):
190
  def testNoLocks(self):
191
    lu = _FakeLuWithLocks({}, {})
192
    glm = _FakeGlm(False)
193
    mcpu._VerifyLocks(lu, glm,
194
                      _mode_whitelist=NotImplemented,
195
                      _nal_whitelist=NotImplemented)
196

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

    
208
  def testDifferentMode(self):
209
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
210
      lu = _FakeLuWithLocks({
211
        level: ["foo"],
212
        }, {
213
        level: 0,
214
        locking.LEVEL_NODE_ALLOC: 1,
215
        })
216
      glm = _FakeGlm(False)
217
      try:
218
        mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
219
      except AssertionError, err:
220
        self.assertTrue("using the same mode as nodes" in str(err))
221
      else:
222
        self.fail("Exception not raised")
223

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

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

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

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

    
250
  def testAllWithoutAllocLock(self):
251
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
252
      lu = _FakeLuWithLocks({
253
        level: locking.ALL_SET,
254
        }, {
255
        level: 0,
256
        locking.LEVEL_NODE_ALLOC: 0,
257
        })
258
      glm = _FakeGlm(False)
259
      try:
260
        mcpu._VerifyLocks(lu, glm, _mode_whitelist=[], _nal_whitelist=[])
261
      except AssertionError, err:
262
        self.assertTrue("allocation lock must be used if" in str(err))
263
      else:
264
        self.fail("Exception not raised")
265

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

    
270
  def testAllWithAllocLock(self):
271
    for level in [locking.LEVEL_NODE, locking.LEVEL_NODE_RES]:
272
      lu = _FakeLuWithLocks({
273
        level: locking.ALL_SET,
274
        locking.LEVEL_NODE_ALLOC: locking.ALL_SET,
275
        }, {
276
        level: 0,
277
        locking.LEVEL_NODE_ALLOC: 0,
278
        })
279
      glm = _FakeGlm(True)
280

    
281
      try:
282
        mcpu._VerifyLocks(lu, glm, _mode_whitelist=[],
283
                          _nal_whitelist=[_FakeLuWithLocks])
284
      except AssertionError, err:
285
        self.assertTrue("whitelisted for not acquiring" in str(err))
286
      else:
287
        self.fail("Exception not raised")
288

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

    
292

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