From e71081b856b06513cc1e56a9adb2a619967f0eae Mon Sep 17 00:00:00 2001 From: Rafi Khardalian Date: Thu, 13 Jun 2013 05:09:45 +0000 Subject: Fix resizes with attached file-based volumes Bug 1190364 get_instance_disk_info() now takes an additional, optional argument of block_device_info. When passed in, we use it to filter out volumes, such that they are not returned. Previously, any devices classified as "file" as parsed from the instance XML were considered local disks. This assumption is incorrect, since some volumes are simply files, rather than block devices. Added a new test, based almost entirely off the existing test case for this function, which represents an XML file with two fake file-based (NFS-like) volumes and associated block_device_info to claim those volumes. Change-Id: I4809a8fd68eb0f709347aa7cad0fa85389ade41c --- nova/virt/libvirt/driver.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 4544d35fb..4168e38c6 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 @@ -3540,7 +3541,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: @@ -3573,15 +3575,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) @@ -3592,6 +3606,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)) @@ -3700,7 +3719,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 -- cgit