Fix qemu-img rebase code to support Qemu 6.1. Ref https://github.com/GNS3/gns3-server/pull/1962

This commit is contained in:
grossmj 2021-09-05 22:18:46 +09:30
parent 99d7d0c769
commit 611570a863
3 changed files with 10 additions and 6 deletions

View File

@ -1864,12 +1864,12 @@ class QemuVM(BaseNode):
if retcode == 3:
# image has leaked clusters, but is not corrupted, let's try to fix it
log.warning("Qemu image {} has leaked clusters".format(disk_image))
if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", "{}".format(disk_image)])) == 3:
if await self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", "{}".format(disk_image)]) == 3:
self.project.emit("log.warning", {"message": "Qemu image '{}' has leaked clusters and could not be fixed".format(disk_image)})
elif retcode == 2:
# image is corrupted, let's try to fix it
log.warning("Qemu image {} is corrupted".format(disk_image))
if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "all", "{}".format(disk_image)])) == 2:
if await self._qemu_img_exec([qemu_img_path, "check", "-r", "all", "{}".format(disk_image)]) == 2:
self.project.emit("log.warning", {"message": "Qemu image '{}' is corrupted and could not be fixed".format(disk_image)})
# ignore retcode == 1. One reason is that the image is encrypted and there is no encrypt.key-secret available
except (OSError, subprocess.SubprocessError) as e:
@ -1882,13 +1882,16 @@ class QemuVM(BaseNode):
# create the disk
await self._create_linked_clone(disk_name, disk_image, disk)
else:
backing_file_format = await self._find_disk_file_format(disk_image)
if not backing_file_format:
raise QemuError("Could not detect format for disk image: {}".format(disk_image))
# Rebase the image. This is in case the base image moved to a different directory,
# which will be the case if we imported a portable project. This uses
# get_abs_image_path(hdX_disk_image) and ignores the old base path embedded
# in the qcow2 file itself.
try:
qcow2 = Qcow2(disk)
await qcow2.rebase(qemu_img_path, disk_image)
await qcow2.rebase(qemu_img_path, disk_image, backing_file_format)
except (Qcow2Error, OSError) as e:
raise QemuError("Could not use qcow2 disk image '{}' for {}: {}".format(disk_image, disk_name, e))

View File

@ -118,18 +118,19 @@ class Qcow2:
except Qcow2Error:
return (base_image, None) # non-qcow2 base images are acceptable (e.g. vmdk, raw image)
async def rebase(self, qemu_img, base_image):
async def rebase(self, qemu_img, base_image, backing_file_format):
"""
Rebase a linked clone in order to use the correct disk
:param qemu_img: Path to the qemu-img binary
:param base_image: Path to the base image
:param backing_file_format: File format of the base image
"""
if not os.path.exists(base_image):
raise FileNotFoundError(base_image)
backing_options, _ = Qcow2.backing_options(base_image)
command = [qemu_img, "rebase", "-u", "-b", backing_options, self._path]
command = [qemu_img, "rebase", "-u", "-b", backing_options, "-F", backing_file_format, self._path]
process = await asyncio.create_subprocess_exec(*command)
retcode = await process.wait()
if retcode != 0:

View File

@ -73,5 +73,5 @@ async def test_rebase(loop, tmpdir):
qcow2 = Qcow2(str(tmpdir / "linked.qcow2"))
assert qcow2.version == 3
assert qcow2.backing_file == "empty8G.qcow2"
await qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"))
await qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"), "qcow2")
assert qcow2.backing_file == str(tmpdir / "empty16G.qcow2")