Migrate to fileutils and lockutils.
Migrate nova to using openstack-common's file and lock utilities. Resolves bug 1063230. Change-Id: I1a4c87856bc08cd33b61d7098ed856baa4583654
This commit is contained in:
@@ -91,9 +91,6 @@ core_opts = [
|
||||
cfg.StrOpt('state_path',
|
||||
default='$pybasedir',
|
||||
help="Top-level directory for maintaining nova's state"),
|
||||
cfg.StrOpt('lock_path',
|
||||
default='$pybasedir',
|
||||
help='Directory to use for lock files'),
|
||||
]
|
||||
|
||||
debug_opts = [
|
||||
|
@@ -18,6 +18,7 @@
|
||||
import os
|
||||
|
||||
from nova import flags
|
||||
from nova.openstack.common import fileutils
|
||||
from nova import test
|
||||
from nova.tests import fake_libvirt_utils
|
||||
from nova.virt.libvirt import imagebackend
|
||||
@@ -56,8 +57,8 @@ class _ImageTestCase(test.TestCase):
|
||||
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
|
||||
fn = self.mox.CreateMockAnything()
|
||||
fn(target=self.TEMPLATE_PATH)
|
||||
self.mox.StubOutWithMock(imagebackend.utils, 'ensure_tree')
|
||||
imagebackend.utils.ensure_tree(self.TEMPLATE_DIR)
|
||||
self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree')
|
||||
imagebackend.fileutils.ensure_tree(self.TEMPLATE_DIR)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
@@ -83,7 +84,7 @@ class _ImageTestCase(test.TestCase):
|
||||
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
|
||||
fn = self.mox.CreateMockAnything()
|
||||
fn(target=self.TEMPLATE_PATH)
|
||||
self.mox.StubOutWithMock(imagebackend.utils, 'ensure_tree')
|
||||
self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree')
|
||||
self.mox.ReplayAll()
|
||||
|
||||
image = self.image_class(self.INSTANCE, self.NAME)
|
||||
@@ -117,7 +118,8 @@ class RawTestCase(_ImageTestCase):
|
||||
|
||||
def prepare_mocks(self):
|
||||
fn = self.mox.CreateMockAnything()
|
||||
self.mox.StubOutWithMock(imagebackend.utils.synchronized, '__call__')
|
||||
self.mox.StubOutWithMock(imagebackend.lockutils.synchronized,
|
||||
'__call__')
|
||||
self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image')
|
||||
self.mox.StubOutWithMock(imagebackend.disk, 'extend')
|
||||
return fn
|
||||
@@ -167,7 +169,8 @@ class Qcow2TestCase(_ImageTestCase):
|
||||
|
||||
def prepare_mocks(self):
|
||||
fn = self.mox.CreateMockAnything()
|
||||
self.mox.StubOutWithMock(imagebackend.utils.synchronized, '__call__')
|
||||
self.mox.StubOutWithMock(imagebackend.lockutils.synchronized,
|
||||
'__call__')
|
||||
self.mox.StubOutWithMock(imagebackend.libvirt_utils,
|
||||
'create_cow_image')
|
||||
self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image')
|
||||
|
@@ -37,6 +37,7 @@ from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova.openstack.common import fileutils
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.openstack.common import log as logging
|
||||
@@ -448,7 +449,7 @@ class CacheConcurrencyTestCase(test.TestCase):
|
||||
# use for tests. So, create the path here so utils.synchronized()
|
||||
# won't delete it out from under one of the threads.
|
||||
self.lock_path = os.path.join(FLAGS.instances_path, 'locks')
|
||||
utils.ensure_tree(self.lock_path)
|
||||
fileutils.ensure_tree(self.lock_path)
|
||||
|
||||
def fake_exists(fname):
|
||||
basedir = os.path.join(FLAGS.instances_path, FLAGS.base_dir_name)
|
||||
|
@@ -24,7 +24,6 @@ from eventlet import greenthread
|
||||
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from nova import utils
|
||||
|
||||
|
||||
class ExceptionTestCase(test.TestCase):
|
||||
@@ -63,96 +62,3 @@ class ProjectTestCase(test.TestCase):
|
||||
helpful_msg = (_("The following migrations are missing a downgrade:"
|
||||
"\n\t%s") % '\n\t'.join(sorted(missing_downgrade)))
|
||||
self.assert_(not missing_downgrade, helpful_msg)
|
||||
|
||||
|
||||
class LockTestCase(test.TestCase):
|
||||
def test_synchronized_wrapped_function_metadata(self):
|
||||
@utils.synchronized('whatever')
|
||||
def foo():
|
||||
"""Bar"""
|
||||
pass
|
||||
self.assertEquals(foo.__doc__, 'Bar', "Wrapped function's docstring "
|
||||
"got lost")
|
||||
self.assertEquals(foo.__name__, 'foo', "Wrapped function's name "
|
||||
"got mangled")
|
||||
|
||||
def test_synchronized_internally(self):
|
||||
"""We can lock across multiple green threads"""
|
||||
saved_sem_num = len(utils._semaphores)
|
||||
seen_threads = list()
|
||||
|
||||
@utils.synchronized('testlock2', external=False)
|
||||
def f(id):
|
||||
for x in range(10):
|
||||
seen_threads.append(id)
|
||||
greenthread.sleep(0)
|
||||
|
||||
threads = []
|
||||
pool = greenpool.GreenPool(10)
|
||||
for i in range(10):
|
||||
threads.append(pool.spawn(f, i))
|
||||
|
||||
for thread in threads:
|
||||
thread.wait()
|
||||
|
||||
self.assertEquals(len(seen_threads), 100)
|
||||
# Looking at the seen threads, split it into chunks of 10, and verify
|
||||
# that the last 9 match the first in each chunk.
|
||||
for i in range(10):
|
||||
for j in range(9):
|
||||
self.assertEquals(seen_threads[i * 10],
|
||||
seen_threads[i * 10 + 1 + j])
|
||||
|
||||
self.assertEqual(saved_sem_num, len(utils._semaphores),
|
||||
"Semaphore leak detected")
|
||||
|
||||
def test_nested_external_works(self):
|
||||
"""We can nest external syncs"""
|
||||
with utils.tempdir() as tempdir:
|
||||
self.flags(lock_path=tempdir)
|
||||
sentinel = object()
|
||||
|
||||
@utils.synchronized('testlock1', external=True)
|
||||
def outer_lock():
|
||||
|
||||
@utils.synchronized('testlock2', external=True)
|
||||
def inner_lock():
|
||||
return sentinel
|
||||
return inner_lock()
|
||||
|
||||
self.assertEqual(sentinel, outer_lock())
|
||||
|
||||
def test_synchronized_externally(self):
|
||||
"""We can lock across multiple processes"""
|
||||
with utils.tempdir() as tempdir:
|
||||
self.flags(lock_path=tempdir)
|
||||
rpipe1, wpipe1 = os.pipe()
|
||||
rpipe2, wpipe2 = os.pipe()
|
||||
|
||||
@utils.synchronized('testlock1', external=True)
|
||||
def f(rpipe, wpipe):
|
||||
try:
|
||||
os.write(wpipe, "foo")
|
||||
except OSError, e:
|
||||
self.assertEquals(e.errno, errno.EPIPE)
|
||||
return
|
||||
|
||||
rfds, _wfds, _efds = select.select([rpipe], [], [], 1)
|
||||
self.assertEquals(len(rfds), 0, "The other process, which was"
|
||||
" supposed to be locked, "
|
||||
"wrote on its end of the "
|
||||
"pipe")
|
||||
os.close(rpipe)
|
||||
|
||||
pid = os.fork()
|
||||
if pid > 0:
|
||||
os.close(wpipe1)
|
||||
os.close(rpipe2)
|
||||
|
||||
f(rpipe1, wpipe2)
|
||||
else:
|
||||
os.close(rpipe1)
|
||||
os.close(wpipe2)
|
||||
|
||||
f(rpipe2, wpipe1)
|
||||
os._exit(0)
|
||||
|
Reference in New Issue
Block a user