#!/usr/bin/bash

message_output()
{
	printf "[%s] %s\n" "$(date '+%F %T.%N')" "$@"
}

error_message()
{
	message_output "$@" >&2
}

error_exit()
{
	error_message "$@, exiting"
	exit 1
}

log_message()
{
	message_output "$@"
}

# restart if we catch hup to re-read the config
hup_restart()
{
	log_message "caught SIGHUP, restarting"
	exec "$@"
}
trap hup_restart SIGHUP

# defaults
SCOUTFS_FENCED_CONFIG_FILE=${SCOUTFS_FENCED_CONFIG_FILE:-/etc/scoutfs/scoutfs-fenced.conf}
SCOUTFS_FENCED_DELAY=2
#SCOUTFS_FENCED_RUN
#SCOUTFS_FENCED_RUN_ARGS

test -n "$SCOUTFS_FENCED_CONFIG_FILE" || \
	error_exit "SCOUTFS_FENCED_CONFIG_FILE isn't set"
test -r "$SCOUTFS_FENCED_CONFIG_FILE" || \
	error_exit "SCOUTFS_FENCED_CONFIG_FILE isn't readable file"

log_message "reading config file $SCOUTFS_FENCED_CONFIG_FILE"

. "$SCOUTFS_FENCED_CONFIG_FILE" || \
	error_exit "error sourcing $SCOUTFS_FENCED_CONFIG_FILE as bash script"

for conf in "${!SCOUTFS_FENCED_@}"; do
	log_message "    config var $conf=${!conf}"
done

test -n "$SCOUTFS_FENCED_RUN" || \
	error_exit "SCOUTFS_FENCED_RUN must be set"
test -x "$SCOUTFS_FENCED_RUN" || \
	error_exit "SCOUTFS_FENCED_RUN '$SCOUTFS_FENCED_RUN' isn't executable"

#
# Main loop watching for fence request across all filesystems.   The
# server can shut down without waiting for pending fence requests to
# finish.  All of the interaction with the fence directory and files can
# fail at any moment.  We will generate log messages when the dir or
# files disappear.
#

# silence error messages
quiet_cat()
{
	cat "$@" 2>/dev/null
}

while sleep $SCOUTFS_FENCED_DELAY; do
	shopt -s nullglob
	for fence in /sys/fs/scoutfs/*/fence/*; do

		srv=$(basename $(dirname $(dirname $fence)))
		fenced="$(quiet_cat $fence/fenced)"
		error="$(quiet_cat $fence/error)"
		rid="$(quiet_cat $fence/rid)"
		ip="$(quiet_cat $fence/ipv4_addr)"
		reason="$(quiet_cat $fence/reason)"

		# request dirs can linger then disappear after fenced/error is set
		if [ ! -d "$fence" -o "$fenced" == "1" -o "$error" == "1" ]; then
			continue
		fi

		log_message "server $srv fencing rid $rid at IP $ip for $reason"

		# export _REQ_ vars for run to use
		export SCOUTFS_FENCED_REQ_RID="$rid"
		export SCOUTFS_FENCED_REQ_IP="$ip"

		$SCOUTFS_FENCED_RUN $SCOUTFS_FENCED_RUN_ARGS
		rc=$?
		if [ "$rc" != 0 ]; then
			log_message "server $srv fencing rid $rid saw error status $rc"
			echo 1 > "$fence/error"
			continue
		fi

		echo 1 > "$fence/fenced"
	done
done
