cli: implement qemu direct linux boot

This commit is contained in:
Malte Poll 2023-05-16 14:13:10 +02:00 committed by Malte Poll
parent daea874b46
commit 79986a2b25
7 changed files with 188 additions and 44 deletions

View File

@ -464,8 +464,11 @@ func (c *Creator) createQEMU(ctx context.Context, cl terraformClient, lv libvirt
CountWorkers: opts.WorkerCount,
StateDiskSizeGB: opts.Config.StateDiskSizeGB,
},
LibvirtURI: libvirtURI,
LibvirtSocketPath: libvirtSocketPath,
LibvirtURI: libvirtURI,
LibvirtSocketPath: libvirtSocketPath,
// TODO(malt3): auto select boot mode based on attestation variant.
// requires image info v2.
BootMode: "uefi",
ImagePath: imagePath,
ImageFormat: opts.Config.Provider.QEMU.ImageFormat,
CPUCount: opts.Config.Provider.QEMU.VCPUs,
@ -474,6 +477,11 @@ func (c *Creator) createQEMU(ctx context.Context, cl terraformClient, lv libvirt
MetadataLibvirtURI: metadataLibvirtURI,
NVRAM: opts.Config.Provider.QEMU.NVRAM,
Firmware: opts.Config.Provider.QEMU.Firmware,
// TODO(malt3) enable once we have a way to auto-select values for these
// requires image info v2.
// BzImagePath: placeholder,
// InitrdPath: placeholder,
// KernelCmdline: placeholder,
}
if err := cl.PrepareWorkspace(path.Join("terraform", strings.ToLower(cloudprovider.QEMU.String())), &vars); err != nil {

View File

@ -52,37 +52,45 @@ resource "docker_container" "qemu_metadata" {
module "control_plane" {
source = "./modules/instance_group"
role = "control-plane"
amount = var.control_plane_count
vcpus = var.vcpus
memory = var.memory
state_disk_size = var.state_disk_size
cidr = "10.42.1.0/24"
network_id = libvirt_network.constellation.id
pool = libvirt_pool.cluster.name
boot_volume_id = libvirt_volume.constellation_os_image.id
machine = var.machine
firmware = var.firmware
nvram = var.nvram
name = var.name
source = "./modules/instance_group"
role = "control-plane"
amount = var.control_plane_count
vcpus = var.vcpus
memory = var.memory
state_disk_size = var.state_disk_size
cidr = "10.42.1.0/24"
network_id = libvirt_network.constellation.id
pool = libvirt_pool.cluster.name
boot_mode = var.constellation_boot_mode
boot_volume_id = libvirt_volume.constellation_os_image.id
kernel_volume_id = local.kernel_volume_id
initrd_volume_id = local.initrd_volume_id
kernel_cmdline = local.kernel_cmdline
machine = var.machine
firmware = var.firmware
nvram = var.nvram
name = var.name
}
module "worker" {
source = "./modules/instance_group"
role = "worker"
amount = var.worker_count
vcpus = var.vcpus
memory = var.memory
state_disk_size = var.state_disk_size
cidr = "10.42.2.0/24"
network_id = libvirt_network.constellation.id
pool = libvirt_pool.cluster.name
boot_volume_id = libvirt_volume.constellation_os_image.id
machine = var.machine
firmware = var.firmware
nvram = var.nvram
name = var.name
source = "./modules/instance_group"
role = "worker"
amount = var.worker_count
vcpus = var.vcpus
memory = var.memory
state_disk_size = var.state_disk_size
cidr = "10.42.2.0/24"
network_id = libvirt_network.constellation.id
pool = libvirt_pool.cluster.name
boot_mode = var.constellation_boot_mode
boot_volume_id = libvirt_volume.constellation_os_image.id
kernel_volume_id = local.kernel_volume_id
initrd_volume_id = local.initrd_volume_id
kernel_cmdline = var.constellation_cmdline
machine = var.machine
firmware = var.firmware
nvram = var.nvram
name = var.name
}
resource "libvirt_pool" "cluster" {
@ -98,6 +106,22 @@ resource "libvirt_volume" "constellation_os_image" {
format = var.image_format
}
resource "libvirt_volume" "constellation_kernel" {
name = "${var.name}-kernel"
pool = libvirt_pool.cluster.name
source = var.constellation_kernel
format = "raw"
count = var.constellation_boot_mode == "direct-linux-boot" ? 1 : 0
}
resource "libvirt_volume" "constellation_initrd" {
name = "${var.name}-initrd"
pool = libvirt_pool.cluster.name
source = var.constellation_initrd
format = "raw"
count = var.constellation_boot_mode == "direct-linux-boot" ? 1 : 0
}
resource "libvirt_network" "constellation" {
name = "${var.name}-network"
mode = "nat"
@ -109,3 +133,9 @@ resource "libvirt_network" "constellation" {
enabled = true
}
}
locals {
kernel_volume_id = var.constellation_boot_mode == "direct-linux-boot" ? libvirt_volume.constellation_kernel[0].id : null
initrd_volume_id = var.constellation_boot_mode == "direct-linux-boot" ? libvirt_volume.constellation_initrd[0].id : null
kernel_cmdline = var.constellation_boot_mode == "direct-linux-boot" ? var.constellation_cmdline : null
}

View File

@ -7,22 +7,29 @@ terraform {
}
}
locals {
state_disk_size_byte = 1073741824 * var.state_disk_size
ip_range_start = 100
}
resource "libvirt_domain" "instance_group" {
name = "${var.name}-${var.role}-${count.index}"
count = var.amount
memory = var.memory
vcpu = var.vcpus
machine = var.machine
firmware = var.firmware
nvram {
file = "/var/lib/libvirt/qemu/nvram/${var.role}-${count.index}_VARS.fd"
template = var.nvram
firmware = local.firmware
dynamic "nvram" {
for_each = var.boot_mode == "uefi" ? [1] : []
content {
file = "/var/lib/libvirt/qemu/nvram/${var.role}-${count.index}_VARS.fd"
template = var.nvram
}
}
dynamic "xml" {
for_each = var.boot_mode == "uefi" ? [1] : []
content {
xslt = file("${path.module}/domain.xsl")
}
}
kernel = local.kernel
initrd = local.initrd
cmdline = local.cmdline
tpm {
backend_type = "emulator"
backend_version = "2.0"
@ -44,9 +51,6 @@ resource "libvirt_domain" "instance_group" {
type = "pty"
target_port = "0"
}
xml {
xslt = file("${path.module}/domain.xsl")
}
}
resource "libvirt_volume" "boot_volume" {
@ -63,3 +67,12 @@ resource "libvirt_volume" "state_volume" {
size = local.state_disk_size_byte
format = "qcow2"
}
locals {
state_disk_size_byte = 1073741824 * var.state_disk_size
ip_range_start = 100
kernel = var.boot_mode == "direct-linux-boot" ? var.kernel_volume_id : null
initrd = var.boot_mode == "direct-linux-boot" ? var.initrd_volume_id : null
cmdline = var.boot_mode == "direct-linux-boot" ? [{ "_" = var.kernel_cmdline }] : null
firmware = var.boot_mode == "uefi" ? var.firmware : null
}

View File

@ -33,11 +33,38 @@ variable "pool" {
description = "name of the storage pool to use"
}
variable "boot_mode" {
type = string
description = "boot mode. Can be 'uefi' or 'direct-linux-boot'"
validation {
condition = can(regex("^(uefi|direct-linux-boot)$", var.boot_mode))
error_message = "boot_mode must be 'uefi' or 'direct-linux-boot'"
}
}
variable "boot_volume_id" {
type = string
description = "id of the constellation boot disk"
}
variable "kernel_volume_id" {
type = string
description = "id of the constellation kernel volume"
default = ""
}
variable "initrd_volume_id" {
type = string
description = "id of the constellation initrd volume"
default = ""
}
variable "kernel_cmdline" {
type = string
description = "kernel cmdline"
default = ""
}
variable "role" {
type = string
description = "role of the node in the constellation. either 'control-plane' or 'worker'"
@ -50,7 +77,7 @@ variable "machine" {
variable "firmware" {
type = string
description = "path to UEFI firmware file."
description = "path to UEFI firmware file. Ignored for direct-linux-boot."
}
variable "nvram" {
@ -62,4 +89,3 @@ variable "name" {
type = string
description = "name prefix of the cluster VMs"
}

View File

@ -10,3 +10,27 @@ output "initSecret" {
value = random_password.initSecret.result
sensitive = true
}
output "validate_constellation_kernel" {
value = null
precondition {
condition = var.constellation_boot_mode != "direct-linux-boot" || length(var.constellation_kernel) > 0
error_message = "constellation_kernel must be set if constellation_boot_mode is 'direct-linux-boot'"
}
}
output "validate_constellation_initrd" {
value = null
precondition {
condition = var.constellation_boot_mode != "direct-linux-boot" || length(var.constellation_initrd) > 0
error_message = "constellation_initrd must be set if constellation_boot_mode is 'direct-linux-boot'"
}
}
output "validate_constellation_cmdline" {
value = null
precondition {
condition = var.constellation_boot_mode != "direct-linux-boot" || length(var.constellation_cmdline) > 0
error_message = "constellation_cmdline must be set if constellation_boot_mode is 'direct-linux-boot'"
}
}

View File

@ -3,11 +3,41 @@ variable "libvirt_uri" {
description = "libvirt socket uri"
}
variable "constellation_boot_mode" {
type = string
description = "constellation boot mode. Can be 'uefi' or 'direct-linux-boot'"
validation {
condition = anytrue([
var.constellation_boot_mode == "uefi",
var.constellation_boot_mode == "direct-linux-boot",
])
error_message = "constellation_boot_mode must be 'uefi' or 'direct-linux-boot'"
}
}
variable "constellation_os_image" {
type = string
description = "constellation OS file path"
}
variable "constellation_kernel" {
type = string
description = "constellation Kernel file path"
default = ""
}
variable "constellation_initrd" {
type = string
description = "constellation initrd file path"
default = ""
}
variable "constellation_cmdline" {
type = string
description = "constellation kernel cmdline"
default = ""
}
variable "image_format" {
type = string
default = "qcow2"

View File

@ -280,6 +280,9 @@ type QEMUVariables struct {
LibvirtURI string
// LibvirtSocketPath is the path to the libvirt socket in case of unix socket.
LibvirtSocketPath string
// BootMode is the boot mode to use.
// Can be either "uefi" or "direct-linux-boot".
BootMode string
// CPUCount is the number of CPUs to allocate to each node.
CPUCount int
// MemorySizeMiB is the amount of memory to allocate to each node, in MiB.
@ -298,6 +301,12 @@ type QEMUVariables struct {
NVRAM string
// Firmware is the path to the firmware.
Firmware string
// BzImagePath is the path to the bzImage (kernel).
BzImagePath string
// InitrdPath is the path to the initrd.
InitrdPath string
// KernelCmdline is the kernel command line.
KernelCmdline string
}
// String returns a string representation of the variables, formatted as Terraform variables.
@ -308,6 +317,10 @@ func (v *QEMUVariables) String() string {
writeLinef(b, "libvirt_socket_path = %q", v.LibvirtSocketPath)
writeLinef(b, "constellation_os_image = %q", v.ImagePath)
writeLinef(b, "image_format = %q", v.ImageFormat)
writeLinef(b, "constellation_boot_mode = %q", v.BootMode)
writeLinef(b, "constellation_kernel = %q", v.BzImagePath)
writeLinef(b, "constellation_initrd = %q", v.InitrdPath)
writeLinef(b, "constellation_cmdline = %q", v.KernelCmdline)
writeLinef(b, "vcpus = %d", v.CPUCount)
writeLinef(b, "memory = %d", v.MemorySizeMiB)
writeLinef(b, "metadata_api_image = %q", v.MetadataAPIImage)