#!/bin/bash
cd "$(dirname "$(readlink -f "$0")")"

#define defaults
cpu=1
memory=1
root_disk=10
variant="archlinux"
path="/virtual/disks/"
dhcp_opts=""
ssh_key_dir="../../identity_files"
dhcp_dir="../../dhcp_files"
mac=52:54:00:`openssl rand -hex 1`:`openssl rand -hex 1`:`openssl rand -hex 1`
branch="prod"
deflate="y"
ansible="y"

#get variables
numre='^[0-9]+$'
macre='^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$'
ipsegre='^[0-255]$'

while true; do read -p "Name of new vm/server (caps allowed, not fqdn): " v;if [ -z $v ]; then echo "error: name is required";else name=$v;break;fi;done
while true; do read -p "Number of CPU cores (default $cpu): " v;if [ -z $v ]; then break;else if ! [[ $v =~ $numre ]] ; then echo "error: not a number";else cpu=$v; break;fi;fi;done
while true; do read -p "Ram in GB (default $memory): " v;if [ -z $v ]; then break;else if ! [[ $v =~ $numre ]] ; then echo "error: not a number";else memory=$v; break;fi;fi;done
while true; do read -p "Root disk size in GB (default $root_disk): " v;if [ -z $v ]; then break;else if ! [[ $v =~ $numre ]] ; then echo "error: not a number";else root_disk=$v; break;fi;fi;done
while true; do read -p "Path to store root disk (default $path): " v;if [ -z $v ]; then path="$path/$name.qcow2"; break;else if ! [ -d $v ] ; then echo "error: not a directory";else path="$v/$name.qcow2"; break;fi;fi;done
variant=$(dialog --clear --title "Select Linux variant to use" --menu "Choose one of the following options:" 15 40 4 \
archlinux "Arch Linux" \
alma "Alma Linux 9" \
2>&1 >/dev/tty);clear
while true; do read -p "Mac address (default $mac): " v;if [ -z $v ]; then break;else if ! [[ $v =~ $macre ]] ; then echo "error: invalid mac address";else mac=$v; break;fi;fi;done
#add subnet list
eval "dhcp_sets=(`grep "#" $dhcp_dir/subnets/172.* | grep -o 172.* | sort -t . -k 1,1n -k 2,2n -k 3,3n | sed -e "s/:# /.* \'/" | sed -e "s/$/\'/"`)"
subnet=$(dialog --clear --title "Select subnet to use" --menu "Choose one of the following: " 20 100 10 "${dhcp_sets[@]}" 2>&1 >/dev/tty);subnet=`echo $subnet | grep -oP "172.16.\d+"`;clear;
while true; do read -p "Specify last segment of IP (defaults to next available): " v;if [ -z $v ]; then break;else if ! [[ $v =~ $numre ]] ; then echo "error: not a number";else ip=$v; break;fi;fi;done
while true; do read -p "Specify branch of build_ansible to use (defult $branch): " v;if [ -z $v ]; then break;else branch=$v;break;fi;done
while true; do read -p "Full path to extra disk to attach (if applicable, default none): " v;if [ -z $v ]; then break;else if ! [ -f $v ] ; then echo "error: file doesn't exist";else attach=$v;break;fi;fi;done
while true; do read -p "Autodeflate memory on use y/n (default $deflate)? " v;if [ -z $v ]; then break;elif [ "$v" == "y" ];then break; elif [ "$v" == "n" ];then deflate=$v;break;else echo "error: select y or n";fi;done
while true; do read -p "Autorun ansible build script (default $ansible)? " v;if [ -z $v ]; then break;elif [ "$v" == "y" ];then break; elif [ "$v" == "n" ];then ansible=$v;break;else echo "error: select y or n";fi;done

path=`echo $path | sed -s 's/\/\//\//'`
attach=`echo $attach | sed -s 's/\/\//\//'`

echo ""
echo "Name: $name"
echo "CPU: $cpu"
echo "Ram: $memory"
echo "Root Disk: $root_disk"
echo "Path: $path"
echo "Variant: $variant"
echo "Mac: $mac"
echo "Subnet: $subnet"
echo "IP: $ip"
echo "Branch: $branch"
echo "Attach: $attach"
echo "Deflate: $deflate"
echo "Run Ansible: $ansible"
echo ""

read -p "Is this correct (y/n)? " v;if [ "$v" != "y" ];then "Exiting, restart to reenter info"; exit;fi

dhcp_opts=" -m $mac"
if [ -n $subnet ]; then dhcp_opts+=" -s $subnet";fi
if [ -n $ip ]; then dhcp_opts+=" -i $ip";fi

lname=`echo $name | tr '[:upper:]' '[:lower:]'`

img=`./shared_scripts/download_install_image.sh $variant`

memory=$((memory*1024))

#update DHCP
./shared_scripts/update_dhcp.sh $dhcp_opts $lname

# determine if extra disk should be attached
if [ -n "$attach" ]; then attach="--disk ${attach},discard=unmap";fi

#determine if deflate should be on
if [[ "$deflate" == "y" ]]; then deflate="--memballoon model=virtio,autodeflate=on";else deflate="--memballoon model=virtio";fi

case "$variant" in
  "archlinux")
    # create cloud-init - replace by grabbing these directly from git
    mkdir -p /tmp/cloud-init

    echo "#cloud-config
users:
  - name: root
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILG56T1k766Cru14kyXI8WXSJwlO2sVhmH6JeRWy+mfe root@host.actcur.com" > /tmp/cloud-init/user-data

    # create new base VM
    virt-install --name=$name --vcpus=$cpu --memory=$memory --disk path=$path,size=$root_disk,sparse=true,discard=unmap,bus=scsi ${attach} --os-variant=$variant --network bridge=br1,mac=$mac $deflate --cdrom=$img --graphics vnc --cloud-init user-data="/tmp/cloud-init/user-data" --autoconsole=none

    #wait until server is available
    echo "Waiting for server to be available"
    while true
    do
      sleep 1
      ping -c 1 ${lname}.actcur.com 2>&1 > /dev/null
      if [ $? -eq 0 ]; then break;fi
    done
    echo "server up, waiting for ssh"

    sleep 60

    sed "s/REPLACE_HOSTNAME/${lname}.actcur.com/g" ../base_files/user_configuration.json > /tmp/user_configuration.json
    rs=$((root_disk*1024-206))
    sed -i "s/REPLACE_SIZE/${rs}/g" /tmp/user_configuration.json

    ssh-keygen -R ${lname}.actcur.com
    ssh-keyscan ${lname}.actcur.com | grep -v "#" | grep "ssh-ed25519 " >> ~/.ssh/known_hosts

    scp -i $ssh_key_dir/id_arch_builder /tmp/user_configuration.json ${lname}.actcur.com:/tmp/user_configuration.json
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "systemctl mask reflector.service; echo 'Server = https://pkg.actcur.com/repo/archlinux/\$repo/os/\$arch' > /etc/pacman.d/mirrorlist"
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "archinstall --config /tmp/user_configuration.json --silent"
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "ln -s /usr/lib/systemd/system/sshd.service /mnt/archinstall/etc/systemd/system/multi-user.target.wants/sshd.service"
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "cp -r /root/.ssh/ /mnt/archinstall/root/;reboot"
    ;;
  "alma")
    # set up kickstart file
    sed "s/REPLACE_HOSTNAME/${lname}.actcur.com/g" ../base_files/kickstart.cfg > /tmp/kickstart.cfg

    # create new VM
    virt-install --name=$name --vcpus=$cpu --memory=$memory --disk path=$path,size=$root_disk,sparse=true,discard=unmap,bus=scsi --os-variant=almalinux9 --network bridge=br1,mac=$mac $deflate --location=$img --graphics vnc --initrd-inject /tmp/kickstart.cfg --extra-args "inst.ks=file:/kickstart.cfg" --autoconsole=none

    echo "server up, waiting for install to complete"

    sleep 60

    # wait for install to complete and server to shut down/reboot
    while true
    do
      sleep 1
      ping -c 1 ${lname}.actcur.com 2>&1 > /dev/null
      if [ $? -ne 0 ]; then break;fi
    done
    ;;
esac

sleep 10
virsh start $name

#wait until server is available
echo "Waiting for server to be available"
while true
do
  sleep 1
  ping -c 1 ${lname}.actcur.com 2>&1 > /dev/null
  if [ $? -eq 0 ]; then break;fi
done
echo "server up, waiting for ssh"

sleep 30

ssh-keygen -R ${lname}.actcur.com
ssh-keyscan ${lname}.actcur.com | grep -v "#" | grep "ssh-ed25519 " >> ~/.ssh/known_hosts

# install some dependencies
case "$variant" in
  "arch")
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "pacman -Sy --noconfirm ansible-core git"
    ;;
  "alma")
    ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "dnf config-manager --set-enabled crb;yum install -y ansible-core git epel-release"
  ;;
esac

ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "ansible-galaxy collection install community.general"
ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "ansible-galaxy collection install community.crypto"
ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "ansible-galaxy collection install ansible.posix"

# Set up ansible
ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "mkdir /ansible/; curl -k 'https://git.actcur.com/actcur-ansible/playbook-builder/raw/branch/$branch/build_ansible.sh' -H 'accept: application/raw' -o /ansible/build_ansible.sh;echo "$branch" > /ansible/branch"

if [[ "$ansible" == "y" ]]; then
  # Run ansible twice - some configurations don't take effect on first run (i.e. when they are dependent on other configurations)
  ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "/bin/bash /ansible/build_ansible.sh"

  ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "/bin/bash /ansible/build_ansible.sh"
fi

ssh -i $ssh_key_dir/id_arch_builder ${lname}.actcur.com "git config --global user.email 'jayne.git@actcur.com';git config --global user.name 'Jayne Passmore'"

systemctl restart nfs-server