| #!/bin/bash | 
 |  | 
 | set -eux | 
 |  | 
 | action="$1" | 
 | vm="$2" | 
 | device="${3-0}" | 
 | part="${4-}" | 
 |  | 
 | function xe_min() { | 
 |   local cmd="$1" | 
 |   shift | 
 |   xe "$cmd" --minimal "$@" | 
 | } | 
 |  | 
 | function run_udev_settle() { | 
 |   which_udev=$(which udevsettle) || true | 
 |   if [ -n "$which_udev" ]; then | 
 |       udevsettle | 
 |   else | 
 |       udevadm settle | 
 |   fi | 
 | } | 
 |  | 
 | vm_uuid=$(xe_min vm-list name-label="$vm") | 
 | vdi_uuid=$(xe_min vbd-list params=vdi-uuid vm-uuid="$vm_uuid" \ | 
 |                            userdevice="$device") | 
 |  | 
 | dom0_uuid=$(xe_min vm-list is-control-domain=true) | 
 |  | 
 | function get_mount_device() { | 
 |   vbd_uuid=$1 | 
 |  | 
 |   dev=$(xe_min vbd-list params=device uuid="$vbd_uuid") | 
 |   if [[ "$dev" =~ "sm/" || "$dev" =~ "blktap-2/" ]]; then | 
 |     DEBIAN_FRONTEND=noninteractive \ | 
 |         apt-get --option "Dpkg::Options::=--force-confold" --assume-yes \ | 
 |         install kpartx &> /dev/null || true | 
 |     mapping=$(kpartx -av "/dev/$dev" | sed -ne 's,^add map \([a-z0-9\-]*\).*$,\1,p' | sed -ne "s,^\(.*${part}\)\$,\1,p") | 
 |     if [ -z "$mapping" ]; then | 
 |        echo "Failed to find mapping" | 
 |        exit -1 | 
 |     fi | 
 |  | 
 |     local device="/dev/mapper/${mapping}" | 
 |     for (( i = 0; i < 5; i++ )) ; do | 
 |         if [ -b $device ] ; then | 
 |             echo $device | 
 |             return | 
 |         fi | 
 |         sleep 1 | 
 |     done | 
 |     echo "ERROR: timed out waiting for dev-mapper" | 
 |     exit 1 | 
 |   else | 
 |     echo "/dev/$dev$part" | 
 |   fi | 
 | } | 
 |  | 
 | function clean_dev_mappings() { | 
 |   dev=$(xe_min vbd-list params=device uuid="$vbd_uuid") | 
 |   if [[ "$dev" =~ "sm/" || "$dev" =~ "blktap-2/" ]]; then | 
 |     kpartx -dv "/dev/$dev" | 
 |   fi | 
 | } | 
 |  | 
 | function open_vdi() { | 
 |   vbd_uuid=$(xe vbd-create vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid" \ | 
 |                          device=autodetect) | 
 |   mp=$(mktemp -d) | 
 |   xe vbd-plug uuid="$vbd_uuid" | 
 |  | 
 |   run_udev_settle | 
 |  | 
 |   mount_device=$(get_mount_device "$vbd_uuid") | 
 |   mount "$mount_device" "$mp" | 
 |   echo "Your vdi is mounted at $mp" | 
 | } | 
 |  | 
 | function close_vdi() { | 
 |   vbd_uuid=$(xe_min vbd-list vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid") | 
 |   mount_device=$(get_mount_device "$vbd_uuid") | 
 |   run_udev_settle | 
 |   umount "$mount_device" | 
 |  | 
 |   clean_dev_mappings | 
 |  | 
 |   xe vbd-unplug uuid=$vbd_uuid | 
 |   xe vbd-destroy uuid=$vbd_uuid | 
 | } | 
 |  | 
 | if [ "$action" == "open" ]; then | 
 |   open_vdi | 
 | elif [ "$action" == "close" ]; then | 
 |   close_vdi | 
 | fi |