[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 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?

> +        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.

> +    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,..."

> +    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...

> +    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"?

> +    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"
> +    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.

> +    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



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.