enable uefi boot
This patch enables uefi boot with the libvirt driver. This feature is without some kind of functional testing and therefore considered experimental. Co-Authored-By: XinXiaohui <xiaohui.xin@intel.com> Change-Id: I9d8b2896e4bd29f67ebab6ce1bc927aae271c3e7 Implements: blueprint boot-from-uefi
This commit is contained in:
parent
3d4c8edd6b
commit
9e2dfb61ed
@ -2034,6 +2034,10 @@ class RequestSpecNotFound(NotFound):
|
||||
msg_fmt = _("RequestSpec not found for instance %(instance_uuid)s")
|
||||
|
||||
|
||||
class UEFINotSupported(Invalid):
|
||||
msg_fmt = _("UEFI is not supported")
|
||||
|
||||
|
||||
class NMINotSupported(Invalid):
|
||||
msg_fmt = _("Injecting NMI is not supported")
|
||||
|
||||
|
@ -1792,6 +1792,31 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest):
|
||||
</devices>
|
||||
</domain>""")
|
||||
|
||||
def test_config_uefi(self):
|
||||
obj = config.LibvirtConfigGuest()
|
||||
obj.virt_type = "kvm"
|
||||
obj.memory = 100 * units.Mi
|
||||
obj.vcpus = 1
|
||||
obj.name = "uefi"
|
||||
obj.uuid = "f01cf68d-515c-4daf-b85f-ef1424d93bfc"
|
||||
obj.os_type = "x86_64"
|
||||
obj.os_loader = '/tmp/OVMF.fd'
|
||||
obj.os_loader_type = 'pflash'
|
||||
xml = obj.to_xml()
|
||||
|
||||
self.assertXmlEqual(xml, """
|
||||
<domain type="kvm">
|
||||
<uuid>f01cf68d-515c-4daf-b85f-ef1424d93bfc</uuid>
|
||||
<name>uefi</name>
|
||||
<memory>104857600</memory>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type>x86_64</type>
|
||||
<loader readonly='yes' type='pflash'>/tmp/OVMF.fd</loader>
|
||||
<nvram template="/tmp/OVMF.fd"></nvram>
|
||||
</os>
|
||||
</domain>""")
|
||||
|
||||
def test_config_boot_menu(self):
|
||||
obj = config.LibvirtConfigGuest()
|
||||
obj.virt_type = "kvm"
|
||||
|
@ -2632,6 +2632,56 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
self.assertIsInstance(cfg.devices[2],
|
||||
vconfig.LibvirtConfigGuestConsole)
|
||||
|
||||
def test_has_uefi_support_with_invalid_version(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
with mock.patch.object(drvr._host,
|
||||
'has_min_version', return_value=False):
|
||||
self.assertFalse(drvr._has_uefi_support())
|
||||
|
||||
def test_has_uefi_support_not_supported_arch(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
caps.host = vconfig.LibvirtConfigCapsHost()
|
||||
caps.host.cpu = vconfig.LibvirtConfigCPU()
|
||||
caps.host.cpu.arch = "alpha"
|
||||
self.assertFalse(drvr._has_uefi_support())
|
||||
|
||||
@mock.patch('os.path.exists', return_value=False)
|
||||
def test_has_uefi_support_with_no_loader_existed(self, mock_exist):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
self.assertFalse(drvr._has_uefi_support())
|
||||
|
||||
@mock.patch('os.path.exists', return_value=True)
|
||||
def test_has_uefi_support(self, mock_has_version):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
caps.host = vconfig.LibvirtConfigCapsHost()
|
||||
caps.host.cpu = vconfig.LibvirtConfigCPU()
|
||||
caps.host.cpu.arch = "x86_64"
|
||||
|
||||
with mock.patch.object(drvr._host,
|
||||
'has_min_version', return_value=True):
|
||||
self.assertTrue(drvr._has_uefi_support())
|
||||
|
||||
def test_get_guest_config_with_uefi(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
|
||||
image_meta = objects.ImageMeta.from_dict({
|
||||
"disk_format": "raw",
|
||||
"properties": {"hw_firmware_type": "uefi"}})
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
|
||||
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
|
||||
instance_ref,
|
||||
image_meta)
|
||||
with test.nested(
|
||||
mock.patch.object(drvr, "_has_uefi_support",
|
||||
return_value=True)):
|
||||
cfg = drvr._get_guest_config(instance_ref, [],
|
||||
image_meta, disk_info)
|
||||
self.assertEqual(cfg.os_loader_type, "pflash")
|
||||
|
||||
def test_get_guest_config_with_block_device(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
|
||||
|
@ -1858,6 +1858,7 @@ class LibvirtConfigGuest(LibvirtConfigObject):
|
||||
self.sysinfo = None
|
||||
self.os_type = None
|
||||
self.os_loader = None
|
||||
self.os_loader_type = None
|
||||
self.os_kernel = None
|
||||
self.os_initrd = None
|
||||
self.os_cmdline = None
|
||||
@ -1903,7 +1904,17 @@ class LibvirtConfigGuest(LibvirtConfigObject):
|
||||
if self.os_kernel is not None:
|
||||
os.append(self._text_node("kernel", self.os_kernel))
|
||||
if self.os_loader is not None:
|
||||
os.append(self._text_node("loader", self.os_loader))
|
||||
# Generate XML nodes for UEFI boot.
|
||||
if self.os_loader_type == "pflash":
|
||||
loader = self._text_node("loader", self.os_loader)
|
||||
loader.set("type", "pflash")
|
||||
loader.set("readonly", "yes")
|
||||
os.append(loader)
|
||||
nvram = self._text_node("nvram", "")
|
||||
nvram.set("template", self.os_loader)
|
||||
os.append(nvram)
|
||||
else:
|
||||
os.append(self._text_node("loader", self.os_loader))
|
||||
if self.os_initrd is not None:
|
||||
os.append(self._text_node("initrd", self.os_initrd))
|
||||
if self.os_cmdline is not None:
|
||||
|
@ -114,6 +114,8 @@ from nova.volume import encryptors
|
||||
|
||||
libvirt = None
|
||||
|
||||
uefi_logged = False
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Downtime period in milliseconds
|
||||
@ -307,6 +309,11 @@ DEFAULT_FIREWALL_DRIVER = "%s.%s" % (
|
||||
libvirt_firewall.__name__,
|
||||
libvirt_firewall.IptablesFirewallDriver.__name__)
|
||||
|
||||
DEFAULT_UEFI_LOADER_PATH = {
|
||||
"x86_64": "/usr/share/OVMF/OVMF_CODE.fd",
|
||||
"aarch64": "/usr/share/AAVMF/AAVMF_CODE.fd"
|
||||
}
|
||||
|
||||
MAX_CONSOLE_BYTES = 100 * units.Ki
|
||||
|
||||
# The libvirt driver will prefix any disable reason codes with this string.
|
||||
@ -422,6 +429,9 @@ MIN_QEMU_NUMA_HUGEPAGE_VERSION = (2, 1, 0)
|
||||
# fsFreeze/fsThaw requirement
|
||||
MIN_LIBVIRT_FSFREEZE_VERSION = (1, 2, 5)
|
||||
|
||||
# UEFI booting support
|
||||
MIN_LIBVIRT_UEFI_VERSION = (1, 2, 9)
|
||||
|
||||
# Hyper-V paravirtualized time source
|
||||
MIN_LIBVIRT_HYPERV_TIMER_VERSION = (1, 2, 2)
|
||||
MIN_QEMU_HYPERV_TIMER_VERSION = (2, 0, 0)
|
||||
@ -4118,6 +4128,14 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
return flavor
|
||||
return instance.flavor
|
||||
|
||||
def _has_uefi_support(self):
|
||||
# This means that the host can support uefi booting for guests
|
||||
supported_archs = [arch.X86_64, arch.AARCH64]
|
||||
caps = self._host.get_capabilities()
|
||||
return ((caps.host.cpu.arch in supported_archs) and
|
||||
self._host.has_min_version(MIN_LIBVIRT_UEFI_VERSION) and
|
||||
os.path.exists(DEFAULT_UEFI_LOADER_PATH[caps.host.cpu.arch]))
|
||||
|
||||
def _configure_guest_by_virt_type(self, guest, virt_type, caps, instance,
|
||||
image_meta, flavor, root_device_name):
|
||||
if virt_type == "xen":
|
||||
@ -4127,6 +4145,20 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
if caps.host.cpu.arch in (arch.I686, arch.X86_64):
|
||||
guest.sysinfo = self._get_guest_config_sysinfo(instance)
|
||||
guest.os_smbios = vconfig.LibvirtConfigGuestSMBIOS()
|
||||
hw_firmware_type = image_meta.properties.get('hw_firmware_type')
|
||||
if hw_firmware_type == fields.FirmwareType.UEFI:
|
||||
if self._has_uefi_support():
|
||||
global uefi_logged
|
||||
if not uefi_logged:
|
||||
LOG.warn(_LW("uefi support is without some kind of "
|
||||
"functional testing and therefore "
|
||||
"considered experimental."))
|
||||
uefi_logged = True
|
||||
guest.os_loader = DEFAULT_UEFI_LOADER_PATH[
|
||||
caps.host.cpu.arch]
|
||||
guest.os_loader_type = "pflash"
|
||||
else:
|
||||
raise exception.UEFINotSupported()
|
||||
guest.os_mach_type = self._get_machine_type(image_meta, caps)
|
||||
if image_meta.properties.get('hw_boot_menu') is None:
|
||||
guest.os_bootmenu = strutils.bool_from_string(
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add support for enabling uefi boot with libvirt.
|
Loading…
Reference in New Issue
Block a user