#!/bin/sh

#
# Shutdown a Linux cluster
# Version 0.2
# spd at daphne.cps.unizar.es
# Tue May 31 09:00:31 CEST 2005
# Tue Jul  1 11:58:29 CEST 2008 - Concurrent nodes shutdown
#
# REQUIRES
#       fping from http://www.fping.com/
#       Or native ping if has -c -w options
#       .rhosts or authorized_keys/ssh-agent
# ENVIRONMENT
#       HOSTS   List of space separated hostnames
#       RSH_CLIENT   rsh client. Defaults to ssh
# TODO
#       Timeout option for the shutdown of the frontend
#


VERSION="0.2"


GRACE=5
DO=
FRONTEND=:
ABORT=false
MESSAGE=""

#HOSTS=${HOSTS:="setme"}
HOSTS=setme
HOSTNAME=`hostname`
PATH=$PATH:/usr/local/sbin:/usr/local/etc

#
# Customize this so "HOSTS" is the list of your nodes
#
if [ "$HOSTS" = "setme" ]
then
	HOSTS=`awk '/^192.*atps-n0/{print $3}' /etc/hosts`
fi


CMD=`basename $0`
usage()
{
echo "Use: $0 -VIDhnsg"
echo "         -V: version"
#echo "         -I: internet version"
#echo "         -D: download and install update"
echo "         -h: help"
echo "         -n: do nothing"
echo "         -s: use ssh"
echo "         -g: grace minutes (default $GRACE)"
echo "         -c: do not shutdown frontend"
echo "         -a: abort"
echo "         -m: message (must be the last option)"
	exit 1
}

set -- `getopt VIDhnscag:m: "$@"`

if test $? != 0
then
	usage
	exit 1
fi


for i in "$@"
do
	case $i in
	-s) RSH_CLIENT="ssh"; shift;;
	-n) DO=echo; shift;;
	-a) ABORT=:; shift;;
	-c) FRONTEND=false; shift;;
	-m) shift; MESSAGE="$*"; shift;;
	-g) GRACE=$2; shift; shift;;
	-V) echo "$VERSION"; exit 0;;
	-I)
		echo "not implemented"
		exit 1
		;;
	-D)
		echo "not implemented"
		exit 1
		;;
	-h)
		usage
		;;
	--) shift; break;;
	esac
done
	
GRACES=`expr $GRACE '*' 60`



if [ -z "$RSH_CLIENT" ]
then
	if test -x /usr/bin/remsh
	then
		RSH_CLIENT=/usr/bin/remsh
	else
		RSH_CLIENT=ssh
	fi
fi

if [ -x /usr/local/sbin/fping ]
then
	PING="fping -q -t 251"
else
	PING="ping -c 1 -w 2"
fi


SHUTDOWN="/sbin/shutdown -t0 -h now"

echo "#### Shutting the cluster down." >&2

if [ "_$MESSAGE" == "_" ]
then
	:
else
	echo "$MESSAGE" | wall
fi

if [ -t 0 ]
then
	echo "Press CTRL-C to abort, still $GRACES seconds left" >&2
fi
sleep $GRACES

echo "#### Shutting down internal nodes." >&2


for f in $HOSTS
do
	if [ "$f" != "atps-n001" ]
	then
		echo "####################    " $f >&2
		$PING $f >/dev/null 2>&1 &&\
		(
			$RSH_CLIENT -n $f $DO $SHUTDOWN &
		)||(
			echo $f: dead >&2
		)
	fi
done

NOTDONE=:

#
# Customize this if your network includes devices other than cluster nodes
#

MAX=60
TOT=0
while $NOTDONE
do
	ALIVE=`ping -c 8 -b 192.168.1.255 2>&1 |\
	grep "bytes from" |\
	egrep -v "192\.168\.1\.1:|192\.168\.1\.250:" |\
	awk -F"[ :]" '{print $4}' |\
	sort -u -t . -k4n`

	if [ "_$ALIVE" != "_" ]
	then
		echo "Some nodes are still alive, waiting... `expr $MAX - $TOT`" >&2
		echo "$ALIVE"
		sleep 5
		TOT=`expr $TOT + 5`
		if [ $TOT -ge $MAX ]
		then
			NOTDONE=false
			echo "Timeout" >&2
		fi
	else
		NOTDONE=false
	fi
done


if $FRONTEND
then
	echo "#### Shutting the front-end down." >&2
	echo "#### Start front-end first when starting the cluster" >&2
	if [ -t 0 ]
	then
		echo "Press CTRL-C to abort, 10 seconds left" >&2
		sleep 5
		echo "Press CTRL-C to abort, 5 seconds left" >&2
		sleep 1
		echo "Press CTRL-C to abort, 4 seconds left" >&2
		sleep 1
		echo "Press CTRL-C to abort, 3 seconds left" >&2
		sleep 1
		echo "Press CTRL-C to abort, 2 seconds left" >&2
		sleep 1
		echo "Press CTRL-C to abort, 1 second left" >&2
		sleep 1
	fi
	cd /
	$DO eval $SHUTDOWN
fi

