#!/bin/bash set -e # Configuration VM_DIR="${VM_DIR:-$(pwd)/control-plane-vm}" CONTROLPLANE_NAME="talos-controlplane" MEMORY="2048" # 2GB per VM CPUS="2" DISK_SIZE="10G" # 10GB disk TALOS_ISO_URL="https://github.com/siderolabs/talos/releases/download/v1.11.0/metal-arm64.iso" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Create VM directory create_vm_dir() { local vm_name=$1 local vm_path="$VM_DIR/$vm_name" mkdir -p "$vm_path" echo "$vm_path" } # Download Talos ISO if not exists download_talos_iso() { local iso_path="$VM_DIR/talos.iso" if [[ ! -f "$iso_path" ]]; then log_info "Downloading Talos ISO..." curl -L -o "$iso_path" "$TALOS_ISO_URL" else log_info "Talos ISO already exists" fi echo "$iso_path" } # Create disk image create_disk_image() { local vm_path=$1 local vm_name=$2 local disk_path="$vm_path/disk.qcow2" if [[ ! -f "$disk_path" ]]; then # log_info "Creating disk image for $vm_name..." qemu-img create -f qcow2 "$disk_path" "$DISK_SIZE" else log_warn "Disk image already exists for $vm_name" fi echo "$disk_path" } # Generate unique MAC address generate_mac() { local vm_name=$1 local hash=$(echo "$vm_name" | md5sum | cut -c1-6) printf "52:54:00:%s:%s:%s" "${hash:0:2}" "${hash:2:2}" "${hash:4:2}" } # Create VM startup script create_vm_script() { local vm_path=$1 local vm_name=$2 local mac_address=$3 local iso_path=$4 local disk_path=$5 local script_path="$vm_path/start.sh" # Use a function to escape the variables cat > "$script_path" << EOF #!/bin/bash qemu-system-aarch64 \\ -name "$vm_name" \\ -machine virt,highmem=off \\ -accel hvf \\ -cpu host \\ -smp "$CPUS" \\ -m "${MEMORY}M" \\ -drive file="$disk_path",if=virtio,format=qcow2 \\ -cdrom "$iso_path" \\ -netdev user,id=net0 \\ -device virtio-net-pci,netdev=net0,mac=$mac_address \\ -nographic \\ -serial mon:stdio EOF chmod +x "$script_path" echo "$script_path" } # Create systemd service file (optional) create_service_file() { local vm_path=$1 local vm_name=$2 local script_path=$3 local service_path="$vm_path/$vm_name.service" cat > "$service_path" << EOF [Unit] Description=Talos VM - $vm_name After=network.target [Service] Type=simple ExecStart=$script_path WorkingDirectory=$vm_path Restart=always User=$USER [Install] WantedBy=multi-user.target EOF echo "$service_path" } # Main execution main() { log_info "Creating Talos VMs with QEMU..." if ! command -v qemu-system-aarch64 &> /dev/null; then log_error "QEMU is not installed. Install with: brew install qemu" exit 1 fi local iso_path=$(download_talos_iso) log_info "Creating controlplane VM..." local controlplane_path=$(create_vm_dir "$CONTROLPLANE_NAME") local controlplane_disk=$(create_disk_image "$controlplane_path" "$CONTROLPLANE_NAME") local controlplane_mac=$(generate_mac "$CONTROLPLANE_NAME") local controlplane_script=$(create_vm_script "$controlplane_path" "$CONTROLPLANE_NAME" "$controlplane_mac" "$iso_path" "$controlplane_disk") create_service_file "$controlplane_path" "$CONTROLPLANE_NAME" "$controlplane_script" local manage_script="$VM_DIR/manage-vm.sh" cat > "$manage_script" << 'EOF' #!/bin/bash VM_DIR="$(cd "$(dirname "$0")" && pwd)" start_vm() { echo "Starting Talos VM..." "$VM_DIR/talos-controlplane/start.sh" & } stop_vm() { echo "Stopping Talos VM..." pkill -f "qemu-system-aarch64.*talos-controlplane" } case "$1" in start) start_vm ;; stop) stop_vm ;; status) pgrep -f "qemu-system-aarch64.*talos-controlplane" > /dev/null && echo "VM is running" || echo "VM is stopped" ;; *) echo "Usage: $0 {start|stop|status}" exit 1 ;; esac EOF chmod +x "$manage_script" log_info "VM creation complete!" log_info "VM files located at: $VM_DIR" log_info "" log_info "To start VM: $manage_script start" log_info "To stop VM: $manage_script stop" log_info "" log_info "Controlplane MAC: $controlplane_mac" } main "$@"