Backport UEFI boot mode support for Qemu VMs

This commit is contained in:
grossmj 2023-06-21 17:56:34 +09:30
parent 3dbc714f37
commit d5cfb85de5
5 changed files with 64 additions and 0 deletions

View File

@ -122,6 +122,7 @@ class QemuVM(BaseNode):
self._kernel_image = "" self._kernel_image = ""
self._kernel_command_line = "" self._kernel_command_line = ""
self._tpm = False self._tpm = False
self._uefi = False
self._legacy_networking = False self._legacy_networking = False
self._replicate_network_connection_state = True self._replicate_network_connection_state = True
self._create_config_disk = False self._create_config_disk = False
@ -833,6 +834,30 @@ class QemuVM(BaseNode):
log.info('QEMU VM "{name}" [{id}] has disabled the Trusted Platform Module (TPM)'.format(name=self._name, id=self._id)) log.info('QEMU VM "{name}" [{id}] has disabled the Trusted Platform Module (TPM)'.format(name=self._name, id=self._id))
self._tpm = tpm self._tpm = tpm
@property
def uefi(self):
"""
Returns whether UEFI boot mode is activated for this QEMU VM.
:returns: boolean
"""
return self._uefi
@uefi.setter
def uefi(self, uefi):
"""
Sets whether UEFI boot mode is activated for this QEMU VM.
:param uefi: boolean
"""
if uefi:
log.info(f'QEMU VM "{self._name}" [{self._id}] has enabled the UEFI boot mode')
else:
log.info(f'QEMU VM "{self._name}" [{self._id}] has disabled the UEFI boot mode')
self._uefi = uefi
@property @property
def options(self): def options(self):
""" """
@ -1994,12 +2019,16 @@ class QemuVM(BaseNode):
options = [] options = []
if self._bios_image: if self._bios_image:
if self._uefi:
raise QemuError("Cannot use a bios image and the UEFI boot mode at the same time")
if not os.path.isfile(self._bios_image) or not os.path.exists(self._bios_image): if not os.path.isfile(self._bios_image) or not os.path.exists(self._bios_image):
if os.path.islink(self._bios_image): if os.path.islink(self._bios_image):
raise QemuError("bios image '{}' linked to '{}' is not accessible".format(self._bios_image, os.path.realpath(self._bios_image))) raise QemuError("bios image '{}' linked to '{}' is not accessible".format(self._bios_image, os.path.realpath(self._bios_image)))
else: else:
raise QemuError("bios image '{}' is not accessible".format(self._bios_image)) raise QemuError("bios image '{}' is not accessible".format(self._bios_image))
options.extend(["-bios", self._bios_image.replace(",", ",,")]) options.extend(["-bios", self._bios_image.replace(",", ",,")])
elif self._uefi:
options.extend(["-bios", "OVMF.fd"]) # the OVMF bios image should be in the image directory
return options return options
def _linux_boot_options(self): def _linux_boot_options(self):

BIN
gns3server/disks/OVMF.fd Normal file

Binary file not shown.

View File

@ -194,6 +194,10 @@ QEMU_CREATE_SCHEMA = {
"description": "Enable the Trusted Platform Module (TPM) in Qemu", "description": "Enable the Trusted Platform Module (TPM) in Qemu",
"type": ["boolean", "null"], "type": ["boolean", "null"],
}, },
"uefi": {
"description": "Enable the UEFI boot mode in Qemu",
"type": ["boolean", "null"],
},
"create_config_disk": { "create_config_disk": {
"description": "Automatically create a config disk on HDD disk interface (secondary slave)", "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
"type": ["boolean", "null"], "type": ["boolean", "null"],
@ -392,6 +396,10 @@ QEMU_UPDATE_SCHEMA = {
"description": "Enable the Trusted Platform Module (TPM) in Qemu", "description": "Enable the Trusted Platform Module (TPM) in Qemu",
"type": ["boolean", "null"], "type": ["boolean", "null"],
}, },
"uefi": {
"description": "Enable the UEFI boot mode in Qemu",
"type": ["boolean", "null"],
},
"create_config_disk": { "create_config_disk": {
"description": "Automatically create a config disk on HDD disk interface (secondary slave)", "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
"type": ["boolean", "null"], "type": ["boolean", "null"],
@ -603,6 +611,10 @@ QEMU_OBJECT_SCHEMA = {
"description": "Enable the Trusted Platform Module (TPM) in Qemu", "description": "Enable the Trusted Platform Module (TPM) in Qemu",
"type": "boolean", "type": "boolean",
}, },
"uefi": {
"description": "Enable the UEFI boot mode in Qemu",
"type": "boolean",
},
"create_config_disk": { "create_config_disk": {
"description": "Automatically create a config disk on HDD disk interface (secondary slave)", "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
"type": ["boolean", "null"], "type": ["boolean", "null"],
@ -678,6 +690,7 @@ QEMU_OBJECT_SCHEMA = {
"legacy_networking", "legacy_networking",
"replicate_network_connection_state", "replicate_network_connection_state",
"tpm", "tpm",
"uefi",
"create_config_disk", "create_config_disk",
"on_close", "on_close",
"cpu_throttling", "cpu_throttling",

View File

@ -188,6 +188,11 @@ QEMU_TEMPLATE_PROPERTIES = {
"type": "boolean", "type": "boolean",
"default": False "default": False
}, },
"uefi": {
"description": "Enable the UEFI boot mode in Qemu",
"type": "boolean",
"default": False
},
"create_config_disk": { "create_config_disk": {
"description": "Automatically create a config disk on HDD disk interface (secondary slave)", "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
"type": "boolean", "type": "boolean",

View File

@ -387,6 +387,23 @@ async def test_bios_option(vm, tmpdir, fake_qemu_img_binary):
assert ' '.join(['-bios', str(tmpdir / "test.img")]) in ' '.join(options) assert ' '.join(['-bios', str(tmpdir / "test.img")]) in ' '.join(options)
async def test_uefi_boot_mode_option(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._uefi = True
options = await vm._build_command()
assert ' '.join(['-bios', 'OVMF.fd']) in ' '.join(options)
async def test_uefi_with_bios_image_already_configured(vm, tmpdir, fake_qemu_img_binary):
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
vm._bios_image = str(tmpdir / "test.img")
vm._uefi = True
with pytest.raises(QemuError):
await vm._build_command()
async def test_vnc_option(vm, fake_qemu_img_binary): async def test_vnc_option(vm, fake_qemu_img_binary):
vm._console_type = 'vnc' vm._console_type = 'vnc'