#!/bin/bash
#emacs: -*- mode: shell-script; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- 
#ex: set sts=4 ts=4 sw=4 noet:

# fail early
set -eu

build_dir=$PWD/build
dist_dir=$PWD/dist
vendor="NeuroDebian"
vm_version="8.0.0"
vm_ostype=Debian
vendor_url="http://neuro.debian.net"
product_url="${vendor_url}/vm.html"
di_port=10100                   # port to start webserver on

# Generic definitions
eula="This virtual appliance contains Free and Open Source Software (FOSS) released under licenses compliant with the Debian Free Software Guidelines (DFSG, see http://www.debian.org/social_contract), such as, GPL, BSD, MIT, etc.  Such software is free to be used or customized for any purpose.

However, by default this virtual machine is also enabled to install additional software from Debian and NeuroDebian repositories that is distributed under more restrictive licenses (e.g. closed-source, non-commercial, research-only). It is the user's responsibility to adhere to the terms and conditions of any particular software that is installed and used in this virtual machine. Copyright and license details for any installed PACKAGE are available in /usr/share/doc/PACKAGE/copyright inside the virtual machine."

# The defaults to be modified from cmdline
di_cd=
# look here for more details about the default IP of the host:
# # http://www.virtualbox.org/manual/ch09.html#changenat
mirror_host=10.0.0.1:9999
di_tz='US/Eastern'
di_preseed_in=

function usage {
echo "Usage: $0 [OPTIONS]

Create ND VirtualBox appliance.

Options:
  -p PRESEED_IN path to preesed.cfg.in file for d-i
  -i ISO        path to debian installation iso file
  -m MIRROR     debian mirror to use for installation
  -t TIME_ZONE  time zone of virtual machine
  -h            Show this help and exit
"
}

# Process cmdline
while getopts "p:i:" OPTION
do
  case $OPTION in
      "p") di_preseed_in="$OPTARG";;
      "i") di_cd="$OPTARG";;
      "m") mirror_host="$OPTARG";;
      "t") di_tz="$OPTARG";;
      "h") exit 1;;
  esac
done

if [ -z "$di_cd" ] ; then
    echo "You must specify the iso image (-i)" >&2
    exit 1
fi

if [ -z "$di_preseed_in" ]; then
    # deduce release and use corresponding directory here
    release=$(basename "$di_cd" | cut -d- -f2)
    di_preseed_in=$(dirname $0)/../d-i/$release/preseed.cfg.in
    if [ ! -e "$di_preseed_in" ]; then
        echo "$di_preseed_in is not found. Specify one with -p" >&2
        exit 2
    fi
fi

# Figure out our IP address for VM to reach webserver
eth=`route | awk '/default/{print $8;}'`
di_host=`ip addr show dev $eth | sed -ne '/inet /s, *inet \([0-9.]*\)/.*,\1,gp'`

# Generate preseed file
# yoh could not escape Python here
di_preseed=${di_preseed_in%.in}
python3 -c "open('$di_preseed', 'w').write(open('$di_preseed_in').read() % {'DI_HTTP_HOSTNAME': '$di_host:$di_port', 'MIRROR_HTTP_HOSTNAME': '$mirror_host', 'TIME_ZONE': '$di_tz'})"

# By default 32bit unless installer image has amd64
# TODO: might need to make more robust?
vm_arch=i386
vm_arch_name=" (32bit)"
if file $di_cd | grep -q ' amd64 '; then
    vm_arch=amd64
    vm_ostype+="_64"
    vm_arch_name=" (64bit)"
fi

vm_fprefix="${vendor}_${vm_version}_${vm_arch}" # common prefix for files
#vm_disk="$build_dir/nd-${vm_version}_${vm_arch}.vdi"
vm_disk="$build_dir/${vm_fprefix}.vdi"
vm_name="${vendor} ${vm_version} ${vm_arch_name}"
# Let's use OVA since 4.x
# vm_ovf="${dist_dir}/${vm_fprefix}.ovf"
vm_ova="${dist_dir}/${vm_fprefix}.ova"
product_name="${vendor} VirtualMachine (${vm_arch})"

_info() {
    echo "I: $*"
}

clean_buildvm() {
# TODO: remove whenever done
VBoxManage storagectl "${vm_name}" \
    --name "SATA Controller" --remove || :
VBoxManage storagectl "${vm_name}" \
    --name "IDE Controller" --remove || :

VBoxManage closemedium disk "${vm_disk}" || :
VBoxManage unregistervm "${vm_name}" --delete || :
rm -f ${vm_disk}
}

clean_buildvm >&/dev/null                   # clean things up

#exit
# Check that no previous VM was left (can happen if previous failures
# were "valid")
if VBoxManage list vms | grep -q "^\"${vm_name}\".*"; then
    echo "VM $vm_name still exists -- something is wrong, Can't continue" >&2
    exit 1
fi

_info Assure build directory
mkdir -p $build_dir

_info Create HardDisk for the VM
VBoxManage createhd --filename $vm_disk \
    --size 40960 --format VDI
  # documented but not implemented:
  #  --comment "Drive for NeuroDebian VM installer"

_info Create VM
VBoxManage createvm --name "${vm_name}" --register \
    --ostype "${vm_ostype}" --basefolder $build_dir

_info Tune VM
VBoxManage modifyvm "${vm_name}" \
    --audio alsa \
    --audiocontroller  ac97 \
    --boot1 disk \
    --boot2 dvd \
    --cpus 1 \
    --ioapic  on \
    --memory 1048 \
    --mouse usbtablet \
    --nic1 nat \
    --rtcuseutc on \
    --usb on \
    --vram 32

# Add HD controllers
VBoxManage storagectl "${vm_name}" \
    --name "IDE Controller" \
    --add ide \
    --controller "PIIX4"
VBoxManage storageattach "${vm_name}" \
    --storagectl "IDE Controller" \
    --port 0 \
    --device 0 \
    --type dvddrive \
    --medium  $di_cd

VBoxManage storagectl "${vm_name}" \
    --name "SATA Controller" \
    --add sata \
    --controller "IntelAHCI"

VBoxManage storageattach  "${vm_name}" \
    --storagectl "SATA Controller" \
    --port 0 \
    --device 0 \
    --type hdd \
    --medium "${vm_disk}"

VBoxManage showvminfo  "${vm_name}"

_info "Run Debian Installer"
# When boot menu appears you will have to
# press Esc
# type  auto url=$di_host
# press Enter"

# start local web server to serve preseed file
builtin cd $(dirname ${di_preseed})
python3 -m SimpleHTTPServer ${di_port} >&/dev/null &
di_pid=$!
builtin cd -



VBoxManage startvm "${vm_name}"

# TODO: see if we could just use virtinst (virt-install tool) to run d-i
#       with pre-seeding without this hackery.  See
#       http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
#       for an example
sleep 5                         # give some time to make sure we get to menu
# Send our sequence -- cruel way
#VBoxManage controlvm "${vm_name}" keyboardputscancode \
#    01 81 \
#    1e 9e 16 96 14 94 18 98 39 b9 16 96 13 93 26 a6 0d 8d 23 a3 15 95 20 a0 13 93 1e 9e \
#    1c 9c # ESCAPE, auto url=hydra, ENTER
echo "typeGuest \"${vm_name}\" \"&ESC;Wauto url=${di_host}|;${di_port}/$(basename ${di_preseed})&ENTER;\"" | /usr/lib/virtualbox/vboxshell.py

# wait for it to finish! -- found no cleaner way :-/
sleep 10
while VBoxManage showvminfo "${vm_name}" | grep -q running; do
    sleep 5
done

# kill the web server
kill ${di_pid} || echo "Could not kill the webserver"

_info Compacting VDI
sudo ./nd_compactvdi "${vm_disk}"

_info Exporting the appliance
if [ -e "$vm_ova" ]; then
    vm_ova_old=$vm_ova.`date +"20%y%m%d%H%M"`
    _info Previous OVA image exists, renaming it to $vm_ova_old
    mv "$vm_ova" "$vm_ova_old"
fi
VBoxManage export "${vm_name}" -o "$vm_ova" \
	--vsys 0 \
	--product "${product_name}" \
	--producturl "${product_url}" \
	--vendor "${vendor}" \
	--vendorurl "http://neuro.debian.net" \
	--version "$vm_version" \
	--eula "$eula"

_info Cleaning after ourselves
clean_buildvm

_info Testing import of the appliance
VBoxManage import "$vm_ova" --vsys 0 --eula accept

_info Starting imported machine
VBoxManage startvm "${vm_name}"
