summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-06-27 23:58:36 +0000
committerGerrit Code Review <review@openstack.org>2013-06-27 23:58:36 +0000
commit368efa77959cf7c5167045a491887f68d28f2d4e (patch)
treebed5c942f2a16552f285645b7e733387d3d4af8b
parent8dc7ff69f24c643167c9e961dd301d7b08291be8 (diff)
parente71081b856b06513cc1e56a9adb2a619967f0eae (diff)
downloadnova-368efa77959cf7c5167045a491887f68d28f2d4e.tar.gz
nova-368efa77959cf7c5167045a491887f68d28f2d4e.tar.xz
nova-368efa77959cf7c5167045a491887f68d28f2d4e.zip
Merge "Fix resizes with attached file-based volumes"
-rw-r--r--nova/tests/virt/libvirt/test_libvirt.py80
-rw-r--r--nova/tests/virt/test_virt_drivers.py3
-rwxr-xr-xnova/virt/libvirt/driver.py26
3 files changed, 103 insertions, 6 deletions
diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
index 308030f9f..5636e1706 100644
--- a/nova/tests/virt/libvirt/test_libvirt.py
+++ b/nova/tests/virt/libvirt/test_libvirt.py
@@ -2691,6 +2691,80 @@ class LibvirtConnTestCase(test.TestCase):
db.instance_destroy(self.context, instance_ref['uuid'])
+ def test_get_instance_disk_info_excludes_volumes(self):
+ # Test data
+ instance_ref = db.instance_create(self.context, self.test_instance)
+ dummyxml = ("<domain type='kvm'><name>instance-0000000a</name>"
+ "<devices>"
+ "<disk type='file'><driver name='qemu' type='raw'/>"
+ "<source file='/test/disk'/>"
+ "<target dev='vda' bus='virtio'/></disk>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/test/disk.local'/>"
+ "<target dev='vdb' bus='virtio'/></disk>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/fake/path/to/volume1'/>"
+ "<target dev='vdc' bus='virtio'/></disk>"
+ "<disk type='file'><driver name='qemu' type='qcow2'/>"
+ "<source file='/fake/path/to/volume2'/>"
+ "<target dev='vdd' bus='virtio'/></disk>"
+ "</devices></domain>")
+
+ # Preparing mocks
+ vdmock = self.mox.CreateMock(libvirt.virDomain)
+ self.mox.StubOutWithMock(vdmock, "XMLDesc")
+ vdmock.XMLDesc(0).AndReturn(dummyxml)
+
+ def fake_lookup(instance_name):
+ if instance_name == instance_ref['name']:
+ return vdmock
+ self.create_fake_libvirt_mock(lookupByName=fake_lookup)
+
+ GB = 1024 * 1024 * 1024
+ fake_libvirt_utils.disk_sizes['/test/disk'] = 10 * GB
+ fake_libvirt_utils.disk_sizes['/test/disk.local'] = 20 * GB
+ fake_libvirt_utils.disk_backing_files['/test/disk.local'] = 'file'
+
+ self.mox.StubOutWithMock(os.path, "getsize")
+ os.path.getsize('/test/disk').AndReturn((10737418240))
+ os.path.getsize('/test/disk.local').AndReturn((3328599655))
+
+ ret = ("image: /test/disk\n"
+ "file format: raw\n"
+ "virtual size: 20G (21474836480 bytes)\n"
+ "disk size: 3.1G\n"
+ "cluster_size: 2097152\n"
+ "backing file: /test/dummy (actual path: /backing/file)\n")
+
+ self.mox.StubOutWithMock(os.path, "exists")
+ os.path.exists('/test/disk.local').AndReturn(True)
+
+ self.mox.StubOutWithMock(utils, "execute")
+ utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+ '/test/disk.local').AndReturn((ret, ''))
+
+ self.mox.ReplayAll()
+ conn_info = {'driver_volume_type': 'fake'}
+ info = {'block_device_mapping': [
+ {'connection_info': conn_info, 'mount_device': '/dev/vdc'},
+ {'connection_info': conn_info, 'mount_device': '/dev/vdd'}]}
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ info = conn.get_instance_disk_info(instance_ref['name'],
+ block_device_info=info)
+ info = jsonutils.loads(info)
+ self.assertEquals(info[0]['type'], 'raw')
+ self.assertEquals(info[0]['path'], '/test/disk')
+ self.assertEquals(info[0]['disk_size'], 10737418240)
+ self.assertEquals(info[0]['backing_file'], "")
+ self.assertEquals(info[0]['over_committed_disk_size'], 0)
+ self.assertEquals(info[1]['type'], 'qcow2')
+ self.assertEquals(info[1]['path'], '/test/disk.local')
+ self.assertEquals(info[1]['virt_disk_size'], 21474836480)
+ self.assertEquals(info[1]['backing_file'], "file")
+ self.assertEquals(info[1]['over_committed_disk_size'], 18146236825)
+
+ db.instance_destroy(self.context, instance_ref['uuid'])
+
def test_spawn_with_network_info(self):
# Preparing mocks
def fake_none(*args, **kwargs):
@@ -5136,7 +5210,8 @@ class LibvirtDriverTestCase(test.TestCase):
self.counter = 0
self.checked_shared_storage = False
- def fake_get_instance_disk_info(instance, xml=None):
+ def fake_get_instance_disk_info(instance, xml=None,
+ block_device_info=None):
return '[]'
def fake_destroy(instance):
@@ -5188,7 +5263,8 @@ class LibvirtDriverTestCase(test.TestCase):
'disk_size': '83886080'}]
disk_info_text = jsonutils.dumps(disk_info)
- def fake_get_instance_disk_info(instance, xml=None):
+ def fake_get_instance_disk_info(instance, xml=None,
+ block_device_info=None):
return disk_info_text
def fake_destroy(instance):
diff --git a/nova/tests/virt/test_virt_drivers.py b/nova/tests/virt/test_virt_drivers.py
index a21993597..6cc9bef43 100644
--- a/nova/tests/virt/test_virt_drivers.py
+++ b/nova/tests/virt/test_virt_drivers.py
@@ -106,7 +106,8 @@ class _FakeDriverBackendTestCase(object):
def fake_make_drive(_self, _path):
pass
- def fake_get_instance_disk_info(_self, instance, xml=None):
+ def fake_get_instance_disk_info(_self, instance, xml=None,
+ block_device_info=None):
return '[]'
self.stubs.Set(nova.virt.libvirt.driver.LibvirtDriver,
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index ca673579b..f20a27900 100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -1434,7 +1434,8 @@ class LibvirtDriver(driver.ComputeDriver):
write_to_disk=True)
# NOTE (rmk): Re-populate any missing backing files.
- disk_info_json = self.get_instance_disk_info(instance['name'], xml)
+ disk_info_json = self.get_instance_disk_info(instance['name'], xml,
+ block_device_info)
self._create_images_and_backing(context, instance, disk_info_json)
# Initialize all the necessary networking, block devices and
@@ -3539,7 +3540,8 @@ class LibvirtDriver(driver.ComputeDriver):
dom = self._lookup_by_name(instance["name"])
self._conn.defineXML(dom.XMLDesc(0))
- def get_instance_disk_info(self, instance_name, xml=None):
+ def get_instance_disk_info(self, instance_name, xml=None,
+ block_device_info=None):
"""Preparation block migration.
:params instance:
@@ -3572,15 +3574,27 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.warn(msg)
raise exception.InstanceNotFound(instance_id=instance_name)
+ # NOTE (rmk): When block_device_info is provided, we will use it to
+ # filter out devices which are actually volumes.
+ block_device_mapping = driver.block_device_info_get_mapping(
+ block_device_info)
+
+ volume_devices = set()
+ for vol in block_device_mapping:
+ disk_dev = vol['mount_device'].rpartition("/")[2]
+ volume_devices.add(disk_dev)
+
disk_info = []
doc = etree.fromstring(xml)
disk_nodes = doc.findall('.//devices/disk')
path_nodes = doc.findall('.//devices/disk/source')
driver_nodes = doc.findall('.//devices/disk/driver')
+ target_nodes = doc.findall('.//devices/disk/target')
for cnt, path_node in enumerate(path_nodes):
disk_type = disk_nodes[cnt].get('type')
path = path_node.get('file')
+ target = target_nodes[cnt].attrib['dev']
if disk_type != 'file':
LOG.debug(_('skipping %s since it looks like volume'), path)
@@ -3591,6 +3605,11 @@ class LibvirtDriver(driver.ComputeDriver):
instance_name)
continue
+ if target in volume_devices:
+ LOG.debug(_('skipping disk %(path)s (%(target)s) as it is a '
+ 'volume'), {'path': path, 'target': target})
+ continue
+
# get the real disk size or
# raise a localized error if image is unavailable
dk_size = int(os.path.getsize(path))
@@ -3699,7 +3718,8 @@ class LibvirtDriver(driver.ComputeDriver):
block_device_info=None):
LOG.debug(_("Starting migrate_disk_and_power_off"),
instance=instance)
- disk_info_text = self.get_instance_disk_info(instance['name'])
+ disk_info_text = self.get_instance_disk_info(instance['name'],
+ block_device_info=block_device_info)
disk_info = jsonutils.loads(disk_info_text)
# copy disks to destination