Unix & Linux Stack Exchange
Q&A for users of Linux, FreeBSD and other Unix-like operating systems
Latest Questions
0
votes
1
answers
38
views
terraform resource dependency with count(loop)
I'm trying to create stack of multiple vms on KVM_HOST with terraform. The catch is, I'm using pxeboot & kickstart to do installation. Kickstart file needs to carry some dynamic information, like static IPs, hostname etc, therefore I have to create it for each vm, and this kickstart file needs to st...
I'm trying to create stack of multiple vms on KVM_HOST with terraform. The catch is, I'm using pxeboot & kickstart to do installation. Kickstart file needs to carry some dynamic information, like static IPs, hostname etc, therefore I have to create it for each vm, and this kickstart file needs to stay there till vm reads it & starts installation. Then next kickstart file is created for vm 2, and it needs to stay there till vm2 reads it for installation. So there should be some delay in creating these resources, either with loop or depend_on parameter, but what I'm getting is, kickstart files for all vms are generated right away, last one is overriding, of course, so correct info is not passed.
here's two resources which I need to loop in sequence for number of variable value qty
variable "vm_count" {
type = number
default = 1
}
below are resources
resource "null_resource" "delay" {
count = var.vm_count
provisioner "local-exec" {
command = "sleep 150"
}
depends_on = [libvirt_domain.vm]
}
resource "local_file" "kickstart_file" {
count = var.vm_count
content = templatefile("ks.tpl", {
ip = "192.168.1.${117 + count.index}"
netmask = var.netmask
gateway = var.gateway
dns = var.dns
hostname = "${var.hostname}-${count.index + 1}"
disk_size_rounded = ((var.disk_size - 1) * 1024) -1
})
filename = "/var/www/html/kickstart/ks-terraform.cfg"
}
resource "libvirt_domain" "vm" {
count = var.vm_count
name = "${var.hostname}-${count.index + 1}"
memory = var.memory
vcpu = var.cpu
arch = "x86_64"
cpu {
mode = "host-passthrough"
}
boot_device {
dev = ["hd", "network"]
}
disk {
volume_id = libvirt_volume.default_disk[count.index].id
}
graphics {
type = "vnc"
listen_type = "address"
autoport = true
}
network_interface {
bridge = "virbr0"
macvtap = false
}
depends_on = [local_file.kickstart_file, null_resource.delay]
}
how can I improve the logic with depends on or for_each?
Sollosa
(1993 rep)
Feb 11, 2025, 02:11 PM
• Last activity: Feb 11, 2025, 07:18 PM
0
votes
0
answers
46
views
how to make terraform pass static IP information to kvm virtual machine with variables, in a kickstart pxeboot enabled env?
I have a kvm host, with bridge network, so the vms get IP info directly from router itself. I have created a pxeboot env with dnsmasq acting as dhcp proxy, and kickstart as method of installation passed via pxeboot menu. So far all working fine. but here's the problem, whenever I want to set static...
I have a kvm host, with bridge network, so the vms get IP info directly from router itself.
I have created a pxeboot env with dnsmasq acting as dhcp proxy, and kickstart as method of installation passed via pxeboot menu. So far all working fine.
but here's the problem, whenever I want to set static IP on a vm, I have to modify kickstart file with IP information. this is manageable for small number of vms, but now I introduced terraform for vm provisioning , and I want IP information to be passed on with use of terraform variables to kickstart file.
so below is line of kickstart with static IP info
network --bootproto=static --device=enp1s0 --ip=192.168.1.220 --netmask=255.255.255.0 --gateway=192.168.1.1 --nameserver=8.8.8.8 --noipv6 --activate
and here's variables that I have defined in terraform code
variable "vm_ip" {
default = "192.168.1.200"
}
variable "vm_netmask" {
default = "255.255.255.0"
}
variable "gat_eway" {
default = "192.168.1.1"
}
variable "name_server" {
default = "8.8.8.8"
}
any idea how to pass these variables to kickstart, so vm can get static IP with use of terraform variables?
Sollosa
(1993 rep)
Feb 3, 2025, 06:48 PM
• Last activity: Feb 3, 2025, 08:11 PM
0
votes
5
answers
137
views
How can I replace the last occurrence of " before ] (text-manipulation)
I'm doing some text manipulation and I want to replace the last occurrence of `"` (with `", "four"`) before `]` which could be in different lines. (this essentially adds a new item in the array) e.g: array = ["one", "two", "three"] other_array = ["one", "two", "three"] array = ["one", "two", "three"...
I'm doing some text manipulation and I want to replace the last occurrence of
"
(with ", "four"
) before ]
which could be in different lines. (this essentially adds a new item in the array)
e.g:
array = ["one", "two", "three"]
other_array = ["one", "two", "three"]
array = ["one", "two",
"three"]
array =
[
"one",
"two",
"three"
]
array = ["one", "two",
"three"
]
should become
array = ["one", "two", "three", "four"]
other_array = ["one", "two", "three"]
array = ["one", "two",
"three", "four"]
array =
[
"one",
"two",
"three", "four"
]
array = ["one", "two",
"three", "four"
]
P.S: -We are guaranteed to get a valid array so array = ["one", "two]", "three"]
is invalid as strings inside the array follow this pattern [a-zA-Z0-9] so you are guaranteed to get that
-Also note that they are other arrays but the one i'm interested in is an array named "array" which is unique.
Tried sed
#this works for the first scenario:
sed 's/\(array.*"\)\([^"]*]\)/\1, "newItem"\2/' file.txt
# but couldn't figure out how to do this for scenarios #2 & #3
kyles
(33 rep)
May 6, 2024, 09:29 AM
• Last activity: May 7, 2024, 05:08 PM
2
votes
2
answers
1455
views
cloudinit does not run for qemu/kvm systems created by terraform and libvirt provider
I'm trying to provision a VM on qemu/kvm hypervisor using cloudinit with terraform and the libvirt provider. I can get the machine to start, but the cloudinit is not getting kicked off. I know that the user-data being used will work as I've tested it without using terraform, but instead using kvm to...
I'm trying to provision a VM on qemu/kvm hypervisor using cloudinit with terraform and the libvirt provider. I can get the machine to start, but the cloudinit is not getting kicked off. I know that the user-data being used will work as I've tested it without using terraform, but instead using kvm to spin up a machine with a second terminal running a web server to server up the user-data file. All of this is being performed on Ubuntu 18.04.
I've tried this using cloud images for ubuntu and centos. Both will create the VM and boot up to the login prompt. Neither will actually provision the contents of the user-data though. I've also tried this using a lower version of the libvirt provider (of those still available) to the same results.
I've done some extensive searching trying to see if anyone else has similar issues. Most of the sites/questions I've found were from StackExchange sites, as well as github issues and bug reports, which I didn't capture to document unfortunately. All of them tend to be something in the user-data that is missing. None of them have been using the version of the libvirt provider I am, but instead almost always version 0.6.2. I tried to use that version of the provider in my main.tf file, but the init command returns an error that the version doesn't exist and can't be downloaded.
main.tf (only difference between centos and ubuntu is the cloud image file/location and prefix variable)
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
version = "0.7.0"
}
}
}
# instantiate the provider
provider "libvirt" {
uri = "qemu:///system"
}
variable "prefix" {
default = "terraform_centos"
}
data "template_file" "user_data" {
template = file("${path.module}/cloud_init.cfg")
}
resource "libvirt_cloudinit_disk" "commoninit" {
name = "commoninit.iso"
user_data = data.template_file.user_data.rendered
}
resource "libvirt_volume" "qcow_volume" {
name = "${var.prefix}.img"
source = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 "
format = "qcow2"
}
resource "libvirt_domain" "centos" {
name = var.prefix
vcpu = 2
memory = 4096
disk {
volume_id = libvirt_volume.qcow_volume.id
}
cloudinit = libvirt_cloudinit_disk.commoninit.id
console {
type = "pty"
target_port = "0"
target_type = "serial"
}
console {
type = "pty"
target_type = "virtio"
target_port = "1"
}
network_interface {
network_name = "default"
}
}
user-data file (as with main.tf, only changes between the two distros being tested is the hostname)
-yaml
#cloud-config
autoinstall:
version: 1
identity:
hostname: terraform_centos
username: vagrant
password: $6$dnWt7N17fTD$8.m3Rgf400iSyxLa/kUtunGUgE3N4foSg/y31HNnsGBUTpoMOmS3O9U/nJFvZjXpQTrLFrAcK5vok5EI0KZA90
locale: en_US
keyboard:
layout: us
ssh:
install-server: true
authorized-keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
allow-pw: true
storage:
layout:
name: direct
packages:
- gcc
- build-essential
late-commands:
- "echo 'vagrant ALL=(ALL) NOPASSWD: ALL' >> /target/etc/sudoers.d/vagrant"
- "chmod 440 /target/etc/sudoers.d/vagrant"
Finally, the kvm command that actually gets cloudinit to work. This is after starting a quick python web server in another shell. Along with mounting the iso image into /mnt so that the kernel/initrd will be accessible.
-bash
kvm -no-reboot -m 4096 -drive file=focal.img,format=raw,cache=none,if=virtio -cdrom ~/isoImages/ubuntu-20.04.5-live-server-amd64.iso -kernel /mnt/casper/vmlinuz -initrd /mnt/casper/initrd -append 'autoinstall ds=nocloud-net;s=http://_gateway:3003/ ' -vnc :1
Qemu/kvm version info
$ virsh version
Compiled against library: libvirt 4.0.0
Using library: libvirt 4.0.0
Using API: QEMU 4.0.0
Running hypervisor: QEMU 2.11.1
Terraform version info
$ terraform version
Terraform v1.3.6
on linux_amd64
+ provider registry.terraform.io/dmacvicar/libvirt v0.7.0
+ provider registry.terraform.io/hashicorp/template v2.2.0
Because I'm using cloud images for the two distros, there isn't a default username/password that I can log in with to check logs on the VM directly. I do have access to the console via virt-manager and the virsh console command. Both are sitting at a login prompt, at which the vagrant user returns a login incorrect message.
If any further information is needed, please let me know. I'm open to suggestions on what needs to be done to get this to work.
Jonathan Heady
(121 rep)
Dec 16, 2022, 07:27 PM
• Last activity: Nov 7, 2023, 11:47 PM
2
votes
0
answers
2051
views
partitionning additional disks as LVM with cloud-init
I'm using terraform and cloud-init to setup new VMs. I want to have additional disks setup and mounted in the new VM, with XFS partitions on top of LVM. Right now the only way I've found that allows me to do that is with this: ``` runcmd: - [ sgdisk, -e, /dev/sdb ] - [ sgdisk, -e, /dev/sdc ] - [ par...
I'm using terraform and cloud-init to setup new VMs.
I want to have additional disks setup and mounted in the new VM, with XFS partitions on top of LVM.
Right now the only way I've found that allows me to do that is with this:
runcmd:
- [ sgdisk, -e, /dev/sdb ]
- [ sgdisk, -e, /dev/sdc ]
- [ partprobe ]
- [ parted, -s, /dev/sdb, unit, mib, mkpart, primary, '1', "100%" ]
- [ parted, -s, /dev/sdc, unit, mib, mkpart, primary, '1', "100%" ]
- [ parted, -s, /dev/sdb, set, "1", lvm, "on" ]
- [ parted, -s, /dev/sdc, set, "1", lvm, "on" ]
- [ pvcreate, /dev/sdb1 ]
- [ pvcreate, /dev/sdc1 ]
- [ vgcreate, u01, /dev/sdb1]
- [ vgcreate, u02, /dev/sdc1]
- [ lvcreate, -l, "100%FREE", -n, oradata, u01]
- [ lvcreate, -l, "100%FREE", -n, backup, u02]
- [ mkfs.xfs, /dev/mapper/u01-oradata ]
- [ mkfs.xfs, /dev/mapper/u02-backup ]
- [ mount, -a ]
Is there any way I can use the disk_setup/fs_setup for this?
Edzilla
(21 rep)
Oct 12, 2023, 08:19 PM
• Last activity: Oct 12, 2023, 08:20 PM
0
votes
0
answers
184
views
Stopping parameter expansion in write_file content of cloud-init userdata
## Background I'm using Terraform and cloud-init to provision an Ubuntu VM. The Terraform template contains an embedded cloud-init `user_data` section that contains a `write_file` directive to write a bash script. The hierarchy looks like this: - Terraform template - cloud-init user_data - write_con...
## Background
I'm using Terraform and cloud-init to provision an Ubuntu VM.
The Terraform template contains an embedded cloud-init
user_data
section that contains a write_file
directive to write a bash script. The hierarchy looks like this:
- Terraform template
- cloud-init user_data
- write_content
- bash script
Inside the bash script, I have the following function
mkcd() {
mkdir -p "${1}"
cd "${1}"
}
## Problem and question
When the file is written inside the VM, it looks like this:
mkcd() {
mkdir -p "1"
cd "1"
}
The ${1}
is replaced with just a 1
. The desired behavior is to have the function appear in the written file exactly as it appears in the Terraform template.
**How do I get the function to appear in the written file exactly like this?:**
mkcd() {
mkdir -p "${1}"
cd "${1}"
}
## Troubleshooting
I have also tried this:
mkcd() {
mkdir -p "$\{1}"
cd "$\{1}"
}
The file is written exactly as shown, with the backslashes retained.
McKenzieCarr
(1 rep)
Mar 12, 2023, 07:48 PM
1
votes
1
answers
587
views
assign IP to kvm guest on bridge (terrafom)
I am trying to deploy VM guest via terraform on KVM. the guest VM is deployed but does not get an IP. what am I doing wrong? here is my main.tf : ``` terraform { required_providers { libvirt = { source = "dmacvicar/libvirt" } } } provider "libvirt" { uri = "qemu:///system" } resource "libvirt_volume...
I am trying to deploy VM guest via terraform on KVM.
the guest VM is deployed but does not get an IP.
what am I doing wrong?
here is my main.tf :
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
}
}
}
provider "libvirt" {
uri = "qemu:///system"
}
resource "libvirt_volume" "centos7-qcow2" {
name = "centos7.qcow2"
pool = "default"
source = "http://......qcow2 "
format = "qcow2"
}
data "template_file" "user_data" {
template = "${file("${path.module}/cloud_init.cfg")}"
}
data "template_file" "cloudinit_network" {
template = "${file("${path.module}/network.cfg")}"
vars = {}
}
resource "libvirt_cloudinit_disk" "commoninit" {
name = "commoninit.iso"
user_data = "${data.template_file.user_data.rendered}"
network_config = data.template_file.cloudinit_network.rendered
}
resource "libvirt_domain" "gw2" {
name = "gw2"
memory = "8192"
vcpu = 4
cloudinit = libvirt_cloudinit_disk.commoninit.id
qemu_agent = true
network_interface {
addresses = ["10.100.86.201"]
bridge = "br0"
#wait_for_lease = true
}
boot_device {
dev = [ "hd", "network"]
}
disk {
volume_id = "${libvirt_volume.centos7-qcow2.id}"
}
console {
type = "pty"
target_type = "serial"
target_port = "0"
}
graphics {
type = "spice"
listen_type = "address"
autoport = true
}
}
output "ips" {
value = libvirt_domain.gw2.*.network_interface.0.addresses
}
my network.cfg file:
version: 2
ethernets:
eth0:
dhcp4: true
dhcp6: false
Thank you for the help!
___________________
my terraform version:
Terraform v1.0.10
on linux_amd64
+ provider registry.terraform.io/dmacvicar/libvirt v0.6.11
+ provider registry.terraform.io/hashicorp/template v2.2.0
user536811
(11 rep)
Aug 8, 2022, 02:22 PM
• Last activity: Mar 2, 2023, 03:56 PM
1
votes
0
answers
267
views
Unable to redirect stdout for background terraform process after it received input from named pipe
I have a terraform file: ```terraform terraform { required_version = "1.3.5" } locals { a = "foo" b = "bar" } ``` in a bash terminal, I can do: ```bash $ echo "local.a" | terraform console "foo" $ echo "local.b" | terraform console "bar" ``` Now what I'm trying to do is start a process running `terr...
I have a terraform file:
terraform {
required_version = "1.3.5"
}
locals {
a = "foo"
b = "bar"
}
in a bash terminal, I can do:
$ echo "local.a" | terraform console
"foo"
$ echo "local.b" | terraform console
"bar"
Now what I'm trying to do is start a process running terraform console
in the background and feed it commands.
This is what I've tried (following this answer https://serverfault.com/a/815253) :
$ mkfifo /tmp/srv-input
$ tail -f /tmp/srv-input | terraform console >>output.txt 2>&1 &
this starts the background process correctly:
$ ps -ax | grep terraform
6030 pts/0 Sl 0:01 terraform console
if I then run:
$ echo "local.a" > /tmp/srv-input
the output file, output.txt
is empty.
$ cat output.txt
$
If I run:
$ echo "local.c" > /tmp/srv-input # invalid input
the output file, output.txt
contains the (expected) error:
$ cat output.txt
╷
│ Error: Reference to undeclared local value
│
│ on line 1:
│ (source code not available)
│
│ A local value with the name "c" has not been declared. Did you mean "a"?
╵
+ Exit 1 tail -f /tmp/srv-input | terraform console >> output.txt 2>&1
----------
Why is only the stderr being redirected to the log file, but not stdout?
Foo
(242 rep)
Dec 15, 2022, 02:07 PM
1
votes
0
answers
37
views
Deploy new instances with the same terraform file without damaging the old one's
I am using a terraform file to deploy 2 VM instances in parallel (on KVM). now I need to deploy another 2 VM instances with the same terraform file. how can I do this without damaging the old instances? when running again the "terraform apply" command, it recreated the old machines... Thanks for the...
I am using a terraform file to deploy 2 VM instances in parallel (on KVM).
now I need to deploy another 2 VM instances with the same terraform file.
how can I do this without damaging the old instances?
when running again the "terraform apply" command, it recreated the old machines...
Thanks for the answers!
Orly Orly
(123 rep)
Nov 13, 2022, 09:01 AM
Showing page 1 of 9 total questions