#! /usr/bin/ksh
#
# ident	"@(#)cvmreconfig.sh	1.18	03/04/15 SMI"
#
# Copyright 1997-2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# cvmreconfig - reconfiguration program for Veritas Clustered Volume Manager
#
# Input:
#       Environment variables:
#               ${CLUSTNAME}
#               ${CURRSTEP}
#               ${CURRNODES}
#		${ALLNODES}
#               ${LOCALNODEID}
#               ${RECONF_SCRIPTS}
#
# Action:	Run reconfiguration programs based on current ucmm step
#
# Output:	Return 0 if success
#		Return 1 if failure
#		Return 200 if result is to be ignored
#		Return 205 if another reconfiguration is needed
#

#
# set some flags (NOTE: they are not set implicitly in subroutines)
#
# set -x # print commands as executed
# set -e # execute ERR trap on command error
# set -u # treat unset variables as an error
# set -f # disable file name generation

#
# Cluster Events
#
#
# command used to publish substep events
#
PUB_EVENT="/usr/cluster/lib/ucmm/ucmm_substep_event";
#
# command used to get timestamp data to be published
#
TIMESTAMP="/usr/cluster/lib/ucmm/ucmm_timestamp";
#
# get beginning timeofday and hrtime for calculating event times later
#
# we use an external program to get timestamps in nanosecond resolution
# as the format of our event publication messages is in this data type.
#
# NOTE: if an error occurs, do not report the error as availability is
# more important than event execution times. Since we do math on these
# variables later, if the command fails we need to ensure that they
# are not null, else the math will cause the script to exit causing
# node death.
#
BEGIN_HRTIME=$(${TIMESTAMP} -h) || BEGIN_HRTIME=0;
BEGIN_TOD=$(${TIMESTAMP} -t) || BEGIN_TOD=0;
#
# Cluster Event Severities
#
# NOTE: these values must be in sync with the cl_eventdefs.h file
#
CL_EVENT_SEV_INFO=0;
CL_EVENT_SEV_WARNING=1;
CL_EVENT_SEV_ERROR=2;
CL_EVENT_SEV_CRITICAL=3;
CL_EVENT_SEV_FATAL=4;

#
# Local variables
#
pre="SUNWcvm.cvmreconfig";
cfgmatch="/usr/cluster/lib/ucmm/cfgmatch";
cvm_cfgfile="/opt/SUNWcvm/etc/cvm.conf";
hatimerun="/usr/cluster/bin/hatimerun";
run_reserve="/usr/cluster/lib/sc/reserve";
vxclust="/usr/sbin/vxclust";
vxdctl="/usr/sbin/vxdctl";
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/opt/SUNWcvm/lib";

#
# Include common files
#
include=.;
RECONF_SCRIPTS="${RECONF_SCRIPTS:-/usr/cluster/lib/ucmm}";
${include} ${RECONF_SCRIPTS}/ucmm_reconf.common;


#
#	make sure that device fencing has completed
#
hw_reserve() {
	${run_reserve} -l;
	return $?;
}



#
#	abort command
#
cvmabort_cmd() {

	${vxclust} $* || return $?;

	set_cvm_status OFFLINE "abort step completed";

	return 0;

}

#
#	return command
#
cvmreturn_cmd() {

	set_cvm_status DEGRADED "reconfiguration in progress"

	${vxclust} $* || return $?;

	return 0;

}

#
#	start command
#
cvmstart_cmd() {

	#
	# get volume manager configuration daemon mode
	#
	mode=$(${hatimerun} -t 30 ${vxdctl} mode 2>/dev/null);
	if [[ $? != 0 || -z ${mode} ]]; then
		scds_syslog -p error -t "${pre}.cvmstart_cmd" -m \
			"Could not determine volume configuration daemon mode";
		return 1;
	fi

	#
	# vxdctl mode reports whether vxconfigd is running (if so it's mode).
	#
	case ${mode} in
		*not-running*)	# Abort node if Volume manager is not running.
			scds_syslog -p error -t "${pre}.cvmstart_cmd" -m \
				"Volume configuration daemon not running.";
			return 1;
		;;
	esac

	${vxclust} $* || return $?;
	return 0;

}

#
#	step1 command
#
cvmstep1_cmd() {

	${vxclust} $* || return $?;	
	return 0;

}

#
#	step2 command
#
cvmstep2_cmd() {

	${vxclust} $* || return $?;
	return 0;

}

#
#	step3 command
#
cvmstep3_cmd() {

	${vxclust} $* || return $?;
	return 0;

}

#
#	step4 command
#
cvmstep4_cmd() {

	${vxclust} $* || return $?;
	return 0;

}

#
#	step6 command
#
cvmstep6_cmd() {

	scds_syslog -p notice -t "${pre}.cvmstep6_cmd" -m \
		"cluster volume manager shared access mode enabled";
	name=$(/bin/uname -n);
	case $(${vxdctl} -c mode 2>/dev/null) in
		*MASTER*) vm_on_node="master";;
		*SLAVE*) vm_on_node="slave";;
		*) vm_on_node="unknown";;
	esac
	scds_syslog -p notice -t "${pre}.cvmstep6_cmd" -m \
		"- node %s vm_on_node is %s" "${name}" "${vm_on_node}";

	set_cvm_status OK "";
	return 0;

}

#
#	stop command
#
cvmstop_cmd() {

	${vxclust} $* || return $?;

	set_cvm_status OFFLINE "stop step completed";
	return 0;

}

#
#	validate command
#
cvmvalidate_cmd() {

	initcvm || return $?;
	return 0;

}


initcvm() {

        if [[ -d ${vxclust} || ! -x ${vxclust} ]]; then
		scds_syslog -p error -t "${pre}.initcvm" -m \
                        "Veritas is not properly installed, %s not found." \
			"${vxclust}";
		return 1;
        fi

	return 0;

}

#############################################################
# set_cvm_status
#   Sets resource status
#       Parameter 1: <status> (not validated)
#                OK,  DEGRADED,  FAULTED, UNKNOWN, or OFFLINE.
#       Parameter 2: <message>
#
#############################################################
set_cvm_status()
{
	typeset rs_status="${1:-UNKNOWN}";
	typeset msg=${2:-""};
	typeset cvm_rt="SUNW.rac_cvm:*";
	typeset rs_name_key="cvm.resource_name";
	typeset rg_name_key="cvm.resource_group_name";
	typeset rs_name="";
	typeset group="";

	rs_name=$(${cfgmatch} ${rs_name_key} ${cvm_cfgfile});

	if [ -z "${rs_name}" ]; then
		# CVM resource is not configured.
		# Entry not found in cvm.conf file
		# Don't update status

		return 0;
	fi

	group=$(${cfgmatch} ${rg_name_key} ${cvm_cfgfile});
	if [ -z "${group}" ]; then 
		# Cannot find group name, don't update status
		return 0;
	fi

	$SCHA_RS_SETSTATUS -R ${rs_name} -G ${group} -s ${rs_status} -m "${msg}";
	return 0

}

# turns on tracing for all functions
#
# typeset -tf $(typeset +f)

#
#	main switch statement, execute appropriate reconfiguration step
#
#
# Initialize the substep name to unknown, each case will re-define to
# something appropriate for the step executing
#
# It is important that the only exit point in this script is at the very
# end in order that the event code not have to be invoked at all exit
# points.
#
# Also, the status variable is used to track the exit code as well as the
# type of event severity used when publishing events.
# 
#
status=0;
PUB_SUBSTEP="unknown";
case ${CURRSTEP} in

	cmmstart)
		PUB_SUBSTEP="cvmstart";
		initcvm || status=$?;
		if (( status == 0 )); then
			cvmstart_cmd start ${CLUSTNAME} ${cvm_cfgfile} \
				|| status=$?;
		fi
		;;

	cmmabort)
		PUB_SUBSTEP="cvmabort";
		cvmabort_cmd abort ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmreturn)
		PUB_SUBSTEP="cvmreturn";
		initcvm || status=$?;
		cvmreturn_cmd return ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmstep1)
		PUB_SUBSTEP="hw_reserve";
		hw_reserve || status=$?;
		;;

	cmmstep2)
		PUB_SUBSTEP="cvmstep1";
		cvmstep1_cmd step1 ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmstep3)
		PUB_SUBSTEP="cvmstep2";
		cvmstep2_cmd step2 ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmstep8)
		PUB_SUBSTEP="cvmstep3";
		cvmstep3_cmd step3 ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmstep9)
		PUB_SUBSTEP="cvmstep4";
		cvmstep4_cmd step4 ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	cmmstep10)
		PUB_SUBSTEP="cvmstep6";
		cvmstep6_cmd || status=$?;
		;;

	cmmstop)
		PUB_SUBSTEP="cvmstop";
		cvmstop_cmd stop ${CLUSTNAME} ${cvm_cfgfile} || status=$?;
		;;

	validate)
		PUB_SUBSTEP="validate";
		cvmvalidate_cmd validate ${cvm_cfgfile} || status=$?;
		;;
	*)
		scds_syslog -p error -t "${pre}" -m \
			"Unknown step: %s" "${CURRSTEP}";
		status=200;
		;;

esac

#
# calculate execution time
#
# NOTE: if an error occurs, do not report the error as availability is
# more important than event execution times. Since we do math on these
# variables later, if the command fails we need to ensure that they
# are not null, else the math will cause the script to exit causing
# node death.
#
END_HRTIME=$(${TIMESTAMP} -h) || END_HRTIME=0;
(( DURATION = END_HRTIME - BEGIN_HRTIME ));

#
# publish the event
#
if (( status == 0 || status == 200 || status == 205 )); then
	#
	# publish non-fatal return codes as informational severity events
	#
	${PUB_EVENT} -s ${CL_EVENT_SEV_INFO} \
		-N ${CURRSTEP} \
		-n "${PUB_SUBSTEP}" \
		-t ${BEGIN_TOD} -d ${DURATION} -r ${status};
else
	#
	# publish fatal return codes as error severity events
	#
	${PUB_EVENT} -s ${CL_EVENT_SEV_ERROR} \
		-N ${CURRSTEP} \
		-n "${PUB_SUBSTEP}" \
		-t ${BEGIN_TOD} -d ${DURATION} -r ${status};

	set_cvm_status "FAULTED" "Error in step ${PUB_SUBSTEP}";
fi

exit ${status};
