#!/bin/bash
#############################################
# VirtualBox VM Scripts - vm-setup
# by ulisse aka A. Livio Beccaria
#
# vm-setup sets a VM up
#############################################

APP_NAME="vm-setup - VirtualBox VM Scripts"
VERSION="18.5.4"
AUTHOR="DiSIT"

# source folder
SRC_DIR="$(dirname $(readlink -f $0))"

#include common code
. "${SRC_DIR}/settings/common"


###############################################################################
# Title
##############
title () {
    echo -e "$APP_NAME by $AUTHOR"
    echo "v.$VERSION"
    echo
}
###############################################################################



###############################################################################
# Debug info
##################
debug() {
    if [[ ${DEBUG} == 1 ]]; then
        echo "Debug info:"
        echo -e "\tVM_ID = ${VM_ID}"
        echo -e "\tUPDATE = ${UPDATE}"
        echo -e "\tDEBUG = ${DEBUG}"
        echo
    fi
}
###############################################################################



###############################################################################
# Usage
#######
usage () {
    if [[ "$@" != "" ]]; then
        echo >&2 "$@"
        echo
    fi
    echo "Usage: $0 <vm_id> [-u | --update] [-d | --debug] [-h | --help]"
    echo
    echo -e "\t-u --update:\tSet VM for update (administrator only)"
    echo -e "\t-d --debug:\tPrint some debug information"
    echo -e "\t-h --help:\tPrint this help"
    echo
    print_vm_list
    echo
    exit 1
}
###############################################################################


# print title
title


###############################################################################
# Parse arguments
#################

[[ "$#" -ge 1 ]] || usage "ERROR: too few arguments."

UPDATE=0
DEBUG=0
VM_ID=""

while [ "$1" != "" ]; do
    PARAM=`echo $1 | awk -F= '{print $1}'`
    VALUE=`echo $1 | awk -F= '{print $2}'`
    case ${PARAM} in
        -h | --help)
            usage ""
            exit 0
            ;;
        -u | --update)
            UPDATE=1
            shift
            ;;
        -d | --debug)
            DEBUG=1
            shift
            ;;
        *)
            if [[ "${VM_ID}" == "" ]]; then
                VM_ID=${PARAM}
                shift
            else
                usage "ERROR: unknown argument \"${PARAM}\"."
                exit 1
            fi
            ;;
    esac
done
###############################################################################


# print debug info if needed
debug


# include global settings
. $SRC_DIR/settings/settings

# VM_ID lookup in settings files by ID or NAME
if [ ! -f "$SRC_DIR/settings/${VM_ID}.settings" ]; then
    result=`get_vm_id_by_name "${VM_ID}"`
    VM_ID=$result
    if [ ! -f "$SRC_DIR/settings/${VM_ID}.settings" ]; then
        usage "ERROR: wrong vm_id."
    fi
fi

# import VM settings
. "$SRC_DIR/settings/${VM_ID}.settings"

VM_DIR="${MACHINES_DIR}/${VM_NAME}"

# if registered, unregister it
VBoxManage showvminfo "${VM_NAME}" &> /dev/null
if [ $? -eq 0 ]; then
    VBoxManage unregistervm "${VM_NAME}"
fi

# remove VM's folder
rm -rf "${VM_DIR}" &> /dev/null

# create VM
echo -n "Creating VM... "
UUID=`VBoxManage createvm --name "${VM_NAME}" --ostype ${OS_TYPE} --basefolder "${MACHINES_DIR}" | grep -m1 UUID | awk '{print $2}'`
echo "OK"
echo
echo -e "\tName: ${VM_NAME}"
echo -e "\tUUID: ${UUID}"
echo

echo -n "Configuring VM... "


if [[ ${CREATE_VM} == 1 ]]; then
    # register VM
    VBoxManage registervm "${VM_DIR}/${VM_NAME}.vbox"
    
    # network
    VBoxManage modifyvm "${VM_NAME}" --nictype1 ${NIC_TYPE} --nic1 nat --natpf1 "http, tcp, , 80, , 8080"


    # hardware UUID
    VBoxManage modifyvm "${VM_NAME}" --hardwareuuid ${HARDWARE_UUID}
    
    # USB
    VBoxManage modifyvm "${VM_NAME}" --usb on --usbehci off --usbxhci off
    
    # System: Memory, Chipset, Pointing device, I/O APIC, # of CPUs, PAE,
    # Paravirtualization interface, Hardware Virtualization, Nested Paging
    VBoxManage modifyvm "${VM_NAME}" --memory ${MEMORY} --chipset ${CHIPSET} \
        --mouse ${POINTING_DEVICE} --ioapic ${IO_APIC} --cpus ${CPUS} \
        --paravirtprovider ${PARAVIRT_PROVIDER} \
        --hwvirtex ${HW_VIRTEX} --nestedpaging ${NESTED_PAGING}
    
    # all other things
    VBoxManage modifyvm "${VM_NAME}" --vram ${VRAM} --snapshotfolder "${USER_TMP_DIR}" \
        --accelerate2dvideo ${ACCEL_2D} --accelerate3d ${ACCEL_3D} \
        --clipboard bidirectional --draganddrop bidirectional \
        --audio ${AUDIO_DRIVER} --audiocontroller ${AUDIO_CONTROLLER} \
        --description "${DESCRIPTION}" \
        # not working, bug in VB version >= 5.2
        #--audioin on --audioout on 
    
    # set storage type to "normal" to allow update, otherwise "immutable"
    if [[ ${UPDATE} == 1 ]]; then
        if [[ "${DISK_IMAGE_1}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_1}" --type normal
        fi
        if [[ "${DISK_IMAGE_2}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_2}" --type normal
        fi
        if [[ "${DISK_IMAGE_3}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_3}" --type normal
        fi
        if [[ "${DISK_IMAGE_4}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_4}" --type normal
        fi
    else
        if [[ "${DISK_IMAGE_1}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_1}" --type immutable
        fi
        if [[ "${DISK_IMAGE_2}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_2}" --type immutable
        fi
        if [[ "${DISK_IMAGE_3}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_3}" --type immutable
        fi
        if [[ "${DISK_IMAGE_4}" != "" ]]; then
            VBoxManage modifyhd "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_4}" --type immutable
        fi
    fi
    
    # add storage
    VBoxManage storagectl "${VM_NAME}" --name ${STORAGE_CONTROLLER_NAME} --add ${STORAGE_CONTROLLER_TYPE} --hostiocache on --portcount 4
    VBoxManage storageattach "${VM_NAME}" --storagectl ${STORAGE_CONTROLLER_NAME} --port 0 --device 0 --type dvddrive --medium emptydrive
    if [[ "${DISK_IMAGE_1}" != "" ]]; then
        VBoxManage storageattach "${VM_NAME}" --storagectl ${STORAGE_CONTROLLER_NAME} --port 1 --device 0 --type hdd --medium "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_1}"
    fi
    if [[ "${DISK_IMAGE_2}" != "" ]]; then
        VBoxManage storageattach "${VM_NAME}" --storagectl ${STORAGE_CONTROLLER_NAME} --port 2 --device 0 --type hdd --medium "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_2}"
    fi
    if [[ "${DISK_IMAGE_3}" != "" ]]; then
        VBoxManage storageattach "${VM_NAME}" --storagectl ${STORAGE_CONTROLLER_NAME} --port 3 --device 0 --type hdd --medium "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_3}"
    fi
    if [[ "${DISK_IMAGE_4}" != "" ]]; then
        VBoxManage storageattach "${VM_NAME}" --storagectl ${STORAGE_CONTROLLER_NAME} --port 4 --device 0 --type hdd --medium "${IMG_HOME}/${VM_ID}/${DISK_IMAGE_4}"
    fi
    
    # shared folders
    VBoxManage sharedfolder add "${VM_NAME}" --name "${SF_LINUX_NAME}" --hostpath "${SF_LINUX_TARGET}"
    VBoxManage sharedfolder add "${VM_NAME}" --name "${SF_MEDIA_NAME}" --hostpath "${SF_MEDIA_TARGET}"
    
    # TWEAK enableIn and enabledOut audio attributes (5.2.x bug, enableOut does not get properly set)
    # we need to wait some time for the configuration to be written on disk before tweaking it
    #for i in {1..10}; do echo -ne "$i"'\b'; sleep 1; done; echo -ne '\b'
    #sed -i 's@\(AudioAdapter.*enabledIn="\)\([^"]*\)\("\)@\1'"`echo "true"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    #sed -i 's@\(AudioAdapter.*enabledOut="\)\([^"]*\)\("\)@\1'"`echo "true"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
else
    # use template
    cp "${TEMPLATE_DIR}/${TEMPLATE}.vbox" "${VM_DIR}/${VM_NAME}.vbox"
    # se servisse: " = \x22
    sed -i 's@\(Machine.*uuid="\)\([^"]*\)\("\)@\1'"`echo "${UUID}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    sed -i 's@\(Machine.*name="\)\([^"]*\)\("\)@\1'"`echo "${VM_NAME}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    sed -i 's@\(Machine.*snapshotFolder="\)\([^"]*\)\("\)@\1'"`echo "${USER_TMP_DIR}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    sed -i 's@\(SharedFolder.*name="'"`echo "${SF_LINUX_NAME}"`"'".*hostPath="\)\([^"]*\)\("\)@\1'"`echo "${SF_LINUX_TARGET}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    sed -i 's@\(SharedFolder.*name="'"`echo "${SF_MEDIA_NAME}"`"'".*hostPath="\)\([^"]*\)\("\)@\1'"`echo "${SF_MEDIA_TARGET}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    sed -i 's@\(MACAddress="\)\([^"]*\)\("\)@\1'"`printf '080027%02X%02X%02X' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"

    if [ "${DIFF_DISK_FILE}" != "" ]; then
        sed -i 's@\(HardDisk.*location="\)\([^"]*diff_[^"]*\)\("\)@\1'"`echo "${USER_TMP_DIR}/${DIFF_DISK_FILE}"`"'\3@g' "${VM_DIR}/${VM_NAME}.vbox"
    fi
    
    # register VM
    VBoxManage registervm "${VM_DIR}/${VM_NAME}.vbox"
fi

echo "OK"
echo
exit 0