#!/bin/bash

# Vereiste packages installeren
sudo apt install libguestfs-tools jq -y

# Functie om het eerstvolgende vrije VMID te bepalen
find_next_free_vmid() {
    # Haal de lijst van bestaande VMIDs op uit het JSON-bestand
    local existing_ids=$(jq -r '.ids | keys | .[]' /etc/pve/.vmlist | sort -n)
    local vmid=100  # Begin bij een standaard VMID, bijvoorbeeld 100

    for id in $existing_ids; do
        if [[ $vmid -lt $id ]]; then
            # Als de huidige $vmid kleiner is dan de eerstvolgende in de lijst, is deze vrij
            echo $vmid
            return
        fi
        # Anders verhogen we $vmid om naar het volgende te kijken
        ((vmid++))
    done

    # Als we geen vrije ID in de lijst vinden, retourneer de volgende beschikbare ID
    echo $vmid
}

# Configuratievariabelen
VMID=$(find_next_free_vmid)                 # VM ID
VMNAME="test"               # Naam van de VM
VMUSER="test"               # Gebruikersnaam
VMPASSWORD="test"           # Wachtwoord voor de gebruiker (leeg voor alleen SSH-sleutels)
SSH_KEYS_PATH1=""
DISK_SIZE="20"            # Disk grootte in GiB
BRIDGE="vmbr0"
MEMORY="4096"
CORES="4"
STORAGE="btrfs"              # Opslaglocatie
OSKEUZE="5"              # Naam en versie van het besturingssysteem, bijv. "Debian 12"
TEMPLATE="n"             # Of de VM als template moet worden ingesteld (j/n)

SSH_KEY_TEXT=""

# Parseer de argumenten met getopts
while getopts "n:u:p:k:d:b:m:c:s:o:t:" opt; do
  case ${opt} in
    n) VMNAME="${OPTARG}" ;;
    u) VMUSER="${OPTARG}" ;;
    p) VMPASSWORD="${OPTARG}" ;;
    k) SSH_KEYS_PATH1="${OPTARG}" ;;
    d) DISK_SIZE="${OPTARG}" ;;
    b) BRIDGE="${OPTARG}" ;;
    m) MEMORY="${OPTARG}" ;;
    c) CORES="${OPTARG}" ;;
    s) STORAGE="${OPTARG}" ;;
    o) OSKEUZE="${OPTARG}" ;;
    t) TEMPLATE="${OPTARG}" ;;
    \?) echo "Usage: $0 [-n vmname] [-u username] [-p password] [-k ssh_key] [-d disk_size] [-b bridge] [-m memory] [-c cores] [-s storage] [-o oskeuze] [-t template]" ;;
  esac
done

# Echo de variabelen voor bevestiging
echo "VM Name: $VMNAME"
echo "VM User: $VMUSER"
echo "VM Password: $VMPASSWORD"
echo "SSH Key Path: $SSH_KEYS_PATH1"
echo "Disk Size: $DISK_SIZE"
echo "Bridge: $BRIDGE"
echo "Memory: $MEMORY"
echo "Cores: $CORES"
echo "Storage: $STORAGE"
echo "OS Choice: $OSKEUZE"
echo "Template: $TEMPLATE"

# Controleer verplichte variabelen
if [[ -z "$VMID" || -z "$VMNAME" || -z "$VMUSER" || -z "$DISK_SIZE" || -z "$STORAGE" || -z "$OSKEUZE" ]]; then
    echo "Error: Een of meer verplichte variabelen zijn niet ingesteld. Vul alle vereiste variabelen in."
    exit 1
fi

# OS-specificatie en image-toewijzing
case "$OSKEUZE" in
    "1")
        IMAGE_URL="https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2"
        IMAGE_NAME="debian-11-generic-amd64.qcow2"
        ;;
    "2")
        IMAGE_URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
        IMAGE_NAME="debian-12-generic-amd64.qcow2"
        ;;
    "3")
        IMAGE_URL="https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
        IMAGE_NAME="jammy-server-cloudimg-amd64.img"
        ;;
    "4")
        IMAGE_URL="https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
        IMAGE_NAME="noble-server-cloudimg-amd64.img"
        ;;
    "5")
        IMAGE_URL="https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2"
        IMAGE_NAME="AlmaLinux-9-GenericCloud-latest.x86_64.qcow2"
        ;;
    *)
        echo "Error: Ongeldige OS-keuze. Controleer de waarde van OSKEUZE."
        exit 1
        ;;
esac

# Download de OS image
mkdir -p /tmp
wget -O /tmp/"$IMAGE_NAME" "$IMAGE_URL"

if [ -n "$SSH_KEYS_PATH1" ] && [ -f "$SSH_KEYS_PATH1" ]; then
    touch /tmp/temporary_ssh_key.pub
    echo "$SSH_KEYS_PATH1" > /tmp/temporary_ssh_key.pub
    # Sla de naam van het tijdelijke bestand op in een variabele
    SSH_KEYS_PATH="/tmp/temporary_ssh_key.pub"
else
    SSH_KEYS_PATH=""
fi

# Controleer de disk type
DISKTYPE=$(pvesm status | awk -v storage="$STORAGE" 'NR>1 && $1 == storage {print $2}')

# Pas de image aan
case $OSKEUZE in
    1|2|3|4)  # Debian en Ubuntu
        virt-customize --install qemu-guest-agent,htop,curl,avahi-daemon,console-setup,cron,cifs-utils,mtr,bash-completion,bind9-utils,lsof,mc,mlocate,screen,sysstat,tmux,wget,zabbix-agent -a /tmp/"$IMAGE_NAME"
        virt-customize --run-command "systemctl enable --now qemu-guest-agent" -a /tmp/"$IMAGE_NAME"

        case $SSH_KEYS_PATH in
            '')  # leeg
                virt-customize -a /tmp/"$IMAGE_NAME" \
                               --run-command 'sed -i "s/^#PasswordAuthentication yes/PasswordAuthentication yes/" /etc/ssh/sshd_config' \
                               --run-command 'sed -i "s/^PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config' \
                               --run-command 'systemctl restart sshd'
                ;;
            /tmp/temporary_ssh_key.pub)  # iets
                ;;
        esac

        virt-customize -a /tmp/"$IMAGE_NAME" --truncate /etc/machine-id --truncate /var/lib/dbus/machine-id
        ;;
    5)  # RHEL
        virt-customize --install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -a /tmp/"$IMAGE_NAME"
        virt-customize --install qemu-guest-agent,htop,curl,cifs-utils,firewalld,mtr,bash-completion,bind-utils,lsof,mc,mlocate,perl,perl-Date-Calc,perl-Data-Dumper,perl-Getopt-Long,perl-libs,screen,sysstat,tmux,wget,zabbix-agent -a /tmp/"$IMAGE_NAME"
        virt-customize --selinux-relabel -a /tmp/"$IMAGE_NAME"
        virt-customize --run-command "systemctl enable --now firewalld" -a /tmp/"$IMAGE_NAME"
        virt-customize --run-command "systemctl enable --now qemu-guest-agent" -a /tmp/"$IMAGE_NAME"

        case $SSH_KEYS_PATH in
            '')  # leeg
                virt-customize -a /tmp/"$IMAGE_NAME" \
                               --run-command 'sed -i "s/^#PasswordAuthentication yes/PasswordAuthentication yes/" /etc/ssh/sshd_config' \
                               --run-command 'sed -i "s/^PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config' \
                               --run-command 'systemctl restart sshd'
                ;;
            /tmp/temporary_ssh_key.pub)  # iets
                ;;
        esac

        ;;
    *)  # Anders
        ;;
esac


virt-customize -a /tmp/"$IMAGE_NAME" --truncate /etc/machine-id --truncate /var/lib/dbus/machine-id

# Maak een nieuwe VM
qm create $VMID --name $VMNAME --memory $MEMORY --cores $CORES --net0 virtio,bridge=$BRIDGE,firewall=1 --agent 1

# Importeer de aangepaste image
qm importdisk $VMID /tmp/"$IMAGE_NAME" $STORAGE

# Configureer de VM disks
case $DISKTYPE in
    dir|btrfs)  #file en btrfs storage
        qm set $VMID --scsihw virtio-scsi-single --scsi0 $STORAGE:$VMID/vm-$VMID-disk-0.raw,discard=on,iothread=1,ssd=1,format=raw
        ;;
    lvm|lvmthin|zfspool)  #lvm en zfs storage
        qm set $VMID --scsihw virtio-scsi-single --scsi0 $STORAGE:vm-$VMID-disk-0,discard=on,iothread=1,ssd=1,format=raw
        ;;
esac

qm set $VMID --ide0 $STORAGE:cloudinit,format=raw
qm set $VMID --ide2 none,media=cdrom
qm set $VMID --bios ovmf
qm set $VMID --machine q35
qm set $VMID --tablet 0
qm set $VMID --serial0 socket

# Stel netwerkinstellingen en CPU-configuraties in
qm set $VMID --ipconfig0 ip=dhcp,ip6=auto
qm set $VMID --cpu cputype=host,flags="+md-clear;+spec-ctrl;+aes"
qm set $VMID --numa 1
qm set $VMID --sockets 1

# Configureer Cloud-Init
qm set $VMID --ciuser $VMUSER
qm set $VMID --cipassword $VMPASSWORD
qm set $VMID --ciupgrade 1
qm set $VMID --onboot 1
[[ -n "$SSH_KEYS_PATH" && -f "$SSH_KEYS_PATH" ]] && qm set $VMID --sshkeys "$SSH_KEYS_PATH"

#case $SSH_KEYS_PATH in
#    '')  # leeg
#        ;;
#    /tmp/temporary_ssh_key.pub)  # iets
#        qm set $VMID --sshkeys /tmp/temporary_ssh_key.pub
#        ;;
#esac

qm set $VMID --efidisk0 $STORAGE:0,format=raw,pre-enrolled-keys=1

# Stel de bootvolgorde en disk grootte in
qm set $VMID --boot order="scsi0;ide2;net0"
qm resize $VMID scsi0 "${DISK_SIZE}G"

# Zet de VM om in een template als geselecteerd
if [[ "$TEMPLATE" == "j" ]]; then
    qm template $VMID
fi

# starten vm
rm -f /tmp/"$IMAGE_NAME"
rm -f /tmp/temporary_ssh_key.pub

qm start $VMID

# ip ophalen
# Maximum aantal pogingen (1 minuut / 5 seconden = 12 pogingen)
MAX_ATTEMPTS=24  # Aantal pogingen voordat de foutmelding wordt weergegeven
ATTEMPT=0
ETH0_STATS=""  # Zorg ervoor dat ETH0_STATS wordt geleegd bij elke iteratie

# Probeer om de IP-informatie en statistieken op te halen
while [ -z "$ETH0_STATS" ] && [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
    echo "Trying to retrieve IP and stats information... Attempt $((ATTEMPT + 1)) of $MAX_ATTEMPTS"

    # Haal de netwerkinformatie op
    IP_INFO=$(qm agent $VMID network-get-interfaces 2>/dev/null)

    # Controleer of de QEMU guest agent beschikbaar is
    if [[ "$IP_INFO" == *"QEMU guest agent is not running"* ]]; then
        echo "QEMU guest agent is not running. Retrying..."
    elif [[ -z "$IP_INFO" ]]; then
        echo "No network information received. Retrying..."
    else
        # Controleer specifiek of eth0 bestaat en statistieken bevat
        ETH0_STATS=$(echo "$IP_INFO" | jq -r '.[] | select(.name == "eth0" and .statistics != null)')

        if [ -n "$ETH0_STATS" ]; then
            echo "Valid IP and statistics found for eth0!"
            break  # Als eth0 statistieken heeft, stop de poging
        else
            echo "No valid statistics found for eth0. Retrying..."
        fi
    fi

    # Wacht 1 seconde voordat je opnieuw probeert
    sleep 1
    ((ATTEMPT++))
done

# Controleer of we een geldig resultaat hebben gekregen
if [ -z "$ETH0_STATS" ]; then
    echo "Unable to retrieve IP or statistics for eth0 after $MAX_ATTEMPTS attempts."
    exit 1
else
    # Parse en toon IPv4 en IPv6 adressen voor de eth0 interface met statistieken
    echo "$ETH0_STATS" | jq -r '.["ip-addresses"][] | [.["ip-address-type"], .["ip-address"]] | @tsv' | \
    while IFS=$'\t' read -r ip_type ip; do
        echo "eth0 - $ip_type: $ip"
    done
fi

# Opruimen
echo "VM $VMNAME met ID $VMID succesvol aangemaakt."
