diff --git a/heartbeat/iscsi b/heartbeat/iscsi index c79670c18..3f110fe37 100755 --- a/heartbeat/iscsi +++ b/heartbeat/iscsi @@ -1,422 +1,429 @@ #!/bin/sh # # iSCSI OCF resource agent # Description: manage iSCSI disks (add/remove) using open-iscsi # # Copyright Dejan Muhamedagic # (C) 2007 Novell Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # # See usage() and meta_data() below for more details... # # OCF instance parameters: # OCF_RESKEY_portal: the iSCSI portal address or host name (required) # OCF_RESKEY_target: the iSCSI target (required) # OCF_RESKEY_iscsiadm: iscsiadm program path (optional) # OCF_RESKEY_discovery_type: discovery type (optional; default: sendtargets) # # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Defaults OCF_RESKEY_udev_default="yes" OCF_RESKEY_iscsiadm_default="iscsiadm" OCF_RESKEY_discovery_type_default="sendtargets" : ${OCF_RESKEY_udev=${OCF_RESKEY_udev_default}} : ${OCF_RESKEY_iscsiadm=${OCF_RESKEY_iscsiadm_default}} : ${OCF_RESKEY_discovery_type=${OCF_RESKEY_discovery_type_default}} usage() { methods=`iscsi_methods` methods=`echo $methods | tr ' ' '|'` cat < 1.0 OCF Resource Agent for iSCSI. Add (start) or remove (stop) iSCSI targets. Manages a local iSCSI initiator and its connections to iSCSI targets The iSCSI portal address in the form: {ip_address|hostname}[":"port] Portal address The iSCSI target IQN. Target IQN Target discovery type. Check the open-iscsi documentation for supported discovery types. Target discovery type open-iscsi administration utility binary. iscsiadm binary If the next resource depends on the udev creating a device then we wait until it is finished. On a normally loaded host this should be done quickly, but you may be unlucky. If you are not using udev set this to "no", otherwise we will spin in a loop until a timeout occurs. udev EOF } iscsi_methods() { cat <= "2.0-872" changed discovery semantics # see http://www.mail-archive.com/open-iscsi@googlegroups.com/msg04883.html # there's a new discoverydb command which should be used instead discovery open_iscsi_discovery() { local output local severity=err local discovery_variant="discovery" local options="" local cmd local version=`$iscsiadm --version | awk '{print $3}'` ocf_version_cmp "$version" "2.0-871" if [ $? -eq 2 ]; then # newer than 2.0-871? discovery_variant="discoverydb" [ "$discovery_type" = "sendtargets" ] && options="-D" fi cmd="$iscsiadm -m $discovery_variant -p $OCF_RESKEY_portal -t $discovery_type $options" ocf_is_probe && severity=info output=`$cmd` if [ $? -ne 0 -o x = "x$output" ]; then [ x != "x$output" ] && { ocf_log $severity "$cmd FAILED" echo "$output" } return 3 fi portal=`echo "$output" | awk -v target="$OCF_RESKEY_target" ' $NF==target{ if( NF==3 ) portal=$2; # sles compat mode else portal=$1; sub(",.*","",portal); print portal; }'` case `echo "$portal" | wc -w` in 0) #target not found echo "$output" ocf_log $severity "target $OCF_RESKEY_target not found at portal $OCF_RESKEY_portal" return 1 ;; 1) #we're ok return 0 ;; *) # handle multihome hosts reporting multiple portals for p in $portal; do if [ "$OCF_RESKEY_portal" = "$p" ]; then portal="$OCF_RESKEY_portal" return 0 fi done echo "$output" ocf_log err "sorry, can't handle multihomed hosts unless you specify the portal exactly" return 2 ;; esac } open_iscsi_add() { $iscsiadm -m node -p $1 -T $2 -l } open_iscsi_remove() { $iscsiadm -m node -p $1 -T $2 -u } open_iscsi_status() { $iscsiadm -m session 2>/dev/null | grep -qs "$2$" } # # NB: this is udev specific! # wait_for_udev() { dev=/dev/disk/by-path/ip-$portal-iscsi-$OCF_RESKEY_target while :; do ls $dev* >/dev/null 2>&1 && break ocf_log warning "waiting for udev to create $dev" sleep 1 done } iscsi_status() { - if $disk_status $portal $OCF_RESKEY_target; then + if $disk_status "$portal" $OCF_RESKEY_target; then return $OCF_SUCCESS else return $OCF_NOT_RUNNING fi } iscsi_start() { if iscsi_status; then ocf_log info "iscsi $portal $OCF_RESKEY_target already running" return $OCF_SUCCESS else $add_disk $portal $OCF_RESKEY_target || return $OCF_ERR_GENERIC case "$udev" in [Yy]es) wait_for_udev || return $OCF_ERR_GENERIC ;; *) ;; esac if iscsi_status; then return $OCF_SUCCESS else return $OCF_ERR_GENERIC fi fi } iscsi_stop() { if iscsi_status; then $remove_disk $portal $OCF_RESKEY_target || return $OCF_ERR_GENERIC if iscsi_status; then return $OCF_ERR_GENERIC else return $OCF_SUCCESS fi else ocf_log info "iscsi $portal $OCF_RESKEY_target already stopped" return $OCF_SUCCESS fi } iscsi_monitor() { - if $disk_status $portal $OCF_RESKEY_target; then + if $disk_status "$portal" $OCF_RESKEY_target; then return $OCF_SUCCESS - else + else return $OCF_NOT_RUNNING - fi + fi } # # 'main' starts here... # if [ $# -ne 1 ]; then usage exit $OCF_ERR_ARGS fi # These operations don't require OCF instance parameters to be set case "$1" in meta-data) meta_data exit $OCF_SUCCESS;; usage) usage exit $OCF_SUCCESS;; methods) iscsi_methods exit $OCF_SUCCESS;; esac if [ x = "x$OCF_RESKEY_target" ]; then ocf_log err "target parameter not set" exit $OCF_ERR_CONFIGURED fi if [ x = "x$OCF_RESKEY_portal" ]; then ocf_log err "portal parameter not set" exit $OCF_ERR_CONFIGURED fi case `uname` in Linux) setup=open_iscsi_setup ;; *) ocf_log info "platform `uname` may not be supported" setup=open_iscsi_setup ;; esac LSB_STATUS_STOPPED=3 $setup rc=$? if [ $rc -ne 0 ]; then ocf_log info "iscsi initiator utilities not installed or not setup" case "$1" in stop) exit $OCF_SUCCESS;; monitor) exit $OCF_NOT_RUNNING;; status) exit $LSB_STATUS_STOPPED;; *) exit $rc;; esac fi if [ `id -u` != 0 ]; then ocf_log err "$0 must be run as root" exit $OCF_ERR_PERM fi discovery_type=${OCF_RESKEY_discovery_type} udev=${OCF_RESKEY_udev} $discovery # discover and setup the real portal string (address) case $? in 0) ;; 1) [ "$1" = stop ] && exit $OCF_SUCCESS [ "$1" = monitor ] && exit $OCF_NOT_RUNNING [ "$1" = status ] && exit $LSB_STATUS_STOPPED exit $OCF_ERR_GENERIC ;; -2) exit $OCF_ERR_GENERIC;; +2) [ "$1" = stop ] && { + iscsi_monitor || exit $OCF_SUCCESS + } + ocf_is_probe && { + iscsi_monitor; exit + } + exit $OCF_ERR_GENERIC +;; 3) ocf_is_probe && exit $OCF_NOT_RUNNING exit $OCF_ERR_GENERIC ;; esac # which method was invoked? case "$1" in start) iscsi_start ;; stop) iscsi_stop ;; status) if iscsi_status then echo iscsi target $OCF_RESKEY_target running exit $OCF_SUCCESS else echo iscsi target $OCF_RESKEY_target stopped exit $OCF_NOT_RUNNING fi ;; monitor) iscsi_status ;; validate-all) # everything already validated # just exit successfully here. exit $OCF_SUCCESS;; *) iscsi_methods exit $OCF_ERR_UNIMPLEMENTED;; esac # # vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0