# node-vm: a single MAAS-managed OpenStack node VM (D-103's "OpenTofu creates
# the node-VM libvirt domains (SHIM -- Section 9)" -- Stage 3 / buildout-design
# Phase 2). BLANK disk, PXE-boot -- this is deliberately NOT the cloud-init +
# pre-built-image pattern (that's a separate, still-unbuilt module for Office1
# service VMs / OPNsense; see opentofu/README.md). MAAS enlists, commissions,
# and deploys these VMs after OpenTofu creates them; OpenTofu does not image
# them itself.
#
# Every attribute below is used exactly as shown in the provider's own
# examples/domain_with_network.tf and examples/alpine_cloudinit.tf (fetched
# and read directly this session, tag v0.9.8) -- attribute-style nested
# objects (`os = { ... }`, `devices = { ... }`), NOT classic HCL blocks. The
# ONE inference in this file, clearly marked below, is the per-device `boot`
# object's internal shape (`order`) -- confirmed to EXIST as a field name on
# both `interfaces` and `disks` entries (matching native libvirt's per-device
# <boot order='N'/>), but its exact internal shape was not independently
# confirmed from a real example. VERIFY with `tofu providers schema -json`
# before the first real apply; if wrong, `tofu plan` will simply reject the
# attribute name, not silently misconfigure anything.
resource "libvirt_volume" "disk" {
name = "${var.vm_name}-disk.qcow2"
pool = var.pool_name
capacity = var.disk_size_bytes
format = {
type = "qcow2"
}
}
resource "libvirt_domain" "node" {
name = var.vm_name
memory = var.memory_mib
vcpu = var.vcpu
type = "kvm"
running = true
os = {
type = "hvm"
type_arch = "x86_64"
type_machine = "q35"
}
devices = {
disks = [
{
source = {
volume = {
pool = libvirt_volume.disk.pool
volume = libvirt_volume.disk.name
}
}
target = {
dev = "vda"
bus = "virtio"
}
driver = {
type = "qcow2"
}
# boot.order shape UNVERIFIED (see file header) -- disk boots second,
# network boots first (PXE).
boot = {
order = 2
}
}
]
interfaces = [
for i, net_name in var.network_names : {
model = {
type = "virtio"
}
source = {
network = {
network = net_name
}
}
# only the first (PXE) interface gets an explicit boot order;
# see the disk boot-order note above for the same caveat.
boot = i == 0 ? { order = 1 } : null
}
]
}
}