summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-02-25 01:24:23 +0000
committerGerrit Code Review <review@openstack.org>2012-02-25 01:24:23 +0000
commitb02cefe64631d51cebdfb5e3a83d22cdfea3b767 (patch)
tree89c21761bde7957380500cd6696e1f3630422041 /nova/tests
parentf7140d66c9a476a8d38fc428d4d011356cb87823 (diff)
parent2fbccc0c693193533284330325f5803c8c6ce52a (diff)
downloadnova-b02cefe64631d51cebdfb5e3a83d22cdfea3b767.tar.gz
nova-b02cefe64631d51cebdfb5e3a83d22cdfea3b767.tar.xz
nova-b02cefe64631d51cebdfb5e3a83d22cdfea3b767.zip
Merge "Clean stale lockfiles on service startup : fixes bug 785955"
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/test_utils.py149
1 files changed, 149 insertions, 0 deletions
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index 93146876e..843b48dd3 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -18,6 +18,8 @@ import __builtin__
import datetime
import hashlib
import os
+import os.path
+import socket
import StringIO
import tempfile
@@ -811,3 +813,150 @@ class Iso8601TimeTest(test.TestCase):
west = utils.parse_isotime(str)
normed = utils.normalize_time(west)
self._instaneous(normed, 2012, 2, 13, 23, 53, 07, 0)
+
+
+class TestLockCleanup(test.TestCase):
+ """unit tests for utils.cleanup_file_locks()"""
+
+ def setUp(self):
+ super(TestLockCleanup, self).setUp()
+
+ self.pid = os.getpid()
+ self.dead_pid = self._get_dead_pid()
+ self.lock_name = 'nova-testlock'
+ self.lock_file = os.path.join(FLAGS.lock_path,
+ self.lock_name + '.lock')
+ self.hostname = socket.gethostname()
+ print self.pid, self.dead_pid
+ try:
+ os.unlink(self.lock_file)
+ except OSError as (errno, strerror):
+ if errno == 2:
+ pass
+
+ def _get_dead_pid(self):
+ """get a pid for a process that does not exist"""
+
+ candidate_pid = self.pid - 1
+ while os.path.exists(os.path.join('/proc', str(candidate_pid))):
+ candidate_pid -= 1
+ if candidate_pid == 1:
+ return 0
+ return candidate_pid
+
+ def _get_sentinel_name(self, hostname, pid, thread='MainThread'):
+ return os.path.join(FLAGS.lock_path,
+ '%s.%s-%d' % (hostname, thread, pid))
+
+ def _create_sentinel(self, hostname, pid, thread='MainThread'):
+ name = self._get_sentinel_name(hostname, pid, thread)
+ open(name, 'wb').close()
+ return name
+
+ def test_clean_stale_locks(self):
+ """verify locks for dead processes are cleaned up"""
+
+ # create sentinels for two processes, us and a 'dead' one
+ # no actve lock
+ sentinel1 = self._create_sentinel(self.hostname, self.pid)
+ sentinel2 = self._create_sentinel(self.hostname, self.dead_pid)
+
+ utils.cleanup_file_locks()
+
+ self.assertTrue(os.path.exists(sentinel1))
+ self.assertFalse(os.path.exists(self.lock_file))
+ self.assertFalse(os.path.exists(sentinel2))
+
+ os.unlink(sentinel1)
+
+ def test_clean_stale_locks_active(self):
+ """verify locks for dead processes are cleaned with an active lock """
+
+ # create sentinels for two processes, us and a 'dead' one
+ # create an active lock for us
+ sentinel1 = self._create_sentinel(self.hostname, self.pid)
+ sentinel2 = self._create_sentinel(self.hostname, self.dead_pid)
+ os.link(sentinel1, self.lock_file)
+
+ utils.cleanup_file_locks()
+
+ self.assertTrue(os.path.exists(sentinel1))
+ self.assertTrue(os.path.exists(self.lock_file))
+ self.assertFalse(os.path.exists(sentinel2))
+
+ os.unlink(sentinel1)
+ os.unlink(self.lock_file)
+
+ def test_clean_stale_with_threads(self):
+ """verify locks for multiple threads are cleaned up """
+
+ # create sentinels for four threads in our process, and a 'dead'
+ # process. no lock.
+ sentinel1 = self._create_sentinel(self.hostname, self.pid, 'Default-1')
+ sentinel2 = self._create_sentinel(self.hostname, self.pid, 'Default-2')
+ sentinel3 = self._create_sentinel(self.hostname, self.pid, 'Default-3')
+ sentinel4 = self._create_sentinel(self.hostname, self.pid, 'Default-4')
+ sentinel5 = self._create_sentinel(self.hostname, self.dead_pid,
+ 'Default-1')
+
+ utils.cleanup_file_locks()
+
+ self.assertTrue(os.path.exists(sentinel1))
+ self.assertTrue(os.path.exists(sentinel2))
+ self.assertTrue(os.path.exists(sentinel3))
+ self.assertTrue(os.path.exists(sentinel4))
+ self.assertFalse(os.path.exists(self.lock_file))
+ self.assertFalse(os.path.exists(sentinel5))
+
+ os.unlink(sentinel1)
+ os.unlink(sentinel2)
+ os.unlink(sentinel3)
+ os.unlink(sentinel4)
+
+ def test_clean_stale_with_threads_active(self):
+ """verify locks for multiple threads are cleaned up """
+
+ # create sentinels for four threads in our process, and a 'dead'
+ # process
+ sentinel1 = self._create_sentinel(self.hostname, self.pid, 'Default-1')
+ sentinel2 = self._create_sentinel(self.hostname, self.pid, 'Default-2')
+ sentinel3 = self._create_sentinel(self.hostname, self.pid, 'Default-3')
+ sentinel4 = self._create_sentinel(self.hostname, self.pid, 'Default-4')
+ sentinel5 = self._create_sentinel(self.hostname, self.dead_pid,
+ 'Default-1')
+
+ os.link(sentinel1, self.lock_file)
+
+ utils.cleanup_file_locks()
+
+ self.assertTrue(os.path.exists(sentinel1))
+ self.assertTrue(os.path.exists(sentinel2))
+ self.assertTrue(os.path.exists(sentinel3))
+ self.assertTrue(os.path.exists(sentinel4))
+ self.assertTrue(os.path.exists(self.lock_file))
+ self.assertFalse(os.path.exists(sentinel5))
+
+ os.unlink(sentinel1)
+ os.unlink(sentinel2)
+ os.unlink(sentinel3)
+ os.unlink(sentinel4)
+ os.unlink(self.lock_file)
+
+ def test_clean_bogus_lockfiles(self):
+ """verify lockfiles are cleaned """
+
+ lock1 = os.path.join(FLAGS.lock_path, 'nova-testlock1.lock')
+ lock2 = os.path.join(FLAGS.lock_path, 'nova-testlock2.lock')
+ lock3 = os.path.join(FLAGS.lock_path, 'testlock3.lock')
+
+ open(lock1, 'wb').close()
+ open(lock2, 'wb').close()
+ open(lock3, 'wb').close()
+
+ utils.cleanup_file_locks()
+
+ self.assertFalse(os.path.exists(lock1))
+ self.assertFalse(os.path.exists(lock2))
+ self.assertTrue(os.path.exists(lock3))
+
+ os.unlink(lock3)