Gotcha: dmacvicar/libvirt provider v0.9.x API is completely different from v0.7/0.8¶
Symptom¶
Every resource in a config written for the old provider version fails:
An argument named "source" is not expected here.
An argument named "format" is not expected here.
An argument named "base_volume_id" is not expected here.
The argument "type" is required, but no definition was found.
Blocks of type "disk" are not expected here.
Root cause¶
The dmacvicar/libvirt provider v0.9.x was a major rewrite that maps
the HCL schema 1:1 to the libvirt XML structure, rather than providing
the higher-level abstractions of v0.7/v0.8. Almost every resource has
a different API.
Migration table¶
| v0.7/0.8 | v0.9.x |
|---|---|
libvirt_volume.source = "<path>" |
libvirt_volume.create = { content = { url = "<path>" } } |
libvirt_volume.format = "qcow2" |
libvirt_volume.target = { format = { type = "qcow2" } } |
libvirt_volume.base_volume_id = <id> |
libvirt_volume.backing_store = { path = <path>, format = { type = "qcow2" } } |
libvirt_volume.size = <bytes> |
libvirt_volume.capacity = <bytes> |
libvirt_cloudinit_disk.pool = "<pool>" |
Removed. Use path or upload to a volume separately. |
libvirt_cloudinit_disk.meta_data (optional) |
meta_data is now REQUIRED |
libvirt_domain.cloudinit = <id> |
Removed. Upload ISO into a libvirt_volume, attach as cdrom disk device. |
libvirt_domain.memory = 4096 (MiB implied) |
memory = 4096 + memory_unit = "MiB" (defaults to KiB!) |
libvirt_domain { disk { ... } } |
devices = { disks = [{ ... }] } |
libvirt_domain { network_interface { ... } } |
devices = { interfaces = [{ type = "network", source = { network = { network = "default" } }, model = { type = "virtio" } }] } |
libvirt_domain { console { ... } } |
devices = { consoles = [{ ... }] } |
libvirt_domain { graphics { ... } } |
devices = { graphics = [{ vnc = { auto_port = true, listen = "..." } }] } |
| (inferred from os type) | type = "kvm" is now REQUIRED |
network_interface[0].addresses[0] output |
Removed. Use virsh domifaddr or libvirt_domain_interface_addresses data source. |
boot_devices = ["hd"] |
boot_devices = [{ dev = "hd" }] (list of objects, not strings) |
How we figured it out¶
tofu providers schema -jsondumps the full schema from the installed provider- Extracted attribute names and types with a Python script
- For complex nested types (devices, os), extracted the full JSON structure
- Cross-referenced with the provider's GitHub repo examples
- Iterated: validate → fix → validate until clean
Critical: features and CPU mode¶
The v0.9.x provider does NOT set features { acpi; apic } or
cpu { mode = "host-passthrough" } by default. Without these, modern
Linux guests hang during GRUB boot. See grub-acpi-apic.md.
How to prevent¶
- Don't assume any attribute names from the old provider docs
- Always run
tofu validatebeforetofu apply - Use
tofu providers schema -jsonas the authoritative reference - Start with a minimal working config and add features incrementally
Environment¶
- dmacvicar/libvirt provider v0.9.7
- OpenTofu v1.11.6