libvirt - 使用内置固件自动选择功能进行UEFI固件配置¶
https://blueprints.launchpad.net/nova/+spec/libvirt-firmware-auto-selection
Libvirt 引入了其内置的 UEFI 固件自动选择功能,该功能会根据请求的功能自动填充 UEFI 固件文件的 CODE 文件和 VAR 文件的路径。此功能更加复杂,并且能够检测到最近引入的几个新标志,例如 AMD SEV 或无状态固件。
本文档建议用内置功能替换 nova 中现有的逻辑,这样我们就不必维护自己的逻辑,并利用底层 libvirt 中改进的机制。
问题描述¶
最近的 libvirt 能够根据请求的功能(例如
安全启动
amd-sev/amd-sev-es/amd-sev-snp
无状态固件
为使用 UEFI 启动的域选择合适的固件文件。此功能在 libvirt 中称为自动选择,它读取 qemu 包在发行版中提供的固件描述文件中维护的标志。
Nova 在引入安全启动支持时引入了自己的逻辑。由于 nova 显式定义了使用 UEFI 启动的每个实例的固件文件,libvirt 会跳过其自动选择功能并相应地使用指定的 文件。但是 nova 中现有的逻辑仅考虑 secure-boot 标志,因此无法为其他功能选择合适的固件。因此,具有附加功能的实例可能会使用错误的固件文件启动。一个例子是无状态固件,应该使用带有“stateless”标志的固件文件,但当前的 nova 可能不会考虑此标志,并且可能会使用一个 CODE 文件启动实例,
该 CODE 文件关联着非零 VAR 文件。
除了新的功能标志外,最近的 QEMU 包还引入了新型的 ROM 类型固件。Libvirt 可以识别这些固件,但 nova 无法处理这些新型固件,因为用于定义固件路径文件的键不同。
用例¶
作为云管理员,我希望 nova 根据用户请求的功能选择合适的固件文件,而无需额外配置。
作为云用户,我希望我的实例能够使用与请求的功能相对应的固件启动。
提议的变更¶
我们建议对 libvirt 驱动程序生成 guest XML 的方式进行以下更改,以便 libvirt 根据请求的功能选择固件文件。
在定义域时,停止显式传递 code 文件和 var 文件的路径。
当前 nova 在生成 guest XML 时会填充 loader 元素和 nvram 元素。以下示例描述了具有 secure-boot 的 guest XML 的
os元素。<os> <type machine='q35'>hvm</type> <loader type='pflash' readonly='yes' secure='yes'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader> <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'/> <boot dev='hd'/> <smbios mode='sysinfo'/> </os>
一旦实施了提议的更改,nova 将不再填充这些文件路径,而是为 secure-boot 添加固件功能元素。以下示例描述了具有 secure-boot 的 guest XML 的
os元素。<os firmware='efi'> <type machine='q35'>hvm</type> <loader secure='yes'/> <firmware> <feature enabled='yes' name='secure-boot'/> </firmware> <boot dev='hd'/> <smbios mode='sysinfo'/> </os>
请注意,
firmware='efi'是告诉 libvirt 检测固件文件路径的关键。为了保持不使用 secure-boot 的 guest 的现有行为,如果未请求 secure-boot 功能,则会在 guest XML 中显式拒绝该功能。
<os firmware='efi'> <type machine='q35'>hvm</type> <loader secure='no'/> <firmware> <feature enabled='no' name='secure-boot'/> </firmware> <boot dev='hd'/> <smbios mode='sysinfo'/> </os>
但是,libvirt 不需要这些固件功能元素来支持无状态固件(libvirt 读取 loader 元素中的 stateless 属性)和 AMD SEV/SEV-ES(libvirt 读取 launchSecurity 元素)。例如,当请求无状态固件时,guest XML 的
os元素应如下所示。<os firmware='efi'> <type machine='q35'>hvm</type> <loader secure='no' stateless='yes'/> <firmware> <feature enabled='no' name='secure-boot'/> </firmware> <boot dev='hd'/> <smbios mode='sysinfo'/> </os>
在以下操作期间,检查现有 guest XML 中的 loader 元素和 nvram 元素,然后显式传递这些元素并禁用自动检测以生成新的 guest XML,以便在这些操作期间不会重新选择固件文件。
硬重启(和启动)
实时迁移
注意
如果实例启动时 domain xml 不存在(例如,如果实例从卷启动并且其主机已重新安装),则有可能 domain xml 不存在。在这种情况下,xml 将从头开始生成,并且在操作之后固件文件路径可能会更改。
备选方案¶
另一种方法是在 nova 中实现相同的自动选择逻辑,但这需要付出努力才能使实现与 libvirt 保持一致。这会导致对未来代码维护的担忧,而没有带来很大的好处。
数据模型影响¶
无
REST API 影响¶
无
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
在生成 domain XML 的操作之后(例如
启动,当域定义不存在于 hypervisor 上时
重建
搁置
调整大小或冷迁移
疏散
性能影响¶
无
其他部署者影响¶
部署者必须确保固件描述文件(通常位于 /usr/share/qemu/firmware/)已更新,以包含预期功能的标志。
开发人员影响¶
无
升级影响¶
如“最终用户影响”部分所述,当使用新的 libvirt 驱动程序启动时,实例可能会使用不同的(但正确的)固件启动。
升级后,如果固件描述文件都不包含所需的标志(sev 标志和无状态标志),而这些标志之前未经过检查,则实例创建可能会失败。
实现¶
负责人¶
- 主要负责人
kajinamit (irc: tkajinam)
- 其他贡献者
无
工作项¶
添加对现有 libvirt XML 中使用的固件文件的检测
更新 libvirt 驱动程序生成 XML 文件的方式,仅在显式提供这些文件时才填充固件文件路径。
更新实时迁移和硬重启,以便在生成新的 XML 文件时传递当前使用的固件文件。
应根据新的逻辑添加单元测试和功能测试。
依赖项¶
使用自动选择功能需要 Libvirt >= 5.2.0。这已由最低 libvirt 版本检查强制执行。
QEMU 固件及其描述文件已更新,以包含 nova 请求的功能的标志。受支持的发行版安装的固件描述文件大多包含所需的标志,但已知 Ubuntu 24.04 需要更新才能支持 AMD SEV-ES。有关详细信息,请参阅 Bug 2122286。
测试¶
需要扩展或添加相应的单元/功能测试,以涵盖
在实例 XML 生成期间传递的简化 XML 文件,该文件不包含显式固件文件路径
硬重启或实时迁移生成的 XML 文件应包含显式固件文件路径,这些路径与现有域 XML 中的路径相对应。
对于安全启动和无状态固件,可以向 tempest 添加新的场景测试。但是,目前在 CI 中用于 guest OS 的 cirros 不支持 UEFI 启动,我们需要一个不同的(并且可能更重的)guest OS 来支持这些功能。如果确定我们无法在 CI 中使用这些 guest,则可以在本地测试这些功能。
此外,AMD SEV 和 AMD SEV-ES 在 CI 中没有可用的实际固件,因此这些将手动测试。
文档影响¶
无
参考资料¶
历史¶
发布名称 |
描述 |
|---|---|
2026.1 Gazpacho |
已批准 |