#!/bin/sh 

LD_LIBRARY_PATH=$CRAY_SSPROOT/lib
PATH=$PATH:$CRAY_SSPROOT/bin
export PATH LD_LIBRARY_PATH

#
# domain_remove usage function.
#
domain_remove_usage()
{
	echo "Usage: domain_remove  host_name"
}

#
# domain_create usage function.
#
domain_create_usage()
{
	echo "Usage: domain_create  host_name  system_board_number"
}

#
# Verify this command is executed within a "main" machine
# environment.
#
correct_environment()
{
	if [ ! -r ${MACHINE_CONFIG} ]; then
		echo "$program cannot execute outside the \"main\" environment."
		exit 1
	fi
}

#
# Function to check super-user id.
#
superuser()
{
	IDSTR="`id`"
	UID=`expr "$IDSTR" : 'uid=\([0-9][0-9]*\)(.*'`
	if [ "$UID" != "0" ]; then
		echo "You must be super-user to run this command."
		exit 1
	fi
}


domain_create_command()
{

	CLEANUP_STATE=0
#
# define some commonly used file paths.
#
	NEW_MACHINE_BLACKLIST=${CRAY_SSPROOT}/etc/${LOOPBACKMACHINE}/blacklist
	NEW_MACHINE_REDLIST=${CRAY_SSPROOT}/etc/${LOOPBACKMACHINE}/redlist
	NEW_MACHINE_ETC=${CRAY_SSPROOT}/etc/${LOOPBACKMACHINE}
	NEW_MACHINE_DATA=${CRAY_SSPROOT}/data/${LOOPBACKMACHINE}
	NEW_MACHINE_MESSAGES=${CRAY_SSPLOGS}/${LOOPBACKMACHINE}/messages
	NEW_MACHINE_LOGDIR=${CRAY_SSPLOGS}/${LOOPBACKMACHINE}
	PHYSICAL_HOST=${CRAY_SSPROOT}/etc/${LOOPBACKMACHINE}/physical_host

#
# Verify that the machine_config file does not have the LOOPBACKMACHINE
# already.
#
	egrep "^${LOOPBACKMACHINE}[ 	]*:" ${MACHINE_CONFIG} > ${TEMP_FILE}
	if [ -s ${TEMP_FILE} ]; then
		echo "Domain ${LOOPBACKMACHINE} already exists as a machine."
		FAILURE=1
		return
	fi

#
# Verify that the LOOPBACKBAORD number is available, that is, no
# other machines are using it.
#
	egrep "^[^:]*:[         ]*[0-9 ]* ${LOOPBACKBOARD} [0-9 ]*" ${MACHINE_CONFIG} > ${TEMP_FILE}
	if [ -s ${TEMP_FILE} ]; then
		echo "Board ${LOOPBACKBOARD} is being used."
		FAILURE=1
		return
	else
		/bin/rm -f ${TEMP_FILE}
		egrep "^[^:]*:[         ]*[0-9 ]* ${LOOPBACKBOARD}$" ${MACHINE_CONFIG} > ${TEMP_FILE}
		if [ -s ${TEMP_FILE} ]; then
			echo "Board ${LOOPBACKBOARD} is being used."
			FAILURE=1
			return
		fi
	fi

# Old algorithm that is replaced with the above "egrep" regular expression.
#	found=0
#	for entry in `grep -v "^#" ${MACHINE_CONFIG}`; do
#		boards=`echo $entry | sed -e 's/[^:]*://'`
#		for board in $boards; do
#			if [ ${board} -eq ${LOOPBACKBOARD} ]; then
#				found=1
#				machine=`echo $entry | grep "^[^:]"`
#				break
#			fi
#		done
#	done
#
#	if [ $found -eq 1 ]; then
#		echo "Board ${LOOPBACKBOARD} is being used."
#		FAILURE=1
#		return
#	fi

#
# Verify LOOPBACKBOARD is blacklist'ed and redlist'ed for this "main"
# environment.
#
	egrep "^sysbd[	 ]*[0-9 ]*${LOOPBACKBOARD}[0-9 ]*" ${MAIN_BLACKLIST} > ${TEMP_FILE}
	if [ ! -s ${TEMP_FILE} ]; then
		echo "System board ${LOOPBACKBOARD} must be black listed first."
		FAILURE=1
		return
	fi

	ADD_TO_REDLIST=0
	egrep "^sysbd[	 ]*[0-9 ]*${LOOPBACKBOARD}[0-9 ]*" ${MAIN_REDLIST} > ${TEMP_FILE}
	if [ ! -s ${TEMP_FILE} ]; then
		ADD_TO_REDLIST=1
	fi

#
# Verify that the NEWMACHINE_ETC does not exist.
#
	if [ -r ${NEW_MACHINE_ETC} ]; then
		echo "The ${NEW_MACHINE_ETC} already exists."
		FAILURE=1
		return
	fi

#
# Verify that the NEW_MACHINE_DATA does not exist.
#
	if [ -r ${NEW_MACHINE_DATA} ]; then
		echo "The ${NEW_MACHINE_DATA} already exists."
		FAILURE=1
		return
	fi

#
# Verify the HOSTS file does hot have the LOOPBACKMACHINE within it.
#
	egrep "^${LOOPBACKMACHINE}[ 	]+" ${HOSTS} > ${TEMP_FILE}
	if [ -s ${TEMP_FILE} ]; then
		echo "The ${LOOPBACKMACHINE} already exists in ${HOSTS}"
		FAILURE=1
		return
	fi

#
# See if there is an available host id (eeprom.image) file for the new
# loopback machine. This code looks at the link count for each host id
# file, if it is not 1, it is available for use.
#
	
	FILE=`ls -l ${HOST_EEPROMS}/host_ids_* | awk '{ if ($2 == 1) {print $9; exit}}' -`
	if test -n "$FILE" 
	then
		HOST_ID_FILE=$FILE
	else
		echo "There are not any host ids available."
		FAILURE=1
		return
	fi
#
# See if we need to add this system board to the redlist.
#
	if [ $ADD_TO_REDLIST -eq 1 ]; then
		echo "System board ${LOOPBACKBOARD} is not red listed, adding now."
		echo "sysbd ${LOOPBACKBOARD}" >> ${MAIN_REDLIST}
	fi

########################################################################
# The basic checks are complete. Begin creating directories and files. #
########################################################################
	echo "Cross checking is complete, proceeding...."

	CLEANUP_STATE=1
#
# Create the NEW_MACHINE_ETC directory.
#
	mkdir ${NEW_MACHINE_ETC}
	chmod 0755 ${NEW_MACHINE_ETC}
	chown ssp ${NEW_MACHINE_ETC}

#
# Create the logs directory
#
	mkdir ${NEW_MACHINE_LOGDIR}
	chmod 0755 ${NEW_MACHINE_LOGDIR}
	chown ssp ${NEW_MACHINE_LOGDIR}
	mkdir ${NEW_MACHINE_LOGDIR}/post
	chmod 0755 ${NEW_MACHINE_LOGDIR}/post
	chown ssp ${NEW_MACHINE_LOGDIR}/post

#
# Create the redlist and blacklist files for the new machine.
#
	touch ${NEW_MACHINE_BLACKLIST}
	touch ${NEW_MACHINE_REDLIST}
	chown ssp ${NEW_MACHINE_BLACKLIST} ${NEW_MACHINE_REDLIST}
	for board in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
		if [ ${LOOPBACKBOARD} -ne $board ]; then
			echo "sysbd $board" >> ${NEW_MACHINE_BLACKLIST}
			echo "sysbd $board" >> ${NEW_MACHINE_REDLIST}
		fi
	done

#
# Create the PHYSICAL_HOST file by putting the CRAY_HOSTNAME in it.
#
	echo ${CRAY_HOSTNAME} > ${PHYSICAL_HOST}

#
# Create the messages file in the logs directory.
#
	touch ${NEW_MACHINE_MESSAGES}
	chmod 0755 ${NEW_MACHINE_MESSAGES}
	chown ssp ${NEW_MACHINE_MESSAGES}

#
# Update the HOSTS file with the LOOPBACKMACHINE name and use the jscc
# card number listed in the HOSTS file for CRAY_HOSTNAME.
#
	egrep "^${CRAY_HOSTNAME}[ 	]+" ${HOSTS} > ${TEMP_FILE}
	if [ ! -s ${TEMP_FILE} ]; then
		echo "CRAY_HOSTNAME variable must exist and must be in $HOSTS."
		remove_tmp_file
		exit 1
	fi
	jscc_card=`cat ${TEMP_FILE} | sed -e "s/${CRAY_HOSTNAME}//"`
	echo "${LOOPBACKMACHINE} $jscc_card" >> ${HOSTS}

#
# Update the MACHINE_CONFIG to have the LOOPBACKMACHINE entry.
#
#	echo "${LOOPBACKMACHINE} : ${LOOPBACKBOARD}" >> ${MACHINE_CONFIG}

#
# Copy the general files from the MAIN_MACHINE_ETC directory to new one.
#

	for file in agent_list errmail.rc hostmon.rc; do
		cp ${MAIN_MACHINE_ETC}/${file} ${NEW_MACHINE_ETC}/${file}
	done

	ln ${MAIN_MACHINE_ETC}/hostmon.dat ${NEW_MACHINE_ETC}/hostmon.dat

	for i in CRAY_SD config/CRAY_SD.config; do
		src=${CRAY_SSPROOT}/data/$i
		dest=`echo $src | sed "s/CRAY_SD/${LOOPBACKMACHINE}/"`
		if [ -h ${dest} -o -f ${dest} ]; then
			rm -f ${dest}
		fi
		ln -s ${src} ${dest}
	done

#
# This is not needed since we do not support tip for loopback hosts.
#
# Update the /etc/remote file with LOOPBACKMACHINE information.
#
#	grep "^$LOOPBACKMACHINE" ${REMOTE_FILE} > ${TEMP_FILE}
#	if [ ! -s ${TEMP_FILE} ]; then
#		echo "${LOOPBACKMACHINE}|host|superdragon|CRAY_HOSTNAME:\\" >> ${REMOTE_FILE}
#		echo "\t:dv=/dev/term/a:br#9600:el=^C^S^Q^U^D:ie=%\$:oe=^D:" >> ${REMOTE_FILE}
#	fi

#
# Build the scantool database.
#
#	LD_LIBRARY_PATH=${CRAY_SSPROOT}/lib:/usr/lib
#	CRAY_HOSTNAME=${LOOPBACKMACHINE}
#	export CRAY_HOSTNAME LD_LIBRARY_PATH
#	${CRAY_SSPROOT}/bin/compile_db
#	if [ $? -ne 0 ]; then
#		FAILURE=1
#		return
#	fi
#
# Just do the "main" system compiled binary file link to save disk space.
#
	ln -s ${CRAY_SSPROOT}/data/CRAY_SD/${STARTING_HOST}.binary ${CRAY_SSPROOT}/data/CRAY_SD/${LOOPBACKMACHINE}.binary

#
# Link the new eeprom.image file to HOST_ID_FILE.
#
	ln ${HOST_ID_FILE} ${NEW_MACHINE_ETC}/eeprom.image

#
# Check the "main" host state. If it is up, then use the post "-L" flag;
# otherwise use sysreset to clear the board because post -L would fail if
# the "main" host is not running.
#
#
# Update the MACHINE_CONFIG to have the LOOPBACKMACHINE entry.
#
	echo "${LOOPBACKMACHINE} : ${LOOPBACKBOARD}" >> ${MACHINE_CONFIG}

	echo "Removing board from back plane, please wait....."
	CRAY_HOSTNAME=${STARTING_HOST}
	export CRAY_HOSTNAME
	check_host
	result=$?
	CRAY_HOSTNAME=${LOOPBACKMACHINE}
	export CRAY_HOSTNAME
	if test $result -eq 0
	then
		sd_post -L${LOOPBACKBOARD},`cat ${MAIN_MACHINE_ETC}/bootproc` -Xnone -Rnone
		ret=$?
		if test $ret -lt 65 -o $ret -gt 65
		then
			echo "removal of board from back plane failed, post returned ($ret)"
			notify_hostmon
			return
		fi
	else
		sysreset
	fi
	echo "Board removed from back plane."

	notify_hostmon
}

domain_remove_command()
{
	#
	# full path names.
	#
	MACHINE_ETC=${CRAY_SSPROOT}/etc/${MACHINE_NAME}
	MACHINE_DATA=${CRAY_SSPROOT}/data/${MACHINE_NAME}
	MACHINE_LOGDIR=${CRAY_SSPLOGS}/${MACHINE_NAME}

	if [ $SKIP_CHECKING -eq 0 ]; then
		#
		# check to see if the user started this command in a directory that
		# we are going to remove.
		#

		this_directory=`pwd`
		for f in ${MACHINE_ETC} ${MACHINE_DATA} ${MACHINE_LOGDIR}; do
			cd $f
			file=`pwd`
			if [ -d $file -a $file = $this_directory ]; then
				echo "Cannot run in current working directory,"
				echo "change directories out of this domain file system."
			exit 1
			fi
		done
		cd $this_directory


		#
		# make sure that the request machine MACHINE_NAME is really a single
		# board domain.
		#
		if [ ! -d ${CRAY_SSPROOT}/etc/${MACHINE_NAME} ]; then
			echo "${MACHINE_NAME} domain etc directory does not exist."
			exit 1
		fi
		if [ ! -f ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/physical_host ]; then
			echo "${MACHINE_NAME} is the \"main\" domain and cannot be removed with this command."
			exit 1
		fi
		P_HOST=`cat ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/physical_host`
		egrep "^${MACHINE_NAME}[ 	]*:" ${CRAY_SSPROOT}/etc/${P_HOST}/machine_config > ${TEMP_FILE}
		if [ ! -s ${TEMP_FILE} ]; then
			echo "${MACHINE_NAME} is not in the \"main\" Domain configuration."
			remove_tmp_file
			exit 1
		fi
		if [ ${P_HOST} != ${CRAY_HOSTNAME} ]; then
			echo "The environment ${CRAY_HOSTNAME} is not a \"main\" system."
			exit 1
		fi
		LAST_NAME=${CRAY_HOSTNAME}
		CRAY_HOSTNAME=${MACHINE_NAME}
		export CRAY_HOSTNAME
		check_host
		if [ $? -eq 0 ]; then
			echo "${MACHINE_NAME} is still up, must shutdown first."
			exit 1
		fi
		CRAY_HOSTNAME=${LAST_NAME}
		export CRAY_HOSTNAME
	fi

	echo "Cross checking is complete, proceeding...."

	#
	# stop the obp_helper for this host domain to avoid using cpu on ssp.
	#
	if [ -d ${CRAY_SSPROOT}/etc/${MACHINE_NAME} ]; then
		touch ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/obp_helper.pid
		obp_helper_pid=`cat ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/obp_helper.pid`
		if test -n "$obp_helper_pid"
		then
			ps -ef |grep obp_helper |grep -v grep |grep ${obp_helper_pid} > /dev/null 2>&1
			if test $? -eq 0
			then
				kill -KILL $obp_helper_pid > /dev/null 2>&1
			fi
		fi
	fi

	#
	# Remove the board for this host from the main machine's redlist file.
	#
	if [ -f ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/physical_host ]; then
	P_HOST=`cat ${CRAY_SSPROOT}/etc/${MACHINE_NAME}/physical_host`
		egrep "^${MACHINE_NAME}[ 	]*:" ${CRAY_SSPROOT}/etc/${P_HOST}/machine_config > ${TEMP_FILE}
		host_board=`cat ${TEMP_FILE} | awk '{print $3}'`
		grep -v "^sysbd[ 	]*${host_board}" ${MAIN_REDLIST} > ${TEMP_FILE}
		cp ${TEMP_FILE} ${MAIN_REDLIST}
	fi

	#
	# Remove the etc directory for MACHINE_NAME
	#
	if [ -d ${MACHINE_ETC} ]; then
		rm -rf ${MACHINE_ETC}
	fi

	#
	# Remove the logs directory for MACHINE_NAME
	#
	if [ -d ${MACHINE_LOGDIR} ]; then
		rm -rf ${MACHINE_LOGDIR}
	fi

	#
	#
	# Remove the data directory for MACHINE_NAME
	#
	rm -f ${MACHINE_DATA}/${MACHINE_NAME}.binary*
	if [ -d ${MACHINE_DATA} ]; then
		rm -rf ${MACHINE_DATA}
	fi

	#
	# Clean up the hosts file.
	#
	egrep -v "^${MACHINE_NAME}[ 	]+" ${HOSTS} > ${TEMP_FILE}
	cp ${TEMP_FILE} ${HOSTS}

	#
	# Clean up the machine config file
	#
	egrep -v "^${MACHINE_NAME}[ 	]*:" ${MACHINE_CONFIG} > ${TEMP_FILE}
	cp ${TEMP_FILE} ${MACHINE_CONFIG}



	echo "${MACHINE_NAME} has been removed."

	#
	# Notify hostmon that a configuration change has occurred.
	#
	notify_hostmon
}

#
# procedure called when a trap is caught and domain_create is running.
# unloopback ignores interrupts.
#
cleanup()
{
	#
	# set the original CRAY_HOSTNAME incase is was changed when compile_db
	# is executed.
	#
	touch /tmp/DOMAIN_LOCK
	CRAY_HOSTNAME=$STARTING_HOST
	export CRAY_HOSTNAME
	echo Cleaning up the mess, please wait .....
	domain_remove ${LOOPBACKMACHINE}
	remove_tmp_file
	echo "Done cleaning."
	exit 1
}

#
# Check for any other domain_{create|remove} commands for anywhere under this
# CRAY_SSPROOT. The reason for the global check is the hosts file is altered
# by both commands as well as the machine_config file.
#
check_for_domain_commands()
{
	if [ -f /tmp/DOMAIN_LOCK ]; then
		rm -f /tmp/DOMAIN_LOCK
		SKIP_CHECKING=1
		return
	fi
#	ps -ef | egrep "domain_create|domain_remove" | grep -v grep | grep -v $$ > /dev/null 2>&1
	ps -ef | egrep "domain_create|domain_remove" | grep -v grep | grep -v $$ |
		awk '{
			if ($8 == "/bin/sh" ) {
				size = split($9,mlist,"/")
				if ( mlist[size] == "domain_create" ) {
					print $0
				} else {
					if ( mlist[size] == "domain_remove" ) {
						print $0
					}
				}
			}
		}' - > ${TEMP_FILE}
	if [ -s ${TEMP_FILE} ]; then
		echo "There is another domain command running, try again later."
		remove_tmp_file
		exit 1
	fi
	remove_tmp_file
}

#
# Procedure to remove the temporary file created by domain_create and
# domain_remove.
#
remove_tmp_file()
{
	if [ -f $TEMP_FILE ]; then
		rm -f $TEMP_FILE
		return
	fi
}

notify_hostmon()
{
	touch ${HOSTMON_SIGNAL_FILE}
}

#
# This is the main portion of the script.
#

#
# Set up some file path names used by both loopback and unloopback.
#
HOSTS=${CRAY_SSPROOT}/etc/hosts
HOST_EEPROMS=${CRAY_SSPROOT}/etc/hostids
SYSLOG_CONF=/etc/syslog.conf
SYSLOG_PID=/etc/syslog.pid
REMOTE_FILE=/etc/remote
TEMP_FILE=/tmp/FILE$$
MACHINE_CONFIG=${CRAY_SSPROOT}/etc/${CRAY_HOSTNAME}/machine_config
MAIN_BLACKLIST=${CRAY_SSPROOT}/etc/${CRAY_HOSTNAME}/blacklist
MAIN_REDLIST=${CRAY_SSPROOT}/etc/${CRAY_HOSTNAME}/redlist
MAIN_MACHINE_ETC=${CRAY_SSPROOT}/etc/${CRAY_HOSTNAME}
MAIN_MACHINE_DATA=${CRAY_SSPROOT}/data/${CRAY_HOSTNAME}
STARTING_HOST=$CRAY_HOSTNAME
HOSTMON_SIGNAL_FILE=${CRAY_SSPROOT}/etc/${CRAY_HOSTNAME}/hostmon.notify
SKIP_CHECKING=0

#
# Set if the caller is the super-user
#
#superuser

#
# Verify this is a valid environment to run this command.
#
correct_environment

#
# Check for any other loopback or unloopback commands.
#
check_for_domain_commands

#
# Get the name of the script file and if it is valid then execute
# it by appending the "command" to the name.
#
program=`basename $0`
FAILURE=0

if [ "$program" = "domain_create" ]; then
#
# Verify that the correct number of arguments have been provided.
#

	if [ $# != 2 ]; then
		domain_create_usage
		exit 1
	fi

#
# set the known positional parameters here.
#
	LOOPBACKMACHINE=$1
	LOOPBACKBOARD=$2

	if [ ${LOOPBACKBOARD} -lt 0 -o ${LOOPBACKBOARD} -gt 15 ]; then
		echo "The board number must be 0 to 15 inclusive"
		exit 1
	fi

#
# Setup the interrupt to clean up the files if the user terminates
# before it is completed.

	trap "cleanup" INT HUP TERM

	${program}_command
	remove_tmp_file
	if [ $FAILURE = 1 ]; then
		echo ""
		echo "The script has failed."
		if [ $CLEANUP_STATE = 1 ]; then
			echo "Cleaning up the mess, please wait ....."
			domain_remove $LOOPBACKMACHINE
			echo "Done cleaning"
			exit 1
		fi
		exit 1
	fi
	exit 0
fi

if [ "$program" = "domain_remove" ]; then
	#
	# Verify that the correct number of arguments are provided
	#
	if [ $# != 1 ]; then
		domain_remove_usage
		exit 1
	fi

	trap "" INT HUP TERM
	#
	# Set up the machine name to remove.
	#
	MACHINE_NAME=$1
	${program}_command
	remove_tmp_file
	exit 0
fi

exit 1
