#!/bin/bash

set -eE

rand()
{
	local max=$1

	echo -n $((RANDOM * max /32768))
}

on()
{
	local hosts=$1

	shift
	$PDSH -w $hosts "$@"
}

power()
{
	pm -h powerman "$@"
}

ziostat_start()
{
	local host=$1

	shift
	on $host "zpool iostat $@ >/tmp/ziostat & echo \$! >/tmp/ziostat.pid"
}

ziostat_stop()
{
	local host=$1
	local file=$2

	on $host "kill \$(cat /tmp/ziostat.pid)"
	scp $host:/tmp/ziostat $file
	on $host "rm /tmp/ziostat{,.pid}"
}

vmstat_start()
{
	local host=$1

	shift
	on $host "vmstat $@ >/tmp/vmstat & echo \$! >/tmp/vmstat.pid"
}

vmstat_stop()
{
	local host=$1
	local file=$2

	on $host "kill \$(cat /tmp/vmstat.pid)"
	scp $host:/tmp/vmstat $file
	on $host "rm /tmp/vmstat{,.pid}"
}

mpi_hostfile_create()
{
	local file=$1
	local host

	rm -f $file
	for host in $CLIENTS; do
		echo $host >>$file
	done
}

mpi_run()
{
	local np=$1

	shift
	mpi_hostfile_create /tmp/hostfile
	mpirun --hostfile /tmp/hostfile -np $np "$@"
	rm /tmp/hostfile
}

nid()
{
	local target=$1
	local v=$(echo -n $target | tr '-' '_' | tr '[:lower:]' '[:upper:]')_NID

	echo -n ${!v}
}

#
# E.g., "host mdt-0", "host client-13", "host ost-5", etc.
#
host()
{
	local target=$1
	local nid=$(nid $target)

	#
	# TODO: Print the host on which the target is currently active.
	#
	echo -n ${nid/@*}
}

type()
{
	local target=$1
	local v=$(echo -n $target | tr '-' '_' | tr '[:lower:]' '[:upper:]')_TYPE

	echo -n ${!v}
}

dev()
{
	local target=$1
	local v=$(echo -n $target | tr '-' '_' | tr '[:lower:]' '[:upper:]')_DEV

	echo -n ${!v}
}

csv_has()
{
	local csv=$1
	local v=$2
	local w

	for w in ${csv//,/ }; do
		if [[ $w == $v ]]; then
			return 0
		fi
	done
	return 1
}

csv_add_uniq()
{
	local csv=$1
	local v=$2

	if [[ -z $csv ]]; then
		csv+=$v
	else
		csv+=",$v"
	fi
	echo -n $csv
}

mdss()
{
	local hosts
	local i

	for i in $(seq 0 $(($MDT_COUNT - 1))); do
		hosts=$(csv_add_uniq $hosts $(host mdt-$i))
	done
	echo -n $hosts
}

osss()
{
	local hosts
	local i

	for i in $(seq 0 $(($OST_COUNT - 1))); do
		hosts=$(csv_add_uniq $hosts $(host ost-$i))
	done
	echo -n $hosts
}

client_hosts()
{
	local hosts
	local i

	for i in $(seq 0 $(($CLIENT_COUNT - 1))); do
		hosts=$(csv_add_uniq $hosts $(host client-$i))
	done
	echo -n $hosts
}

mdts()
{
	for i in $(seq 0 $(($MDT_COUNT - 1))); do
		echo mdt-$i
	done
}

osts()
{
	for i in $(seq 0 $(($OST_COUNT - 1))); do
		echo ost-$i
	done
}

poolname(){
	local target=$1

	echo -n ${FSNAME}-${target/-*}${target#*-}
}
dataset()
{
	local target=$1

	echo -n $FSNAME-${target/-*}${target#*-}/${target/-*}${target#*-}
}

combined()
{
	local target_a=$1
	local target_b=$2

	[ $(nid $target_a) = $(nid $target_b) ] && [ $(dev $target_a) = $(dev $target_b) ]
}

format()
{
	local target=$1
	local host=$(host $target)
	local opt_fs
	local opt_target
	local opt_servicenode
	local opt_storage

	if [ $target = mgt ] && combined mgt mdt-0; then
		echo "Skipping formatting MGT combined with MDT 0"
		return
	fi

	if [ $target = mdt-0 ] && combined mgt mdt-0; then
		opt_fs="--mgs --fsname=$FSNAME"
	elif [ $target != mgt ]; then
		opt_fs="--mgsnode=$(nid mgt) --fsname=$FSNAME"
	fi

	if [ $target = mgt ]; then
		opt_target="--mgs"
	else
		opt_target="--${target/-*} --index=${target#*-}"
	fi

	if [[ $(nid $target) = *:* ]]; then
		opt_servicenode="--servicenode=$(nid $target)"
	fi

	if [ $(type $target) = ldiskfs ]; then
		if [ ${target/-*} = mdt ]; then 
		opt_storage="--mkfsoptions='-i 4096' --backfstype=ldiskfs $(dev $target)"
		else
		opt_storage="--backfstype=ldiskfs $(dev $target)"
		fi
	else

		echo "$host: Destroy existing pool $(poolname $target)"
		on $host "zpool destroy $(poolname $target)"
		# Create zpool without cachefile; can't be done
		# with zfs - command as cachefile can't be specified 
		# as property. 
		echo "$host: Create pool $(poolname $target)"
		on $host "zpool create -f $(poolname $target) -o cachefile=none $(dev $target)"
		on $host "zfs set canmount=off $(poolname $target)"
		on $host "zfs list"
#		opt_storage="--mkfsoptions='cachefile=none' --backfstype=zfs $(dataset $target) $(dev $target)"
		opt_storage=" --backfstype=zfs $(dataset $target)"
	fi

	echo "Formatting $target on $host"
	echo "EXECUTE: on $host mkfs.lustre $opt_fs $opt_target $opt_servicenode --reformat $opt_storage"
	on $host "mkfs.lustre $opt_fs $opt_target $opt_servicenode --reformat $opt_storage"
}

mnt()
{
	local target=$1

	echo -n /mnt/$FSNAME-${target/-}
}

mount()
{
	local target=$1
	local host=$(host $target)
	local mnt=$(mnt $target)
	local storage

	if [ $(type $target) = ldiskfs ]; then
		storage=$(dev $target)
	else
		storage=$(dataset $target)
	fi

	echo "Mounting $target on $host"
	on $host "if ! mount | grep -q $mnt; then mkdir -p $mnt && mount -t lustre -o user_xattr $storage $mnt; fi"
}

init()
{
	if [ -z "$CONFIG" ]; then
		source config
	else
		source $CONFIG
	fi
}

init
