Statistics
| Branch: | Tag: | Revision:

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

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
# FIXME: Document what BGL whitelist means
43
REQ_BGL_WHITELIST = compat.UniqueFrozenset([
44
  opcodes.OpClusterActivateMasterIp,
45
  opcodes.OpClusterDeactivateMasterIp,
46
  opcodes.OpClusterDestroy,
47
  opcodes.OpClusterPostInit,
48
  opcodes.OpClusterRename,
49
  opcodes.OpClusterRenewCrypto,
50
  opcodes.OpInstanceRename,
51
  opcodes.OpNodeAdd,
52
  opcodes.OpNodeRemove,
53
  opcodes.OpTestAllocator,
54
  ])
55

    
56

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

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

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

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

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

    
81
      prev = timeout
82

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

    
86

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

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

    
105

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

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

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

    
121
  def testDefaults(self):
122
    src = opcodes.OpTestDummy()
123

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

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

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

    
139
    for op in [op1, op2, op3]:
140
      self.assertTrue("OP_TEST_DUMMY" in op.comment)
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
    # FIXME: as priority is mandatory, there is no way
167
    # of specifying "just inherit the priority".
168
    self.assertEqual(op2.comment, "foobar")
169
    self.assertEqual(op2.debug_level, 3)
170

    
171

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

    
177

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

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

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

    
190

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

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

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

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

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

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

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

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

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

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

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

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

    
294

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