#!/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 < 1.0 Manages SCST iSCSI targets. An iSCSI target is a collection of SCSI Logical Units (LUs) exported via a daemon that speaks the iSCSI protocol. SCST iSCSI target export agent The target iSCSI Qualified Name (IQN). Should follow the conventional "iqn.yyyy-mm.<reversed domain name>[:identifier]" syntax. iSCSI target IQN iSCSI network portal addresses. Not supported by all implementations. If unset, the default is to create one portal that listens on all IP addresses. iSCSI portal addresses 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. TODO: List of iSCSI initiators allowed to connect to this target A username used for incoming initiator authentication. If unspecified, allowed initiators will be able to log in without authentication. Incoming account username A password used for incoming initiator authentication. Incoming account password 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. List of iSCSI target parameters 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 < ${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