aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/hotplug/Linux/Makefile1
-rw-r--r--tools/hotplug/Linux/block-iscsi154
2 files changed, 155 insertions, 0 deletions
diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile
index 99bf87f418..8b0d7f4dda 100644
--- a/tools/hotplug/Linux/Makefile
+++ b/tools/hotplug/Linux/Makefile
@@ -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
index 0000000000..8e36852832
--- /dev/null
+++ b/tools/hotplug/Linux/block-iscsi
@@ -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