#!/usr/bin/bash
# create and run clone

set -eu

show_help() {
    cat << EOF >&2
Usage: $(basename "$0") [-n] vmname"
Create a new clone, start the vm (if not yet running) and run virt-viewer.
Squid-Proxy will be started too.
### remove, old ### User Home will be mounted on /media/USERNAME/home
    -n   new clone will be created, even if exists
    -s   qemu:///system instead of default qemu:///session
EOF
}

exit_script() {
    echo "run-vm.sh ${VM_NAME} terminated by trap!" >> "/tmp/${UID}/exit-run-vm.log"
    virsh --connect="${QEMU}" destroy "${VM_NAME}-clone"
    trap - SIGHUP SIGINT SIGTERM # clear the trap
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

check_images() {
   # sync vm-torrents and machine definition file
   sudo -u lmnsynci /usr/local/bin/sync-vm.sh -t

   BACKINGARRAY=()
   imgfile="/lmn/vm/${VM_NAME}.qcow2" && [[ -f "${VM_DIR}/${VM_NAME}.qcow2" ]] && imgfile="${VM_DIR}/${VM_NAME}.qcow2"
   BACKINGARRAY+=("${imgfile}")
   echo "Imgfile=$imgfile"
   if [[ ! -f "${imgfile}" ]] || ! qemu-img info -U "${imgfile}" | grep "file format: qcow2"; then
       if [[ ! -f "/lmn/vm/${VM_NAME}.qcow2.torrent" ]]; then
           echo "no base VM disk '${VM_NAME}.qcow2' found and/or ${VM_NAME} not found on server" >&2
           exit 1
       fi
       # sync vm-disk image by torrent
       echo "Try to sync VM ${VM_NAME} by torrent"
       sudo -u lmnsynci /usr/local/bin/sync-vm.sh "${VM_NAME}"
   fi

   backingfile=$(qemu-img info -U "${imgfile}" | grep "^backing file:" | cut -d ' ' -f 3)
   while [[ ! -z "${backingfile}" ]]; do
       echo "Backingfile required: ${backingfile}"
       imgfile="/lmn/vm/${backingfile}" && [[ -f "${VM_DIR}/${backingfile}" ]] && imgfile="${VM_DIR}/${backingfile}"
       BACKINGARRAY+=("${imgfile}")
       if [[ ! -f "${imgfile}" ]] || ! qemu-img info -U "${imgfile}" | grep "file format: qcow2"; then
           # sync vm-disk image by torrent
           echo "Try to sync backingfile ${backingfile} by torrent"
           sudo -u lmnsynci /usr/local/bin/sync-vm.sh "${backingfile%.qcow2}"
       fi
       backingfile=$(qemu-img info -U "${imgfile}" | grep "^backing file:" | cut -d ' ' -f 3)
   done

   echo "VM-Image and required backingfiles available"
   echo "Now, let's check the images."

   # Check VM-Images in reverse order
   for ((i=${#BACKINGARRAY[@]}-1; i>=0; i--))
   do
       echo "Checking ${BACKINGARRAY[$i]}"
       if ! qemu-img check -U "${BACKINGARRAY[$i]}" 2>/dev/null; then
           echo "check failed!"
           echo "sync ${BACKINGARRAY[$i]} again"
           sudo -u lmnsynci /usr/local/bin/sync-vm.sh $(basename "${BACKINGARRAY[$i]}" .qcow2)
       fi
   done

   echo "VM-Image and required backingfiles available and checked"
}

create-clone() {
    local VM_NAME="$1"
    local VM_DIR="/tmp/${UID}/vm"
    local VM_XML="${VM_DIR}/${VM_NAME}-clone.xml"
    local VM_SYSDIR="/lmn/vm"

    if ! [[ -f "$VM_SYSDIR/${VM_NAME}.xml" && -f "$VM_SYSDIR/${VM_NAME}.qcow2" ]] && ! [[ -f "${VM_DIR}/${VM_NAME}.xml" && -f "${VM_DIR}/${VM_NAME}.qcow2" ]]; then
	echo "xml or qcow2 File does not exists." >&2
	exit 1
    fi

    # Create User-VM-Dir and link system VM-Images
    [[ -d "${VM_DIR}" ]] || mkdir -p "${VM_DIR}"
    sudo /usr/local/bin/link-images.sh

    # Create backing file
    cd "${VM_DIR}"
    qemu-img create -f qcow2 -F qcow2 -b "${VM_NAME}.qcow2" "${VM_NAME}-clone.qcow2"

    # Create machine-definition-file
    cp "${VM_DIR}/${VM_NAME}.xml" "${VM_XML}"

    # set VM_DIR:
    sed -i "s:VMIMAGEDIR:${VM_DIR}:" "${VM_XML}"
    # and actually rename the vm (this also updates part of the storage path):
    sed -i "s/${VM_NAME}/${VM_NAME}-clone/" "${VM_XML}"
    # set virtiofs-Socket
    sed -i "s:VIRTIOFSSOCKET:/run/user/${UID}/virtiofs-${VM_NAME}.sock:" "${VM_XML}"

    # find macvtap interface MAC address:
    MAC="$(ip link | grep -A1 "vm-macvtap" |
              sed -nE "s%\s+link/ether ([[:xdigit:]:]{17}) .+%\1%p")"
    sed -i -E -e "s/MACMACVTAP/$MAC/" "${VM_XML}"
}

QEMU='qemu:///session'

NEWCLONE=0

while getopts ':ns' OPTION; do
    case "$OPTION" in
        n)
            NEWCLONE=1
            ;;
        s)
            QEMU='qemu:///system'
            ;;
        ?)
        show_help
        exit 1
        ;;
    esac
done

shift "$((OPTIND -1))"

# if less than one arguments supplied, display usage
if [[  $# -ne 1 ]] ; then
    show_help
    exit 1
fi

VM_NAME=$1
VM_DIR="/tmp/${UID}/vm"

# check, if we have to start squid
if ! killall -s 0 squid; then
    echo "starting squid."
    /usr/sbin/squid -f /etc/squid/squid-usermode.conf
fi

# because virsh has problems with long pathnames, using diffent configdir
export XDG_CONFIG_HOME="/tmp/${UID}/.config"

if  ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
    echo "VM not yet running."
    check_images
    if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then
        create-clone "${VM_NAME}"
    fi
    # delete the old vm
    virsh --connect=qemu:///session undefine "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist"
    # finally, create the new vm
    virsh --connect=qemu:///session define "${VM_DIR}/${VM_NAME}-clone.xml"
    #trap exit_script SIGHUP SIGINT SIGTERM
    [[ "${QEMU}" = 'qemu:///session' ]] && sudo /usr/local/bin/start-virtiofsd.sh "${VM_NAME}"
    virsh --connect="${QEMU}" start "${VM_NAME}-clone"
fi
echo "starting viewer"
trap exit_script SIGHUP SIGINT SIGTERM
virt-viewer --connect="${QEMU}" --full-screen "${VM_NAME}-clone"