#!/bin/sh
# $Id$
#
# Script:	rsfrc
#
# Description:	RSF-1 startup/shutdown script
#		Use the 'restart' option if services are already up
#		Use the 'kill' option to stop RSF-1 but leave
#		services running. WARNING: this option may cause an
#		incorrect failover if the remote end is in automatic mode!
#
# Platform:	Unix
#
# Author:	High-Availability Ltd / Paul Griffiths-Todd
#
. /opt/HAC/bin/rsf.sh

#
# Sourcing rsf.sh reads DB properties - once they are read, they are kept in
# the environment and sourcing rsf.sh again does not read the properties.
# We don't want that caching mechanism here though because every cluster
# process will inherit the environment from this one, meaning the props will
# never be read even when they are changed by the user.
#
DB_PROPS_DEFINED=

state=$1

#
# Simple shell function to select a single argument.
# Usage: argn <arg_number> arg1 arg1...
# eg. argn 2 one two three -> two
argn()
{
    local argn_index
    argn_index="$1"
    shift
    eval echo "\${${argn_index}}"
}

# Usage: set_branding_info <filename>
# Call with the name of a json branding file. Reads the file and sets
# variables to what it finds. Does NOT parse the file, just looks for
# lines of the form
#	"name" : "value" [,]
# and returns the value from the last occurence of each wanted "name"
# in the file. Ignores lines with unrecognised leading characters, so
# comments with a leading '#' are not scanned.
# See the sed command below for the names read & corresponding variables.
set_branding_info()
{
    # First remove any old values, then scan the file for new ones.
    brand_domain=''
    brand_company=''
    brand_product=''
    brand_docs=''
    brand_email=''
    brand_url=''
    if match "x$brand_product" "x"; then
	# brand_product not set. Read branding file if it exists
        rsfetcdir="${PRODUCT_ETC:-'/opt/HAC/RSF-1/etc'}" # RSF-1 etc directory
	branding_file=${1:="$rsfetcdir/.branding.json"}
	if test -r "$branding_file"; then
            eval $(sed -e 's/^[ \t]*//'  -e 's/[, \t]*$//'	\
		       -e 's/"[ \t]*:[ \t]*"/"="/'		\
		       -e 's/^"companyName"/brand_company/p'	\
		       -e 's/^"productName"/brand_product/p'	\
		       -e 's/^"supportDocs"/brand_docs/p'	\
		       -e 's/^"supportEmail"/brand_email/p'	\
		       -e 's/^"supportUrl"/brand_url/p'		\
		       -n "$branding_file")
	fi

	if match "x$brand_product" "x"; then
	    # brand_product still not set, so not in branding file.
	    # Fall back to HAC branding, using rsf.sh info if available.
	    brand_product="${PRODUCT:-RSF-1}"
	    brand_company="${COMPANY_NAME:-High-Availability.Com}"
	    brand_docs=''
	    brand_domain=${COMPANY_DOMAIN:-www.high-availability.com}
	    brand_email="${brand_domain:+support@}${brand_domain}"
	    brand_url="${brand_domain:+http://}${brand_domain}/"
	fi
    fi
}


copyright()
{
    match "x$brand_product" x && \
	set_branding_info "${RSF1_HOME:-/opt/HAC}/RSF-1/etc/.branding.json"

    echo
    if match "$brand_product" "${PRODUCT:-RSF-1}"; then
	echo "                              ____  _____ ______   ___"
	echo "                             / __ \/ ___// ____/  <  /"
	echo "                            / /_/ /\__ \/ /_______/ / "
	echo "                           / _, _/___/ / __/_____/ /  "
	echo "                          /_/ |_|/____/_/       /_/   "

	echo
	echo "          $brand_product (c) Copyright ${brand_company} Ltd, 1995-`date +%Y`"
	echo "                       $brand_url"
	echo "              (For support email $brand_email)"
    else
	match x"$brand_product" x || echo "    $brand_product"
	match x"$brand_company" x || echo "    Copyright (c) $brand_company"
	match x"$brand_docs" x    || echo "    For help see $brand_docs"

	if match x"$brand_url" "x?*"; then
	    echo "    For support visit $brand_url"
	    match x"$brand_email" x || echo "             or email $brand_email"
	else
	    match x"$brand_email" x   || echo "    For support email $brand_email"
	fi
    fi
}


#
# Prompt before killing RSF-1
confirm_kill()
{
	if [ "${confirmed}" = "true" ]; then
		return 0
	fi

	copyright

	cat <<"EOF"
                 _       _                  _
                | |     / /___ __________  (_)___  ____ _
                | | /| / / __ `/ ___/ __ \/ / __ \/ __ `/
                | |/ |/ / /_/ / /  / / / / / / / / /_/ /
                |__/|__/\__,_/_/  /_/ /_/_/_/ /_/\__, /
                                                /____/

        Killing rsfmon can cause a split-brain scenario to occur,
        resulting in application data corruption. Only kill rsfmon if
        you are aware of the risks and are certain you want to proceed

EOF

	echo "Do you really want to kill rsfmon (yes/no) ?"
	if xor yes no yes; then
	    exit 1
	fi
}

PROXMOXRULE="/lib/udev/rules.d/99-rsf1-proxmox.rules"
proxmox_uninstall_udevrule()
{
    PROXMOXRULE="/lib/udev/rules.d/99-rsf1-proxmox.rules"

    rm -f ${PROXMOXRULE}
}

proxmox_install_udevrule()
{
    ORIGFILE="/lib/udev/rules.d/60-zvol.rules"
    PROXMOXRULE="/lib/udev/rules.d/99-rsf1-proxmox.rules"

    if [ -f "${ORIGFILE}" ] ; then
	SETTING=`grep 'SYMLINK+=' ${ORIGFILE} | awk 'BEGIN { FS =  "SYMLINK\\\\+=" } ; {print $2}' | sed 's/"//g'`
	RESTART=no

	#
	# If the setting is just the zvol device then the additional rule
	# is required.
	if [ "${SETTING}" = "zvol/%c" ] ; then
	    if [ ! -f ${PROXMOXRULE} ] ; then
		RESTART=yes
		echo "Installing udev rule ${PROXMOXRULE}"
		cat > ${PROXMOXRULE} <<EOF
#
# Additional rule to create /dev/<zpool name> symbolic link for Proxmox ZFS over iSCSI
#
KERNEL=="zd*", SUBSYSTEM=="block", ACTION=="add|change", PROGRAM=="/lib/udev/zvol_id $devnode", SYMLINK+="%c"
EOF
	    fi
	fi

	#
	# Otherwise, if the setting does both /dev and /dev/zvol then remove the additional rule.
	if [ "${SETTING}" = "zvol/%c %c" -a -f ${PROXMOXRULE} ] ; then
	    RESTART=yes
	    echo "Removing udev rule ${PROXMOXRULE}"
	    rm -f ${PROXMOXRULE}
	fi

	if [ "${RESTART}" = "yes" ] ; then
	    udevadm control --reload
	fi
    fi
}

#
# Tidy up the restart file - every time!
rm -f /tmp/rsfmonrestart

# rsf-1 is now a service under SMF. Need to keep in sync with that service.
# svcadm enable  rsf-1 --> rsfrc start --SMF
#  - if FILE exists, change start to restart
# svcadm disable rsf-1 --> rsfrc stop  --SMF
# rsfrc start --> svcadm enable rsf-1
# rsfrc stop --> svcadm disable rsf-1
# rsfrc restart --> touch FILE, svcadm enable rsf-1
# rsfrc * --> rsfrc *
#
# Hot upgrade:
# User -> rsfctl kill
# User -> pkgrm rsf-1
# User -> pkgadd -d rsf-1.pkg
# User -> rsfctl restart
#       -> touch file, svcadm enable rsf-1
#        -> rsfctl start --SMF
#         -> Check FILE exists, change start to restart
#          -> restart rsfmon
RESTART_FILE=${PRODUCT_ETC}/.do-restart
SMF_LOG=/var/svc/log/application-RSF-1-rsf-1:default.log

#
# Solaris and related OS's SMF services.
SVC_PYRPC="RSF-1/pyrpc"
SVC_STMFHA="stmfha"
SVC_RSFSYSEVENTD="RSF-1/rsfsyseventd"
SVC_NEFLIASON="RSF-1/nefliaison"
SVC_HAMONLIAISON="RSF-1/hamonliaison"
SVC_VCENTERLIASON="RSF-1/vcliaison"

if [ -x ${SVCADM} ]; then
    #
    # SMF
    #
    SVC_MANAGER=${SVCADM}
    SVC_MAN_ARG="--SMF"
    #
    # If we have the --SMF argument, carry on as normal
    # because this script was run by SMF
    #
    if [ "$2" = "${SVC_MAN_ARG}" ]; then
        if [ -f ${RESTART_FILE} -a "$state" = "start" ]; then
            #
            # Service manager has told rsf-1 to start
            # but the restart file is in place. We should
            # "restart" instead
            #
            rm -f ${RESTART_FILE}
            echo "Changing state from 'start' to 'restart'"
            state="restart"
        fi
    else
        #
        # No --SMF - script was run manually
        #
        rm -f ${RESTART_FILE}
        case $state in
            "start")
                #
                # User has called rsfctl start - need to start service
                #
                echo "Running ${SVCADM} enable rsf-1"
                echo "See log file at ${SMF_LOG}"
                ${SVCADM} enable rsf-1
                exit 0
                ;;
            "stop")
                #
                # User has called rsfctl stop - need to stop service
                #
                echo "Running ${SVCADM} disable rsf-1"
                echo "See log file at ${SMF_LOG}"
                ${SVCADM} disable rsf-1
                exit 0
                ;;
            "restart")
                #
                # User has called rsfctl restart
                # Slightly more tricky:
                #  - We should do nothing if the service is already running
                #  - If the service is stopped, we should touch the RESTART file
                #    and then start the service
                #  - If the service is in a broken state, we may want to stop
                #
                SMF_STATE="`svcs -H rsf-1|awk '{print $1}'`"
                case ${SMF_STATE} in
                    "enabled")
                        ;;
                    "disabled")
                        touch ${RESTART_FILE}
                        echo "Running ${SVCADM} enable rsf-1"
                        echo "See log file at ${SMF_LOG}"
                        ${SVCADM} enable rsf-1
                        exit 0
                        ;;
                    "maintenance")
                        echo "RSF-1 SMF service is in maintenance mode - not restarting rsfmon"
                        echo "Output from svcs -x rsf-1:"
                        echo
                        svcs -x rsf-1
                        exit 0
                        ;;
                esac
        esac
    fi
elif which systemctl >/dev/null 2>&1; then
    #
    # systemd
    #
    SVC_MANAGER=systemctl
    SVC_MAN_ARG="--SYSD"
    #
    # If we have the --SYSD argument, carry on as normal
    # because this script was run by systemd
    #
    if [ "$2" = "${SVC_MAN_ARG}" ]; then
        if [ -f ${RESTART_FILE} ]; then
            case $state in
            "start")
                #
                # Service manager has told rsf-1 to start but the
                # restart file is in place. We should "restart" instead
                #
                echo "Changing state from 'start' to 'restart'"
                state="restart"
                ;;
            "stop")
                #
                # Service manager has told rsf-1 to stop but the
                # restart file is in place. We should "kill" instead
                #
                echo "Changing state from 'stop' to 'kill'"
                state="kill"
                confirmed="true"
                ;;
            esac
            rm -f ${RESTART_FILE}
        fi
    else
        #
        # No --SYSD - script was run manually
        #
        case $state in
            "start")
                echo "Running systemctl start rsf-1"
                echo "See output of \"systemctl status rsf-1\" for info"
                systemctl start rsf-1
                exit 0
                ;;
            "stop")
                echo "Running systemctl stop rsf-1"
                echo "See output of \"systemctl status rsf-1\" for info"
                systemctl stop rsf-1
                exit 0
                ;;
            "kill")
                confirm_kill
                touch ${RESTART_FILE}
                echo "Running systemctl stop rsf-1"
                echo "See output of \"systemctl status rsf-1\" for info"
                systemctl stop rsf-1
                exit 0
                ;;
            "restart")
                SVC_STATE="`systemctl is-active rsf-1`"
                case ${SVC_STATE} in
                    active)
                        echo "Service rsf-1 already active"
                        ;;
                    inactive|failed)
                        echo "Running systemctl start rsf-1"
                        echo "See output of \"systemctl status rsf-1\" for info"
                        systemctl start rsf-1
                        ;;
                esac
                exit 0
                ;;
        esac
    fi
fi

#
# Block states if any of these file exist (cluster node dependent)
RESOURCE_MONITOR_CONFIG="${PRODUCT_DIR}/agents/etc/resource_agent.cfg"
ALWAYS_BLOCK_STATE="${PRODUCT_ETC}/.force_blocked"
PRESERVE_BLOCK_STATE="${PRODUCT_ETC}/.preserve_blocked"
ALWAYS_UNBLOCK_STATE="${PRODUCT_ETC}/.force_unblocked"

#
# States to check for on start-up.
STATEDIR="${PRODUCT_ETC}/state.`hostname`"
starting="2"

#
# Shutdown delay warning.
DELAY=2

#
# Insert generic rsfmon command line flags here
PRODUCT_MONOPTS=""

if [ -f ${ALWAYS_BLOCK_STATE} ] ; then
    PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -b b"
else
    if [ -f ${PRESERVE_BLOCK_STATE} ] ; then
	PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -b p"
    else
	if [ -f ${ALWAYS_UNBLOCK_STATE} ] ; then
	    PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -b u"
	fi
    fi
fi

if is_metroha; then
    PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -r"
fi

if is_freebsd; then
    PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -r"
fi

if is_linux; then
    PRODUCT_MONOPTS="${PRODUCT_MONOPTS} -r"
fi

###################################################################
# No user modifiable parts from here on...
###################################################################
#
# The following entries are for Fedora/RedHat chkconfig tool.
#
# chkconfig: - 85 15
# description: RSF-1 from High-Availability.Com for managed application failover

#
# This must NOT contain '/' characters
DISC_HB="rsf1_hb_"
export DISC_HB

#
# For Darwin architectures we need to dynamically create links to the
# raw heartbeat devices as OS-X dynamically creates device files, which
# MAY not be in the same order.
create_hb_links()
{
    if [ "`uname -s`" = "Darwin" ] ; then
	delete_hb_links
	eval `diskutil list | awk '/^ *[1-9][0-9]*:/ { if ($3 ~ '"/${DISC_HB}*/"')
		print "ln -s /dev/r" $NF " /dev/" $3 ";" }'`
    fi
}

delete_hb_links()
{
    if [ "`uname -s`" = "Darwin" ] ; then
	rm -f /dev/${DISC_HB}*
    fi
}

#
# Output mesg with prog/state prefix
rcecho()
{
	echo "RSF-1: (${state}) $*"
}

#
# If SMF is loaded and we have RPC with local bind only,
# test and warn.
check_smf_rpc_permission()
{
    if [ -x ${SVCPROP} ] ; then
         local_only=`svcprop -p config/local_only network/rpc/bind`
         if [ "$local_only" = "true" ] ; then
             rcecho "Note: SMF property for network/rpc/bind/local_only is set to true."
             rcecho "This means remote cluster RPC operations will fail!"
             rcecho "Setting local_only property to false..."
             svccfg -s svc:/network/rpc/bind setprop config/local_only = false
             svcadm refresh network/rpc/bind:default
             rcecho "done"
         fi
    fi
}


# If this is nexenta with heartbeats on discs with 4k sectors, start
# rsfmon with a -4 option to adjust heartneat offsets from 512:518 to
# 512:520 and write 4k heartneat so we avoid logging a kernel warning.
adjust_4k_heartbeat_flag_wanted()
{
    # Only return "-4k" for nexenta
    is_nexenta || return

    # Use rsfmon debug output to get this host's MACHINE name
    MY_MACHINE_NAME=$(rsfmon -nc "$PRODUCT_CONFIG" -d2 2>&1 |
	sed -n 's/^.* matching MACHINE.*(\([^ ]*\) 1)$/\1/p')
    #echo >&2 "MY_MACHINE_NAME = $MY_MACHINE_NAME"

    # Now scan $PRODUCT_CONFIG for $MY_MACHINE_NAME's heartbeat discs
    heartbeat_discs=$(awk '
BEGIN { is_me=0; machine="'"$MY_MACHINE_NAME"'";
	pmachine="'"%$MY_MACHINE_NAME"'";
}
/^[ \t]*MACHINE[ \t]/ {
	is_me = 0;
	if (($2 == pmachine) || ($2 == machine))
		is_me = 1;
}
/^[ \t]*DIS[CK][ \t]/ {
	if (is_me) {
		if ($3 ~ /^"/) {
			split($3, a, "\"");
			device = a[2];
		} else {
			split($3, a, ":");
			device = a[1];
		}
		print device;
	}
}' "$PRODUCT_CONFIG")
    #printf "Heartbeat_discs:\n$heartbeat_discs\n"

    # This mhdc test returns true if none of the discs use 4k sectors
    mhdc -dq $heartbeat_discs -c SCSI_BLK4K >/dev/null 2>&1
    MHDC_EXIT=$?
    if [ $MHDC_EXIT -eq 0 ]; then
        return 1
    elif [ $MHDC_EXIT -eq 8 ]; then
        return 0
    else
        rcecho "Error occurred while testing HB disk block sizes"
        return 1
    fi
}

#
#
hook_nexenta()
{
    hook_state=$1

    if is_nexenta ; then
        case "${hook_state}" in
            'start')
                #
                # For the purposes of NFS state files, we need to load a
                # module to set CLUSTER_BOOTED to 1.
                # Tells the NFS module to write client state to Sun Cluster's
                # Distributed Stable Storage
                # This was removed for NEF, code left here for reference.
                # ----
                # rcecho "Loading rsf-cluster module"
                # modload ${PRODUCT_MOD}/rsf-cluster
                # ----
                #
                # When we start a ZFS service, we need to do a hot restart
                # of nfs/server. If it's not already online, we can only
                # do a cold start, which won't allow DSS paths to work.
                #
                # Start the server now to make sure it's online before we
                # start any ZFS services.
                #
                rcecho "Starting nfs/server"
                svcadm enable -r nfs/server
                ;;
            'stop')
		#
		# For old times sake.
                # mod_id=`modinfo|nawk '{if ($6 == "rsf-cluster") print $1}'`
		mod_id=$(modinfo | while read line; do
			  match x$(argn 6 $line) x"rsf-cluster" && argn 1 $line
			 done)
                if [ -n "${mod_id}" ]; then
                    rcecho "Unloading rsf-cluster module (${mod_id})"
                    modunload -i ${mod_id}
                fi
                ;;
            'restart')
                ;;
            *)
                ;;
        esac
    fi
}

rtslib_init()
{
    echo "Started `date`" > /tmp/rts.txt

    STATICCONFIG="${PRODUCT_ETC}/iscsi-config.static"

    if [ -d "/etc/target" ] ; then
	RTSCONFIG="/etc/target/saveconfig.json"
	SERVICE="target"
    elif [ -d "/etc/rtslib-fb-target" ] ; then
	RTSCONFIG="/etc/rtslib-fb-target/saveconfig.json"
	SERVICE="rtslib-fb-targetctl"
    else
	rcecho "No iSCSI installation found (no /etc/target or /etc/rtslib-fb-target"
	return
    fi

    if [ -f "${RTSCONFIG}" ] ; then
	rm -f ${RTSCONFIG}
	rcecho "Cleared static iSCSI configuration: ${RTSCONFIG}"
    else
	rcecho "No existing iSCSI configuration to clear"
    fi

    #
    # State can be:
    #  Active: activating (start) since Tue 2025-05-06 15:18:55 BST; 262ms ago
    loop=0
    configcleared="false"
    while [ ${loop} -lt 10 ]
    do
	STATUSLINE=`systemctl status ${SERVICE}|grep Active:`
	code=$?
	echo "Status line = ${STATUSLINE} " >> /tmp/rts.txt

	if [ ${code} -eq 0 ] ; then
	    if [ ! -z "${STATUSLINE}" ] ; then
		ACTIVE=`echo ${STATUSLINE} | awk '{print $2}'`
		STATUS=`echo ${STATUSLINE} | awk '{print $3}'`

		case "${ACTIVE}" in
		    "active")
			if [ "${STATUS}" = "(running)" ]; then
			    echo "Status is active" >> /tmp/rts.txt
			elif [ "${STATUS}" = "(start)" ] ; then
			    echo "Status is start" >> /tmp/rts.txt
			elif [ "${STATUS}" = "(exited)" ] ; then
			    echo "Status exited - clear config!" >> /tmp/rts.txt
			    (targetcli clearconfig confirm=true >> /tmp/rts.txt 2>&1) &
			    configcleared="true"
			    break
			else
			    echo "Unknown status ${STATUS} " >> /tmp/rts.txt
			fi
			;;
		    "inactive"|"failed"|"maintenance")
			echo "Inactive - break out nothing to do" >> /tmp/rts.txt
			# try anyway in case it failed during a load
			(targetcli clearconfig confirm=true >> /tmp/rts.txt 2>&1) &
			configcleared="true"
			return
			;;
		    "activating"|"deactivating"|"reloading")
			echo "Transitioning - wait" >> /tmp/rts.txt
			;;
		    *)
			echo "Unknown state: ${STATUS}" >> /tmp/rts.txt
			(targetcli clearconfig confirm=true >> /tmp/rts.txt 2>&1) &
			configcleared="true"
			break
			;;

		esac
	    else
		if [ ${code} -gt 2 ] ; then
		    return
		fi
	    fi
	else
	    echo "None zero exit code when reading iSCSI status" >> /tmp/rts.txt
	    break
	fi
	loop=`expr ${loop} + 1`
	sleep 1
    done

    if [ "${configcleared}" = "true" ] ; then
	if [ -f "${STATICCONFIG}" ] ; then
	    targetcli restoreconfig "${STATICCONFIG}"
	fi
    fi
}

hook_linux()
{
    if is_linux; then
	if [ -x "${PRODUCT_BIN}/rsfcdb" ] ; then
	    PROXMOX_SUPPORT=`${PRODUCT_BIN}/rsfcdb list_props | grep prop_proxmox_support | awk '{print $3}'`
	    ISCSI_ENABLED=`${PRODUCT_BIN}/rsfcdb list_props|grep -i prop_iscsiEnabled |awk '{print $3}'`

	    if [ "${PROXMOX_SUPPORT}" = "true" ] ; then
		proxmox_install_udevrule
	    else
		proxmox_uninstall_udevrule
	    fi

	    if [ ! -z "${ISCSI_ENABLED}" -a "${ISCSI_ENABLED}" = "true" ] ; then
		rtslib_init
	    fi
	fi
    fi
}

#
#
hook_freebsd()
{
    if is_freebsd; then
	#
	# For TrueNAS we need some trickery to get iSCSI disks working.
	if [ "${PROP_TN_INITIATOR_ROLL}" == "true" ] ; then
	    if [ -x ${PRODUCT_BIN}/initiator-roll.sh ] ; then
		rm -f ${PRODUCT_ETC}/.scsi_key
		${PRODUCT_BIN}/initiator-roll.sh
	    fi
	fi

        echo "Setting debugflags to allow for disc heartbeats"
        sysctl kern.geom.debugflags=0x10

        if ! getpid rpcbind >/dev/null; then
            echo "Starting rpcbind"
            rpcbind &
            if [ $? -ne 0 ]; then
                echo "Failed to start rpcbind!" >&2
            fi
        fi

        CTLDRC=${PRODUCT_ETC}/rc.appliance.c/S30ctld
        CTLCFG_BOOT=/etc/ctl.conf
        CTLCFG_RSF1=${PRODUCT_ETC}/ctl.conf

        if [ -f ${CTLDRC} -a -f ${CTLCFG_RSF1} ]; then
            rotatelogs "${PRODUCT_LOGDIR}" "${CTLD_LOG}"
            CTLD_PIDFILE=/var/run/ctld.pid
            if [ -f ${CTLD_PIDFILE} ]; then
                CTLD_PID="`cat ${CTLD_PIDFILE}`"
                kill -KILL ${CTLD_PID}
                rm -f ${CTLD_PIDFILE}
            fi

            services="`awk '
            BEGIN {
                s = ""
            }
            {
                if ($1 == "SERVICE") {
                    if (s != "") {
                        s = s ","
                    }
                    s = s $2
                }
            }
            END {
                print s
            }' ${PRODUCT_CONFIG}`"

            rcecho "Running ${CTLDRC} remove-all ${services}"
            ${CTLDRC} remove-all ${services}
            cat <<-EOF > ${CTLCFG_BOOT}
			#########################################################################
			# This file is generated automatically by the RSF-1 clustering software
			# Please do not manually edit this file.
			# Instead, edit the file ${CTLCFG_RSF1}
			# If the changes relate to a service configured under the RSF-1 cluster,
			# you should then run:
			# setenv RSF_SERVICE <service>
			# ${PRODUCT_ETC}/rc.appliance.c/S30ctld update
			#########################################################################

			EOF
            cat ${CTLCFG_RSF1} >> ${CTLCFG_BOOT}
        fi
    fi
}

killrsf()
{
	signal=$1
        type=$2

	if [ ! -f "${PRODUCT_PID}" ]; then
		rcecho "rsfmon not running"
		return 1
	else
		rsf_pid=`cat "${PRODUCT_PID:-'/dev/null'}" 2> /dev/null`
                if [ "$2" = "pgrp" ] ; then
			kill -${signal} -${rsf_pid}
                else
			kill -${signal} ${rsf_pid}
		fi
		return $?
	fi
}

script="`basename $0`"
rev='$Revision$'

case "${state}" in
'start_msg')
	echo "Starting ${COMPANY} RSF-1"
	;;

'stop_msg')
	echo "Stopping ${COMPANY} RSF-1"
	;;

'blockstart')
	touch "${DONOTSTARTHA}"
	;;

'forcestart' | 'start')
	if [ -f "${DONOTSTARTHA}" -a "${state}" != "forcestart" ] ; then
	    rcecho "file '${DONOTSTARTHA}' exists not performing normal start-up - exit"
	    exit 0
	fi

	if [ "${state}" = "forcestart" ] ; then
	    if [ -x "${SVCADM}" ] ; then
		rcecho "Reloading RPC/bind"
		${SVCADM} restart rpc/bind
	    fi
	    sleep 1
	    rm -f "${DONOTSTARTHA}"
	fi

	if rsfcli isrunning >/dev/null 2>&1; then
	    echo "RSF-1 is already running!"
	    exit 0
	fi

	if [ -d ${STATEDIR} ]; then
	    for service in `ls ${STATEDIR}`; do
	        state=`cat ${STATEDIR}/${service} | awk {'print $2'}`
	        [ ${state} = ${starting} ] && rm ${STATEDIR}/${service}
	    done
	fi

	if [ -d ${METROHA_DIR} ]; then
	    rm -f ${METROHA_DIR}/site_failover_override.*
	fi

	cleanup_rsf_pid_dir

	hook_freebsd
	hook_linux

	#
	# Remove the reserved drives file so we don't panic on boot
	rm -f ${PRODUCT_ETC}/.reserved_drives

	copyright
	check_smf_rpc_permission

	if [ -f ${PRODUCT_ETC}/.disable_disc_heartbeats ] ; then
	    rm -f ${PRODUCT_ETC}/.disable_disc_heartbeats >/dev/null 2>&1
	fi

	if [ -z "${PROP_MHDC_USE_PGR3}" ] ; then
	    rcecho "WARNING: missing environment prop: PROP_MHDC_USE_PGR3"
	else
            if [ "${PROP_MHDC_USE_PGR3}" = "${BOOL_STR_FALSE}" ]; then
                # SCSI2 not supported on HPE systems using Microsemi HBAs
                # Need to make sure those systems are using PGR3
                # Implementation note: Microsemi cards use the startpqi driver
                if modinfo|grep smartpqi >/dev/null && smbios|grep "Vendor: HPE" >/dev/null; then
                    # Set PGR3 in the DB to avoid running this check every time. Also avoids any
                    # possibility of inadvertently switching to and from PGR3 in the future.
                    # If the card is swapped for a non-Microsemi card, we want to keep using PGR3
                    rcecho "Detected HPE platform with Microsemi HBA - setting DB to use PGR3"
                    ${CDB_EXEC} update prop_mhdc_use_pgr3 ${BOOL_STR_TRUE}
                    # Also set the prop in this process's environment
                    # in case it is used by a subprocess
                    PROP_MHDC_USE_PGR3=${BOOL_STR_TRUE}
	            export PROP_MHDC_USE_PGR3
                fi
            fi
        fi
	rcecho "Starting rsfmon"
	rotatelogs "${PRODUCT_LOGDIR}" "${RSF1_LOG}"

	#
	# Rotate STMFHA logs.
	STMFHA_LOGS=`ls -1 ${STMFHA_LOGDIR}/${STMFHA_LOG}* 2>/dev/null|egrep -v "\.[0-99]$"`
	for logfile in ${STMFHA_LOGS};do
	    rotatelogs "${STMFHA_LOGDIR}" "${logfile##*/}"
	done

	#
	# Rotate RPC logs for STMF and Cluster Services.
	rotatelogs "${PRODUCT_LOGDIR}" `basename "${RPC_CLUSTER_STMF_LOG}"`
	rotatelogs "${PRODUCT_LOGDIR}" `basename "${RPC_CLUSTER_SERVICES_LOG}"`
	#rotatelogs "${PRODUCT_LOGDIR}" `basename "${RPC_PYTHON_SERVICES_LOG}"`

	create_hb_links
	adjust_4k=""
	if adjust_4k_heartbeat_flag_wanted; then
	    adjust_4k="-4"
	fi
	${CTRUN} rsfmon ${PRODUCT_MONOPTS} ${adjust_4k} -i > ${COMPANY_DIR}/RSF-1/log/${RSF1_LOG} 2>&1 &

	#
	# Start resource agent if configured.
	if [ -f ${RESOURCE_MONITOR_CONFIG} -a -x ${PRODUCT_BIN}/rsfagent ] ; then
	    rcecho "Starting RSF-1 resource agent"
	    ${PRODUCT_BIN}/rsfagent --resource-agent start
	fi

	#
	# Solaris and derivatives only block. Start the rpcstmfha/rsfsyseventd/pyrpc/liason processes.
	if [ -x ${SVCADM} ]; then
            if [ -z "${RPC_CLUSTER_STMF}" -o -z "${PROP_COMSTAR_SUPPORT}" ] ; then
		rcecho "WARNING: missing environment prop: RPC_CLUSTER_STMF and/or PROP_COMSTAR_SUPPORT"
            else
		if [ -f "${RPC_CLUSTER_STMF}" -a "${PROP_COMSTAR_SUPPORT}" = "${BOOL_STR_TRUE}" ] ; then
                    if [ -f /usr/lib/libiscsit.so.1 -o -f /lib/libiscsit.so.1 -o -f /usr/local/lib/libiscsit.so.1 ] && \
			[ -f /usr/lib/libstmf.so.1   -o -f /lib/libstmf.so.1   -o -f /usr/local/lib/libstmf.so.1   ]; then
			#
			# We clear/enable SVC_RYPC twice - once here and once below - LEAVE BOTH
			# it may be duplicated but we don't want to change the noop.
			rcecho "Starting RSF-1 STMF RPC process and syseventd."
			for svc in ${SVC_STMFHA} ${SVC_RSFSYSEVENTD} ${SVC_PYRPC} ${SVC_NEFLIASON} ${SVC_HAMONLIAISON} ${SVC_VCENTERLIASON}; do
			    if svcs ${svc} >/dev/null 2>&1; then
				${SVCADM} clear ${svc} 2>/dev/null
				${SVCADM} enable ${svc}
			    fi
			done
                    else
			rcecho "Cannot start RSF-1 RPC process - unable to find libstmf and/or libiscsit."
                    fi
		fi
            fi
	fi

	#
	# Pre-load the stmf libraries by running stmfha now with a no-op subcommand
	[ -n "${PROG_STMFHA}" ] && ${PROG_STMFHA} -h >/dev/null 2>&1 &

	#
	# Now run the Python RPC service.
	if [ -x ${SVCADM} ] ; then
            if svcs ${SVC_PYRPC} >/dev/null 2>&1; then
                ${SVCADM} clear ${SVC_PYRPC} 2>/dev/null
                ${SVCADM} enable ${SVC_PYRPC}
            fi
	elif [ -f /etc/rc.d/rsfrpc ]; then
            if service rsfrpc status >/dev/null 2>&1; then
                rcecho "Starting RSF-1 cluster RPC Python services."
                service rsfrpc start
            else
                echo "Not starting RSF-1 RPC Python service - it is already running."
            fi
	elif [ -x "${RPC_PYTHON_CTL}" ] ; then
	    if ${HAC_PYTHON} "${RPC_PYTHON_CTL}" status >/dev/null 2>&1; then
	        echo "Not starting RSF-1 RPC Python process, ${RPC_PYTHON_CTL} indicates it is already running."
	    else
	        rcecho "Starting RSF-1 cluster RPC Python services."
	        #LTL insert here the preload for the memory allocator
	        ${CTRUN} ${HAC_PYTHON} ${RPC_PYTHON_CTL} start
	    fi
	fi

	if [ -f "${STMFPROXY_CONFIG}" -a -x ${PRODUCT_BIN}/stmfproxy.sh ] ; then
	    rcecho "Starting stmfproxy monitor"
	    ${PRODUCT_BIN}/stmfproxy.sh start
	fi

	hook_nexenta start
	;;

'restart')
	if rsfcli isrunning >/dev/null 2>&1 ; then
	    echo "RSF-1 is already running!"
	    exit 0
	fi

	copyright
	rcecho "Restarting rsfmon"

	create_hb_links
	adjust_4k=""
	if adjust_4k_heartbeat_flag_wanted; then
	    adjust_4k="-4"
	fi
	${CTRUN} rsfmon ${PRODUCT_MONOPTS} ${adjust_4k} >> ${COMPANY_DIR}/RSF-1/log/${RSF1_LOG} 2>&1 &
        hook_nexenta restart
	;;

'kill')
	confirm_kill
	rcecho "Stopping RSF-1 monitoring in ${DELAY} seconds..."
	sleep ${DELAY}
	killrsf KILL pgrp
	if [ $? -ne 0 ]; then
		if [ -f "${PRODUCT_PID}" ]; then
			rm -f ${PRODUCT_PID}
		fi
		rcecho "Couldn't kill RSF-1 (not running?)"
		exit 1
	fi
	rm -f ${PRODUCT_PID}
	delete_hb_links
	if [ "`uname -s`" = "Darwin" ] ; then
	    sleep 5
	fi
	rcecho "RSF-1 stopped"
	;;

'stop')
	copyright

	#
	# Stop resource agent if configured.
	if [ -f ${RESOURCE_MONITOR_CONFIG} -a -x ${PRODUCT_BIN}/rsfagent ] ; then
	    rcecho "Stopping RSF-1 resource agent"
	    ${PRODUCT_BIN}/rsfagent --resource-agent stop
	fi

	rcecho "Stopping RSF-1 monitoring and services in ${DELAY} seconds..."
	sleep ${DELAY}

        hook_nexenta stop

	killrsf TERM noprg
	if [ $? -ne 0 ]; then
		rcecho "Couldn't stop RSF-1 (not running?)"
		if [ -f "${PRODUCT_PID}" ]; then
			rm -f ${PRODUCT_PID}
		fi
		exit 0
	fi
	i=0
	while [ -f "${PRODUCT_PID}" ]	# PID file removed when rsfmon exits
	do
		sleep 5
		i=`expr $i + 1`
		if [ $i -ge 120 ]; then
			rcecho "Service(s) not dying, aborting"
			killrsf KILL noprg
			rm -f ${PRODUCT_PID}
			exit 1
		fi
	done
	delete_hb_links
	if [ "`uname -s`" = "Darwin" ] ; then
	    sleep 5
	fi

	if [ -f "${STMFPROXY_CONFIG}" -a -x ${PRODUCT_BIN}/stmfproxy.sh ] ; then
	    rcecho "Stopping stmfproxy monitor"
	    ${PRODUCT_BIN}/stmfproxy.sh stop
	fi

    #
    # For old times sake.
	RPCPID=`ps -ef|grep rpcmapmgr|grep -v grep |awk '{print $2}'` # old version
	if [ ! -z "${RPCPID}" ] ; then
	    kill ${RPCPID}
	fi

	#
	# Stop the STMF RPC process and syseventd
	if [ -x ${SVCADM} ]; then
	    for svc in ${SVC_STMFHA} ${SVC_RSFSYSEVENTD} ${SVC_PYRPC} ${SVC_NEFLIASON} ${SVC_HAMONLIAISON} ${SVC_VCENTERLIASON}; do
		if svcs ${svc} >/dev/null 2>&1; then
	            ${SVCADM} disable ${svc}
		fi
	    done
	fi

	#############################################################################################
	#
	# This whole block is legacy to handle the old service start up/shut down.
	#
	#############################################################################################
	if [ -f ${RPC_PYTHON_SERVICES_LOCK} ] ; then
	    PID=`cat ${RPC_PYTHON_SERVICES_LOCK}`
	    kill -9 ${PID}
	    rcecho "${script} `date`: stopped rsfpmon python cluster services monitor pid ${PID}"
	fi

	RPCPID=`ps -ef|awk '{ if ($(NF-1) == prog) print $2 }' prog=${RPC_PYTHON_SERVICES}`
	if [ ! -z "${RPCPID}" ] ; then
	    kill ${RPCPID}
	    rcecho "${script} `date`: stopped ${RPC_PYTHON_SERVICES} pid ${RPCPID}"
	fi
	#############################################################################################
	#
	# End of legacy block.
	#
	#############################################################################################

	rcecho "RSF-1 and services stopped"
	;;

'-v')
	echorev
	;;

*)
	echo "Usage: ${script} <start|forcestart|blockstart|restart|kill|stop>"
	;;

esac

exit 0
