Merge "libvirt: Wire up 'os_secure_boot' property"
This commit is contained in:
commit
bf4d4c16fd
|
@ -23,8 +23,8 @@ EXTRA_SPEC_VALIDATORS = [
|
|||
base.ExtraSpecValidator(
|
||||
name='os:secure_boot',
|
||||
description=(
|
||||
'Determine whether secure boot is enabled or not. Currently only '
|
||||
'supported by the HyperV driver.'
|
||||
'Determine whether secure boot is enabled or not. Only supported '
|
||||
'by the libvirt and HyperV drivers.'
|
||||
),
|
||||
value={
|
||||
'type': str,
|
||||
|
|
|
@ -1891,6 +1891,10 @@ class UEFINotSupported(Invalid):
|
|||
msg_fmt = _("UEFI is not supported")
|
||||
|
||||
|
||||
class SecureBootNotSupported(Invalid):
|
||||
msg_fmt = _("Secure Boot is not supported by host")
|
||||
|
||||
|
||||
class TriggerCrashDumpNotSupported(Invalid):
|
||||
msg_fmt = _("Triggering crash dump is not supported")
|
||||
|
||||
|
|
|
@ -1993,6 +1993,36 @@ class FakeLibvirtFixture(fixtures.Fixture):
|
|||
'features': ['acpi-s3', 'amd-sev', 'verbose-dynamic'],
|
||||
'tags': [],
|
||||
},
|
||||
{
|
||||
'description': 'UEFI firmware for x86_64, with SB+SMM',
|
||||
'interface-types': ['uefi'],
|
||||
'mapping': {
|
||||
'device': 'flash',
|
||||
'executable': {
|
||||
'filename': '/usr/share/OVMF/OVMF_CODE.secboot.fd',
|
||||
'format': 'raw',
|
||||
},
|
||||
'nvram-template': {
|
||||
'filename': '/usr/share/OVMF/OVMF_VARS.secboot.fd',
|
||||
'format': 'raw',
|
||||
},
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'architecture': 'x86_64',
|
||||
'machines': ['pc-q35-*'],
|
||||
},
|
||||
],
|
||||
'features': [
|
||||
'acpi-s3',
|
||||
'amd-sev',
|
||||
'enrolled-keys',
|
||||
'requires-smm',
|
||||
'secure-boot',
|
||||
'verbose-dynamic',
|
||||
],
|
||||
'tags': [],
|
||||
},
|
||||
{
|
||||
'description': 'UEFI firmware for aarch64',
|
||||
'interface-types': ['uefi'],
|
||||
|
@ -2015,7 +2045,7 @@ class FakeLibvirtFixture(fixtures.Fixture):
|
|||
],
|
||||
'features': ['verbose-static'],
|
||||
"tags": [],
|
||||
}
|
||||
},
|
||||
]
|
||||
self.useFixture(
|
||||
fixtures.MockPatch(
|
||||
|
|
|
@ -5008,10 +5008,86 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||
CONF.libvirt.virt_type, instance_ref, image_meta)
|
||||
cfg = drvr._get_guest_config(
|
||||
instance_ref, [], image_meta, disk_info)
|
||||
# these values are derived from the FakeLibvirtFixture
|
||||
# these paths are derived from the FakeLibvirtFixture
|
||||
self.assertEqual('/usr/share/OVMF/OVMF_CODE.fd', cfg.os_loader)
|
||||
self.assertEqual('/usr/share/OVMF/OVMF_VARS.fd', cfg.os_nvram_template)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_get_guest_config_with_secure_boot_required(
|
||||
self, host_has_support,
|
||||
):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
drvr._host._supports_uefi = True
|
||||
drvr._host._supports_secure_boot = host_has_support
|
||||
|
||||
image_meta = objects.ImageMeta.from_dict({
|
||||
'disk_format': 'raw',
|
||||
# secure boot requires UEFI
|
||||
'properties': {
|
||||
'hw_firmware_type': 'uefi',
|
||||
'hw_machine_type': 'q35',
|
||||
'os_secure_boot': 'required',
|
||||
},
|
||||
})
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
|
||||
disk_info = blockinfo.get_disk_info(
|
||||
CONF.libvirt.virt_type, instance_ref, image_meta)
|
||||
if host_has_support:
|
||||
# if the host supports it, we should get the feature
|
||||
cfg = drvr._get_guest_config(
|
||||
instance_ref, [], image_meta, disk_info)
|
||||
# these paths are derived from the FakeLibvirtFixture
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_CODE.secboot.fd', cfg.os_loader)
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_VARS.secboot.fd', cfg.os_nvram_template)
|
||||
self.assertTrue(cfg.os_loader_secure)
|
||||
else:
|
||||
# if not, we should see an exception
|
||||
self.assertRaises(
|
||||
exception.SecureBootNotSupported,
|
||||
drvr._get_guest_config,
|
||||
instance_ref, [], image_meta, disk_info)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_get_guest_config_with_secure_boot_optional(
|
||||
self, host_has_support,
|
||||
):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
drvr._host._supports_uefi = True
|
||||
drvr._host._supports_secure_boot = host_has_support
|
||||
|
||||
image_meta = objects.ImageMeta.from_dict({
|
||||
'disk_format': 'raw',
|
||||
# secure boot requires UEFI
|
||||
'properties': {
|
||||
'hw_firmware_type': 'uefi',
|
||||
'hw_machine_type': 'q35',
|
||||
'os_secure_boot': 'optional',
|
||||
},
|
||||
})
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
|
||||
disk_info = blockinfo.get_disk_info(
|
||||
CONF.libvirt.virt_type, instance_ref, image_meta)
|
||||
cfg = drvr._get_guest_config(
|
||||
instance_ref, [], image_meta, disk_info)
|
||||
if host_has_support:
|
||||
# if the host supports it we should get the feature
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_CODE.secboot.fd', cfg.os_loader)
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_VARS.secboot.fd', cfg.os_nvram_template)
|
||||
self.assertTrue(cfg.os_loader_secure)
|
||||
else:
|
||||
# if not, silently ignore
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_CODE.fd', cfg.os_loader)
|
||||
self.assertEqual(
|
||||
'/usr/share/OVMF/OVMF_VARS.fd', cfg.os_nvram_template)
|
||||
self.assertFalse(cfg.os_loader_secure)
|
||||
|
||||
def test_check_uefi_support_aarch64(self):
|
||||
self.mock_uname.return_value = fakelibvirt.os_uname(
|
||||
'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64)
|
||||
|
|
|
@ -5822,6 +5822,29 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
caps.host.cpu.arch == fields.Architecture.AARCH64
|
||||
)
|
||||
|
||||
def _check_secure_boot_support(
|
||||
self,
|
||||
arch: str,
|
||||
machine_type: str,
|
||||
firmware_type: str,
|
||||
) -> bool:
|
||||
if not self._host.supports_secure_boot:
|
||||
# secure boot requires host configuration
|
||||
return False
|
||||
|
||||
if firmware_type != fields.FirmwareType.UEFI:
|
||||
# secure boot is only supported with UEFI
|
||||
return False
|
||||
|
||||
if (
|
||||
arch == fields.Architecture.X86_64 and
|
||||
'q35' not in machine_type
|
||||
):
|
||||
# secure boot on x86_64 requires the Q35 machine type
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _get_supported_perf_events(self):
|
||||
if not len(CONF.libvirt.enabled_perf_events):
|
||||
return []
|
||||
|
@ -5887,8 +5910,35 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
# architecture that we have no default machine type for
|
||||
raise exception.UEFINotSupported()
|
||||
|
||||
loader, nvram_template = self._host.get_loader(
|
||||
arch, mach_type, has_secure_boot=False)
|
||||
os_secure_boot = hardware.get_secure_boot_constraint(
|
||||
flavor, image_meta)
|
||||
if os_secure_boot == 'required':
|
||||
# hard fail if we don't support secure boot and it's
|
||||
# required
|
||||
if not self._check_secure_boot_support(
|
||||
arch, mach_type, hw_firmware_type,
|
||||
):
|
||||
raise exception.SecureBootNotSupported()
|
||||
|
||||
guest.os_loader_secure = True
|
||||
elif os_secure_boot == 'optional':
|
||||
# only enable it if the host is configured appropriately
|
||||
guest.os_loader_secure = self._check_secure_boot_support(
|
||||
arch, mach_type, hw_firmware_type,
|
||||
)
|
||||
else:
|
||||
guest.os_loader_secure = False
|
||||
|
||||
try:
|
||||
loader, nvram_template = self._host.get_loader(
|
||||
arch, mach_type,
|
||||
has_secure_boot=guest.os_loader_secure)
|
||||
except exception.UEFINotSupported as exc:
|
||||
if guest.os_loader_secure:
|
||||
# we raise a specific exception if we requested secure
|
||||
# boot and couldn't get that
|
||||
raise exception.SecureBootNotSupported() from exc
|
||||
raise
|
||||
|
||||
guest.os_loader = loader
|
||||
guest.os_loader_type = 'pflash'
|
||||
|
|
Loading…
Reference in New Issue