mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Merge branch 'master' into 2.2
# Conflicts: # gns3server/compute/qemu/qemu_vm.py
This commit is contained in:
commit
99d7d0c769
@ -1691,24 +1691,15 @@ class QemuVM(BaseNode):
|
|||||||
backing_file_format = await self._find_disk_file_format(disk_image)
|
backing_file_format = await self._find_disk_file_format(disk_image)
|
||||||
if not backing_file_format:
|
if not backing_file_format:
|
||||||
raise QemuError("Could not detect format for disk image: {}".format(disk_image))
|
raise QemuError("Could not detect format for disk image: {}".format(disk_image))
|
||||||
command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image), "-F", backing_file_format, "-f", "qcow2", disk]
|
backing_options, base_qcow2 = Qcow2.backing_options(disk_image)
|
||||||
try:
|
if base_qcow2 and base_qcow2.crypt_method:
|
||||||
base_qcow2 = Qcow2(disk_image)
|
# Workaround for https://gitlab.com/qemu-project/qemu/-/issues/441
|
||||||
if base_qcow2.crypt_method:
|
# (we have to pass -u and the size). Also embed secret name.
|
||||||
# Workaround for https://gitlab.com/qemu-project/qemu/-/issues/441
|
command = [qemu_img_path, "create", "-b", backing_options,
|
||||||
# Also embed a secret name so it doesn't have to be passed to qemu -drive ...
|
"-F", backing_file_format, "-f", "qcow2", "-u", disk, str(base_qcow2.size)]
|
||||||
options = {
|
else:
|
||||||
"encrypt.key-secret": os.path.basename(disk_image),
|
command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image),
|
||||||
"driver": "qcow2",
|
"-F", backing_file_format, "-f", "qcow2", disk]
|
||||||
"file": {
|
|
||||||
"driver": "file",
|
|
||||||
"filename": disk_image,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
command = [qemu_img_path, "create", "-b", "json:"+json.dumps(options, separators=(',', ':')),
|
|
||||||
"-f", "qcow2", "-u", disk, str(base_qcow2.size)]
|
|
||||||
except Qcow2Error:
|
|
||||||
pass # non-qcow2 base images are acceptable (e.g. vmdk, raw image)
|
|
||||||
|
|
||||||
retcode = await self._qemu_img_exec(command)
|
retcode = await self._qemu_img_exec(command)
|
||||||
if retcode:
|
if retcode:
|
||||||
@ -1891,10 +1882,13 @@ class QemuVM(BaseNode):
|
|||||||
# create the disk
|
# create the disk
|
||||||
await self._create_linked_clone(disk_name, disk_image, disk)
|
await self._create_linked_clone(disk_name, disk_image, disk)
|
||||||
else:
|
else:
|
||||||
# The disk exists we check if the clone works
|
# 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:
|
try:
|
||||||
qcow2 = Qcow2(disk)
|
qcow2 = Qcow2(disk)
|
||||||
await qcow2.validate(qemu_img_path)
|
await qcow2.rebase(qemu_img_path, disk_image)
|
||||||
except (Qcow2Error, OSError) as e:
|
except (Qcow2Error, OSError) as e:
|
||||||
raise QemuError("Could not use qcow2 disk image '{}' for {}: {}".format(disk_image, disk_name, e))
|
raise QemuError("Could not use qcow2 disk image '{}' for {}: {}".format(disk_image, disk_name, e))
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import struct
|
import struct
|
||||||
@ -88,6 +89,35 @@ class Qcow2:
|
|||||||
return None
|
return None
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def backing_options(base_image):
|
||||||
|
"""
|
||||||
|
If the base_image is encrypted qcow2, return options for the upper layer
|
||||||
|
which include a secret name (equal to the basename)
|
||||||
|
|
||||||
|
:param base_image: Path to the base file (which may or may not be qcow2)
|
||||||
|
|
||||||
|
:returns: (base image string, Qcow2 object representing base image or None)
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
base_qcow2 = Qcow2(base_image)
|
||||||
|
if base_qcow2.crypt_method:
|
||||||
|
# Embed a secret name so it doesn't have to be passed to qemu -drive ...
|
||||||
|
options = {
|
||||||
|
"encrypt.key-secret": os.path.basename(base_image),
|
||||||
|
"driver": "qcow2",
|
||||||
|
"file": {
|
||||||
|
"driver": "file",
|
||||||
|
"filename": base_image,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return ("json:"+json.dumps(options, separators=(',', ':')), base_qcow2)
|
||||||
|
else:
|
||||||
|
return (base_image, base_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):
|
||||||
"""
|
"""
|
||||||
Rebase a linked clone in order to use the correct disk
|
Rebase a linked clone in order to use the correct disk
|
||||||
@ -98,21 +128,10 @@ class Qcow2:
|
|||||||
|
|
||||||
if not os.path.exists(base_image):
|
if not os.path.exists(base_image):
|
||||||
raise FileNotFoundError(base_image)
|
raise FileNotFoundError(base_image)
|
||||||
command = [qemu_img, "rebase", "-u", "-b", base_image, self._path]
|
backing_options, _ = Qcow2.backing_options(base_image)
|
||||||
|
command = [qemu_img, "rebase", "-u", "-b", backing_options, self._path]
|
||||||
process = await asyncio.create_subprocess_exec(*command)
|
process = await asyncio.create_subprocess_exec(*command)
|
||||||
retcode = await process.wait()
|
retcode = await process.wait()
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
raise Qcow2Error("Could not rebase the image")
|
raise Qcow2Error("Could not rebase the image")
|
||||||
self._reload()
|
self._reload()
|
||||||
|
|
||||||
async def validate(self, qemu_img):
|
|
||||||
"""
|
|
||||||
Run qemu-img info to validate the file and its backing images
|
|
||||||
|
|
||||||
:param qemu_img: Path to the qemu-img binary
|
|
||||||
"""
|
|
||||||
command = [qemu_img, "info", "--backing-chain", self._path]
|
|
||||||
process = await asyncio.create_subprocess_exec(*command)
|
|
||||||
retcode = await process.wait()
|
|
||||||
if retcode != 0:
|
|
||||||
raise Qcow2Error("Could not validate the image")
|
|
||||||
|
Loading…
Reference in New Issue
Block a user