Improvements to DevStack's XenServer scripts

I have ensured:
- template gets re-used on second run
- template includes XenServer tools, and custom user accounts
- take snapshot before first boot, for easy re-run
- make host_ip_iface work with either eth2 or eth3
- make ssh into domU checks looser
- above is all ground work for improved jenkins tests
- added some more comments to make it scripts clearer

Change-Id: I5c45370bf8a1393d669480e196b13f592d29154f
diff --git a/tools/xen/scripts/install-os-vpx.sh b/tools/xen/scripts/install-os-vpx.sh
index fe5e810..7f2f3e6 100755
--- a/tools/xen/scripts/install-os-vpx.sh
+++ b/tools/xen/scripts/install-os-vpx.sh
@@ -19,7 +19,12 @@
 
 set -eux
 
-. /etc/xensource-inventory
+if [ -a /etc/xensource-inventory]
+then
+    . /etc/xensource-inventory
+else
+    . /etc/xcp/inventory
+fi
 
 NAME="XenServer OpenStack VPX"
 DATA_VDI_SIZE="500MiB"
diff --git a/tools/xen/scripts/manage-vdi b/tools/xen/scripts/manage-vdi
index a0a27e8..7f12ebc 100755
--- a/tools/xen/scripts/manage-vdi
+++ b/tools/xen/scripts/manage-vdi
@@ -20,6 +20,26 @@
 
 dom0_uuid=$(xe_min vm-list is-control-domain=true)
 
+get_mount_device()
+{
+  vbd_uuid=$1
+
+  dev=$(xe_min vbd-list params=device uuid="$vbd_uuid")
+  if [[ "$dev" =~ "sm/" ]]; then
+    DEBIAN_FRONTEND=noninteractive \
+        apt-get --option "Dpkg::Options::=--force-confold" --assume-yes \
+        install kpartx || true &> /dev/null
+    mapping=$(kpartx -av "/dev/$dev" | sed -ne 's,^add map \([a-f0-9\-]*\).*$,\1,p' | sed -ne "s,^\(.*${part}\)\$,\1,p")
+    if [ -z "$mapping" ]; then
+       echo "Failed to find mapping"
+       exit -1
+    fi
+    echo "mapper/${mapping}"
+  else
+    echo "/dev/$dev$part"
+  fi
+}
+
 open_vdi()
 {
   vbd_uuid=$(xe vbd-create vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid" \
@@ -27,26 +47,30 @@
   mp=$(mktemp -d)
   xe vbd-plug uuid="$vbd_uuid"
 
-  udevsettle
-  dev=$(xe_min vbd-list params=device uuid="$vbd_uuid")
-  mount "/dev/$dev$part" "$mp"
+  which_udev=$(which udevsettle) || true
+  if [ -n "$which_udev" ]; then
+      udevsettle
+  else
+      udevadm settle
+  fi
+
+  mount_device=$(get_mount_device "$vbd_uuid")
+  mount "$mount_device" "$mp"
   echo "Your vdi is mounted at $mp"
 }
 
 close_vdi()
 {
   vbd_uuid=$(xe_min vbd-list vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid")
-  dev=$(xe_min vbd-list params=device uuid="$vbd_uuid")
-  umount "/dev/$dev$part"
+  mount_device=$(get_mount_device "$vbd_uuid")
+  umount "$mount_device"
 
   xe vbd-unplug uuid=$vbd_uuid
   xe vbd-destroy uuid=$vbd_uuid
 }
 
-if [ "$action" == "open" ]
-then
+if [ "$action" == "open" ]; then
   open_vdi
-elif [ "$action" == "close" ]
-then
+elif [ "$action" == "close" ]; then
   close_vdi
 fi
diff --git a/tools/xen/scripts/on_exit.sh b/tools/xen/scripts/on_exit.sh
new file mode 100755
index 0000000..a4db39c
--- /dev/null
+++ b/tools/xen/scripts/on_exit.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+set -o xtrace
+
+declare -a on_exit_hooks
+
+on_exit()
+{
+    for i in $(seq $((${#on_exit_hooks[*]} - 1)) -1 0)
+    do
+        eval "${on_exit_hooks[$i]}"
+    done
+}
+
+add_on_exit()
+{
+    local n=${#on_exit_hooks[*]}
+    on_exit_hooks[$n]="$*"
+    if [[ $n -eq 0 ]]
+    then
+        trap on_exit EXIT
+    fi
+}
diff --git a/tools/xen/scripts/uninstall-os-vpx.sh b/tools/xen/scripts/uninstall-os-vpx.sh
index a82f3a0..0feaec7 100755
--- a/tools/xen/scripts/uninstall-os-vpx.sh
+++ b/tools/xen/scripts/uninstall-os-vpx.sh
@@ -17,19 +17,19 @@
 #    under the License.
 #
 
-remove_data=
-if [ "$1" = "--remove-data" ]
-then
-  remove_data=1
-fi
+set -ex
 
-set -eu
+# By default, don't remove the templates
+REMOVE_TEMPLATES=${REMOVE_TEMPLATES:-"false"}
+if [ "$1" = "--remove-templates" ]; then
+  REMOVE_TEMPLATES=true
+fi
 
 xe_min()
 {
   local cmd="$1"
   shift
-  /opt/xensource/bin/xe "$cmd" --minimal "$@"
+  xe "$cmd" --minimal "$@"
 }
 
 destroy_vdi()
@@ -39,11 +39,8 @@
   local dev=$(xe_min vbd-list uuid=$vbd_uuid params=userdevice)
   local vdi_uuid=$(xe_min vbd-list uuid=$vbd_uuid params=vdi-uuid)
 
-  if [ "$type" = 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ]
-  then
-    echo -n "Destroying data disk... "
+  if [ "$type" == 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ]; then
     xe vdi-destroy uuid=$vdi_uuid
-    echo "done."
   fi
 }
 
@@ -52,50 +49,36 @@
   local vm_uuid="$1"
   local power_state=$(xe_min vm-list uuid=$vm_uuid params=power-state)
 
-  if [ "$power_state" != "halted" ]
-  then
-    echo -n "Shutting down VM... "
+  if [ "$power_state" != "halted" ]; then
     xe vm-shutdown vm=$vm_uuid force=true
-    echo "done."
   fi
 
-  if [ "$remove_data" = "1" ]
-  then
-    for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g')
-    do
-      destroy_vdi "$v"
-    done
-  fi
+  for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do
+    destroy_vdi "$v"
+  done
 
-  echo -n "Deleting VM... "
   xe vm-uninstall vm=$vm_uuid force=true >/dev/null
-  echo "done."
 }
 
 uninstall_template()
 {
   local vm_uuid="$1"
 
-  if [ "$remove_data" = "1" ]
-  then
-    for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g')
-    do
-      destroy_vdi "$v"
-    done
-  fi
+  for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do
+    destroy_vdi "$v"
+  done
 
-  echo -n "Deleting template... "
   xe template-uninstall template-uuid=$vm_uuid force=true >/dev/null
-  echo "done."
 }
 
-
-for u in $(xe_min vm-list other-config:os-vpx=true | sed -e 's/,/ /g')
-do
+# remove the VMs and their disks
+for u in $(xe_min vm-list other-config:os-vpx=true | sed -e 's/,/ /g'); do
   uninstall "$u"
 done
 
-for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g')
-do
-  uninstall_template "$u"
-done
+# remove the templates
+if [ "$REMOVE_TEMPLATES" == "true" ]; then
+  for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g'); do
+    uninstall_template "$u"
+  done
+fi
diff --git a/tools/xen/scripts/xenoneirictemplate.sh b/tools/xen/scripts/xenoneirictemplate.sh
index 1d9ec5e..c5ae990 100755
--- a/tools/xen/scripts/xenoneirictemplate.sh
+++ b/tools/xen/scripts/xenoneirictemplate.sh
@@ -3,7 +3,7 @@
 ## on Xenserver 6.0.2 Net install only
 ## Original Author: David Markey <david.markey@citrix.com>
 ## Author: Renuka Apte <renuka.apte@citrix.com>
-## This is not an officially supported guest OS on XenServer 6.02
+## This is not an officially supported guest OS on XenServer 6.0.2
 
 BASE_DIR=$(cd $(dirname "$0") && pwd)
 source $BASE_DIR/../../../localrc
@@ -15,11 +15,15 @@
     exit 1
 fi
 
-distro="Ubuntu 11.10"
+distro="Ubuntu 11.10 for DevStack"
 arches=("32-bit" "64-bit")
 
 preseedurl=${1:-"http://images.ansolabs.com/devstackubuntupreseed.cfg"}
 
+NETINSTALL_LOCALE=${NETINSTALL_LOCALE:-en_US}
+NETINSTALL_KEYBOARD=${NETINSTALL_KEYBOARD:-us}
+NETINSTALL_IFACE=${NETINSTALL_IFACE:-eth3}
+
 for arch in ${arches[@]} ; do
     echo "Attempting $distro ($arch)"
     if [[ -n $(xe template-list name-label="$distro ($arch)" params=uuid --minimal) ]] ; then
@@ -30,7 +34,11 @@
             echo "NETINSTALLIP not set in localrc"
             exit 1
         fi
-        pvargs="-- quiet console=hvc0 partman/default_filesystem=ext3 locale=en_US console-setup/ask_detect=false keyboard-configuration/layoutcode=us netcfg/choose_interface=eth3 netcfg/get_hostname=os netcfg/get_domain=os auto url=${preseedurl}"
+        # Some of these settings can be found in example preseed files
+        # however these need to be answered before the netinstall
+        # is ready to fetch the preseed file, and as such must be here
+        # to get a fully automated install
+        pvargs="-- quiet console=hvc0 partman/default_filesystem=ext3 locale=${NETINSTALL_LOCALE} console-setup/ask_detect=false keyboard-configuration/layoutcode=${NETINSTALL_KEYBOARD} netcfg/choose_interface=${NETINSTALL_IFACE} netcfg/get_hostname=os netcfg/get_domain=os auto url=${preseedurl}"
         if [ "$NETINSTALLIP" != "dhcp" ]
         then
             netcfgargs="netcfg/disable_autoconfig=true netcfg/get_nameservers=${NAMESERVERS} netcfg/get_ipaddress=${NETINSTALLIP} netcfg/get_netmask=${NETMASK} netcfg/get_gateway=${GATEWAY} netcfg/confirm_static=true"