add logic to automatically detect firmware irrespective of the Linux distribution

This commit is contained in:
Lukas Greve
2025-10-20 11:28:28 +02:00
parent 7317e390c9
commit 8271e05336
2 changed files with 74 additions and 12 deletions

View File

@@ -20,19 +20,15 @@ resource "libvirt_domain" "domain" {
# ---- optional UEFI support ------------------------------------ # ---- optional UEFI support ------------------------------------
# Firmware only add the string when a path is supplied # Firmware only add the string when a path is supplied
firmware = can(var.uefi_firmware) && length(var.uefi_firmware) > 0 ? var.uefi_firmware : null firmware = local.detected_firmware
# NVRAM block dynamic block that is evaluated once per VM # NVRAM block dynamic block that is evaluated once per VM
dynamic "nvram" { dynamic "nvram" {
# create the block once if a firmware path *and* a template were given for_each = (local.detected_firmware != null && local.detected_nvram != null) ? [1] : []
for_each = (can(var.uefi_firmware) && length(var.uefi_firmware) > 0
&& can(var.uefi_nvram_template) && length(var.uefi_nvram_template) > 0
) ? [1] : []
content { content {
# The NVRAM filename is perVM, but we can honour an optional suffix
file = "/var/lib/libvirt/qemu/nvram/${var.vm_name}-${count.index}${var.uefi_nvram_file_suffix}_VARS.fd" file = "/var/lib/libvirt/qemu/nvram/${var.vm_name}-${count.index}${var.uefi_nvram_file_suffix}_VARS.fd"
template = var.uefi_nvram_template template = local.detected_nvram
} }
} }
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@@ -105,23 +105,25 @@ variable "dns_local_only" {
default = false default = false
} }
# Improved UEFI variables with automatic detection
variable "uefi_firmware" { variable "uefi_firmware" {
description = <<EOT description = <<EOT
Path to the UEFI firmware binary (OVMF_CODE.fd, QEMU_CODE.fd, …). Enable UEFI support. Set to true to enable UEFI with auto-detected firmware,
Leave empty (or omit on the module call) to create a plain BIOS VM. or provide a specific path to the firmware binary.
Set to false or omit to create a plain BIOS VM.
EOT EOT
type = string type = string
default = "" # “BIOS only” when empty default = ""
} }
variable "uefi_nvram_template" { variable "uefi_nvram_template" {
description = <<EOT description = <<EOT
Path to an NVRAM template that backs the UEFI NVRAM. Path to an NVRAM template that backs the UEFI NVRAM.
If you specify a template, the VM will get a writable NVRAM block. If you specify a template, the VM will get a writable NVRAM block.
Leave empty for a plain BIOS VM or if you dont need UEFI NVRAM. Leave empty for a plain BIOS VM or if you don't need UEFI NVRAM.
EOT EOT
type = string type = string
default = "" # no NVRAM when empty default = ""
} }
variable "uefi_nvram_file_suffix" { variable "uefi_nvram_file_suffix" {
@@ -135,7 +137,71 @@ variable "uefi_nvram_file_suffix" {
default = "" default = ""
} }
# Computed variable for network domain (derived from vm_name) # Computed variable for network domain (derived from vm_name)
locals { locals {
computed_network_domain = var.network_domain != "" ? var.network_domain : "${var.vm_name}.local" computed_network_domain = var.network_domain != "" ? var.network_domain : "${var.vm_name}.local"
# List of common UEFI firmware paths in order of preference
uefi_firmware_paths = [
"/usr/share/edk2/ovmf/OVMF_CODE.4m.fd",
"/usr/share/edk2/x64/OVMF_CODE.4m.fd",
"/usr/share/OVMF/OVMF_CODE.4m.fd",
"/usr/share/ovmf/OVMF_CODE.4m.fd",
"/usr/share/edk2/ovmf/OVMF_CODE.fd",
"/usr/share/edk2/x64/OVMF_CODE.fd",
"/usr/share/OVMF/OVMF_CODE.fd",
"/usr/share/ovmf/OVMF_CODE.fd"
]
uefi_nvram_paths = [
"/usr/share/edk2/ovmf/OVMF_VARS.4m.fd",
"/usr/share/edk2/x64/OVMF_VARS.4m.fd",
"/usr/share/OVMF/OVMF_VARS.4m.fd",
"/usr/share/ovmf/OVMF_VARS.4m.fd",
"/usr/share/edk2/ovmf/OVMF_VARS.fd",
"/usr/share/edk2/x64/OVMF_VARS.fd",
"/usr/share/OVMF/OVMF_VARS.fd",
"/usr/share/ovmf/OVMF_VARS.fd"
]
# Helper function to find first existing file
find_first_existing = {
for path in local.uefi_firmware_paths :
path => true if fileexists(path)
}
# Function to get first available firmware path or null
detected_firmware = (
var.uefi_firmware == "true" || var.uefi_firmware == "" ? (
length(local.find_first_existing) > 0 ?
keys(local.find_first_existing)[0] :
null
) : (
var.uefi_firmware != "" ? var.uefi_firmware : null
)
)
# Same for NV-RAM template
find_first_nvram = {
for path in local.uefi_nvram_paths :
path => true if fileexists(path)
}
detected_nvram = (
var.uefi_firmware == "true" || var.uefi_firmware == "" ? (
length(local.find_first_nvram) > 0 ?
keys(local.find_first_nvram)[0] :
null
) : (
var.uefi_nvram_template != "" ? var.uefi_nvram_template : null
)
)
# Validate that both firmware and NVRAM are provided together if one is specified
firmware_and_nvram_valid = (
(local.detected_firmware != null && local.detected_nvram == null) ||
(local.detected_firmware == null && local.detected_nvram == null) ||
(local.detected_firmware != null && local.detected_nvram != null)
)
} }