|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] hotplug/Linux: add iscsi block hotplug script
On 26/04/13 17:17, Ian Campbell wrote:
> On Fri, 2013-04-26 at 14:30 +0100, Roger Pau Monne wrote:
>> 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@xxxxxxxxxx>
>> Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
>> Cc: Ian Jackson <ian.jackson@xxxxxxxxxx>
>> ---
>> Changes since v1:
>> * Added an example in the script header to show the usage.
>> * Changed shebang to use bash.
>> * Replace type with command, for portability reasons.
>> * Replace echo with fatal/log functions.
>> * Include block-common.sh.
>> * Prevent infinite loop when waitign for device to settle.
>> * Only redirect stdout to /dev/null.
>> Changes due to 4.3 release freeze:
>> * We can no longer provide a user/password, because they will be
>> stored in xenstore "params" backend node, which can be read by the
>> guest.
>> * Only works with PV domains because we don't have a hook in libxl to
>> pass the block device created by the script to Qemu.
>> * Doesn't work with pygrub because we don't call the script until
>> pygrub has already been executed, and even if we called it earlier
>> we still need a hook in order to provide the right block device to
>> pygrub.
>> Changes since v1:
>> * Add -e to script shebang, and use 'set +e' if we know hotplug
>> execution might fail.
>> ---
>> tools/hotplug/Linux/Makefile | 1 +
>> tools/hotplug/Linux/block-iscsi | 209
>> +++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 210 insertions(+), 0 deletions(-)
>> create mode 100644 tools/hotplug/Linux/block-iscsi
>>
>> diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile
>> index 0605559..98c7738 100644
>> --- a/tools/hotplug/Linux/Makefile
>> +++ b/tools/hotplug/Linux/Makefile
>> @@ -21,6 +21,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 0000000..9f74c20
>> --- /dev/null
>> +++ b/tools/hotplug/Linux/block-iscsi
>> @@ -0,0 +1,209 @@
>> +#!/bin/bash -e
>> +#
>> +# Open-iSCSI Xen block device hotplug script
>> +#
>> +# Author Roger Pau Monnà <roger.pau@xxxxxxxxxx>
>> +#
>> +# 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"
>> + return 1
>> + fi
>> + if [ "$multipath" = "y" ] && ! command -v multipath > /dev/null 2>&1;
>> then
>> + fatal "Unable to find multipath"
>
> this isn't critical unless the user asked for multipath I think?
That's why we check for $multipath = "y", if the user requested
multipath and the hotplug script cannot find it, crash.
>
>> + return 1
>> + 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"
>> + return 1
>> + fi
>> + if [ "$multipath" != "y" ] && [ "$multipath" != "n" ]; then
>> + fatal "multipath valid values are y and n, $multipath not a valid
>> value"
>> + return 1
>
> fatal already exits.
Ack, will change all occurrences.
>
>> + fi
>> + return 0
>> +}
>> +
>> +# 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"
>> + return 1
>> + fi
>> + done
>> + sddev=$(readlink -f /dev/disk/by-path/*"$iqn"-lun-0 || true)
>> + if [ ! -b "$sddev" ]; then
>> + fatal "Unable to find attached device path"
>> + return 1
>> + 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"
>> + return 1
>> + fi
>> + dev="/dev/mapper/$mdev"
>> + else
>> + dev="$sddev"
>> + fi
>> + return 0
>> +}
>> +
>> +# Attaches the target $iqn in $portal and sets $dev to point to the
>> +# multipath device
>> +attach()
>> +{
>> + set +e
>> + iscsiadm -m node --targetname "$iqn" -p "$portal" --login > /dev/null
>> + rc=$?
>> + set -e
>> + if [ $rc -ne 0 ]; then
>> + fatal "Unable to connect to target"
>> + return 1
>> + fi
>
> This is roughly the same as do_or_die iscsiadm -m node etc , apart from
> the specifics of the log message.
>
> If you want to keep the message as is then is it the same as
> iscsiadm -m node ... || fatal "Unable,..."
I've switched to do_or_die, at the end the message didn't provide much
more info, and it's probably better to print the command that failed.
>> + find_device
>
> set -e is back in force here, so won't this barf before you have a
> chance to check $?
>
> In fact now I look at it find device either calls fatal (and exits) or
> returns 0...
Yes, since the script calls fatal I've removed all the checks for the
return values of internal functions.
>
>> + if [ $? -ne 0 ]; then
>> + fatal "Unable to find iSCSI device"
>> + return 1
>> + fi
>> + return 0
>> +}
>> +
>> +# 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
>> + set +e
>> + iscsiadm -m session 2>&1 | grep -q "$iqn"
>
> Does the use of a pipe here make this incompatible with do_or_die? or
> the use of || fatal "mmm"?
In this specific case I should use &&, because we expect the command to
fail.
>
>> + rc=$?
>> + set -e
>> + if [ $rc -eq 0 ]; then
>> + fatal "Device already opened"
>> + return 1
>> + fi
>> + # Discover portal targets
>> + set +e
>> + iscsiadm -m discovery -t st -p $portal 2>&1 | grep -q "$iqn"
Here a || is appropriate.
>> + rc=$?
>> + set -e
>> + if [ $rc -ne 0 ]; then
>> + fatal "No matching target iqn found"
>> + return 1
>> + fi
>> + return 0
>> +}
>> +
>> +# Attaches the device and writes xenstore backend entries to connect
>> +# the device
>> +add()
>> +{
>> + attach
>> + if [ $? -ne 0 ]; then
>> + fatal "Failed to attach device"
>> + return 1
>> + fi
>
> attach either succeeds or exits.
Done.
>
>> + write_dev $dev
>> + return 0
>> +}
>> +
>> +# Disconnects the device
>> +remove()
>> +{
>> + find_device
>> + if [ $? -ne 0 ]; then
>> + fatal "Unable to find device"
>> + return 1
>> + fi
>> + set +e
>> + iscsiadm -m node --targetname "$iqn" -p "$portal" --logout > /dev/null
>> + rc=$?
>> + set -e
>> + if [ $rc -ne 0 ]; then
>> + fatal "Unable to disconnect target"
>> + return 1
>> + fi
>> + return 0
>> +}
>> +
>> +command=$1
>> +target=$(xenstore-read $XENBUS_PATH/params || true)
>> +if [ -z "$target" ]; then
>> + fatal "No information about the target"
>> + exit 1
>> +fi
>> +
>> +parse_target "$target"
>> +
>> +check_tools || exit 1
>> +
>> +case $command in
>> +add)
>> + prepare
>> + add
>> + exit $?
>> + ;;
>> +remove)
>> + remove
>> + exit $?
>> + ;;
>> +*)
>> + exit 1
>> + ;;
>> +esac
I'm going to send v3 ASAP with all the comments addressed.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |