]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
hotplug/Linux: add iscsi block hotplug script
authorRoger Pau Monne <roger.pau@citrix.com>
Thu, 2 May 2013 11:38:55 +0000 (13:38 +0200)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 8 May 2013 10:51:30 +0000 (11:51 +0100)
This hotplug script has been tested with IET and NetBSD iSCSI targets,
without authentication.

This hotplug script will only work with PV guests not using pygrub.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
tools/hotplug/Linux/Makefile
tools/hotplug/Linux/block-iscsi [new file with mode: 0644]

index 99bf87f4189ff995f2b7d1b5842a9e4cde96af0f..8b0d7f4dda493af90c11620c4d185e83755467b5 100644 (file)
@@ -22,6 +22,7 @@ XEN_SCRIPTS += blktap
 XEN_SCRIPTS += xen-hotplug-cleanup
 XEN_SCRIPTS += external-device-migrate
 XEN_SCRIPTS += vscsi
+XEN_SCRIPTS += block-iscsi
 XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
 XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
 XEN_SCRIPT_DATA += block-common.sh
diff --git a/tools/hotplug/Linux/block-iscsi b/tools/hotplug/Linux/block-iscsi
new file mode 100644 (file)
index 0000000..8e36852
--- /dev/null
@@ -0,0 +1,154 @@
+#!/bin/bash -e
+#
+# Open-iSCSI Xen block device hotplug script
+#
+# Author Roger Pau MonnĂ© <roger.pau@citrix.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; version 2.1 only. with the special
+# exception on linking described in file LICENSE.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# Usage:
+#
+# Target should be specified using the following syntax:
+#
+# script=block-iscsi,vdev=xvda,target=iqn=<iqn>,portal=<portal IP>
+#
+# Portal address must be in IP format.
+#
+
+dir=$(dirname "$0")
+. "$dir/block-common.sh"
+
+remove_label()
+{
+    echo $1 | sed "s/^\("$2"\)//"
+}
+
+check_tools()
+{
+    if ! command -v iscsiadm > /dev/null 2>&1; then
+        fatal "Unable to find iscsiadm tool"
+    fi
+    if [ "$multipath" = "y" ] && ! command -v multipath > /dev/null 2>&1; then
+        fatal "Unable to find multipath"
+    fi
+}
+
+# Sets the following global variables based on the params field passed in as
+# a parameter: iqn, portal, auth_method, user, multipath, password
+parse_target()
+{
+    # set multipath default value
+    multipath="n"
+    for param in $(echo "$1" | tr "," "\n")
+    do
+        case $param in
+        iqn=*)
+            iqn=$(remove_label $param "iqn=")
+            ;;
+        portal=*)
+            portal=$(remove_label $param "portal=")
+            ;;
+        multipath=*)
+            multipath=$(remove_label $param "multipath=")
+            ;;
+        esac
+    done
+    if [ -z "$iqn" ] || [ -z "$portal" ]; then
+        fatal "iqn= and portal= are required parameters"
+    fi
+    if [ "$multipath" != "y" ] && [ "$multipath" != "n" ]; then
+        fatal "multipath valid values are y and n, $multipath not a valid value"
+    fi
+}
+
+# Sets $dev to point to the device associated with the value in iqn
+find_device()
+{
+    count=0
+    while [ ! -e /dev/disk/by-path/*"$iqn"-lun-0 ]; do
+        sleep 0.1
+        count=`expr $count + 1`
+        if [ count = 100 ]; then
+            # 10s timeout while waiting for iSCSI disk to settle
+            fatal "timeout waiting for iSCSI disk to settle"
+        fi
+    done
+    sddev=$(readlink -f /dev/disk/by-path/*"$iqn"-lun-0 || true)
+    if [ ! -b "$sddev" ]; then
+        fatal "Unable to find attached device path"
+    fi
+    if [ "$multipath" = "y" ]; then
+        mdev=$(multipath -ll "$sddev" | head -1 | awk '{ print $1}')
+        if [ ! -b /dev/mapper/"$mdev" ]; then
+            fatal "Unable to find attached device multipath"
+        fi
+        dev="/dev/mapper/$mdev"
+    else
+        dev="$sddev"
+    fi
+}
+
+# Attaches the target $iqn in $portal and sets $dev to point to the
+# multipath device
+attach()
+{
+    do_or_die iscsiadm -m node --targetname "$iqn" -p "$portal" --login > /dev/null
+    find_device
+}
+
+# Discovers targets in $portal and checks that $iqn is one of those targets
+# Also sets the auth parameters to attach the device
+prepare()
+{
+    # Check if target is already opened
+    iscsiadm -m session 2>&1 | grep -q "$iqn" && fatal "Device already opened"
+    # Discover portal targets
+    iscsiadm -m discovery -t st -p $portal 2>&1 | grep -q "$iqn" || \
+        fatal "No matching target iqn found"
+}
+
+# Attaches the device and writes xenstore backend entries to connect
+# the device
+add()
+{
+    attach
+    write_dev $dev
+}
+
+# Disconnects the device
+remove()
+{
+    find_device
+    do_or_die iscsiadm -m node --targetname "$iqn" -p "$portal" --logout > /dev/null
+}
+
+command=$1
+target=$(xenstore-read $XENBUS_PATH/params || true)
+if [ -z "$target" ]; then
+    fatal "No information about the target"
+fi
+
+parse_target "$target"
+
+check_tools || exit 1
+
+case $command in
+add)
+    prepare
+    add
+    ;;
+remove)
+    remove
+    ;;
+*)
+    exit 1
+    ;;
+esac