summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorRafi Khardalian <rafi@metacloud.com>2013-05-05 22:18:33 +0000
committerDan Smith <danms@us.ibm.com>2013-05-09 13:45:33 -0700
commit9290bddd9f270d8ea4fbd6d953a8634473979cd5 (patch)
tree5d404222788b0db82aaf1792e5c6efb05abacfa0 /nova
parent495c0355a1be90e11a698d6cbca0261155cee3d3 (diff)
Make resize/migrated shared storage aware
Fixes bug 1177247 Added some logic to check for whether or not we are on a shared filesystem and set shared_storage accordingly. We perform similar checks in other areas of the code, typically through RPC calls. However, all the resize/migrate code is slated to be refactored for Hava, so the idea was to keep this patch as minimally intrusive as possible. When shared_storage is true, we pass that on to the cleanup call so that it no longer executes an rm via SSH, which was ultimately destroying the original instance directory. Change-Id: Ie9decedd373c000211c171df64e1e96fe78e5081
Diffstat (limited to 'nova')
-rw-r--r--nova/tests/test_libvirt.py39
-rwxr-xr-xnova/virt/libvirt/driver.py37
2 files changed, 70 insertions, 6 deletions
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index edafd67c1..77c27f4c0 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -3734,6 +3734,38 @@ class LibvirtConnTestCase(test.TestCase):
conn.set_cache_mode(fake_conf)
self.assertEqual(fake_conf.driver_cache, 'fake')
+ def _test_shared_storage_detection(self, is_same):
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+ self.mox.StubOutWithMock(conn, 'get_host_ip_addr')
+ self.mox.StubOutWithMock(utils, 'execute')
+ self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(os, 'unlink')
+ conn.get_host_ip_addr().AndReturn('bar')
+ utils.execute('ssh', 'foo', 'touch', mox.IgnoreArg())
+ os.path.exists(mox.IgnoreArg()).AndReturn(is_same)
+ if is_same:
+ os.unlink(mox.IgnoreArg())
+ else:
+ utils.execute('ssh', 'foo', 'rm', mox.IgnoreArg())
+ self.mox.ReplayAll()
+ return conn._is_storage_shared_with('foo', '/path')
+
+ def test_shared_storage_detection_same_host(self):
+ self.assertTrue(self._test_shared_storage_detection(True))
+
+ def test_shared_storage_detection_different_host(self):
+ self.assertFalse(self._test_shared_storage_detection(False))
+
+ def test_shared_storage_detection_easy(self):
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+ self.mox.StubOutWithMock(conn, 'get_host_ip_addr')
+ self.mox.StubOutWithMock(utils, 'execute')
+ self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(os, 'unlink')
+ conn.get_host_ip_addr().AndReturn('foo')
+ self.mox.ReplayAll()
+ self.assertTrue(conn._is_storage_shared_with('foo', '/path'))
+
class HostStateTestCase(test.TestCase):
@@ -4753,6 +4785,7 @@ class LibvirtDriverTestCase(test.TestCase):
.migrate_disk_and_power_off. """
self.counter = 0
+ self.checked_shared_storage = False
def fake_get_instance_disk_info(instance, xml=None):
return '[]'
@@ -4771,11 +4804,17 @@ class LibvirtDriverTestCase(test.TestCase):
def fake_os_path_exists(path):
return True
+ def fake_is_storage_shared(dest, inst_base):
+ self.checked_shared_storage = True
+ return False
+
self.stubs.Set(self.libvirtconnection, 'get_instance_disk_info',
fake_get_instance_disk_info)
self.stubs.Set(self.libvirtconnection, '_destroy', fake_destroy)
self.stubs.Set(self.libvirtconnection, 'get_host_ip_addr',
fake_get_host_ip_addr)
+ self.stubs.Set(self.libvirtconnection, '_is_storage_shared_with',
+ fake_is_storage_shared)
self.stubs.Set(utils, 'execute', fake_execute)
self.stubs.Set(os.path, 'exists', fake_os_path_exists)
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 41c39db17..516c4eb63 100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -3450,16 +3450,39 @@ class LibvirtDriver(driver.ComputeDriver):
"""Manage the local cache of images."""
self.image_cache_manager.verify_base_images(context, all_instances)
- def _cleanup_remote_migration(self, dest, inst_base, inst_base_resize):
+ def _cleanup_remote_migration(self, dest, inst_base, inst_base_resize,
+ shared_storage=False):
"""Used only for cleanup in case migrate_disk_and_power_off fails."""
try:
if os.path.exists(inst_base_resize):
utils.execute('rm', '-rf', inst_base)
utils.execute('mv', inst_base_resize, inst_base)
- utils.execute('ssh', dest, 'rm', '-rf', inst_base)
+ if not shared_storage:
+ utils.execute('ssh', dest, 'rm', '-rf', inst_base)
except Exception:
pass
+ def _is_storage_shared_with(self, dest, inst_base):
+ # NOTE (rmk): There are two methods of determining whether we are
+ # on the same filesystem: the source and dest IP are the
+ # same, or we create a file on the dest system via SSH
+ # and check whether the source system can also see it.
+ shared_storage = (dest == self.get_host_ip_addr())
+ if not shared_storage:
+ tmp_file = uuid.uuid4().hex + '.tmp'
+ tmp_path = os.path.join(inst_base, tmp_file)
+
+ try:
+ utils.execute('ssh', dest, 'touch', tmp_path)
+ if os.path.exists(tmp_path):
+ shared_storage = True
+ os.unlink(tmp_path)
+ else:
+ utils.execute('ssh', dest, 'rm', tmp_path)
+ except Exception:
+ pass
+ return shared_storage
+
def migrate_disk_and_power_off(self, context, instance, dest,
instance_type, network_info,
block_device_info=None):
@@ -3482,12 +3505,13 @@ class LibvirtDriver(driver.ComputeDriver):
# copy disks to destination
# rename instance dir to +_resize at first for using
# shared storage for instance dir (eg. NFS).
- same_host = (dest == self.get_host_ip_addr())
inst_base = libvirt_utils.get_instance_path(instance)
inst_base_resize = inst_base + "_resize"
+
+ shared_storage = self._is_storage_shared_with(dest, inst_base)
try:
utils.execute('mv', inst_base, inst_base_resize)
- if same_host:
+ if shared_storage:
dest = None
utils.execute('mkdir', '-p', inst_base)
else:
@@ -3503,7 +3527,7 @@ class LibvirtDriver(driver.ComputeDriver):
utils.execute('qemu-img', 'convert', '-f', 'qcow2',
'-O', 'qcow2', from_path, tmp_path)
- if same_host:
+ if shared_storage:
utils.execute('mv', tmp_path, img_path)
else:
libvirt_utils.copy_image(tmp_path, img_path, host=dest)
@@ -3514,7 +3538,8 @@ class LibvirtDriver(driver.ComputeDriver):
except Exception:
with excutils.save_and_reraise_exception():
self._cleanup_remote_migration(dest, inst_base,
- inst_base_resize)
+ inst_base_resize,
+ shared_storage)
return disk_info_text