#!/bin/sh
# Tries to work around LP bug #696454, i.e. that if the root /dev/nbd0 device
# is unmounted on shutdown then nbd read errors occur, and if it isn't, then
# the nbd-server process on the server doesn't terminate.
# Called by init scripts on reboot or shutdown.

case "$RUNLEVEL" in
    0)
        key="o"
        command="poweroff -f"
        ;;
    6)
        key="b"
        command="reboot"
        ;;
    *)
        echo "nbd-disconnect should only be called by initscripts on reboot/shutdown." >&2
        exit 1
        ;;
esac

disconnect() {
    # Stop trapping
    trap - 0 HUP INT QUIT KILL SEGV PIPE TERM

    # ltsp-client-core.upstart needs "console output" to show stderr
    echo "nbd-disconnect executing: $command" >&2
    # Cache the command in order to use it after nbd-client disconnects
    $command --version >/dev/null 2>&1
    nbd-client -d "$root"
    $command
    # Hopefully this should never be reached
    echo "$key" > /proc/sysrq-trigger
}

# Disconnect swap nbd devices first
while read device etc; do
    case "$device" in
        /dev/nbd[0-9])
            swapoff "$device"
            nbd-client -d "$device"
            ;;
        /dev/mapper/swap[0-9])
            nbd_device=$(cryptsetup status "$device" | awk '/device:/{print $2}')
            swapoff "$device"
            cryptsetup remove "$device"
            case "$nbd_device" in
                /dev/nbd[1-9]) 
                    nbd-client -d "$nbd_device"
                    ;;
            esac
            ;;
    esac
done < /proc/swaps

# If we're not using an nbd root, exit
unset root
for param in $(cat /proc/cmdline); do
    case "$param" in
        root=/dev/nbd[0-9])
            root="${param#root=}"
            ;;
    esac
done
test -n "$root" || exit 0

trap "disconnect" 0 HUP INT QUIT KILL SEGV PIPE TERM
sync
# Give up to 5 seconds for other services to be called.
# If they finish before that time, process termination will start, and the trap
# will be called.
sleep 5
