#!/bin/sh
# Problem report helper script

PROG="$0"
LOCAL=no
FNAME=""
CLUSTER_NAME=""
DIR=""
CLUSTERS_DIR="/etc/pstorage/clusters"
MAKE_REPORT="/usr/bin/pstorage-make-report"
SSH_OPTS="-o PasswordAuthentication=no -o StrictHostKeyChecking=no"
LOG_LINES=1000

cleanup() {
	rm -rf "$DIR"
}

prepare_logs() {
	local CLUSTER_DIR="$1"
	local SERVICE="$2"
	local LOGDIR=$(readlink "$CLUSTER_DIR/logs")
	local LOG="$LOGDIR/$SERVICE.log.gz.0"
	local LOGTAIL="$LOGDIR/$SERVICE.log.tail"
	local INODE1=$(stat -c '%i' "$LOG")
	/etc/init.d/pstorage-"$SERVICE"d reload "$CLUSTER_DIR" >/dev/null
	# wait until log is reopened
	for i in $(seq 1 10); do
		local INODE2=$(stat -c '%i' "$LOG")
		[ "$INODE1" -ne "$INODE2" ] && break
		# wait 100ms
		sleep .1
	done
	local LOGN=0
	local LINES_LEFT="$LOG_LINES"
	rm -f "$LOGTAIL"
	while true; do
		LOG="$LOGDIR/$SERVICE.log.gz.$LOGN"
		[ ! -f "$LOG" ] && break
		LOGN=$(expr "$LOGN" + 1)
		rm -f "$LOG.idx"
		/usr/libexec/pstorage/log_viewer -m -f "$LOG" >/dev/null
		[ ! -f "$LOG.idx" ] && continue;
		local NUMIND=$(/usr/libexec/pstorage/log_viewer -l -f "$LOG" | wc -l)
		local NTAIL=1
		local GOT_LINES=0
		while true; do
			local INDL=$(/usr/libexec/pstorage/log_viewer -l -f "$LOG" | tail -n "$NTAIL" | head -n 1 | awk '{print $1, $2}')
			/usr/libexec/pstorage/log_viewer -f "$LOG" -b "$INDL" | zcat | tail -n "$LINES_LEFT" > "$LOGTAIL.1"
			GOT_LINES=$(wc -l "$LOGTAIL.1" | awk '{print $1}')
			[ "$GOT_LINES" -eq "$LINES_LEFT" ] && break
			NTAIL=$(expr "$NTAIL" + 1)
			[ "$NTAIL" -gt "$NUMIND" ] && break
		done
		rm -f "$LOG.idx"
		if [ "$GOT_LINES" -gt 0 ]; then
			LINES_LEFT=$(expr "$LINES_LEFT" - "$GOT_LINES")
			mv "$LOGTAIL" "$LOGTAIL.2" 2>/dev/null
			cat "$LOGTAIL.1" "$LOGTAIL.2" > "$LOGTAIL" 2>/dev/null
			rm -f "$LOGTAIL.2" 2>/dev/null
		fi
		rm -f "$LOGTAIL.1"
		[ "$LINES_LEFT" -eq 0 ] && break
	done
	[ -s "$LOGTAIL" ] && echo "$LOGTAIL"
}

for_cluster() {
	local OP="$1"
	local SERVICE="$2"
	local CLUSTER_DIR="${CLUSTERS_DIR}/$CLUSTER_NAME"
	cat "${CLUSTER_DIR}/$SERVICE.list" 2>/dev/null | grep -v '^#' | grep -v '^\s*$' | while read dir; do
		("$OP" "${dir}" "$SERVICE")
	done
}

get_mounts_info()
{
        local tmp_dir=$1
        mounts=`cat /proc/self/mounts | awk '{if ($1 == "pstorage://'"$CLUSTER_NAME"'" && $3 == "fuse.pstorage") printf("%s/.pstorage.info\n", $2)}'`
        [ "x$mounts" = "x" ] && return 0
        for m in $mounts; do
                mkdir -p "$tmp_dir/$m"
                for f in `ls $m`; do
                        cat "$m/$f" > "$tmp_dir/$m/$f"
                done
        done
}

prepare_file_list() {
	cat <<EOF
/etc/pstorage/auth.modules
/etc/pstorage/mds.config
/etc/pstorage/cs.config
/etc/pstorage/host_id
$CLUSTERS_DIR/$CLUSTER_NAME/mds.list
$CLUSTERS_DIR/$CLUSTER_NAME/cs.list
$CLUSTERS_DIR/$CLUSTER_NAME/bs.list
$CLUSTERS_DIR/$CLUSTER_NAME/mds.config
$CLUSTERS_DIR/$CLUSTER_NAME/cs.config
/root/.pstorage/$CLUSTER_NAME
EOF
	for_cluster prepare_logs mds
	for_cluster prepare_logs cs
}

local_work() {
	get_mounts_info "$DIR/"
	prepare_file_list | tar --ignore-failed-read -cz -C "$DIR" . -C / -T -
	# check tar exit code: 2 = failure
	[ $? -ne 2 ]
}

remote_work() {
	if ! pstorage -c "$CLUSTER_NAME" stat --xml >"$DIR/stat.xml" 2>/dev/null; then
		echo "Failed to get information about the cluster"
		return 1
	fi
	pstorage -c "$CLUSTER_NAME" get-event >"$DIR/event.log" 2>/dev/null
	for host in $(cat "$DIR/stat.xml" | grep -o '<host>.*</host>' | sed -e 's/<host>\(.*\)<\/host>/\1/' -e 's/:[0-9]*$//' | sort -u); do
		/sbin/ip a 2>/dev/null | grep $host 2>&1 > /dev/null
		if [ $? -ne 0 ] ; then
			ssh $SSH_OPTS root@"$host" "$MAKE_REPORT" --local "$CLUSTER_NAME" >"$DIR/$host.tgz" 2>"$DIR/$host.log" &&
			echo "Collected report from host $host." ||
			echo "Failed to collect report from host $host."
		else
			"$MAKE_REPORT" --local "$CLUSTER_NAME" >"$DIR/$host.tgz" 2>"$DIR/$host.log" &&
                        echo "Collected report from host $host." ||
                        echo "Failed to collect report from host $host."

		fi
	done

	if [ ! "$FNAME" ]; then
		DATE=$(date +"%Y%m%d-%k%M%S")
		FNAME=pstorage-report-"$DATE".tgz
	fi
	tar -czf "$FNAME" -C "$DIR" .
	echo
	echo "The report is created and saved to $FNAME."
	echo "Please send the report to the Parallels support."
}

usage() {
	echo "Usage: $PROG [-f FILE] CLUSTER_NAME" 1>&2
	exit 1
}

if ! options=$(getopt -o lf:h -l local,file:,help -- "$@")
then
	# something went wrong, getopt will put out an error message for us
	exit 1
fi

eval set -- "$options"

while [ $# -gt 0 ]; do
	case $1 in
		-l|--local) LOCAL="yes" ;;
		-f|--file) FNAME="$2" ; shift;;
		-h|--help) usage ;;
		(--) shift; break;;
		(-*) echo "$PROG: error - unrecognized option $1" 1>&2; exit 1;;
		(*) break;;
	esac
	shift
done

[ $# -ne 1 ] && usage
CLUSTER_NAME="$1"

trap cleanup EXIT
DIR=$(mktemp -d)
if ! [ "$DIR" ]; then
	echo "Failed to create temporary directory" 1>&2
	exit 1
fi

if [ "$LOCAL" = "yes" ]; then
	local_work
else
	remote_work
fi
