#!/bin/bash # Note: Not using 'set -e' here because we handle errors explicitly # and arithmetic operations can cause false failures with set -e VM_NAME="$1" GOLDEN_IMAGE="$2" MAX_WAIT="${3:-30}" if [ -z "$VM_NAME" ] || [ -z "$GOLDEN_IMAGE" ]; then echo "Usage: $0 [max_wait_seconds]" exit 1 fi echo "[Provision] Creating VM: $VM_NAME" # Create linked clone (very fast - just a pointer to base) VM_DISK="/var/lib/libvirt/images/${VM_NAME}.qcow2" echo "[Provision] Creating overlay disk: $VM_DISK" sudo qemu-img create -f qcow2 -b "$GOLDEN_IMAGE" -F qcow2 "$VM_DISK" 2>/dev/null # Define and start VM echo "[Provision] Starting VM with virt-install..." VIRT_INSTALL_OUTPUT=$(sudo virt-install \ --name "$VM_NAME" \ --memory 2048 \ --vcpus 2 \ --disk path="$VM_DISK",format=qcow2 \ --import \ --os-variant rocky9-unknown \ --network network=default \ --noautoconsole \ --wait 0 \ --transient \ 2>&1) || { echo "[Provision] ERROR: virt-install failed" echo "$VIRT_INSTALL_OUTPUT" | grep -v "WARNING" echo "[Provision] Cleaning up disk..." sudo rm -f "$VM_DISK" echo "ERROR" exit 1 } # Wait for IP address echo "[Provision] Waiting for VM to obtain IP address (max ${MAX_WAIT}s)..." COUNTER=0 while [ $COUNTER -lt $MAX_WAIT ]; do # Try to get IP from DHCP lease (explicitly use system connection) IP=$(sudo virsh -c qemu:///system domifaddr "$VM_NAME" --source lease 2>/dev/null | awk '/ipv4/ {print $4}' | cut -d/ -f1 | head -1) if [ -n "$IP" ] && [ "$IP" != "0.0.0.0" ]; then echo "[Provision] IP obtained: $IP" echo "$IP" exit 0 fi sleep 2 ((COUNTER++)) # Show progress every 5 iterations if [ $((COUNTER % 5)) -eq 0 ]; then echo "[Provision] Still waiting... (${COUNTER}/${MAX_WAIT}s)" fi done echo "[Provision] ERROR: Could not obtain IP for $VM_NAME after $MAX_WAIT seconds" echo "[Provision] Destroying failed VM..." sudo virsh destroy "$VM_NAME" 2>/dev/null || true sudo virsh undefine "$VM_NAME" 2>/dev/null || true sudo rm -f "$VM_DISK" echo "ERROR" exit 1