#!/bin/sh

NO_COL="\033[0m"
GREEN="\033[1;32m"

usage() {
	echo "$(basename "$0"): run a command on multiple nodes"
	echo ""
	echo "$(basename "$0") [-h] [-p] <cluster> <role> <command>"
	echo ""
	echo "-h --help      show this help"
	echo "-p --parallel  run command on all nodes in parallel (default is sequential)"
	echo "<cluster>      the name of the cluster"
	echo "<role>         the role of the node(s), or 'all'"
	echo "<command>      the command to run"
	echo ""
	echo "Example: $(basename "$0") mycluster controller uptime"
	echo "         $(basename "$0") -p mycluster all cat /etc/hostname"
}

green_echo () {
	echo "${GREEN}${1}${NO_COL}"
}

sshi () {
	unset SSH_AUTH_SOCK
	ssh -i /etc/openstack-cluster-installer/id_rsa -o ConnectTimeout=10 "$@"
}

iterate_on_hosts () {
	# copied from /usr/bin/oci-cluster-upgrade-openstack-release
	if [ "${1}" = "-p" ] || [ "${1}" = "--parallel" ] ; then
		USE_PARALLEL=yes
		shift
	else
		USE_PARALLEL=no
	fi
	HOST_LIST=${1}
	FUNCTION=${2}
	shift
	shift

	MAX_PARALLEL=8

	if [ "${USE_PARALLEL}" = "yes" ] ; then
		CNT=1
		for i in ${HOST_LIST} ; do
			${FUNCTION} "${i}" "$@" &
			CNT=$(( ${CNT} + 1))
			if [ ${CNT} -gt ${MAX_PARALLEL} ] ; then
				CNT=1
				wait
			fi
		done
		wait
	else
		for i in ${HOST_LIST} ; do
			${FUNCTION} "${i}" "$@"
		done
	fi
}

ssh_on_nodes () {
	HOST=${1}
	shift
	HOST_IP=$(echo "${HOST}" | cut -d, -f1)
	HOST_NAME=$(echo "${HOST}" | cut -d, -f2)

	green_echo "-> ${HOST_NAME}"
	sshi "root@${HOST_IP}" "$@"
}

parallel=""
CLUSTER_NAME=$1
shift
case "${CLUSTER_NAME}" in
	"-h"|"--help")
		usage
		exit
	;;
	"-p"|"--parallel")
		parallel="-p"
		CLUSTER_NAME=$1
		shift
	;;
	*)
	;;
esac

role=$1
shift
cmd="$*"

green_echo "---> Fetching nodes info"
if [ "$role" = "all" ]; then
	where=""
else
	where="role='$role' AND"
fi

NODES=$(ocicli -csv machine-list -a | q -H -d, "SELECT Cur_ip,hostname FROM - WHERE $where cluster='${CLUSTER_NAME}' AND status='installed' ORDER BY hostname" | tr '\n' ' ')

if [ -z "$NODES" ]; then
	echo "Unable to find nodes of type '$role' on cluster '$CLUSTER_NAME'" > /dev/stderr
	exit 1
fi

green_echo "---> Running command"

iterate_on_hosts $parallel "${NODES}" ssh_on_nodes "$cmd"
