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
This commit is contained in:
Eric Harney 2013-12-18 19:11:44 -05:00 committed by Gerrit Code Review
parent f52cb1b1c4
commit 186221779a
2 changed files with 38 additions and 5 deletions

View File

@ -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)

View File

@ -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']}