#!/bin/sh
#

PROG=`basename $0`
DIR=`dirname $0`
SSHOPTS="-l root -o PasswordAuthentication=no -o ConnectTimeout=5"

msg() {
	echo $@ >&2
}
usage() {
	echo "usage: $0 <dir>"
	echo "	dir: working directory (with the control file)"
	exit 0
}

[ $# -eq 0 ] && usage
WORKDIR=$1
test -d "$WORKDIR" || usage

CTSCTRL=~/.cts
CTRL=$WORKDIR/control
CSV=$WORKDIR/bench.csv
STATS=$WORKDIR/bench.stats

test -f $CTRL && . $CTRL

@datadir@/@PACKAGE@/tests/cts/cluster_test 500 || {
	msg "cluster_test failed"
	exit 1
}

test -f $CTSCTRL ||  {
	msg no CTS control file $CTSCTRL
	exit 1
}
. $CTSCTRL

: ${CTS_logfacility:=local7}
: ${CTS_stack:=corosync}
: ${CTS_logfile:="@CRM_LOG_DIR@/ha-log-bench"}
: ${CTS_adv:="--schema pacemaker-1.2 --clobber-cib -r"}
: ${RUNS:=3}
: ${CTSTESTS:="--benchmark"}
: ${CTSDIR:="@datadir@/@PACKAGE@/tests/cts"}

[ "$CTS_node_list" ] || {
	msg no node list specified
	exit 1
}

case "$CTS_stack" in
corosync) CRM_REPORT_OPTS="--corosync";;
*) msg "$CTS_stack: cluster stack not recognized"; exit 1;;
esac

CTSOPTS="--stack $CTS_stack --at-boot $CTS_boot $CTS_adv"
CTSOPTS="$CTSOPTS --facility $CTS_logfacility --logfile $CTS_logfile"

if [ "x$CTS_stonith" != "x" ]; then
	CTSOPTS="$CTSOPTS --stonith-type $CTS_stonith"
	[ "x$CTS_stonith_args" != "x" ] &&
		CTSOPTS="$CTSOPTS --stonith-params \"$CTS_stonith_args\""
else
	CTSOPTS="$CTSOPTS --stonith 0"
fi

CTSOPTS="$CTSOPTS $CTSTESTS"

fibonacci() {
	local limit=$1
	local n=2 prev=1 tmp_n
	while [ $n -le $limit ]; do
		echo $n
		tmp_n=$n
		n=$((n+prev))
		prev=$tmp_n
	done
	[ $prev -ne $limit ] && echo $limit
}
[ "$SERIES" ] ||
	SERIES=$(fibonacci `echo $CTS_node_list | wc -w`)

get_nodes() {
	local c_nodes
	c_nodes=`echo $CTS_node_list | awk -v n=$1 '
		{ for( i=1; i<=NF; i++ ) node[cnt++]=$i }
		END{for( i=0; i<n; i++ ) print node[i] }
	'`
	if [ `echo $c_nodes | wc -w` != $1 ]; then
		msg "not enough nodes in $CTSCTRL"
		exit 1
	fi
	echo $c_nodes
}
node_cleanup() {
	msg "CIB cleanup ($nodes)"
	local n
	for n in $nodes; do
		ssh $SSHOPTS $n 'rm @CRM_CONFIG_DIR@/*'
	done
}
testnum() {
	printf '%03d' $1
}
mkreports() {
	msg "Creating reports for the CTS run"
	local ctsdir=$1
	grep "Running test " $ctsdir/ctsrun.out | tr -d \[\] |
	awk '{print $6,$NF}' |
	while read type num; do
		teststg="`testnum $num`-$type"
		(
		cd $ctsdir
		crm_report $CRM_REPORT_OPTS -f cts:$num -n "$nodes" `pwd`/$teststg < /dev/null
		)
	done
}
runcts() {
	local odir=$1
	msg "Running CTS"
	python $CTSDIR/CTSlab.py $CTSOPTS --nodes "$nodes" > $odir/ctsrun.out 2>&1 &
	ctspid=$!
	tail -f $odir/ctsrun.out &
	tailpid=$!
	wait $ctspid
	kill $tailpid >/dev/null 2>&1
}

bench_re='CTS:.*runtime:'
diginfo() {
	local d v
	local ctsdir=$1
	local s="$2"
	filter=$3
	(
	cd $ctsdir
	for r in [0-9]*.tar.bz2; do
		tar xjf $r
		d=`basename $r .tar.bz2`
		for v in `grep $bench_re $d/ha-log.txt | eval $filter`; do
			s="$s,$v"
		done
		rm -r $d
	done
	echo $s
	)
}
printheader() {
	diginfo $1 "" "awk '{print \$(NF-2)}'"
}
printstats() {
	diginfo $1 "$clusize" "awk '{print \$(NF)}'"
}
printmedians() {
	local f=$1
	local s="$clusize"
	local middle=$((RUNS/2 + 1))
	set `head -1 $f | sed 's/,/ /g'`
	local cols=$#
	local i v
	for i in `seq 2 $cols`; do
		v=`awk -v i=$i -F, '{print $i}' < $f | sort -n | head -$middle | tail -1`
		s="$s,$v"
	done
	echo $s
}

rm -f $CSV
tmpf=`mktemp`
test -f "$tmpf" || {
	msg "can't create temporary file"
	exit 1
}
trap "rm -f $tmpf" 0
for clusize in $SERIES; do
	nodes=`get_nodes $clusize`
	outdir=$WORKDIR/$clusize
	rm -rf $outdir
	mkdir -p $outdir
	rm -f $tmpf
	node_cleanup
	for i in `seq $RUNS`; do
		> $CTS_logfile
		mkdir -p $outdir/$i
		runcts $outdir/$i
		mkreports $outdir/$i
		printstats $outdir/$i >> $tmpf
	done
	[ -f "$CSV" ] || printheader $outdir/1 > $CSV
	printmedians $tmpf >> $CSV
	cat $tmpf >> $STATS
	msg "Statistics for $clusize-node cluster saved"
done
msg "Tests done for series $SERIES, output in $CSV and $STATS"
