Date: Fri, 29 Jan 2010 00:24:13 +0100 From: Miroslav Lachman <000.fbsd@quip.cz> To: freebsd-rc@freebsd.org, Daniel Braniss <danny@cs.huji.ac.il> Subject: rc script for iSCSI initiator Message-ID: <4B621C9D.8050101@quip.cz>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------030905040909050409020100 Content-Type: text/plain; charset=ISO-8859-2; format=flowed Content-Transfer-Encoding: 7bit Hi, iSCSI initiator is in the base for a long time, but there is not rc.d/iscsi script to start iSCSI sessions. I found one old in mailing list and take it as base for my work. I attached two versions. *rc.d_iscsi.all.txt* manage all defined targets at start / stop command *rc.d_iscsi.individual.txt* can selectively start / stop individual sessions (targets defined in /etc/iscsi.conf and in rc.conf iscsi_targets="") It is not intended to direct commit, it is just work in progress and needs some discussion and improvements from rc folks. Scripts are too verbose for better debugging. Both of them can be called as: /etc/rc.d/iscsi start|stop The "individual" version can be called: /etc/rc.d/iscsi start|stop [target_name] For example: # /etc/rc.d/iscsi start styx_storage_1 debug.iscsi_initiator: 2 -> 0 Starting iSCSI session for styx_storage_1 Waiting for /dev/ufs/styx0p1: . OK /dev/ufs/styx0p1: FILE SYSTEM CLEAN; SKIPPING CHECKS /dev/ufs/styx0p1: clean, 856565848 free (896 frags, 107070619 blocks, 0.0% fragmentation) /dev/ufs/styx0p1 on /vol1 (ufs, local, soft-updates, fsid 2d3d5e4b8b67f290) # /etc/rc.d/iscsi stop styx_storage_1 Unmounting iSCSI volumes for styx_storage_1 /dev/ufs/styx0p1: unmount from /vol1 Stopping iSCSI session for: styx_storage_1 .....All iSCSI sessions were stopped My main problem with this script is how to get a PID of started iscontrol and as I didn't found a "right way" to do it, the script contains some ugly hack with writing temporary file. This must be fixed by somebody more skilled than me. I am open to any comments, sugesstions, warnings etc. Miroslav Lachman --------------030905040909050409020100 Content-Type: text/plain; name="rc.d_iscsi.individual.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="rc.d_iscsi.individual.txt" #!/bin/sh # PROVIDE: iscsi # REQUIRE: NETWORKING # BEFORE: DAEMON # KEYWORD: nojail shutdown # # This script supports starting and stopping individual sessions # from the iscsi_targets list: # rc.d/iscsi start my_first_target # rc.d/iscsi stop another_target # # Targets must be defined in /etc/iscsi.conf # Each target has its own fstab file named as $iscsi_fstab.target_name # # Add the following lines to /etc/rc.conf to enable iscsi: # # iscsi_enable="YES" # iscsi_targets="" # list of targets defined in /etc/iscsi.conf # iscsi_fstab="/etc/fstab.iscsi" # prefix for per target fstabs # iscsi_debug="" # 0,1,2 # iscsi_exports="" # iscsi_zfs="" # . /etc/rc.subr name=iscsi rcvar=`set_rcvar` command=/sbin/iscontrol iscsi_enable=${iscsi_enable:-"NO"} iscsi_fstab=${iscsi_fstab:-"/etc/fstab.iscsi"} iscsi_exports=${iscsi_exports:-"/etc/exports.iscsi"} iscsi_debug=${iscsi_debug:-0} start_cmd="iscsi_start" faststop_cmp="iscsi_stop" stop_cmd="iscsi_stop" stop_postcmd="iscsi_poststop" required_modules="iscsi_initiator:iscsi" iscsi_wait() { dev=$1 trap "echo 'Wait loop cancelled'; exit 1" 2 count=0 while true; do if [ -c $dev ]; then break; fi if [ $count -eq 0 ]; then echo -n "Waiting for ${dev}: " fi count=$((${count} + 1)) if [ $count -eq 6 ]; then echo ' FAILED' return 0 break fi echo -n '.' sleep 5; done echo ' OK' return 1 } iscsi_start() { sysctl debug.iscsi_initiator=$iscsi_debug # # start iscontrol for each target if [ -n "${iscsi_targets}" ]; then _tmp_dir=`mktemp -d /tmp/iscsi.XXXXXXXX` || \ err 3 "$name: Can't create temp dir, exiting..." for target in ${iscsi_targets}; do _pid_file="/var/run/iscontrol_${target}.pid" if [ -f "${_pid_file}" ]; then pgrep -F "${_pid_file}" iscontrol > /dev/null _return=$? if [ $_return -eq 0 ]; then echo "Session for ${target} is already running" continue fi echo "Removing stale pidfile ${_pid_file}" rm "${_pid_file}" fi echo "Starting iSCSI session for ${target}" _tmp_iscsi=${_tmp_dir}/iscontrol.${target} ${command} ${rc_flags} -n ${target} > ${_tmp_iscsi} 2>&1 # I do not know the better way to get iscontrol PID head -1 "${_tmp_iscsi}" | sed -E 's/.*\[([0-9]*)\].*/\1/' > "${_pid_file}" # rm -f "$_tmp_iscsi" ## file specified as _tmp_iscsi remains open until iscontrol is closed ## lsof +aL1 /tmp # lists unlinked files, still opened done # rmdir "${_tmp_dir}" else # no targets, no devices, no mounts, just exit warn 'You must specify iscsi_targets list' return 1 fi # We have separate fstab file for each target (/etc/fstab.iscsi.target_name) for target in ${iscsi_targets}; do target_fstab="${iscsi_fstab}.${target}" if [ -f "${target_fstab}" ]; then while read spec file type opt t1 t2 do case ${spec} in \#*|'') ;; *) if iscsi_wait ${spec}; then break; fi # Check if not already mounted and run fsck mount | grep "^${spec} " if [ $? -ne 0 ]; then #echo "type=${type} spec=${spec} file=${file} opt=${opt}" fsck -p -t ${type} ${spec} else debug "${spec} is already mounted, skipping fsck" fi ;; esac done < "${target_fstab}" # Mount all filesystems from given fstab file mount -a -v -F "${target_fstab}" fi done if [ -f "${iscsi_exports}" ]; then # ??? same content will be appended on each start! # it should be checked with diff / uniq cat ${iscsi_exports} >> /etc/exports #/etc/rc.d/mountd reload kill -1 `cat /var/run/mountd.pid` fi if checkyesno zfs_enable; then if checkyesno iscsi_zfs; then sleep 4 zpool import -d /dev/label -a # presumably we can ignore zfs mount -a share -a and swapon # some zfs dataset may be exported "legacy", so hup mountd kill -1 `cat /var/run/mountd.pid` fi fi } iscsi_stop() { for target in ${iscsi_targets}; do target_fstab="${iscsi_fstab}.${target}" if [ -f "${target_fstab}" ]; then echo "Unmounting iSCSI volumes for ${target}" umount -a -fv -F "${target_fstab}" fi done echo -n 'Stopping iSCSI session for:' _poststop=0 # Stop iscontrol for each target if [ -n "${iscsi_targets}" ]; then if [ `sysctl -n net.iscsi.sessions` -gt 0 ]; then # We will run iscsi_poststop loop _poststop=1 fi for target in ${iscsi_targets}; do echo -n " ${target}" _iscsi_pid_file="/var/run/iscontrol_${target}.pid" if [ -f "${_iscsi_pid_file}" ]; then _pid=$(head -1 "${_iscsi_pid_file}") # Safety check if PID from file is PID of iscontrol _grep_pid="$(pgrep -F "${_iscsi_pid_file}" iscontrol)" if [ "${_pid}" = "${_grep_pid}" ]; then kill -HUP ${_pid} && rm "${_iscsi_pid_file}" _pids="${_pids} $_pid" fi else echo -e "\n Cannot stop session ${target}. No PID in /var/run" fi done fi echo '' } iscsi_poststop() { _dying=0 while [ $_poststop -gt 0 -a -n "${_pids}" ]; do if [ -n "$(ps -o pid= -o command= -p ${_pids})" ]; then sleep 2 echo -n '.' _dying=$(($_dying + 1)) if [ $_dying -gt 10 ]; then echo 'Some session does not want stop, giving up' return 1 break fi else echo 'All iSCSI sessions were stopped' return 0 break fi done } load_rc_config $name cmd="$1" if [ $# -gt 0 ]; then shift fi if [ -n "$*" ]; then iscsi_targets="$*" fi run_rc_command "${cmd}" --------------030905040909050409020100 Content-Type: text/plain; name="rc.d_iscsi.all.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="rc.d_iscsi.all.txt" #!/bin/sh # PROVIDE: iscsi # REQUIRE: NETWORKING # BEFORE: DAEMON # KEYWORD: nojail shutdown # # Add the following lines to /etc/rc.conf to enable iscsi: # # iscsi_enable="YES" # iscsi_targets="" # list of targets defined in /etc/iscsi.conf # iscsi_fstab="/etc/fstab.iscsi" # iscsi_debug="" # 0,1,2 # iscsi_exports="" # iscsi_zfs="" # . /etc/rc.subr name=iscsi rcvar=`set_rcvar` command=/sbin/iscontrol iscsi_enable=${iscsi_enable:-"NO"} iscsi_fstab=${iscsi_fstab:-"/etc/fstab.iscsi"} iscsi_exports=${iscsi_exports:-"/etc/exports.iscsi"} iscsi_debug=${iscsi_debug:-0} start_cmd="iscsi_start" faststop_cmp="iscsi_stop" stop_cmd="iscsi_stop" stop_postcmd="iscsi_poststop" required_modules="iscsi_initiator:iscsi" iscsi_wait() { dev=$1 trap "echo 'Wait loop cancelled'; exit 1" 2 count=0 while true; do if [ -c $dev ]; then break; fi if [ $count -eq 0 ]; then echo -n "Waiting for ${dev}: " fi count=$((${count} + 1)) if [ $count -eq 6 ]; then echo ' FAILED' return 0 break fi echo -n '.' sleep 5; done echo ' OK' return 1 } iscsi_start() { sysctl debug.iscsi_initiator=$iscsi_debug # # start iscontrol for each target if [ -n "${iscsi_targets}" ]; then _tmp_dir=`mktemp -d /tmp/iscsi.XXXXXXXX` || \ err 3 "$name: Can't create temp dir, exiting..." for target in ${iscsi_targets}; do _pid_file="/var/run/iscontrol_${target}.pid" if [ -f "${_pid_file}" ]; then pgrep -F "${_pid_file}" iscontrol > /dev/null _return=$? if [ $_return -eq 0 ]; then echo "Session for ${target} is already running" continue fi echo "Removing stale pidfile ${_pid_file}" rm "${_pid_file}" fi echo "Starting iSCSI session for ${target}" _tmp_iscsi=${_tmp_dir}/iscontrol.${target} ${command} ${rc_flags} -n ${target} > ${_tmp_iscsi} 2>&1 # I do not know the better way to get iscontrol PID head -1 "${_tmp_iscsi}" | sed -E 's/.*\[([0-9]*)\].*/\1/' > "${_pid_file}" # rm -f "$_tmp_iscsi" ## file specified as _tmp_iscsi remains open until iscontrol is closed ## lsof +aL1 /tmp # lists unlinked files, still opened done # rmdir "${_tmp_dir}" else # no targets, no devices, no mounts, just exit warn 'You must specify iscsi_targets list' return 1 fi if [ -f "${iscsi_fstab}" ]; then while read spec file type opt t1 t2 do case ${spec} in \#*|'') ;; *) if iscsi_wait ${spec}; then break; fi # Check if not already mounted and run fsck mount | grep "^${spec} " if [ $? -ne 0 ]; then #echo "type=${type} spec=${spec} file=${file} opt=${opt}" fsck -p -t ${type} ${spec} else debug "${spec} is already mounted, skipping fsck" fi ;; esac done < ${iscsi_fstab} # Mount all filesystems from given fstab file mount -a -v -F "${iscsi_fstab}" fi if [ -f "${iscsi_exports}" ]; then # ??? same content will be appended on each start! # it should be checked with diff / uniq cat ${iscsi_exports} >> /etc/exports #/etc/rc.d/mountd reload kill -1 `cat /var/run/mountd.pid` fi if checkyesno zfs_enable; then if checkyesno iscsi_zfs; then sleep 4 zpool import -d /dev/label -a # presumably we can ignore zfs mount -a share -a and swapon # some zfs dataset may be exported "legacy", so hup mountd kill -1 `cat /var/run/mountd.pid` fi fi } iscsi_stop() { if [ -f "${iscsi_fstab}" ]; then echo 'Unmounting all iSCSI volumes:' umount -a -fv -F ${iscsi_fstab} fi echo -n 'Stopping iSCSI session for:' _poststop=0 # Stop iscontrol for each target if [ -n "${iscsi_targets}" ]; then if [ `sysctl -n net.iscsi.sessions` -gt 0 ]; then # We will run iscsi_poststop loop _poststop=1 fi for target in ${iscsi_targets}; do echo -n " ${target}" _iscsi_pid_file="/var/run/iscontrol_${target}.pid" if [ -f "${_iscsi_pid_file}" ]; then _pid=$(head -1 "${_iscsi_pid_file}") # Safety check if PID from file is PID of iscontrol _grep_pid="$(pgrep -F "${_iscsi_pid_file}" iscontrol)" if [ "${_pid}" = "${_grep_pid}" ]; then kill -HUP ${_pid} && rm "${_iscsi_pid_file}" _pids="${_pids} $_pid" fi else echo -e "\n Cannot stop session ${target}. No PID in /var/run" fi done fi echo '' } iscsi_poststop() { _dying=0 while [ $_poststop -gt 0 -a -n "${_pids}" ]; do if [ -n "$(ps -o pid= -o command= -p ${_pids})" ]; then sleep 2 echo -n '.' _dying=$(($_dying + 1)) if [ $_dying -gt 10 ]; then echo 'Some session does not want stop, giving up' return 1 break fi else echo 'All iSCSI sessions were stopped' return 0 break fi done } load_rc_config $name run_rc_command "$1" --------------030905040909050409020100--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4B621C9D.8050101>