From 186221779a92002ff9fa13c254710c0abb3803be Mon Sep 17 00:00:00 2001 From: Eric Harney Date: Wed, 18 Dec 2013 19:11:44 -0500 Subject: [PATCH] GlusterFS: Use correct base argument when deleting attached snaps When deleting the most recent snapshot, the 'file_to_merge' field which translates into the base= field for libvirt's blockRebase call in Nova must be set depending on whether other snapshots exist. If there are no other snapshots, base = None, which results in libvirt clearing the qcow2 backing file pointer for the active disk image. If there are other snapshots, pass the parent of the file being deleted as the new base file. The snapshot info pointer for the prior base file must also be updated in this case. Closes-Bug: #1262880 Change-Id: If7bc8259b031d0406346caafb8f688e65a38dba6 --- cinder/tests/test_glusterfs.py | 25 ++++++++++++++++++++++--- cinder/volume/drivers/glusterfs.py | 18 ++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cinder/tests/test_glusterfs.py b/cinder/tests/test_glusterfs.py index 23874a9b4cd..69a616e0921 100644 --- a/cinder/tests/test_glusterfs.py +++ b/cinder/tests/test_glusterfs.py @@ -1175,7 +1175,7 @@ class GlusterFsDriverTestCase(test.TestCase): snap_ref) def test_delete_snapshot_online_1(self): - """Delete the newest snapshot.""" + """Delete the newest snapshot, with only one snap present.""" (mox, drv) = self._mox, self._driver volume = self._simple_volume() @@ -1226,15 +1226,25 @@ class GlusterFsDriverTestCase(test.TestCase): backing file: %s """ % (snap_file, volume_file) img_info = imageutils.QemuImgInfo(qemu_img_info_output) + + vol_qemu_img_info_output = """image: %s + file format: raw + virtual size: 1.0G (1073741824 bytes) + disk size: 173K + """ % volume_file + volume_img_info = imageutils.QemuImgInfo(vol_qemu_img_info_output) + image_utils.qemu_img_info(snap_path).AndReturn(img_info) + image_utils.qemu_img_info(volume_path).AndReturn(volume_img_info) + drv._read_info_file(info_path, empty_if_missing=True).\ AndReturn(snap_info) delete_info = { 'type': 'qcow2', 'merge_target_file': None, - 'file_to_merge': volume_file, + 'file_to_merge': None, 'volume_id': self.VOLUME_UUID } @@ -1265,7 +1275,7 @@ class GlusterFsDriverTestCase(test.TestCase): drv.delete_snapshot(snap_ref) def test_delete_snapshot_online_2(self): - """Delete the middle snapshot.""" + """Delete the middle of 3 snapshots.""" (mox, drv) = self._mox, self._driver volume = self._simple_volume() @@ -1320,8 +1330,17 @@ class GlusterFsDriverTestCase(test.TestCase): """ % (snap_file, volume_file) img_info = imageutils.QemuImgInfo(qemu_img_info_output) + vol_qemu_img_info_output = """image: %s + file format: raw + virtual size: 1.0G (1073741824 bytes) + disk size: 173K + """ % volume_file + volume_img_info = imageutils.QemuImgInfo(vol_qemu_img_info_output) + image_utils.qemu_img_info(snap_path).AndReturn(img_info) + image_utils.qemu_img_info(volume_path).AndReturn(volume_img_info) + drv._read_info_file(info_path, empty_if_missing=True).\ AndReturn(snap_info) diff --git a/cinder/volume/drivers/glusterfs.py b/cinder/volume/drivers/glusterfs.py index 9279692169c..a7d27621197 100644 --- a/cinder/volume/drivers/glusterfs.py +++ b/cinder/volume/drivers/glusterfs.py @@ -596,6 +596,12 @@ class GlusterfsDriver(nfs.RemoteFsDriver): # file as base. msg = _('No base file found for %s.') % snapshot_path raise exception.GlusterfsException(msg) + + base_path = os.path.join( + self._local_volume_dir(snapshot['volume']), base_file) + base_file_img_info = self._qemu_img_info(base_path) + new_base_file = base_file_img_info.backing_file + base_id = None info_path = self._local_path_volume(snapshot['volume']) + '.info' snap_info = self._read_info_file(info_path) @@ -614,7 +620,8 @@ class GlusterfsDriver(nfs.RemoteFsDriver): 'active_file': active_file, 'snapshot_file': snapshot_file, 'base_file': base_file, - 'base_id': base_id + 'base_id': base_id, + 'new_base_file': new_base_file } return self._delete_snapshot_online(context, @@ -724,8 +731,15 @@ class GlusterfsDriver(nfs.RemoteFsDriver): # info['base'] => snapshot_file file_to_delete = info['base_file'] + if info['base_id'] is None: + # Passing base=none to blockRebase ensures that + # libvirt blanks out the qcow2 backing file pointer + new_base = None + else: + new_base = info['new_base_file'] + snap_info[info['base_id']] = info['snapshot_file'] - delete_info = {'file_to_merge': info['base_file'], + delete_info = {'file_to_merge': new_base, 'merge_target_file': None, # current 'type': 'qcow2', 'volume_id': snapshot['volume']['id']}