-
Notifications
You must be signed in to change notification settings - Fork 496
Description
Problem
Hi there,
A lot of the devices in the examples (or, at least, the Alpine example - I haven't had time to look into the others yet) are invalid with v0.9.1 since they don't yet reflect the updated schema.
For example, in the alpine_cloudinit.tf sample, the disks are missing a nested volume object, the format parameters for disks are incorrect (the old syntax), and a lot of the devices are missing new nested objects or parameters, so the example fails to validate or apply.
I prepared a PR to update the Alpine example so it:
- properly nests the disk source pool and volume in a volume object
- reflects the changes to the libvirt_volume format parameter's syntax (libvirt_volume examples fail to validate in v0.9.1 due to format parameter changes #1241)
- reflects the changes to libvirt_domain devices {disk.source,interfaces,graphics}
- specifies driver="qcow2" for the VM's disk so libvirt doesn't try to boot it as "raw"
There's also a discrepancy with the format parameters in the backing_store and libvirt_volume itself, but I'm not sure if this is actually a problem.
Unsure if this affects other examples but I expect it does. Documentation is also affected.
env
My client machine is running Terraform 1.14, provider 0.9.1 on amd64 Linux, and the provider target is Alma (Rocky/RHEL) 10.1 with libvirt 11.5.0 (11.5.0-4.1.el10_1.alma.1).
Troubleshooting
Disk format
If this devices = { disks = [ { source = {} } ] } syntax is used, Terraform applies fail. The provider now expects a nested volume object (under source).
To reproduce from the example, I pulled down the Alpine example and changed only the provider to:
provider "libvirt" {
uri = "qemu+sshcmd://[email protected]/system"
}First, Terraform fails to apply thanks to the format parameter:
$ terraform apply
╷
│ Error: Unsupported argument
│
│ on main.tf line 17, in resource "libvirt_volume" "alpine_base":
│ 17: format = "qcow2"
│
│ An argument named "format" is not expected here.
╵Disk error is caused by this snippet (same case for both vda and the cdrom):
devices = {
disks = [
{ # root disk
source = {
pool = libvirt_volume.terraform-errata-root-disk.pool
volume = libvirt_volume.terraform-errata-root-disk.name
}
}
]
}Pointing source at a volume object works:
devices = {
disks = [
{ # root disk
source = {
volume = {
pool = libvirt_volume.terraform-errata-root-disk.pool
volume = libvirt_volume.terraform-errata-root-disk.name
}
}
}
]
}Relevant excerpt from the original example (nonfunctional):
devices = {
disks = [
{
source = {
pool = libvirt_volume.alpine_disk.pool
volume = libvirt_volume.alpine_disk.name
}
target = {
dev = "vda"
bus = "virtio"
}
},
{
device = "cdrom"
source = {
pool = libvirt_volume.alpine_seed_volume.pool
volume = libvirt_volume.alpine_seed_volume.name
}
target = {
dev = "sda"
bus = "sata"
}
}
]
}Device changes
After replacing format = "qcow2" with the new target = { format = { type = "qcow2" } }:
$ terraform apply
╷
│ Error: Missing required argument
│
│ on main.tf line 95, in resource "libvirt_domain" "alpine":
│ 95: resource "libvirt_domain" "alpine" {
│
│ The argument "type" is required, but no definition was found.
╵
╷
│ Error: Incorrect attribute value type
│
│ on main.tf line 106, in resource "libvirt_domain" "alpine":
│ 106: devices = {
│ 107: disks = [
│ 108: {
│ 109: source = {
│ 110: volume = {
│ 111: pool = libvirt_volume.alpine_disk.pool
│ 112: volume = libvirt_volume.alpine_disk.name
│ 113: }
│ 114: }
│ 115: target = {
│ 116: dev = "vda"
│ 117: bus = "virtio"
│ 118: }
│ 119: },
│ 120: {
│ 121: device = "cdrom"
│ 122: source = {
│ 123: volume = {
│ 124: pool = libvirt_volume.alpine_seed_volume.pool
│ 125: volume = libvirt_volume.alpine_seed_volume.name
│ 126: }
│ 127: }
│ 128: target = {
│ 129: dev = "sda"
│ 130: bus = "sata"
│ 131: }
│ 132: }
│ 133: ]
│ 134: interfaces = [
│ 135: {
│ 136: type = "network"
│ 137: model = "virtio"
│ 138: source = {
│ 139: network = "default"
│ 140: }
│ 141: }
│ 142: ]
│ 143: graphics = {
│ 144: vnc = {
│ 145: autoport = "yes"
│ 146: listen = "127.0.0.1"
│ 147: }
│ 148: }
│ 149: }
│
│ Inappropriate value for attribute "devices": attribute "interfaces": element 0: attribute "source":
│ attribute "network": object required, but have string.
╵After adding the type = "kvm" argument to the libvirt_domain definition and modifying the interfaces = [ { model, source } ] definitions from:
interfaces = [
{
type = "network"
model = "virtio"
source = {
network = "default"
}
}
]To:
interfaces = [
{
type = "network"
model = { type = "virtio" }
source = {
network = {
network = "default"
}
}
}
]I receive:
$ terraform apply
│ Inappropriate value for attribute "devices": attribute "graphics": list of object required.After changing:
graphics = {
vnc = {
autoport = "yes"
listen = "127.0.0.1"
}
}To:
graphics = [
{
type = "vnc"
vnc = {
autoport = true
listen = "127.0.0.1"
}
}
]Terraform successfully creates all the objects. However, the VM still doesn't boot; it can't read its boot device.
I found this is because, when the backing_store for a volume is defined as:
backing_store = {
path = libvirt_volume.alpine_base.path
source = {
format = {
type = "qcow2"
}
}
}The format parameter doesn't behave the same way as it does for a normal libvirt_volume.
Generated XML in the above case. Note the format type='raw'.
<disk type='volume' device='disk'>
<driver name='qemu' type='qcow2'/>
<source pool='default' volume='alpine-vm.qcow2' index='2'/>
<backingStore type='file' index='3'>
<format type='raw'/>
<source file='/var/lib/libvirt/images/alpine-3.22-base.qcow2'/>
<backingStore/>
</backingStore>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</disk>The backing_store works only if the source is removed (format is nested under just backing_store, not backing_store = { source = {} }:
backing_store = {
path = libvirt_volume.alpine_base.path
format = {
type = "qcow2"
}
}This is an example of the full XML for the disk (when working):
<disk type='volume' device='disk'>
<driver name='qemu' type='qcow2'/>
<source pool='default' volume='alpine-vm.qcow2' index='2'/>
<backingStore type='file' index='3'>
<format type='qcow2'/>
<source file='/var/lib/libvirt/images/alpine-3.22-base.qcow2'/>
<backingStore/>
</backingStore>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</disk>Seems a little odd to me that the format.type is nested under target in the provider, but I'm not sure if that's from the backing API or not.
Testing
Anyway, with all these changes, the VM now boots:
I will submit a PR shortly.