mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
Extraneous space in "status" breaks resource monitoring:
<action name="status " timeout="10" interval="10" depth="0" />
Fixes: https://github.com/SCST-project/scst/issues/80
355 lines
9.9 KiB
Bash
355 lines
9.9 KiB
Bash
#!/bin/bash
|
|
#
|
|
#
|
|
# SCSTTarget OCF RA. Exports and manages iSCSI SCST targets.
|
|
#
|
|
# (c) 2012 Riccardo Bicelli
|
|
# and Linux-HA contributors
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
#######################################################################
|
|
# Initialization:
|
|
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
|
|
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
|
|
|
|
# Set portal to none by default
|
|
OCF_RESKEY_portals_default="none"
|
|
: ${OCF_RESKEY_portals=${OCF_RESKEY_portals_default}}
|
|
|
|
|
|
# Lockfile, used for selecting a target ID
|
|
LOCKFILE=${HA_RSCTMP}/SCSTTarget-${OCF_RESKEY_implementation}.lock
|
|
ISCSI_DAEMON="/usr/local/sbin/iscsi-scstd"
|
|
SYSFS_PATH="/sys/kernel/scst_tgt/targets/iscsi"
|
|
SCST_BASE="/sys/kernel/scst_tgt"
|
|
ISCSI_BASE="${SCST_BASE}/targets/iscsi"
|
|
#######################################################################
|
|
|
|
meta_data() {
|
|
cat <<END
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
|
<resource-agent name="SCSTTarget" version="0.1">
|
|
<version>1.0</version>
|
|
|
|
<longdesc lang="en">
|
|
Manages SCST iSCSI targets. An iSCSI target is a collection of SCSI Logical
|
|
Units (LUs) exported via a daemon that speaks the iSCSI protocol.
|
|
</longdesc>
|
|
<shortdesc lang="en">SCST iSCSI target export agent</shortdesc>
|
|
|
|
<parameters>
|
|
|
|
<parameter name="iqn" required="1" unique="1">
|
|
<longdesc lang="en">
|
|
The target iSCSI Qualified Name (IQN). Should follow the conventional
|
|
"iqn.yyyy-mm.<reversed domain name>[:identifier]" syntax.
|
|
</longdesc>
|
|
<shortdesc lang="en">iSCSI target IQN</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
<parameter name="portals" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
iSCSI network portal addresses. Not supported by all
|
|
implementations. If unset, the default is to create one portal that
|
|
listens on all IP addresses.
|
|
</longdesc>
|
|
<shortdesc lang="en">iSCSI portal addresses</shortdesc>
|
|
<content type="string" default="${OCF_RESKEY_portals_default}"/>
|
|
</parameter>
|
|
|
|
<parameter name="allowed_initiators" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
TODO: Allowed initiators. A space-separated list of initiators allowed to
|
|
connect to this target. Initiators may be listed in any syntax
|
|
the target implementation allows. If this parameter is empty or
|
|
not set, access to this target will be allowed from any initiator.
|
|
</longdesc>
|
|
<shortdesc lang="en">TODO: List of iSCSI initiators allowed to connect
|
|
to this target</shortdesc>
|
|
<content type="string" default=""/>
|
|
</parameter>
|
|
|
|
<parameter name="incoming_username" required="0" unique="1">
|
|
<longdesc lang="en">
|
|
A username used for incoming initiator authentication. If unspecified,
|
|
allowed initiators will be able to log in without authentication.
|
|
</longdesc>
|
|
<shortdesc lang="en">Incoming account username</shortdesc>
|
|
<content type="string"/>
|
|
</parameter>
|
|
|
|
<parameter name="incoming_password" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
A password used for incoming initiator authentication.
|
|
</longdesc>
|
|
<shortdesc lang="en">Incoming account password</shortdesc>
|
|
<content type="string"/>
|
|
</parameter>
|
|
|
|
<parameter name="additional_parameters" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
Additional target parameters. A space-separated list of "name=value"
|
|
pairs which will be passed through to the iSCSI daemon's management
|
|
interface. The supported parameters are implementation
|
|
dependent. Neither the name nor the value may contain whitespace.
|
|
</longdesc>
|
|
<shortdesc lang="en">List of iSCSI target parameters</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
</parameters>
|
|
|
|
<actions>
|
|
<action name="start" timeout="10" />
|
|
<action name="stop" timeout="180" />
|
|
<action name="status" timeout="10" interval="10" depth="0" />
|
|
<action name="monitor" timeout="10" interval="10" depth="0" />
|
|
<action name="meta-data" timeout="5" />
|
|
<action name="validate-all" timeout="10" />
|
|
</actions>
|
|
</resource-agent>
|
|
END
|
|
}
|
|
|
|
|
|
l_load_module () {
|
|
n=`lsmod | grep -c "^$1 "`
|
|
if [ $n -gt 0 ];
|
|
then
|
|
return 0
|
|
else
|
|
modprobe $1> /dev/null 2>&1 || return 1
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
l_start_service () {
|
|
local running
|
|
|
|
# Handler modules are loaded in LUN resource agent
|
|
|
|
# Check if modules are loaded
|
|
if [ ! -d ${SYSFS_PATH} ]; then
|
|
ocf_log info "Loading scst Modules"
|
|
l_load_module scst || return 1
|
|
l_load_module iscsi_scst || return 1
|
|
|
|
#Not critical modules, not unloaded on stop.
|
|
l_load_module crc32c
|
|
l_load_module crc32c_intel
|
|
fi
|
|
|
|
# Start Daemon
|
|
if [ ! "$(pidof ${ISCSI_DAEMON})" ]; then
|
|
ocf_run $ISCSI_DAEMON || return 1
|
|
ocf_run scstadmin -force -noprompt -clear_config >/dev/null 2>&1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
l_stop_service () {
|
|
#Stop SCST Services, if there are no targets active.
|
|
local TARGET_NOT_PRESENT=true
|
|
|
|
#Are there targets active?
|
|
for i in $( ls "${ISCSI_BASE}" ) ; do
|
|
if [ -d "${ISCSI_BASE}/${i}" ]; then
|
|
ocf_log warn "Found target running: ${i}"
|
|
TARGET_NOT_PRESENT=false
|
|
fi
|
|
done
|
|
|
|
#Close sessions
|
|
for i in `/bin/ls ${ISCSI_BASE}/${OCF_RESKEY_iqn}/sessions`; do
|
|
ocf_log warn "Force closing session to initiator ${i}"
|
|
echo "1" > "${ISCSI_BASE}/${OCF_RESKEY_iqn}/sessions/${i}/force_close"
|
|
done
|
|
|
|
#Stop process and unload modules
|
|
if $TARGET_NOT_PRESENT ; then
|
|
ocf_log warn "Daemon not required, stopping ..."
|
|
pkill -TERM -f $ISCSI_DAEMON
|
|
rmmod iscsi_scst
|
|
rmmod scst
|
|
fi
|
|
}
|
|
|
|
SCSTTarget_usage() {
|
|
cat <<END
|
|
usage: $0 {start|stop|status|monitor|validate-all|meta-data}
|
|
|
|
Expects to have a fully populated OCF RA-compliant environment set.
|
|
END
|
|
}
|
|
|
|
SCSTTarget_start() {
|
|
SCSTTarget_monitor
|
|
if [ $? = $OCF_SUCCESS ]; then
|
|
return $OCF_SUCCESS
|
|
fi
|
|
|
|
local param
|
|
local name
|
|
local value
|
|
local initiator
|
|
|
|
# Start Service
|
|
l_start_service
|
|
# Set incoming username and password globally
|
|
if [ "${OCF_RESKEY_incoming_username}" != "" ]; then
|
|
echo "add_attribute IncomingUser ${OCF_RESKEY_incoming_username} ${OCF_RESKEY_incoming_password}" > ${ISCSI_BASE}/mgmt
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log warn "Unable to set CHAP Authentication!"
|
|
fi
|
|
fi
|
|
|
|
ocf_log info "target ${OCF_RESKEY_iqn}: Starting..."
|
|
|
|
# Create Target
|
|
echo "add_target ${OCF_RESKEY_iqn}" > ${ISCSI_BASE}/mgmt || exit $OCF_ERR_GENERIC
|
|
|
|
# Set Allowed Portals
|
|
if [ "${OCF_RESKEY_portals}" != "none" ]; then
|
|
for param in ${OCF_RESKEY_portals}; do
|
|
ocf_log info "Adding allowed portal ${param} to target ${OCF_RESKEY_iqn}"
|
|
echo "add_target_attribute ${OCF_RESKEY_iqn} allowed_portal ${param}" > ${ISCSI_BASE}/mgmt
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log warn "Unable to set Allowed Portal!"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Set incoming username and password
|
|
if [ "${OCF_RESKEY_incoming_username}" != "" ]; then
|
|
echo "add_target_attribute ${OCF_RESKEY_iqn} IncomingUser ${OCF_RESKEY_incoming_username} ${OCF_RESKEY_incoming_password}" > ${ISCSI_BASE}/mgmt
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log warn "Unable to set CHAP Authentication!"
|
|
fi
|
|
fi
|
|
|
|
ocf_log info "Enabling target ${OCF_RESKEY_iqn}"
|
|
# Enable iSCSI Target
|
|
echo 1 > "${ISCSI_BASE}/enabled" || exit $OCF_ERR_GENERIC
|
|
|
|
ocf_log debug "SCST target ${OCF_RESKEY_iqn}: Started."
|
|
|
|
#Debugging purpose
|
|
#scstadmin -write_config /tmp/scst.conf.start
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
SCSTTarget_stop() {
|
|
SCSTTarget_monitor
|
|
|
|
if [ $? = $OCF_SUCCESS ]; then
|
|
local param
|
|
ocf_log info "target ${OCF_RESKEY_iqn}: Stopping..."
|
|
|
|
# Check if there are connected luns
|
|
for i in $( ls "${ISCSI_BASE}/${OCF_RESKEY_iqn}/luns" ) ; do
|
|
if [ -d "${ISCSI_BASE}/${OCF_RESKEY_iqn}/luns/${i}" ]; then
|
|
ocf_log err "Unable to stop target ${OCF_RESKEY_iqn}: lun ${i} connected!"
|
|
exit $OCF_ERR_GENERIC
|
|
fi
|
|
done
|
|
|
|
# Disable Target
|
|
ocf_log info "disabling target ${OCF_RESKEY_iqn}"
|
|
echo 0 > ${ISCSI_BASE}/${OCF_RESKEY_iqn}/enabled || exit $OCF_ERR_GENERIC
|
|
|
|
#Remove Target
|
|
ocf_log info "deleting target ${OCF_RESKEY_iqn}"
|
|
echo "del_target ${OCF_RESKEY_iqn}" > ${ISCSI_BASE}/mgmt
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log err "Unable to delete Target ${OCF_RESKY_iqn}"
|
|
exit $OCF_ERR_GENERIC
|
|
fi
|
|
#Debugging purpose
|
|
#scstadmin -write_config /tmp/scst.conf.stop
|
|
|
|
#Check if other targets are running, then stop service and unload modules
|
|
l_stop_service
|
|
ocf_log info "target ${OCF_RESKEY_iqn}: Stopped."
|
|
fi
|
|
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
SCSTTarget_monitor() {
|
|
if [ -d "${SYSFS_PATH}/${OCF_RESKEY_iqn}" ]; then
|
|
return $OCF_SUCCESS
|
|
else
|
|
return $OCF_NOT_RUNNING
|
|
fi
|
|
}
|
|
|
|
SCSTTarget_validate() {
|
|
# Do we have all required variables?
|
|
local required_vars
|
|
required_vars="iqn"
|
|
for var in ${required_vars}; do
|
|
param="OCF_RESKEY_${var}"
|
|
if [ -z "${!param}" ]; then
|
|
ocf_log error "Missing resource parameter \"$var\"!"
|
|
exit $OCF_ERR_CONFIGURED
|
|
fi
|
|
done
|
|
|
|
if ! ocf_is_probe; then
|
|
check_binary scstadmin
|
|
fi
|
|
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
|
|
case $1 in
|
|
meta-data)
|
|
meta_data
|
|
exit $OCF_SUCCESS
|
|
;;
|
|
usage|help)
|
|
SCSTTarget_usage
|
|
exit $OCF_SUCCESS
|
|
;;
|
|
esac
|
|
|
|
# Everything except usage and meta-data must pass the validate test
|
|
SCSTTarget_validate
|
|
|
|
case $__OCF_ACTION in
|
|
start) SCSTTarget_start;;
|
|
stop) SCSTTarget_stop;;
|
|
monitor|status) SCSTTarget_monitor;;
|
|
#reload) ocf_log err "Reloading..."
|
|
# SCSTTarget_start
|
|
# ;;
|
|
validate-all) ;;
|
|
*) SCSTTarget_usage
|
|
exit $OCF_ERR_UNIMPLEMENTED
|
|
;;
|
|
esac
|
|
rc=$?
|
|
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
|
exit $rc
|