summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2012-03-16 13:25:05 -0700
committerVishvananda Ishaya <vishvananda@gmail.com>2012-03-16 13:56:17 -0700
commiteb42e7fcd7bb67ab951c9bc6c80a78cd23011458 (patch)
treee6813969a63010220c32880c6b645fd2f4438563 /nova/tests
parent1ecf2c5b77d21015bbb4cc9edf7abf96355bb8e3 (diff)
Workaround issue with greenthreads and lockfiles
* Adds a GreenLockFile that always works in greenthreads * Adds test to verify that regular Lockfile is broken * Adds test to verify that GreenLockfile works * Adds note about limitation of external locks * Adds test showing limitation of nested locks * Fixes bug 956313 Change-Id: I11cd1206611aa4862dadd2fcc077c4c2e0f798f6
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/test_misc.py16
-rw-r--r--nova/tests/test_utils.py39
2 files changed, 55 insertions, 0 deletions
diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py
index 0baf38236..63c2773bf 100644
--- a/nova/tests/test_misc.py
+++ b/nova/tests/test_misc.py
@@ -22,6 +22,7 @@ import select
from eventlet import greenpool
from eventlet import greenthread
+import lockfile
from nova import exception
from nova import test
@@ -134,6 +135,21 @@ class LockTestCase(test.TestCase):
self.assertEqual(saved_sem_num, len(utils._semaphores),
"Semaphore leak detected")
+ def test_nested_external_fails(self):
+ """We can not nest external syncs"""
+
+ @utils.synchronized('testlock1', external=True)
+ def outer_lock():
+
+ @utils.synchronized('testlock2', external=True)
+ def inner_lock():
+ pass
+ inner_lock()
+ try:
+ self.assertRaises(lockfile.NotMyLock, outer_lock)
+ finally:
+ utils.cleanup_file_locks()
+
def test_synchronized_externally(self):
"""We can lock across multiple processes"""
rpipe1, wpipe1 = os.pipe()
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index f29da5466..501ff91d0 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -24,7 +24,10 @@ import shutil
import StringIO
import tempfile
+import eventlet
+from eventlet import greenpool
import iso8601
+import lockfile
import mox
import nova
@@ -832,6 +835,42 @@ class Iso8601TimeTest(test.TestCase):
self._instaneous(normed, 2012, 2, 13, 23, 53, 07, 0)
+class TestGreenLocks(test.TestCase):
+ def test_concurrent_green_lock_succeeds(self):
+ """Verify spawn_n greenthreads with two locks run concurrently.
+
+ This succeeds with spawn but fails with spawn_n because lockfile
+ gets the same thread id for both spawn_n threads. Our workaround
+ of using the GreenLockFile will work even if the issue is fixed.
+ """
+ self.completed = False
+ with utils.tempdir() as tmpdir:
+
+ def locka(wait):
+ a = utils.GreenLockFile(os.path.join(tmpdir, 'a'))
+ a.acquire()
+ wait.wait()
+ a.release()
+ self.completed = True
+
+ def lockb(wait):
+ b = utils.GreenLockFile(os.path.join(tmpdir, 'b'))
+ b.acquire()
+ wait.wait()
+ b.release()
+
+ wait1 = eventlet.event.Event()
+ wait2 = eventlet.event.Event()
+ pool = greenpool.GreenPool()
+ pool.spawn_n(locka, wait1)
+ pool.spawn_n(lockb, wait2)
+ wait2.send()
+ eventlet.sleep(0)
+ wait1.send()
+ pool.waitall()
+ self.assertTrue(self.completed)
+
+
class TestLockCleanup(test.TestCase):
"""unit tests for utils.cleanup_file_locks()"""