summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Washenberger <mark.washenberger@rackspace.com>2011-03-09 22:04:29 -0500
committerMark Washenberger <mark.washenberger@rackspace.com>2011-03-09 22:04:29 -0500
commitf23924dfe23e9cd08656fa355957fadeee168c3f (patch)
tree603c52c3a2a67677e5a7a4ff815da15e76e96076
parent378e1d07c3a4318af2bf3375b0c98bc28da0d362 (diff)
parent84c769ce17822eac3788336cbae8f82f03f089cf (diff)
downloadnova-f23924dfe23e9cd08656fa355957fadeee168c3f.tar.gz
nova-f23924dfe23e9cd08656fa355957fadeee168c3f.tar.xz
nova-f23924dfe23e9cd08656fa355957fadeee168c3f.zip
merge lp:nova
-rw-r--r--nova/tests/test_virt.py67
-rw-r--r--nova/virt/libvirt_conn.py19
2 files changed, 81 insertions, 5 deletions
diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py
index dfa607f14..0625296a4 100644
--- a/nova/tests/test_virt.py
+++ b/nova/tests/test_virt.py
@@ -14,6 +14,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import os
+
+import eventlet
from xml.etree.ElementTree import fromstring as xml_to_tree
from xml.dom.minidom import parseString as xml_to_dom
@@ -30,6 +33,70 @@ FLAGS = flags.FLAGS
flags.DECLARE('instances_path', 'nova.compute.manager')
+def _concurrency(wait, done, target):
+ wait.wait()
+ done.send()
+
+
+class CacheConcurrencyTestCase(test.TestCase):
+ def setUp(self):
+ super(CacheConcurrencyTestCase, self).setUp()
+
+ def fake_exists(fname):
+ basedir = os.path.join(FLAGS.instances_path, '_base')
+ if fname == basedir:
+ return True
+ return False
+
+ def fake_execute(*args, **kwargs):
+ pass
+
+ self.stubs.Set(os.path, 'exists', fake_exists)
+ self.stubs.Set(utils, 'execute', fake_execute)
+
+ def test_same_fname_concurrency(self):
+ """Ensures that the same fname cache runs at a sequentially"""
+ conn = libvirt_conn.LibvirtConnection
+ wait1 = eventlet.event.Event()
+ done1 = eventlet.event.Event()
+ eventlet.spawn(conn._cache_image, _concurrency,
+ 'target', 'fname', False, wait1, done1)
+ wait2 = eventlet.event.Event()
+ done2 = eventlet.event.Event()
+ eventlet.spawn(conn._cache_image, _concurrency,
+ 'target', 'fname', False, wait2, done2)
+ wait2.send()
+ eventlet.sleep(0)
+ try:
+ self.assertFalse(done2.ready())
+ self.assertTrue('fname' in conn._image_sems)
+ finally:
+ wait1.send()
+ done1.wait()
+ eventlet.sleep(0)
+ self.assertTrue(done2.ready())
+ self.assertFalse('fname' in conn._image_sems)
+
+ def test_different_fname_concurrency(self):
+ """Ensures that two different fname caches are concurrent"""
+ conn = libvirt_conn.LibvirtConnection
+ wait1 = eventlet.event.Event()
+ done1 = eventlet.event.Event()
+ eventlet.spawn(conn._cache_image, _concurrency,
+ 'target', 'fname2', False, wait1, done1)
+ wait2 = eventlet.event.Event()
+ done2 = eventlet.event.Event()
+ eventlet.spawn(conn._cache_image, _concurrency,
+ 'target', 'fname1', False, wait2, done2)
+ wait2.send()
+ eventlet.sleep(0)
+ try:
+ self.assertTrue(done2.ready())
+ finally:
+ wait1.send()
+ eventlet.sleep(0)
+
+
class LibvirtConnTestCase(test.TestCase):
def setUp(self):
super(LibvirtConnTestCase, self).setUp()
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 6b555ecbb..f7ed164fd 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -44,9 +44,8 @@ import uuid
from xml.dom import minidom
-from eventlet import greenthread
-from eventlet import event
from eventlet import tpool
+from eventlet import semaphore
import IPy
@@ -515,7 +514,10 @@ class LibvirtConnection(object):
subprocess.Popen(cmd, shell=True)
return {'token': token, 'host': host, 'port': port}
- def _cache_image(self, fn, target, fname, cow=False, *args, **kwargs):
+ _image_sems = {}
+
+ @staticmethod
+ def _cache_image(fn, target, fname, cow=False, *args, **kwargs):
"""Wrapper for a method that creates an image that caches the image.
This wrapper will save the image into a common store and create a
@@ -534,8 +536,15 @@ class LibvirtConnection(object):
if not os.path.exists(base_dir):
os.mkdir(base_dir)
base = os.path.join(base_dir, fname)
- if not os.path.exists(base):
- fn(target=base, *args, **kwargs)
+
+ if fname not in LibvirtConnection._image_sems:
+ LibvirtConnection._image_sems[fname] = semaphore.Semaphore()
+ with LibvirtConnection._image_sems[fname]:
+ if not os.path.exists(base):
+ fn(target=base, *args, **kwargs)
+ if not LibvirtConnection._image_sems[fname].locked():
+ del LibvirtConnection._image_sems[fname]
+
if cow:
utils.execute('qemu-img', 'create', '-f', 'qcow2', '-o',
'cluster_size=2M,backing_file=%s' % base,