From 725387e54f394f396575b84d7ac3e457044917a9 Mon Sep 17 00:00:00 2001 From: Qubad786 Date: Fri, 24 Jan 2025 15:47:16 +0500 Subject: [PATCH] Add support for specifying secureboot for VMs in virt (#15475) --- .../middlewared/api/v25_04_0/virt_instance.py | 3 +++ .../middlewared/plugins/virt/instance.py | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/middlewared/middlewared/api/v25_04_0/virt_instance.py b/src/middlewared/middlewared/api/v25_04_0/virt_instance.py index f460741cd278e..f336ea4dae570 100644 --- a/src/middlewared/middlewared/api/v25_04_0/virt_instance.py +++ b/src/middlewared/middlewared/api/v25_04_0/virt_instance.py @@ -65,6 +65,7 @@ class VirtInstanceEntry(BaseModel): vnc_enabled: bool vnc_port: int | None vnc_password: Secret[NonEmptyString | None] + secure_boot: bool | None # Lets require at least 32MiB of reserved memory @@ -87,6 +88,7 @@ class VirtInstanceCreateArgs(BaseModel): cpu: str | None = None devices: list[DeviceType] | None = None memory: MemoryType | None = None + secure_boot: bool = False enable_vnc: bool = False vnc_port: int | None = Field(ge=5900, le=65535, default=None) zvol_path: NonEmptyString | None = None @@ -145,6 +147,7 @@ class VirtInstanceUpdate(BaseModel, metaclass=ForUpdateMetaclass): enable_vnc: bool vnc_password: Secret[NonEmptyString | None] '''Setting vnc_password to null will unset VNC password''' + secure_boot: bool = False class VirtInstanceUpdateArgs(BaseModel): diff --git a/src/middlewared/middlewared/plugins/virt/instance.py b/src/middlewared/middlewared/plugins/virt/instance.py index 6df34313d199d..90e196abe74c2 100644 --- a/src/middlewared/middlewared/plugins/virt/instance.py +++ b/src/middlewared/middlewared/plugins/virt/instance.py @@ -78,7 +78,10 @@ async def query(self, filters, options): }, **get_vnc_info_from_config(i['config']), 'raw': None, # Default required by pydantic + 'secure_boot': None, } + if entry['type'] == 'VM': + entry['secure_boot'] = True if i['config'].get('security.secureboot') == 'true' else False idmap = None if idmap_current := i['config'].get('volatile.idmap.current'): @@ -144,6 +147,9 @@ async def validate(self, new, schema_name, verrors, old=None): if not old and await self.query([('name', '=', new['name'])]): verrors.add(f'{schema_name}.name', f'Name {new["name"]!r} already exists') + if instance_type != 'VM' and new.get('secure_boot'): + verrors.add(f'{schema_name}.secure_boot', 'Secure boot is only supported for VMs') + if new.get('memory'): meminfo = await self.middleware.call('system.mem_info') if new['memory'] > meminfo['physmem_size']: @@ -155,6 +161,9 @@ async def validate(self, new, schema_name, verrors, old=None): verrors.add(f'{schema_name}.cpu', 'Cannot reserve more than system cores') if old: + if 'secure_boot' not in new: + new['secure_boot'] = old['secure_boot'] + enable_vnc = new.get('enable_vnc') if enable_vnc is False: # User explicitly disabled VNC support, let's remove vnc port @@ -237,11 +246,14 @@ def __data_to_config(self, data: dict, raw: dict = None, instance_type=None): config['boot.autostart'] = str(data['autostart']).lower() if instance_type == 'VM': - config['user.ix_old_raw_qemu_config'] = raw.get('raw.qemu', '') if raw else '' - config['user.ix_vnc_config'] = json.dumps({ - 'vnc_enabled': data['enable_vnc'], - 'vnc_port': data['vnc_port'], - 'vnc_password': data['vnc_password'], + config.update({ + 'security.secureboot': 'true' if data['secure_boot'] else 'false', + 'user.ix_old_raw_qemu_config': raw.get('raw.qemu', '') if raw else '', + 'user.ix_vnc_config': json.dumps({ + 'vnc_enabled': data['enable_vnc'], + 'vnc_port': data['vnc_port'], + 'vnc_password': data['vnc_password'], + }), }) if data.get('enable_vnc') and data.get('vnc_port'):