Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.mcpu_unittest.py @ 4869595d

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

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

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

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

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

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

    
164
    # FIXME: as priority is mandatory, there is no way
165
    # of specifying "just inherit the priority".
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()