1#!/bin/bash -e 2# 3# Open-iSCSI Xen block device hotplug script 4# 5# Author Roger Pau Monné <roger.pau@citrix.com> 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU Lesser General Public License as published 9# by the Free Software Foundation; version 2.1 only. with the special 10# exception on linking described in file LICENSE. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU Lesser General Public License for more details. 16# 17# Usage: 18# 19# Target should be specified using the following syntax: 20# 21# script=block-iscsi,vdev=xvda,target=iqn=<iqn>,portal=<portal IP> 22# 23# Portal address must be in IP format. 24# 25 26dir=$(dirname "$0") 27. "$dir/block-common.sh" 28 29remove_label() 30{ 31 echo $1 | sed "s/^\("$2"\)//" 32} 33 34check_tools() 35{ 36 if ! command -v iscsiadm > /dev/null 2>&1; then 37 fatal "Unable to find iscsiadm tool" 38 fi 39 if [ "$multipath" = "y" ] && ! command -v multipath > /dev/null 2>&1; then 40 fatal "Unable to find multipath" 41 fi 42} 43 44# Sets the following global variables based on the params field passed in as 45# a parameter: iqn, portal, auth_method, user, multipath, password 46parse_target() 47{ 48 # set multipath default value 49 multipath="n" 50 for param in $(echo "$1" | tr "," "\n") 51 do 52 case $param in 53 iqn=*) 54 iqn=$(remove_label $param "iqn=") 55 ;; 56 portal=*) 57 portal=$(remove_label $param "portal=") 58 ;; 59 multipath=*) 60 multipath=$(remove_label $param "multipath=") 61 ;; 62 esac 63 done 64 if [ -z "$iqn" ] || [ -z "$portal" ]; then 65 fatal "iqn= and portal= are required parameters" 66 fi 67 if [ "$multipath" != "y" ] && [ "$multipath" != "n" ]; then 68 fatal "multipath valid values are y and n, $multipath not a valid value" 69 fi 70} 71 72# Sets $dev to point to the device associated with the value in iqn 73find_device() 74{ 75 count=0 76 while [ ! -e /dev/disk/by-path/*"$iqn"-lun-0 ]; do 77 sleep 1 78 count=`expr $count + 1` 79 if [ count = 100 ]; then 80 # 10s timeout while waiting for iSCSI disk to settle 81 fatal "timeout waiting for iSCSI disk to settle" 82 fi 83 done 84 sddev=$(readlink -f /dev/disk/by-path/*"$iqn"-lun-0 || true) 85 if [ ! -b "$sddev" ]; then 86 fatal "Unable to find attached device path" 87 fi 88 if [ "$multipath" = "y" ]; then 89 mdev=$(multipath -ll "$sddev" | head -1 | awk '{ print $1}') 90 if [ ! -b /dev/mapper/"$mdev" ]; then 91 fatal "Unable to find attached device multipath" 92 fi 93 dev="/dev/mapper/$mdev" 94 else 95 dev="$sddev" 96 fi 97} 98 99# Attaches the target $iqn in $portal and sets $dev to point to the 100# multipath device 101attach() 102{ 103 do_or_die iscsiadm -m node --targetname "$iqn" -p "$portal" --login > /dev/null 104 find_device 105} 106 107# Discovers targets in $portal and checks that $iqn is one of those targets 108# Also sets the auth parameters to attach the device 109prepare() 110{ 111 # Check if target is already opened 112 iscsiadm -m session 2>&1 | grep -q "$iqn" && fatal "Device already opened" 113 # Discover portal targets 114 iscsiadm -m discovery -t st -p $portal 2>&1 | grep -q "$iqn" || \ 115 fatal "No matching target iqn found" 116} 117 118# Attaches the device and writes xenstore backend entries to connect 119# the device 120add() 121{ 122 attach 123 write_dev $dev 124} 125 126# Disconnects the device 127remove() 128{ 129 find_device 130 do_or_die iscsiadm -m node --targetname "$iqn" -p "$portal" --logout > /dev/null 131} 132 133command=$1 134target=$(xenstore-read $XENBUS_PATH/params || true) 135if [ -z "$target" ]; then 136 fatal "No information about the target" 137fi 138 139parse_target "$target" 140 141check_tools || exit 1 142 143case $command in 144add) 145 prepare 146 add 147 ;; 148remove) 149 remove 150 ;; 151*) 152 exit 1 153 ;; 154esac 155