Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ dcf315e2

History | View | Annotate | Download (26 kB)

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

    
4
# Copyright (C) 2006, 2007 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
# 0.0510-1301, USA.
20

    
21

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

    
24

    
25
import os
26
import unittest
27
import time
28
import Queue
29

    
30
from ganeti import locking
31
from ganeti import errors
32
from threading import Thread
33

    
34

    
35
class TestSharedLock(unittest.TestCase):
36
  """SharedLock tests"""
37

    
38
  def setUp(self):
39
    self.sl = locking.SharedLock()
40
    # helper threads use the 'done' queue to tell the master they finished.
41
    self.done = Queue.Queue(0)
42

    
43
  def testSequenceAndOwnership(self):
44
    self.assert_(not self.sl._is_owned())
45
    self.sl.acquire(shared=1)
46
    self.assert_(self.sl._is_owned())
47
    self.assert_(self.sl._is_owned(shared=1))
48
    self.assert_(not self.sl._is_owned(shared=0))
49
    self.sl.release()
50
    self.assert_(not self.sl._is_owned())
51
    self.sl.acquire()
52
    self.assert_(self.sl._is_owned())
53
    self.assert_(not self.sl._is_owned(shared=1))
54
    self.assert_(self.sl._is_owned(shared=0))
55
    self.sl.release()
56
    self.assert_(not self.sl._is_owned())
57
    self.sl.acquire(shared=1)
58
    self.assert_(self.sl._is_owned())
59
    self.assert_(self.sl._is_owned(shared=1))
60
    self.assert_(not self.sl._is_owned(shared=0))
61
    self.sl.release()
62
    self.assert_(not self.sl._is_owned())
63

    
64
  def testBooleanValue(self):
65
    # semaphores are supposed to return a true value on a successful acquire
66
    self.assert_(self.sl.acquire(shared=1))
67
    self.sl.release()
68
    self.assert_(self.sl.acquire())
69
    self.sl.release()
70

    
71
  def testDoubleLockingStoE(self):
72
    self.sl.acquire(shared=1)
73
    self.assertRaises(AssertionError, self.sl.acquire)
74

    
75
  def testDoubleLockingEtoS(self):
76
    self.sl.acquire()
77
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
78

    
79
  def testDoubleLockingStoS(self):
80
    self.sl.acquire(shared=1)
81
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
82

    
83
  def testDoubleLockingEtoE(self):
84
    self.sl.acquire()
85
    self.assertRaises(AssertionError, self.sl.acquire)
86

    
87
  # helper functions: called in a separate thread they acquire the lock, send
88
  # their identifier on the done queue, then release it.
89
  def _doItSharer(self):
90
    try:
91
      self.sl.acquire(shared=1)
92
      self.done.put('SHR')
93
      self.sl.release()
94
    except errors.LockError:
95
      self.done.put('ERR')
96

    
97
  def _doItExclusive(self):
98
    try:
99
      self.sl.acquire()
100
      self.done.put('EXC')
101
      self.sl.release()
102
    except errors.LockError:
103
      self.done.put('ERR')
104

    
105
  def _doItDelete(self):
106
    try:
107
      self.sl.delete()
108
      self.done.put('DEL')
109
    except errors.LockError:
110
      self.done.put('ERR')
111

    
112
  def testSharersCanCoexist(self):
113
    self.sl.acquire(shared=1)
114
    Thread(target=self._doItSharer).start()
115
    self.assert_(self.done.get(True, 1))
116
    self.sl.release()
117

    
118
  def testExclusiveBlocksExclusive(self):
119
    self.sl.acquire()
120
    Thread(target=self._doItExclusive).start()
121
    # give it a bit of time to check that it's not actually doing anything
122
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
123
    self.sl.release()
124
    self.assert_(self.done.get(True, 1))
125

    
126
  def testExclusiveBlocksDelete(self):
127
    self.sl.acquire()
128
    Thread(target=self._doItDelete).start()
129
    # give it a bit of time to check that it's not actually doing anything
130
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
131
    self.sl.release()
132
    self.assert_(self.done.get(True, 1))
133

    
134
  def testExclusiveBlocksSharer(self):
135
    self.sl.acquire()
136
    Thread(target=self._doItSharer).start()
137
    time.sleep(0.05)
138
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
139
    self.sl.release()
140
    self.assert_(self.done.get(True, 1))
141

    
142
  def testSharerBlocksExclusive(self):
143
    self.sl.acquire(shared=1)
144
    Thread(target=self._doItExclusive).start()
145
    time.sleep(0.05)
146
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
147
    self.sl.release()
148
    self.assert_(self.done.get(True, 1))
149

    
150
  def testSharerBlocksDelete(self):
151
    self.sl.acquire(shared=1)
152
    Thread(target=self._doItDelete).start()
153
    time.sleep(0.05)
154
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
155
    self.sl.release()
156
    self.assert_(self.done.get(True, 1))
157

    
158
  def testWaitingExclusiveBlocksSharer(self):
159
    self.sl.acquire(shared=1)
160
    # the lock is acquired in shared mode...
161
    Thread(target=self._doItExclusive).start()
162
    # ...but now an exclusive is waiting...
163
    time.sleep(0.05)
164
    Thread(target=self._doItSharer).start()
165
    # ...so the sharer should be blocked as well
166
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
167
    self.sl.release()
168
    # The exclusive passed before
169
    self.assertEqual(self.done.get(True, 1), 'EXC')
170
    self.assertEqual(self.done.get(True, 1), 'SHR')
171

    
172
  def testWaitingSharerBlocksExclusive(self):
173
    self.sl.acquire()
174
    # the lock is acquired in exclusive mode...
175
    Thread(target=self._doItSharer).start()
176
    # ...but now a sharer is waiting...
177
    time.sleep(0.05)
178
    Thread(target=self._doItExclusive).start()
179
    # ...the exclusive is waiting too...
180
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
181
    self.sl.release()
182
    # The sharer passed before
183
    self.assertEqual(self.done.get(True, 1), 'SHR')
184
    self.assertEqual(self.done.get(True, 1), 'EXC')
185

    
186
  def testNoNonBlocking(self):
187
    self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
188
    self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
189
    self.sl.acquire()
190
    self.sl.delete(blocking=0) # Fine, because the lock is already acquired
191

    
192
  def testDelete(self):
193
    self.sl.delete()
194
    self.assertRaises(errors.LockError, self.sl.acquire)
195
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
196
    self.assertRaises(errors.LockError, self.sl.delete)
197

    
198
  def testNoDeleteIfSharer(self):
199
    self.sl.acquire(shared=1)
200
    self.assertRaises(AssertionError, self.sl.delete)
201

    
202
  def testDeletePendingSharersExclusiveDelete(self):
203
    self.sl.acquire()
204
    Thread(target=self._doItSharer).start()
205
    Thread(target=self._doItSharer).start()
206
    time.sleep(0.05)
207
    Thread(target=self._doItExclusive).start()
208
    Thread(target=self._doItDelete).start()
209
    time.sleep(0.05)
210
    self.sl.delete()
211
    # The two threads who were pending return both ERR
212
    self.assertEqual(self.done.get(True, 1), 'ERR')
213
    self.assertEqual(self.done.get(True, 1), 'ERR')
214
    self.assertEqual(self.done.get(True, 1), 'ERR')
215
    self.assertEqual(self.done.get(True, 1), 'ERR')
216

    
217
  def testDeletePendingDeleteExclusiveSharers(self):
218
    self.sl.acquire()
219
    Thread(target=self._doItDelete).start()
220
    Thread(target=self._doItExclusive).start()
221
    time.sleep(0.05)
222
    Thread(target=self._doItSharer).start()
223
    Thread(target=self._doItSharer).start()
224
    time.sleep(0.05)
225
    self.sl.delete()
226
    # The two threads who were pending return both ERR
227
    self.assertEqual(self.done.get(True, 1), 'ERR')
228
    self.assertEqual(self.done.get(True, 1), 'ERR')
229
    self.assertEqual(self.done.get(True, 1), 'ERR')
230
    self.assertEqual(self.done.get(True, 1), 'ERR')
231

    
232

    
233
class TestLockSet(unittest.TestCase):
234
  """LockSet tests"""
235

    
236
  def setUp(self):
237
    self.resources = ['one', 'two', 'three']
238
    self.ls = locking.LockSet(members=self.resources)
239
    # helper threads use the 'done' queue to tell the master they finished.
240
    self.done = Queue.Queue(0)
241

    
242
  def testResources(self):
243
    self.assertEquals(self.ls._names(), set(self.resources))
244
    newls = locking.LockSet()
245
    self.assertEquals(newls._names(), set())
246

    
247
  def testAcquireRelease(self):
248
    self.assert_(self.ls.acquire('one'))
249
    self.assertEquals(self.ls._list_owned(), set(['one']))
250
    self.ls.release()
251
    self.assertEquals(self.ls._list_owned(), set())
252
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
253
    self.assertEquals(self.ls._list_owned(), set(['one']))
254
    self.ls.release()
255
    self.assertEquals(self.ls._list_owned(), set())
256
    self.ls.acquire(['one', 'two', 'three'])
257
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
258
    self.ls.release('one')
259
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
260
    self.ls.release(['three'])
261
    self.assertEquals(self.ls._list_owned(), set(['two']))
262
    self.ls.release()
263
    self.assertEquals(self.ls._list_owned(), set())
264
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
265
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
266
    self.ls.release()
267
    self.assertEquals(self.ls._list_owned(), set())
268

    
269
  def testNoDoubleAcquire(self):
270
    self.ls.acquire('one')
271
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
272
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
273
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
274
    self.ls.release()
275
    self.ls.acquire(['one', 'three'])
276
    self.ls.release('one')
277
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
278
    self.ls.release('three')
279

    
280
  def testNoWrongRelease(self):
281
    self.assertRaises(AssertionError, self.ls.release)
282
    self.ls.acquire('one')
283
    self.assertRaises(AssertionError, self.ls.release, 'two')
284

    
285
  def testAddRemove(self):
286
    self.ls.add('four')
287
    self.assertEquals(self.ls._list_owned(), set())
288
    self.assert_('four' in self.ls._names())
289
    self.ls.add(['five', 'six', 'seven'], acquired=1)
290
    self.assert_('five' in self.ls._names())
291
    self.assert_('six' in self.ls._names())
292
    self.assert_('seven' in self.ls._names())
293
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
294
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
295
    self.assert_('five' not in self.ls._names())
296
    self.assert_('six' not in self.ls._names())
297
    self.assertEquals(self.ls._list_owned(), set(['seven']))
298
    self.ls.add('eight', acquired=1, shared=1)
299
    self.assert_('eight' in self.ls._names())
300
    self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
301
    self.ls.remove('seven')
302
    self.assert_('seven' not in self.ls._names())
303
    self.assertEquals(self.ls._list_owned(), set(['eight']))
304
    self.ls.release()
305
    self.ls.remove(['two'])
306
    self.assert_('two' not in self.ls._names())
307
    self.ls.acquire('three')
308
    self.assertEquals(self.ls.remove(['three']), ['three'])
309
    self.assert_('three' not in self.ls._names())
310
    self.assertEquals(self.ls.remove('three'), [])
311
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
312
    self.assert_('one' not in self.ls._names())
313

    
314
  def testRemoveNonBlocking(self):
315
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
316
    self.ls.acquire('one')
317
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
318
    self.ls.acquire(['two', 'three'])
319
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
320
                      ['two', 'three'])
321

    
322
  def testNoDoubleAdd(self):
323
    self.assertRaises(errors.LockError, self.ls.add, 'two')
324
    self.ls.add('four')
325
    self.assertRaises(errors.LockError, self.ls.add, 'four')
326

    
327
  def testNoWrongRemoves(self):
328
    self.ls.acquire(['one', 'three'], shared=1)
329
    # Cannot remove 'two' while holding something which is not a superset
330
    self.assertRaises(AssertionError, self.ls.remove, 'two')
331
    # Cannot remove 'three' as we are sharing it
332
    self.assertRaises(AssertionError, self.ls.remove, 'three')
333

    
334
  def testAcquireSetLock(self):
335
    # acquire the set-lock exclusively
336
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
337
    # I can still add/remove elements...
338
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
339
    self.assert_(self.ls.add('six'))
340
    self.ls.release()
341
    # share the set-lock
342
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
343
    # adding new elements is not possible
344
    self.assertRaises(AssertionError, self.ls.add, 'five')
345
    self.ls.release()
346

    
347
  def _doLockSet(self, set, shared):
348
    try:
349
      self.ls.acquire(set, shared=shared)
350
      self.done.put('DONE')
351
      self.ls.release()
352
    except errors.LockError:
353
      self.done.put('ERR')
354

    
355
  def _doAddSet(self, set):
356
    try:
357
      self.ls.add(set, acquired=1)
358
      self.done.put('DONE')
359
      self.ls.release()
360
    except errors.LockError:
361
      self.done.put('ERR')
362

    
363
  def _doRemoveSet(self, set):
364
    self.done.put(self.ls.remove(set))
365

    
366
  def testConcurrentSharedAcquire(self):
367
    self.ls.acquire(['one', 'two'], shared=1)
368
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
369
    self.assertEqual(self.done.get(True, 1), 'DONE')
370
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
371
    self.assertEqual(self.done.get(True, 1), 'DONE')
372
    Thread(target=self._doLockSet, args=('three', 1)).start()
373
    self.assertEqual(self.done.get(True, 1), 'DONE')
374
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
375
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
376
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
377
    self.ls.release()
378
    self.assertEqual(self.done.get(True, 1), 'DONE')
379
    self.assertEqual(self.done.get(True, 1), 'DONE')
380

    
381
  def testConcurrentExclusiveAcquire(self):
382
    self.ls.acquire(['one', 'two'])
383
    Thread(target=self._doLockSet, args=('three', 1)).start()
384
    self.assertEqual(self.done.get(True, 1), 'DONE')
385
    Thread(target=self._doLockSet, args=('three', 0)).start()
386
    self.assertEqual(self.done.get(True, 1), 'DONE')
387
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
388
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
389
    Thread(target=self._doLockSet, args=('one', 0)).start()
390
    Thread(target=self._doLockSet, args=('one', 1)).start()
391
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
392
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
393
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
394
    self.ls.release()
395
    self.assertEqual(self.done.get(True, 1), 'DONE')
396
    self.assertEqual(self.done.get(True, 1), 'DONE')
397
    self.assertEqual(self.done.get(True, 1), 'DONE')
398
    self.assertEqual(self.done.get(True, 1), 'DONE')
399
    self.assertEqual(self.done.get(True, 1), 'DONE')
400
    self.assertEqual(self.done.get(True, 1), 'DONE')
401

    
402
  def testConcurrentRemove(self):
403
    self.ls.add('four')
404
    self.ls.acquire(['one', 'two', 'four'])
405
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
406
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
407
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
408
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
409
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
410
    self.ls.remove('one')
411
    self.ls.release()
412
    self.assertEqual(self.done.get(True, 1), 'ERR')
413
    self.assertEqual(self.done.get(True, 1), 'ERR')
414
    self.assertEqual(self.done.get(True, 1), 'ERR')
415
    self.assertEqual(self.done.get(True, 1), 'ERR')
416
    self.ls.add(['five', 'six'], acquired=1)
417
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
418
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
419
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
420
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
421
    self.ls.remove('five')
422
    self.ls.release()
423
    self.assertEqual(self.done.get(True, 1), 'DONE')
424
    self.assertEqual(self.done.get(True, 1), 'DONE')
425
    self.assertEqual(self.done.get(True, 1), 'DONE')
426
    self.assertEqual(self.done.get(True, 1), 'DONE')
427
    self.ls.acquire(['three', 'four'])
428
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
429
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
430
    self.ls.remove('four')
431
    self.assertEqual(self.done.get(True, 1), ['six'])
432
    Thread(target=self._doRemoveSet, args=(['two'])).start()
433
    self.assertEqual(self.done.get(True, 1), ['two'])
434
    self.ls.release()
435

    
436
  def testConcurrentSharedSetLock(self):
437
    # share the set-lock...
438
    self.ls.acquire(None, shared=1)
439
    # ...another thread can share it too
440
    Thread(target=self._doLockSet, args=(None, 1)).start()
441
    self.assertEqual(self.done.get(True, 1), 'DONE')
442
    # ...or just share some elements
443
    Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
444
    self.assertEqual(self.done.get(True, 1), 'DONE')
445
    # ...but not add new ones or remove any
446
    Thread(target=self._doAddSet, args=(['nine'])).start()
447
    Thread(target=self._doRemoveSet, args=(['two'], )).start()
448
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
449
    # this just releases the set-lock
450
    self.ls.release([])
451
    self.assertEqual(self.done.get(True, 1), 'DONE')
452
    # release the lock on the actual elements so remove() can proceed too
453
    self.ls.release()
454
    self.assertEqual(self.done.get(True, 1), ['two'])
455

    
456
  def testConcurrentExclusiveSetLock(self):
457
    # acquire the set-lock...
458
    self.ls.acquire(None, shared=0)
459
    # ...no one can do anything else
460
    Thread(target=self._doLockSet, args=(None, 1)).start()
461
    Thread(target=self._doLockSet, args=(None, 0)).start()
462
    Thread(target=self._doLockSet, args=(['three'], 0)).start()
463
    Thread(target=self._doLockSet, args=(['two'], 1)).start()
464
    Thread(target=self._doAddSet, args=(['nine'])).start()
465
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
466
    self.ls.release()
467
    self.assertEqual(self.done.get(True, 1), 'DONE')
468
    self.assertEqual(self.done.get(True, 1), 'DONE')
469
    self.assertEqual(self.done.get(True, 1), 'DONE')
470
    self.assertEqual(self.done.get(True, 1), 'DONE')
471
    self.assertEqual(self.done.get(True, 1), 'DONE')
472

    
473
  def testEmptyLockSet(self):
474
    # get the set-lock
475
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
476
    # now empty it...
477
    self.ls.remove(['one', 'two', 'three'])
478
    # and adds/locks by another thread still wait
479
    Thread(target=self._doAddSet, args=(['nine'])).start()
480
    Thread(target=self._doLockSet, args=(None, 1)).start()
481
    Thread(target=self._doLockSet, args=(None, 0)).start()
482
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
483
    self.ls.release()
484
    self.assertEqual(self.done.get(True, 1), 'DONE')
485
    self.assertEqual(self.done.get(True, 1), 'DONE')
486
    self.assertEqual(self.done.get(True, 1), 'DONE')
487
    # empty it again...
488
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
489
    # now share it...
490
    self.assertEqual(self.ls.acquire(None, shared=1), set())
491
    # other sharers can go, adds still wait
492
    Thread(target=self._doLockSet, args=(None, 1)).start()
493
    self.assertEqual(self.done.get(True, 1), 'DONE')
494
    Thread(target=self._doAddSet, args=(['nine'])).start()
495
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
496
    self.ls.release()
497
    self.assertEqual(self.done.get(True, 1), 'DONE')
498

    
499

    
500
class TestGanetiLockManager(unittest.TestCase):
501

    
502
  def setUp(self):
503
    self.nodes=['n1', 'n2']
504
    self.instances=['i1', 'i2', 'i3']
505
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
506
                                        instances=self.instances)
507
    self.done = Queue.Queue(0)
508

    
509
  def tearDown(self):
510
    # Don't try this at home...
511
    locking.GanetiLockManager._instance = None
512

    
513
  def testLockingConstants(self):
514
    # The locking library internally cheats by assuming its constants have some
515
    # relationships with each other. Check those hold true.
516
    for i in range(len(locking.LEVELS)):
517
      self.assertEqual(i, locking.LEVELS[i])
518

    
519
  def testDoubleGLFails(self):
520
    self.assertRaises(AssertionError, locking.GanetiLockManager)
521

    
522
  def testLockNames(self):
523
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
524
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
525
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
526
                     set(self.instances))
527
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
528

    
529
  def testInitAndResources(self):
530
    locking.GanetiLockManager._instance = None
531
    self.GL = locking.GanetiLockManager()
532
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
533
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
534
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
535
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
536

    
537
    locking.GanetiLockManager._instance = None
538
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
539
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
540
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
541
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
542
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
543

    
544
    locking.GanetiLockManager._instance = None
545
    self.GL = locking.GanetiLockManager(instances=self.instances)
546
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
547
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
548
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
549
                     set(self.instances))
550
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
551

    
552
  def testAcquireRelease(self):
553
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
554
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
555
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
556
    self.GL.release(locking.LEVEL_NODE)
557
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
558
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
559
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
560
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
561
    self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
562
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
563
    self.GL.release(locking.LEVEL_NODE)
564
    self.GL.release(locking.LEVEL_INSTANCE)
565
    self.GL.release(locking.LEVEL_CONFIG)
566
    self.assertRaises(errors.LockError, self.GL.acquire,
567
                      locking.LEVEL_INSTANCE, ['i5'])
568
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
569
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
570

    
571
  def testBGLDependency(self):
572
    self.assertRaises(AssertionError, self.GL.acquire,
573
                      locking.LEVEL_NODE, ['n1', 'n2'])
574
    self.assertRaises(AssertionError, self.GL.acquire,
575
                      locking.LEVEL_INSTANCE, ['i3'])
576
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
577
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
578
    self.assertRaises(AssertionError, self.GL.release,
579
                      locking.LEVEL_CLUSTER, ['BGL'])
580
    self.assertRaises(AssertionError, self.GL.release,
581
                      locking.LEVEL_CLUSTER)
582
    self.GL.release(locking.LEVEL_NODE)
583
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
584
    self.assertRaises(AssertionError, self.GL.release,
585
                      locking.LEVEL_CLUSTER, ['BGL'])
586
    self.assertRaises(AssertionError, self.GL.release,
587
                      locking.LEVEL_CLUSTER)
588
    self.GL.release(locking.LEVEL_INSTANCE)
589
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
590
    self.assertRaises(AssertionError, self.GL.release,
591
                      locking.LEVEL_CLUSTER)
592

    
593
  def testWrongOrder(self):
594
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
595
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
596
    self.assertRaises(AssertionError, self.GL.acquire,
597
                      locking.LEVEL_NODE, ['n1'])
598
    self.assertRaises(AssertionError, self.GL.acquire,
599
                      locking.LEVEL_INSTANCE, ['i2'])
600
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
601
    self.assertRaises(AssertionError, self.GL.acquire,
602
                      locking.LEVEL_CONFIG, ['config'])
603
    self.GL.release(locking.LEVEL_INSTANCE)
604
    self.assertRaises(AssertionError, self.GL.acquire,
605
                      locking.LEVEL_NODE, ['n1'])
606
    self.assertRaises(AssertionError, self.GL.acquire,
607
                      locking.LEVEL_INSTANCE, ['i2'])
608
    self.assertRaises(AssertionError, self.GL.acquire,
609
                      locking.LEVEL_CONFIG, ['config'])
610

    
611
  # Helper function to run as a thread that shared the BGL and then acquires
612
  # some locks at another level.
613
  def _doLock(self, level, names, shared):
614
    try:
615
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
616
      self.GL.acquire(level, names, shared=shared)
617
      self.done.put('DONE')
618
      self.GL.release(level)
619
      self.GL.release(locking.LEVEL_CLUSTER)
620
    except errors.LockError:
621
      self.done.put('ERR')
622

    
623
  def testConcurrency(self):
624
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
625
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
626
    self.assertEqual(self.done.get(True, 1), 'DONE')
627
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
628
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
629
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
630
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
631
    self.assertEqual(self.done.get(True, 1), 'DONE')
632
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
633
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
634
    self.GL.release(locking.LEVEL_CONFIG)
635
    self.GL.release(locking.LEVEL_INSTANCE)
636
    self.assertEqual(self.done.get(True, 1), 'DONE')
637
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
638
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
639
    self.assertEqual(self.done.get(True, 1), 'DONE')
640
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
641
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
642
    self.GL.release(locking.LEVEL_INSTANCE)
643
    self.assertEqual(self.done.get(True, 1), 'DONE')
644

    
645

    
646
if __name__ == '__main__':
647
  unittest.main()
648
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
649
  #unittest.TextTestRunner(verbosity=2).run(suite)