mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7516 d57e44dd-8a1f-0410-8b47-8ef2f437770f
392 lines
12 KiB
Bash
392 lines
12 KiB
Bash
#!/bin/bash
|
|
#
|
|
#
|
|
# SCSTLun OCF RA. Exports and manages SCST iSCSI Logical Units.
|
|
#
|
|
# (c) 2012 Riccardo Bicelli
|
|
# and Linux-HA contributors
|
|
#
|
|
# Based on ISCSILogicalUnit from Florian Haas, Dejan Muhamedagic,
|
|
#
|
|
#
|
|
#
|
|
# 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
|
|
#######################################################################
|
|
|
|
meta_data() {
|
|
cat <<END
|
|
<?xml version="1.0"?>
|
|
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
|
|
<resource-agent name="SCSTLun" version="0.1">
|
|
<version>1.0</version>
|
|
|
|
<longdesc lang="en">
|
|
Manages SCST iSCSI Logical Unit. An iSCSI Logical unit is a subdivision of
|
|
an SCSI Target, exported via a daemon that speaks the iSCSI protocol.
|
|
</longdesc>
|
|
<shortdesc lang="en">Manages iSCSI Logical Units (LUs)</shortdesc>
|
|
|
|
<parameters>
|
|
|
|
<parameter name="target_iqn" required="1" unique="0">
|
|
<longdesc lang="en">
|
|
The iSCSI Qualified Name (IQN) that this Logical Unit belongs to.
|
|
</longdesc>
|
|
<shortdesc lang="en">iSCSI target IQN</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
<parameter name="device_name" required="1" unique="0">
|
|
<longdesc lang="en">
|
|
Device Name assigned in SCST. When using vdisk handlers it could be an
|
|
arbitrary name. When using other handlers (such as dev_tape or dev_changer) it
|
|
must be a pointer to device in form H:C:I:L.
|
|
</longdesc>
|
|
<shortdesc lang="en">Device Name Assigned in SCST</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
<parameter name="lun" required="1" unique="0">
|
|
<longdesc lang="en">
|
|
The Logical Unit number (LUN) exposed to initiators.
|
|
</longdesc>
|
|
<shortdesc lang="en">Logical Unit number (LUN)</shortdesc>
|
|
<content type="integer" />
|
|
</parameter>
|
|
|
|
<parameter name="handler" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
The handler used (vdisk_blockio, vdisk_fileio, dev_tape ...).</longdesc>
|
|
<shortdesc lang="en">Handler used</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
<parameter name="scsi_id" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
The t10 device ID of LUN. If not specified default SCST value will be used.
|
|
Please note that some initiators, like ESXi, are using only some of the first
|
|
characters to identify LUN, like 4-6 chars.
|
|
</longdesc>
|
|
<shortdesc lang="en">t10 device id</shortdesc>
|
|
<content type="integer" />
|
|
</parameter>
|
|
|
|
<parameter name="scsi_sn" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
SCSI Serial Number
|
|
</longdesc>
|
|
<shortdesc lang="en">SCSI sn</shortdesc>
|
|
<content type="integer" />
|
|
</parameter>
|
|
|
|
|
|
<parameter name="path" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
The path to the block device exposed. A regular file is allowed too.
|
|
</longdesc>
|
|
<shortdesc lang="en">Block device (or file) path</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
<parameter name="additional_parameters" required="0" unique="0">
|
|
<longdesc lang="en">
|
|
Additional LU 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 LU parameters</shortdesc>
|
|
<content type="string" />
|
|
</parameter>
|
|
|
|
</parameters>
|
|
|
|
<actions>
|
|
<action name="start" timeout="15" />
|
|
<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
|
|
}
|
|
|
|
# Initialization ######################################################
|
|
SYSFS_ROOTPATH="/sys/kernel/scst_tgt"
|
|
SYSFS_PATH="/sys/kernel/scst_tgt/targets/iscsi"
|
|
l_module=""
|
|
SCST_BASE="/sys/kernel/scst_tgt"
|
|
ISCSI_BASE="${SCST_BASE}/targets/iscsi"
|
|
#######################################################################
|
|
|
|
l_load_module () {
|
|
n=`lsmod | grep -c "^$1 "`
|
|
if [ $n -gt 0 ];
|
|
then
|
|
return 0
|
|
else
|
|
ocf_log info "Loading Kernel Module ${1}"
|
|
modprobe $1> /dev/null 2>&1 || return 1
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
l_check_module () {
|
|
case "${OCF_RESKEY_handler}" in
|
|
dev_cdrom) l_module=scst_cdrom;;
|
|
dev_changer) l_module=scst_changer;;
|
|
dev_disk*) l_module=scst_disk;;
|
|
dev_modisk*) l_module=scst_modisk;;
|
|
dev_processor) l_module=scst_processor;;
|
|
dev_raid) l_module=scst_raid;;
|
|
dev_tape*) l_module=scst_tape;;
|
|
dev_user) l_module=scst_user;;
|
|
vdisk*|vcdrom) l_module=scst_vdisk;;
|
|
*) l_module=none;;
|
|
esac
|
|
}
|
|
|
|
l_start_handler () {
|
|
#Check Handler, then load module
|
|
l_check_module
|
|
l_load_module $l_module
|
|
}
|
|
|
|
l_stop_handler () {
|
|
local HANDLER_NOT_REQUIRED=true;
|
|
#Check if handler is used for other devices, then unload module.
|
|
|
|
for i in $( ls "${SYSFS_ROOTPATH}/handlers/${OCF_RESKEY_handler}" ) ; do
|
|
if [ -d ${SYSFS_ROOTPATH}/handlers/${OCF_RESKEY_handler}/${i} ]; then
|
|
HANDLER_NOT_REQUIRED=false
|
|
break
|
|
fi
|
|
done
|
|
|
|
if $HANDLER_NOT_REQUIRED ; then
|
|
ocf_log info "Handler ${OCF_RESKEY_handler} not required, unloading kernel module"
|
|
l_check_module
|
|
rmmod $l_module
|
|
return $?
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
SCSTLun_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
|
|
}
|
|
|
|
SCSTLun_start() {
|
|
SCSTLun_monitor
|
|
if [ $? = $OCF_SUCCESS ]; then
|
|
return $OCF_SUCCESS
|
|
fi
|
|
|
|
local params
|
|
if [ ! ${OCF_RESKEY_path} == "" ]; then
|
|
params="filename=${OCF_RESKEY_path}"
|
|
fi
|
|
if [ ! ${OCF_RESKEY_additional_parameters} == "" ]; then
|
|
params="${params} ${OCF_RESKEY_additional_parameters}"
|
|
fi
|
|
|
|
ocf_log info "Disabling target ${OCF_RESKEY_target_iqn}"
|
|
echo 0 > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/enabled"
|
|
|
|
ocf_log info "Starting lun ${OCF_RESKEY_lun} on target ${OCF_RESKEY_target_iqn}"
|
|
# Load Handler Modules
|
|
l_start_handler #|| exit $OCF_ERR_GENERIC
|
|
|
|
# Open Device
|
|
ocf_log info "Opening device ${OCF_RESKEY_device_name}, target ${OCF_RESKEY_target_iqn}"
|
|
echo "add_device ${OCF_RESKEY_device_name} ${params// /;}" > "${SCST_BASE}/handlers/${OCF_RESKEY_handler}/mgmt"
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log err "FAILED to open device ${OCF_RESKEY_device_name}"
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
|
|
# Set SCSI SN and t10 dev id
|
|
if [ ! ${OCF_RESKEY_scsi_sn} == "" ]; then
|
|
ocf_log info "Setting SCSI S/N ${OCF_RESKEY_scsi_sn}"
|
|
|
|
echo "${OCF_RESKEY_scsi_sn}" > "${SCST_BASE}/devices/${OCF_RESKEY_device_name}/usn"
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log warn "FAILED to set SCSI S/N!"
|
|
fi
|
|
|
|
if [ ! ${OCF_RESKEY_scsi_id} == "" ]; then
|
|
ocf_log info "Setting SCSI ID ${OCF_RESKEY_scsi_sn}-${OCF_RESKEY_scsi_id}"
|
|
echo "${OCF_RESKEY_scsi_sn}-${OCF_RESKEY_scsi_id}" > "${SCST_BASE}/devices/${OCF_RESKEY_device_name}/t10_dev_id"
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log warn "FAILED to set SCSI ID!"
|
|
fi
|
|
fi
|
|
|
|
fi
|
|
|
|
# Assign Device to the Target
|
|
ocf_log info "Adding LUN ${OCF_RESKEY_lun}, device ${OCF_RESKEY_device_name}, target ${OCF_RESKEY_target_iqn}"
|
|
echo "add ${OCF_RESKEY_device_name} ${OCF_RESKEY_lun}" > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/luns/mgmt"
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log err "FAILED to add lun ${OCF_RESKEY_lun}"
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
|
|
#Enable target
|
|
ocf_log info "Enabling target ${OCF_RESKEY_target_iqn}"
|
|
echo 1 > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/enabled"
|
|
|
|
ocf_log info "Started lun ${OCF_RESKEY_lun} on target ${OCF_RESKEY_target_iqn}"
|
|
|
|
#Debugging purpose
|
|
#scstadmin -write_config /tmp/scst.conf.start
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
SCSTLun_stop() {
|
|
SCSTLun_monitor
|
|
if [ $? = $OCF_SUCCESS ]; then
|
|
ocf_log info "Stopping lun ${OCF_RESKEY_lun} on target ${OCF_RESKEY_target_iqn}"
|
|
# Disable Target
|
|
|
|
ocf_log info "Disabling target ${OCF_RESKEY_target_iqn}"
|
|
echo 0 > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/enabled"
|
|
|
|
# Drop connections, only if session is using lun
|
|
for i in $( ls "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/sessions" ) ; do
|
|
if [ -d "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/sessions/${i}/luns/${OCF_RESKEY_lun}" ]; then
|
|
ocf_log warn "Force closing session to initiator ${i}"
|
|
echo 1 > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/sessions/${i}/force_close"
|
|
fi
|
|
done
|
|
|
|
ocf_log info "Removing LUN ${OCF_RESKEY_lun}, device ${OCF_RESKEY_device_name}, target ${OCF_RESKEY_target_iqn}"
|
|
echo "del ${OCF_RESKEY_lun}" >${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/luns/mgmt
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log err "FAILED to remove LUN ${OCF_RESKEY_lun} from target ${OCF_RESKEY_target_iqn}"
|
|
#return $OCF_ERR_GENERIC
|
|
#Don't exit, try to remove device anyway.
|
|
fi
|
|
|
|
#Close Device
|
|
ocf_log info "Closing device ${OCF_RESKEY_device_name}"
|
|
echo "del_device ${OCF_RESKEY_device_name}" > "${SCST_BASE}/handlers/vdisk_fileio/mgmt"
|
|
if [ $? -ne 0 ]; then
|
|
ocf_log err "FAILED to remove device ${OCF_RESKEY_device_name}"
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
|
|
# Enable Target
|
|
ocf_log info "Enabling target ${OCF_RESKEY_target_iqn}"
|
|
echo 1 > "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/enabled"
|
|
|
|
|
|
#Debugging purpose
|
|
#scstadmin -write_config /tmp/scst.conf.stop
|
|
|
|
#Stop Handler
|
|
l_stop_handler || exit $OCF_ERR_GENERIC
|
|
fi
|
|
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
SCSTLun_monitor() {
|
|
#Check if underlying device is configured
|
|
if [ -e "${SCST_BASE}/handlers/${OCF_RESKEY_handler}/${OCF_RESKEY_device_name}" ]; then
|
|
return $OCF_SUCCESS
|
|
fi
|
|
|
|
# Check if lun is running.
|
|
if [ -e "${ISCSI_BASE}/${OCF_RESKEY_target_iqn}/luns/${OCF_RESKEY_lun}" ]; then
|
|
return $OCF_SUCCESS
|
|
fi
|
|
|
|
return $OCF_NOT_RUNNING
|
|
}
|
|
|
|
SCSTLun_validate() {
|
|
# Do we have all required variables?
|
|
# TODO: make this check more precise considering handler used!
|
|
|
|
for var in target_iqn lun device_name handler; 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
|
|
# Do we have all required binaries?
|
|
check_binary scstadmin
|
|
|
|
# Is the required kernel functionality available?
|
|
if [ ! -d ${SCST_BASE} ]; then
|
|
ocf_log err "${SCST_BASE} does not exist or is not a directory -- check if required modules are loaded."
|
|
exit $OCF_ERR_INSTALLED
|
|
fi
|
|
fi
|
|
|
|
return $OCF_SUCCESS
|
|
}
|
|
|
|
|
|
case $1 in
|
|
meta-data)
|
|
meta_data
|
|
exit $OCF_SUCCESS
|
|
;;
|
|
usage|help)
|
|
SCSTLun_usage
|
|
exit $OCF_SUCCESS
|
|
;;
|
|
esac
|
|
|
|
# Everything except usage and meta-data must pass the validate test
|
|
SCSTLun_validate
|
|
|
|
case $__OCF_ACTION in
|
|
start) SCSTLun_start;;
|
|
stop) SCSTLun_stop;;
|
|
monitor|status) SCSTLun_monitor;;
|
|
#reload) ocf_log err "Reloading..."
|
|
# SCSTLun_start
|
|
# ;;
|
|
validate-all) ;;
|
|
*) SCSTLun_usage
|
|
exit $OCF_ERR_UNIMPLEMENTED
|
|
;;
|
|
esac
|
|
rc=$?
|
|
ocf_log info "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
|
|
exit $rc
|