Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 08a6c581

History | View | Annotate | Download (26.7 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 162c1c1f Guido Trotter
# Copyright (C) 2006, 2007 Google Inc.
5 162c1c1f Guido Trotter
#
6 162c1c1f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 162c1c1f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 162c1c1f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 162c1c1f Guido Trotter
# (at your option) any later version.
10 162c1c1f Guido Trotter
#
11 162c1c1f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 162c1c1f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 162c1c1f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 162c1c1f Guido Trotter
# General Public License for more details.
15 162c1c1f Guido Trotter
#
16 162c1c1f Guido Trotter
# You should have received a copy of the GNU General Public License
17 162c1c1f Guido Trotter
# along with this program; if not, write to the Free Software
18 162c1c1f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 162c1c1f Guido Trotter
# 0.0510-1301, USA.
20 162c1c1f Guido Trotter
21 162c1c1f Guido Trotter
22 162c1c1f Guido Trotter
"""Script for unittesting the locking module"""
23 162c1c1f Guido Trotter
24 162c1c1f Guido Trotter
25 162c1c1f Guido Trotter
import os
26 162c1c1f Guido Trotter
import unittest
27 162c1c1f Guido Trotter
import time
28 162c1c1f Guido Trotter
import Queue
29 162c1c1f Guido Trotter
30 162c1c1f Guido Trotter
from ganeti import locking
31 a95fd5d7 Guido Trotter
from ganeti import errors
32 162c1c1f Guido Trotter
from threading import Thread
33 162c1c1f Guido Trotter
34 162c1c1f Guido Trotter
35 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
36 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
37 42a999d1 Guido Trotter
_decoratorlock = locking.SharedLock()
38 42a999d1 Guido Trotter
39 42a999d1 Guido Trotter
40 162c1c1f Guido Trotter
class TestSharedLock(unittest.TestCase):
41 d6646186 Guido Trotter
  """SharedLock tests"""
42 162c1c1f Guido Trotter
43 162c1c1f Guido Trotter
  def setUp(self):
44 162c1c1f Guido Trotter
    self.sl = locking.SharedLock()
45 162c1c1f Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
46 162c1c1f Guido Trotter
    self.done = Queue.Queue(0)
47 162c1c1f Guido Trotter
48 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
49 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
50 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
51 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
52 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
53 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
54 162c1c1f Guido Trotter
    self.sl.release()
55 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
56 162c1c1f Guido Trotter
    self.sl.acquire()
57 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
58 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=1))
59 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
60 162c1c1f Guido Trotter
    self.sl.release()
61 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
62 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
63 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
64 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
65 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
66 162c1c1f Guido Trotter
    self.sl.release()
67 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
68 162c1c1f Guido Trotter
69 162c1c1f Guido Trotter
  def testBooleanValue(self):
70 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
71 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
72 162c1c1f Guido Trotter
    self.sl.release()
73 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
74 162c1c1f Guido Trotter
    self.sl.release()
75 162c1c1f Guido Trotter
76 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
77 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
78 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
79 162c1c1f Guido Trotter
80 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
81 162c1c1f Guido Trotter
    self.sl.acquire()
82 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
83 162c1c1f Guido Trotter
84 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
85 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
86 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
87 162c1c1f Guido Trotter
88 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
89 162c1c1f Guido Trotter
    self.sl.acquire()
90 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
91 162c1c1f Guido Trotter
92 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
93 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
94 162c1c1f Guido Trotter
  def _doItSharer(self):
95 a95fd5d7 Guido Trotter
    try:
96 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
97 a95fd5d7 Guido Trotter
      self.done.put('SHR')
98 a95fd5d7 Guido Trotter
      self.sl.release()
99 a95fd5d7 Guido Trotter
    except errors.LockError:
100 a95fd5d7 Guido Trotter
      self.done.put('ERR')
101 162c1c1f Guido Trotter
102 162c1c1f Guido Trotter
  def _doItExclusive(self):
103 a95fd5d7 Guido Trotter
    try:
104 a95fd5d7 Guido Trotter
      self.sl.acquire()
105 a95fd5d7 Guido Trotter
      self.done.put('EXC')
106 a95fd5d7 Guido Trotter
      self.sl.release()
107 a95fd5d7 Guido Trotter
    except errors.LockError:
108 a95fd5d7 Guido Trotter
      self.done.put('ERR')
109 a95fd5d7 Guido Trotter
110 a95fd5d7 Guido Trotter
  def _doItDelete(self):
111 a95fd5d7 Guido Trotter
    try:
112 4354ab03 Guido Trotter
      self.sl.delete()
113 a95fd5d7 Guido Trotter
      self.done.put('DEL')
114 a95fd5d7 Guido Trotter
    except errors.LockError:
115 a95fd5d7 Guido Trotter
      self.done.put('ERR')
116 162c1c1f Guido Trotter
117 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
118 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
119 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
120 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
121 162c1c1f Guido Trotter
    self.sl.release()
122 162c1c1f Guido Trotter
123 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
124 162c1c1f Guido Trotter
    self.sl.acquire()
125 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
126 162c1c1f Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
127 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
128 162c1c1f Guido Trotter
    self.sl.release()
129 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
130 162c1c1f Guido Trotter
131 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
132 a95fd5d7 Guido Trotter
    self.sl.acquire()
133 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
134 a95fd5d7 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
135 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
136 a95fd5d7 Guido Trotter
    self.sl.release()
137 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
138 a95fd5d7 Guido Trotter
139 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
140 162c1c1f Guido Trotter
    self.sl.acquire()
141 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
142 162c1c1f Guido Trotter
    time.sleep(0.05)
143 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
144 162c1c1f Guido Trotter
    self.sl.release()
145 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
146 162c1c1f Guido Trotter
147 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
148 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
149 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
150 162c1c1f Guido Trotter
    time.sleep(0.05)
151 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
152 162c1c1f Guido Trotter
    self.sl.release()
153 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
154 162c1c1f Guido Trotter
155 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
156 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
157 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
158 a95fd5d7 Guido Trotter
    time.sleep(0.05)
159 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
160 a95fd5d7 Guido Trotter
    self.sl.release()
161 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
162 a95fd5d7 Guido Trotter
163 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
164 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
165 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
166 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
167 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
168 162c1c1f Guido Trotter
    time.sleep(0.05)
169 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
170 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
171 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
172 162c1c1f Guido Trotter
    self.sl.release()
173 162c1c1f Guido Trotter
    # The exclusive passed before
174 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
175 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
176 162c1c1f Guido Trotter
177 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
178 162c1c1f Guido Trotter
    self.sl.acquire()
179 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
180 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
181 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
182 162c1c1f Guido Trotter
    time.sleep(0.05)
183 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
184 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
185 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
186 162c1c1f Guido Trotter
    self.sl.release()
187 162c1c1f Guido Trotter
    # The sharer passed before
188 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
189 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
190 162c1c1f Guido Trotter
191 a95fd5d7 Guido Trotter
  def testNoNonBlocking(self):
192 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
193 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
194 a95fd5d7 Guido Trotter
    self.sl.acquire()
195 a95fd5d7 Guido Trotter
    self.sl.delete(blocking=0) # Fine, because the lock is already acquired
196 a95fd5d7 Guido Trotter
197 a95fd5d7 Guido Trotter
  def testDelete(self):
198 a95fd5d7 Guido Trotter
    self.sl.delete()
199 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
200 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
201 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
202 a95fd5d7 Guido Trotter
203 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
204 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
205 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
206 84152b96 Guido Trotter
207 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
208 a95fd5d7 Guido Trotter
    self.sl.acquire()
209 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
210 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
211 a95fd5d7 Guido Trotter
    time.sleep(0.05)
212 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
213 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
214 a95fd5d7 Guido Trotter
    time.sleep(0.05)
215 a95fd5d7 Guido Trotter
    self.sl.delete()
216 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
217 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
218 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
219 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
220 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
221 a95fd5d7 Guido Trotter
222 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
223 a95fd5d7 Guido Trotter
    self.sl.acquire()
224 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
225 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
226 a95fd5d7 Guido Trotter
    time.sleep(0.05)
227 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
228 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
229 a95fd5d7 Guido Trotter
    time.sleep(0.05)
230 a95fd5d7 Guido Trotter
    self.sl.delete()
231 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
232 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
233 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
234 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
235 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
236 a95fd5d7 Guido Trotter
237 162c1c1f Guido Trotter
238 42a999d1 Guido Trotter
class TestSSynchronizedDecorator(unittest.TestCase):
239 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
240 42a999d1 Guido Trotter
241 42a999d1 Guido Trotter
  def setUp(self):
242 42a999d1 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
243 42a999d1 Guido Trotter
    self.done = Queue.Queue(0)
244 42a999d1 Guido Trotter
245 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
246 42a999d1 Guido Trotter
  def _doItExclusive(self):
247 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
248 42a999d1 Guido Trotter
    self.done.put('EXC')
249 42a999d1 Guido Trotter
250 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
251 42a999d1 Guido Trotter
  def _doItSharer(self):
252 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
253 42a999d1 Guido Trotter
    self.done.put('SHR')
254 42a999d1 Guido Trotter
255 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
256 42a999d1 Guido Trotter
    self._doItExclusive()
257 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
258 42a999d1 Guido Trotter
    self._doItSharer()
259 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
260 42a999d1 Guido Trotter
261 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
262 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
263 42a999d1 Guido Trotter
    Thread(target=self._doItSharer).start()
264 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
265 42a999d1 Guido Trotter
    _decoratorlock.release()
266 42a999d1 Guido Trotter
267 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
268 42a999d1 Guido Trotter
    _decoratorlock.acquire()
269 42a999d1 Guido Trotter
    Thread(target=self._doItExclusive).start()
270 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
271 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
272 42a999d1 Guido Trotter
    _decoratorlock.release()
273 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
274 42a999d1 Guido Trotter
275 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
276 42a999d1 Guido Trotter
    _decoratorlock.acquire()
277 42a999d1 Guido Trotter
    Thread(target=self._doItSharer).start()
278 42a999d1 Guido Trotter
    time.sleep(0.05)
279 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
280 42a999d1 Guido Trotter
    _decoratorlock.release()
281 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
282 42a999d1 Guido Trotter
283 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
284 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
285 42a999d1 Guido Trotter
    Thread(target=self._doItExclusive).start()
286 42a999d1 Guido Trotter
    time.sleep(0.05)
287 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
288 42a999d1 Guido Trotter
    _decoratorlock.release()
289 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
290 42a999d1 Guido Trotter
291 42a999d1 Guido Trotter
292 aaae9bc0 Guido Trotter
class TestLockSet(unittest.TestCase):
293 aaae9bc0 Guido Trotter
  """LockSet tests"""
294 aaae9bc0 Guido Trotter
295 aaae9bc0 Guido Trotter
  def setUp(self):
296 aaae9bc0 Guido Trotter
    self.resources = ['one', 'two', 'three']
297 cdb08f44 Michael Hanselmann
    self.ls = locking.LockSet(members=self.resources)
298 aaae9bc0 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
299 aaae9bc0 Guido Trotter
    self.done = Queue.Queue(0)
300 aaae9bc0 Guido Trotter
301 aaae9bc0 Guido Trotter
  def testResources(self):
302 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
303 aaae9bc0 Guido Trotter
    newls = locking.LockSet()
304 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
305 aaae9bc0 Guido Trotter
306 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
307 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
308 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
309 aaae9bc0 Guido Trotter
    self.ls.release()
310 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
311 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
312 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
313 aaae9bc0 Guido Trotter
    self.ls.release()
314 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
315 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
316 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
317 aaae9bc0 Guido Trotter
    self.ls.release('one')
318 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
319 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
320 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
321 aaae9bc0 Guido Trotter
    self.ls.release()
322 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
323 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
324 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
325 aaae9bc0 Guido Trotter
    self.ls.release()
326 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
327 aaae9bc0 Guido Trotter
328 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
329 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
330 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
331 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
332 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
333 aaae9bc0 Guido Trotter
    self.ls.release()
334 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
335 aaae9bc0 Guido Trotter
    self.ls.release('one')
336 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
337 aaae9bc0 Guido Trotter
    self.ls.release('three')
338 aaae9bc0 Guido Trotter
339 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
340 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
341 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
342 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
343 aaae9bc0 Guido Trotter
344 aaae9bc0 Guido Trotter
  def testAddRemove(self):
345 aaae9bc0 Guido Trotter
    self.ls.add('four')
346 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
347 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
348 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
349 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
350 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
351 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
352 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
353 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
354 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
355 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
356 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
357 aaae9bc0 Guido Trotter
    self.ls.add('eight', acquired=1, shared=1)
358 aaae9bc0 Guido Trotter
    self.assert_('eight' in self.ls._names())
359 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
360 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
361 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
362 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['eight']))
363 aaae9bc0 Guido Trotter
    self.ls.release()
364 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
365 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
366 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
367 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
368 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
369 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
370 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
371 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
372 aaae9bc0 Guido Trotter
373 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
374 aaae9bc0 Guido Trotter
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
375 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
376 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
377 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
378 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
379 3f404fc5 Guido Trotter
                      ['two', 'three'])
380 aaae9bc0 Guido Trotter
381 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
382 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
383 aaae9bc0 Guido Trotter
    self.ls.add('four')
384 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
385 aaae9bc0 Guido Trotter
386 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
387 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
388 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
389 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
390 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
391 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
392 aaae9bc0 Guido Trotter
393 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
394 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
395 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
396 3b7ed473 Guido Trotter
    # I can still add/remove elements...
397 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
398 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
399 3b7ed473 Guido Trotter
    self.ls.release()
400 3b7ed473 Guido Trotter
    # share the set-lock
401 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
402 3b7ed473 Guido Trotter
    # adding new elements is not possible
403 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
404 3b7ed473 Guido Trotter
    self.ls.release()
405 3b7ed473 Guido Trotter
406 aaae9bc0 Guido Trotter
  def _doLockSet(self, set, shared):
407 aaae9bc0 Guido Trotter
    try:
408 aaae9bc0 Guido Trotter
      self.ls.acquire(set, shared=shared)
409 aaae9bc0 Guido Trotter
      self.done.put('DONE')
410 aaae9bc0 Guido Trotter
      self.ls.release()
411 aaae9bc0 Guido Trotter
    except errors.LockError:
412 aaae9bc0 Guido Trotter
      self.done.put('ERR')
413 aaae9bc0 Guido Trotter
414 3b7ed473 Guido Trotter
  def _doAddSet(self, set):
415 3b7ed473 Guido Trotter
    try:
416 3b7ed473 Guido Trotter
      self.ls.add(set, acquired=1)
417 3b7ed473 Guido Trotter
      self.done.put('DONE')
418 3b7ed473 Guido Trotter
      self.ls.release()
419 3b7ed473 Guido Trotter
    except errors.LockError:
420 3b7ed473 Guido Trotter
      self.done.put('ERR')
421 3b7ed473 Guido Trotter
422 aaae9bc0 Guido Trotter
  def _doRemoveSet(self, set):
423 aaae9bc0 Guido Trotter
    self.done.put(self.ls.remove(set))
424 aaae9bc0 Guido Trotter
425 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
426 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
427 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
428 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
429 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
430 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
431 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
432 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
433 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
434 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
435 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
436 aaae9bc0 Guido Trotter
    self.ls.release()
437 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
438 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
439 aaae9bc0 Guido Trotter
440 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
441 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
442 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
443 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
444 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 0)).start()
445 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
446 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
447 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
448 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 0)).start()
449 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 1)).start()
450 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
451 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
452 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
453 aaae9bc0 Guido Trotter
    self.ls.release()
454 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
455 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
456 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
457 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
458 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
459 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
460 aaae9bc0 Guido Trotter
461 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
462 aaae9bc0 Guido Trotter
    self.ls.add('four')
463 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
464 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
465 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
466 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
467 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
468 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
469 aaae9bc0 Guido Trotter
    self.ls.remove('one')
470 aaae9bc0 Guido Trotter
    self.ls.release()
471 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
472 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
473 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
474 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
475 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
476 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
477 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
478 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
479 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
480 aaae9bc0 Guido Trotter
    self.ls.remove('five')
481 aaae9bc0 Guido Trotter
    self.ls.release()
482 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
483 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
484 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
485 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
486 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
487 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
488 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
489 aaae9bc0 Guido Trotter
    self.ls.remove('four')
490 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['six'])
491 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'])).start()
492 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
493 aaae9bc0 Guido Trotter
    self.ls.release()
494 aaae9bc0 Guido Trotter
495 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
496 3b7ed473 Guido Trotter
    # share the set-lock...
497 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
498 3b7ed473 Guido Trotter
    # ...another thread can share it too
499 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
500 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
501 3b7ed473 Guido Trotter
    # ...or just share some elements
502 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
503 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
504 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
505 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
506 3b7ed473 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'], )).start()
507 3b7ed473 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
508 3b7ed473 Guido Trotter
    # this just releases the set-lock
509 3b7ed473 Guido Trotter
    self.ls.release([])
510 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
511 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
512 3b7ed473 Guido Trotter
    self.ls.release()
513 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
514 3b7ed473 Guido Trotter
515 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
516 3b7ed473 Guido Trotter
    # acquire the set-lock...
517 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
518 3b7ed473 Guido Trotter
    # ...no one can do anything else
519 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
520 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
521 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['three'], 0)).start()
522 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['two'], 1)).start()
523 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
524 b5c0e9d9 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
525 3b7ed473 Guido Trotter
    self.ls.release()
526 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
527 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
528 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
529 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
530 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
531 3b7ed473 Guido Trotter
532 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
533 b2dabfd6 Guido Trotter
    # get the set-lock
534 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
535 b2dabfd6 Guido Trotter
    # now empty it...
536 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
537 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
538 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
539 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
540 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
541 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
542 b2dabfd6 Guido Trotter
    self.ls.release()
543 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
544 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
545 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
546 b2dabfd6 Guido Trotter
    # empty it again...
547 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
548 b2dabfd6 Guido Trotter
    # now share it...
549 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
550 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
551 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
552 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
553 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
554 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
555 b2dabfd6 Guido Trotter
    self.ls.release()
556 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
557 b2dabfd6 Guido Trotter
558 aaae9bc0 Guido Trotter
559 7ee7c0c7 Guido Trotter
class TestGanetiLockManager(unittest.TestCase):
560 7ee7c0c7 Guido Trotter
561 7ee7c0c7 Guido Trotter
  def setUp(self):
562 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
563 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
564 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
565 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
566 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
567 7ee7c0c7 Guido Trotter
568 7ee7c0c7 Guido Trotter
  def tearDown(self):
569 7ee7c0c7 Guido Trotter
    # Don't try this at home...
570 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
571 7ee7c0c7 Guido Trotter
572 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
573 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
574 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
575 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
576 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
577 7ee7c0c7 Guido Trotter
578 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
579 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
580 7ee7c0c7 Guido Trotter
581 7ee7c0c7 Guido Trotter
  def testLockNames(self):
582 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
583 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
584 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
585 cdb08f44 Michael Hanselmann
                     set(self.instances))
586 7ee7c0c7 Guido Trotter
587 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
588 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
589 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
590 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
591 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
592 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
593 7ee7c0c7 Guido Trotter
594 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
595 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
596 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
597 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
598 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
599 7ee7c0c7 Guido Trotter
600 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
601 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
602 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
603 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
604 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
605 cdb08f44 Michael Hanselmann
                     set(self.instances))
606 7ee7c0c7 Guido Trotter
607 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
608 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
609 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
610 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
611 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
612 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
613 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
614 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
615 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
616 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
617 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
618 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
619 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
620 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
621 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
622 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
623 7ee7c0c7 Guido Trotter
624 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
625 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
626 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
627 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
628 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
629 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
630 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
631 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
632 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
633 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
634 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
635 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
636 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
637 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
638 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
639 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
640 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
641 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
642 7ee7c0c7 Guido Trotter
643 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
644 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
645 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
646 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
647 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
648 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
649 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
650 7ee7c0c7 Guido Trotter
651 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
652 7ee7c0c7 Guido Trotter
  # some locks at another level.
653 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
654 7ee7c0c7 Guido Trotter
    try:
655 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
656 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
657 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
658 7ee7c0c7 Guido Trotter
      self.GL.release(level)
659 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
660 7ee7c0c7 Guido Trotter
    except errors.LockError:
661 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
662 7ee7c0c7 Guido Trotter
663 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
664 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
665 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
666 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
667 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
668 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
669 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
670 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
671 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
672 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
673 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
674 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
675 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
676 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
677 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
678 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
679 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
680 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
681 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
682 7ee7c0c7 Guido Trotter
683 7ee7c0c7 Guido Trotter
684 162c1c1f Guido Trotter
if __name__ == '__main__':
685 162c1c1f Guido Trotter
  unittest.main()
686 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
687 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)