From bd1a8482c530376acc5fedbaa46477cc003766ce Mon Sep 17 00:00:00 2001 From: Eric Harney Date: Fri, 6 Sep 2013 23:26:46 -0400 Subject: [PATCH] Do not use qemu-img --backing-chain or --output=json Initial code for GlusterFS snapshot support in Havana used qemu-img arguments which are too new to run in many environments. Run qemu-img using only arguments which will exist on older platforms. Partial-Bug: #1224030 Change-Id: I5155dac492da67a951ede978c2c46a54c239eb04 --- cinder/tests/test_glusterfs.py | 47 ++++++++++++++++++++++++++-- cinder/volume/drivers/glusterfs.py | 49 ++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/cinder/tests/test_glusterfs.py b/cinder/tests/test_glusterfs.py index 0141c2501..70ed9ce8c 100644 --- a/cinder/tests/test_glusterfs.py +++ b/cinder/tests/test_glusterfs.py @@ -808,7 +808,6 @@ class GlusterFsDriverTestCase(test.TestCase): """ (mox, drv) = self._mox, self._driver - #volume = DumbVolume() volume = self._simple_volume() hashed = drv._get_hash_str(self.TEST_EXPORT1) @@ -873,7 +872,8 @@ class GlusterFsDriverTestCase(test.TestCase): 'backing-filename': volume_file}] drv.get_active_image_from_info(volume).AndReturn(snap_file_2) - drv._get_backing_chain_for_path(snap_path_2).AndReturn(snap_path_chain) + drv._get_backing_chain_for_path(volume, snap_path_2).\ + AndReturn(snap_path_chain) drv._read_info_file(info_path).AndReturn(info_file_dict) @@ -1375,3 +1375,46 @@ class GlusterFsDriverTestCase(test.TestCase): self.assertRaises(exception.GlusterfsException, drv.delete_snapshot, snap_ref) + + def test_get_backing_chain_for_path(self): + (mox, drv) = self._mox, self._driver + + glusterfs.CONF.glusterfs_mount_point_base = self.TEST_MNT_POINT_BASE + + volume = self._simple_volume() + vol_filename = volume['name'] + vol_filename_2 = volume['name'] + '.asdfjkl' + vol_filename_3 = volume['name'] + 'qwertyuiop' + hashed = drv._get_hash_str(self.TEST_EXPORT1) + vol_dir = '%s/%s' % (self.TEST_MNT_POINT_BASE, hashed) + vol_path = '%s/%s' % (vol_dir, vol_filename) + vol_path_2 = '%s/%s' % (vol_dir, vol_filename_2) + vol_path_3 = '%s/%s' % (vol_dir, vol_filename_3) + + mox.StubOutWithMock(drv, '_execute') + mox.StubOutWithMock(drv, '_local_volume_dir') + + qemu_img_output_base = """image: %s + file format: qcow2 + virtual size: 1.0G (1073741824 bytes) + disk size: 173K + """ + qemu_img_output = qemu_img_output_base + 'backing file: %s\n' + + qemu_img_output_1 = qemu_img_output % (vol_filename, vol_filename_2) + qemu_img_output_2 = qemu_img_output % (vol_filename_2, vol_filename_3) + qemu_img_output_3 = qemu_img_output_base % (vol_filename_3) + + drv._local_volume_dir(volume).AndReturn(vol_dir) + drv._execute('qemu-img', 'info', vol_path).\ + AndReturn((qemu_img_output_1, None)) + drv._local_volume_dir(volume).AndReturn(vol_dir) + drv._execute('qemu-img', 'info', vol_path_2).\ + AndReturn((qemu_img_output_2, None)) + drv._local_volume_dir(volume).AndReturn(vol_dir) + drv._execute('qemu-img', 'info', vol_path_3).\ + AndReturn((qemu_img_output_3, None)) + + mox.ReplayAll() + + drv._get_backing_chain_for_path(volume, vol_path) diff --git a/cinder/volume/drivers/glusterfs.py b/cinder/volume/drivers/glusterfs.py index 6f46d2f06..6384a25d8 100644 --- a/cinder/volume/drivers/glusterfs.py +++ b/cinder/volume/drivers/glusterfs.py @@ -603,7 +603,8 @@ class GlusterfsDriver(nfs.RemoteFsDriver): # exist, not | | exist, being |needs ptr update # used here) | | committed down)| if so) - backing_chain = self._get_backing_chain_for_path(active_file_path) + backing_chain = self._get_backing_chain_for_path( + snapshot['volume'], active_file_path) # This file is guaranteed to exist since we aren't operating on # the active file. higher_file = next((os.path.basename(f['filename']) @@ -781,19 +782,43 @@ class GlusterfsDriver(nfs.RemoteFsDriver): run_as_root=True) return self._get_file_format(out) - def _get_backing_chain_for_path(self, path): - """Returns dict containing backing-chain information.""" + def _get_backing_chain_for_path(self, volume, path): + """Returns list of dicts containing backing-chain information. - # TODO(eharney): these args aren't available on el6.4's qemu-img - # Need to rewrite - # --backing-chain added in qemu 1.3.0 - # --output=json added in qemu 1.5.0 + Includes 'filename', and 'backing-filename' for each + applicable entry. - (out, err) = self._execute('qemu-img', 'info', - '--backing-chain', - '--output=json', - path) - return json.loads(out) + Consider converting this to use --backing-chain and --output=json + when environment supports qemu-img 1.5.0. + + :param volume: volume reference + :param path: path to image file at top of chain + + """ + + output = [] + + (out, _err) = self._execute('qemu-img', 'info', path) + new_info = {} + new_info['filename'] = os.path.basename(path) + new_info['backing-filename'] = self._get_backing_file(out) + + output.append(new_info) + + while True: + filename = new_info['backing-filename'] + path = os.path.join(self._local_volume_dir(volume), filename) + (out, _err) = self._execute('qemu-img', 'info', path) + backing_filename = self._get_backing_file(out) + if backing_filename is None: + break + new_info = {} + new_info['filename'] = filename + new_info['backing-filename'] = backing_filename + + output.append(new_info) + + return output def _get_file_format(self, output): for line in output.split('\n'): -- 2.45.2