This is a demo chunk of terraform code that I wrote to easily manage VM's on a Qemu hypervisor. It has some kludge workarounds for some of the shortfalls of the qemu terraform provider. These are mainly:
- attaching virtual disks to a common ancestor COW file
- attaching disks with the correct subdriver
The intended operation of this TF code is that virtual machines can be created by populating one single tfvars file with the desired specs, and then running terraform plan/apply.
This assumes that the user has created a golden image which has cloud-init which has been re-armed to allow running the initial cloud-init config. You can make such a golden image by running through an install of your favorite debian flavored OS (I used Ubuntu) And then run the following to re-arm cloud-init:
apt update && apt -y upgrade && apt -y autoremove && apt clean
userdel -r sysprep
truncate -s0 /etc/hostname
hostnamectl set-hostname localhost
rm /etc/netplan/50-cloud-init.yaml
truncate -s0 /etc/machine-id
rm /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id
cloud-init clean
passwd -dl root
truncate -s0 ~/.bash_history
history -c
shutdown -h now
The cloud-init ISO can be auto-generated, or manually populated with user-supplied files, depending on the variable. If you supply your own cloud-init files, they should be in:
${path.module}/cloudinit_data/${systemName}_network_config
${path.module}/cloudinit_data/${systemName}_user_data
Note: if you set generateCloudInit to false, and these files are not present, terraform will fail!
There are a set of handy bash scripts for generating these files from a template:
generate_netconfig.sh
generate_userdata.sh
These scripts will use the template files in ./cloudinit_data/ The templates are set up for my particular hypervisor network The example cookie2 cloud-init files were generated by running these scripts as such:
./generate_netconfig.sh 192.168.202.51 cookie2
./generate_userdata.sh cookie2
My particular hypervisor was named "rainbow1", which is why that name appears all over.
Variables:
createsize = "200G" # Used in remote-exec, passed as an arg to the qemu-img command to resize a newly created image
systemName = "cookie3" # Used everywhere to name a VM, all of its associated files, and DNS record
systemDescription = "Brought up by terraform" # Sets the domain description in QEMU
memoryMB = 4096 # Sets the RAM allocated to the domain
vcpu = 4 # Sets the number of number of threads allocated to the domain
networkBridge = "br101" # Name of the network bridge on the hypervisor to connect the VM to
baseImageFile = "CookieCutterV3.qcow2" # Name of the golden image file to use as a COW base
qemu_agent = false # Enable or disable the hypervisor's communication to qemu agent on the VM
cpuSpecsmode = "host-passthrough" # sets the CPU mode of the domain
makeAutoStart = true # sets the autostart value of the domain
makeRunning = true # sets the running value of the domain (can be used to create a VM without starting it)
IPAddress = "192.168.202.52" # Populates the cloud-init config passed to the VM, if using auto generated CloudInit, also used to create DNS record
generateCloudInit = true # If True, terraform will generate the cloud-init ISO from these variables. If False, it will build an ISO from supplied files