#!/bin/bash -e

function dryrun() {
  echo "$@" >&2
}

function exists() {
  qvm-ls --raw-data | grep -q "^$1|"
}

function is_running() {
  qvm-ls --raw-data | grep -q "^$1|Running"
}

function is_template() {
  qvm-ls --raw-data | grep -q "^$1|.*|TemplateVM"
}

function is_standalone() {
  qvm-ls --raw-data | grep -q "^$1|.*|StandaloneVM"
}

if [ "$1" == "-n" ] ; then
  dryrun=dryrun
  shift
else
  dryrun=
fi

from=$1
to=$2
if [ -z "$from" -o -z "$to" ] ; then echo "From and To must be VM names" ; exit 64 ; fi
shift
shift

to_start_later=""

function restore_running() {
  for vm in $to_start_later
  do
    echo Starting "$vm" >&2
    $dryrun  qvm-start "$vm" || echo Failed to start "$vm" >&2
  done
}

function fail {
  echo "$@"
  restore_running
  exit 32
}

if exists "$to"
then
  echo "$to already exists — incomplete migration?  Check and retry." >&2
  exit 16
fi

if is_running "$from"
then
  echo Shutting down "$from" >&2
  $dryrun qvm-shutdown --wait --force "$from"
  to_start_later="$to $to_start_later"
fi

echo Cloning "$from" to "$to" >&2
$dryrun  qvm-clone "$@" "$from" "$to" || fail "Could not clone $from to $to"

for globalpref in updatevm clockvm default_dispvm default_audiovm default_guivm default_netvm default_template management_dispvm
do
  if [ "$(qubes-prefs "$globalpref")" == "$from" ]
  then
    echo Migrating global "$globalpref" from "$from" to "$to" >&2
    $dryrun  qubes-prefs "$globalpref" "$to" || fail "Could not set global property $globalpref to $to"      
  fi
done

for vm in $(qvm-ls --raw-list)
do
  vmprefs="audiovm default_dispvm management_dispvm netvm template"
  if is_template "$vm" ; then vmprefs="audiovm default_dispvm management_dispvm netvm" ; fi
  if is_standalone "$vm" ; then vmprefs="audiovm default_dispvm management_dispvm netvm" ; fi
  if [ "$vm" == "dom0" ] ; then vmprefs=default_dispvm ; fi
  for vmpref in $vmprefs
  do
    if [ "$vm" == "$from" ] ; then continue ; fi
    prefval=$(qvm-prefs "$vm" "$vmpref") || fail "Could not get property $vmpref from $vm"
    if [ "$prefval" == "$from" ]
    then
      if [ "$vm" != "dom0" ] && is_running "$vm"
      then
        echo Shutting down "$vm" for preference migration >&2
        $dryrun  qvm-shutdown --wait --force "$vm" || fail "Could not shut down $vm"
        to_start_later="$vm $to_start_later"
      fi
      echo Migrating "$vmpref" in "$vm" from "$from" to "$to" >&2
      $dryrun  qvm-prefs -s "$vm" "$vmpref" "$to" || fail "Could not migrate $vmpref of $vm from $prefval to $to"
    fi
  done
done

echo Removing "$from" >&2
$dryrun  qvm-remove --force "$from" || fail "Could not remove $from"

restore_running

echo VM "$from" has been fully migrated to "$to" >&2
