diff --git a/nbd-find-free b/nbd-find-free new file mode 100755 index 0000000..05a7573 --- /dev/null +++ b/nbd-find-free @@ -0,0 +1,17 @@ +#!/bin/bash +# returns an unused nbd device +for sys_path in /sys/block/nbd[0-9]*; do + [ -d "$sys_path" ] || continue + + if [ -f "$sys_path/size" ] && [ "$(< "$sys_path/size")" -eq 0 ] ; then + TARGET="/dev/${sys_path##*/}" + break + fi +done + +if [ -z "$TARGET" ]; then + echo "Error: no free NBD device found" >&2 + exit 1 +fi + +echo $TARGET diff --git a/nbd-mount b/nbd-mount new file mode 100755 index 0000000..b942a6d --- /dev/null +++ b/nbd-mount @@ -0,0 +1,39 @@ +#!/bin/bash +# readies a VHD device in Linux +# nbd-mount /path/to/vhd /dev/nbd0 +APP_DIR="$(dirname "$0")" +NBD_FIND_FREE="$APP_DIR/nbd-find-free" +DRIVE="$1" +DISK_LABEL="$2" +DISK_PATH="/dev/disk/by-label/$DISK_LABEL" +SLEEP_INTERVAL=0.5 + +# find an empty nbd device +NBD_TARGET="$($NBD_FIND_FREE)" +if [ -z "$NBD_TARGET" ]; then + echo "Cannot find free nbd device" + exit 1 +fi + +# refuse to connect twice +EXISTING_DRIVE=$(pgrep -f "qemu-nbd.*$DRIVE") +if [ -n "$EXISTING_DRIVE" ]; then + echo "$DRIVE already mounted" >&2 + exit 1 +fi +EXISTING_NBD="$(pgrep -f "qemu-nbd.*$NBD_TARGET")" +if [ -n "$EXISTING_NBD" ]; then + echo "$NBD_TARGET already mounted" >&2 + exit 1 +fi + + +# wait for device to appear +if ! [ -e "$DISK_PATH" ]; then + qemu-nbd --connect="$NBD_TARGET" "$DRIVE" + + # poll until the block device node appears or task times out + until [ -L "$DISK_PATH" ] && [ -b "$DISK_PATH" ]; do + sleep "$SLEEP_INTERVAL" + done +fi diff --git a/nbd-ready b/nbd-ready new file mode 100755 index 0000000..bd80455 --- /dev/null +++ b/nbd-ready @@ -0,0 +1,6 @@ +#!/bin/bash +# returns succesful when nbd is ready +if [ -b /dev/nbd0 ]; then + exit 0 +fi +exit 1 diff --git a/nbd-unmount b/nbd-unmount new file mode 100755 index 0000000..9572105 --- /dev/null +++ b/nbd-unmount @@ -0,0 +1,36 @@ +#!/bin/bash +# disconnects a VHD device from linux (should be unmounted) +# nbd-unmount path-to-vhd +DRIVE="$1" +QEMU_NBD_COMMAND="ps aux|grep '[q]emu-nbd.*--connect='|tr -s ' '|cut -f 11- -d ' '" + +if [ -z "$DRIVE" ]; then + echo "Drive not provided" + exit 1 +fi + +if ! [ -f "$DRIVE" ]; then + echo "$DRIVE not existing" + exit 1 +fi + +# iterate over all mounted nbds +NBD_TARGET= +while read MOUNT; do + if echo "$MOUNT" | egrep "$DRIVE$" > /dev/null; then + NBD_TARGET="$(echo "$MOUNT" | sed -E 's!.*(--connect=?|-c\s+)([^[:space:]]+).*!\2!g')" + fi +done < <(eval "$QEMU_NBD_COMMAND") + +if [ -z "$NBD_TARGET" ]; then + echo "$DRIVE not mounted" + exit 1 +fi + +echo going to unmount "$NBD_TARGET" +if mount | grep ^"$NBD_TARGET" -q ; then + echo "$NBD_TARGET mounted, refusing to detach" + exit 1 +fi + +echo qemu-nbd --disconnect=$NBD_TARGET diff --git a/nbd-wait b/nbd-wait new file mode 100755 index 0000000..b22121f --- /dev/null +++ b/nbd-wait @@ -0,0 +1,17 @@ +#!/bin/bash +# wait until nbd is ready +APP_DIR="$(dirname "$0")" +NBD_READY="$APP_DIR/nbd-ready" +INTERVAL=0.5 + +TIMEOUT=$1 +SECONDS=0 + +until $NBD_READY; do + if [ "$TIMEOUT" ] && (( SECONDS >= "$TIMEOUT" )); then + echo "Timeout waiting for NBD" >&2 + exit 1 + fi + + sleep $INTERVAL +done