#!/bin/bash

if [ -z "$COROSYNC_DEFAULT_CONFIG_IFACE" ]; then
	# rpm based distros
	if [ -d /etc/sysconfig ]; then
		[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
		[ -f /etc/sysconfig/cman ] && . /etc/sysconfig/cman
	fi

	# deb based distros
	if [ -d /etc/default ]; then
		[ -f /etc/default/cluster ] && . /etc/default/cluster
		[ -f /etc/default/cman ] && . /etc/default/cman
	fi

	[ -z "$CONFIG_LOADER" ] && CONFIG_LOADER=xmlconfig
	export COROSYNC_DEFAULT_CONFIG_IFACE=$CONFIG_LOADER:cmanpreconfig
fi

get_config_version() {
	local file=$1

	echo "xpath /cluster/@config_version" | \
		xmllint --shell "$file" | \
		grep content | \
	cut -f2 -d=
}

print_usage() {
	echo "Usage:"
	echo ""
	echo "ccs_config_validate [options]"
	echo ""
	echo "Options:"
	echo "  -h               Print this help, then exit"
	echo "  -V               Print program version information, then exit"
	echo "  -v               Produce verbose output"
	echo "  -q               Be very quiet"
	echo ""
	echo "Validating XML configuraton files:"
	echo "  -f configfile    Validate an alternate config file"
	echo "  -l configfile    Validate an alternate config file (load test)"
	echo ""
	echo "Advanced options:"
	echo "  -u               Do not update relaxng schema"
	echo "  -r               Force validation of runtime config"
	echo "  -C config_loader Override config plugin loader"
	echo "  -t tempfile      Force temporay file to tempfile"
	echo "  -n               Do not remove temporary file"
	echo "  -o               Overwrite temporary file (dangerous)"
	echo "  -R version       When validating configuration update, ensure the"
	echo "                   new config is newer than the specified version."
}

check_opts() {
	while [ "$1" != "--" ]; do
		case $1 in
		-h)
			print_usage
			exit 0
		;;
		-V)
			echo "ccs_config_validate version 3.1.7"
			exit 0
		;;
		-t)
			shift
			tempfile="$1"
		;;
		-n)
			notempfilerm=1
		;;
		-o)
			overwritetempfile=1
		;;
		-R)	
			shift
			old_version=$1
		;;
		-C)
			shift
			export COROSYNC_DEFAULT_CONFIG_IFACE=$1:cmanpreconfig
			loaderoverride=1
			if [ -n "$runtimetest" ] || \
			   [ -n "$filetest" ] || \
			   [ -n "$noloadtest" ]; then
				echo "Error: invalid options. -C can not be set together with -l or -r or -f" >&2
				exit 255
			fi
		;;
		-l)
			shift
			export COROSYNC_CLUSTER_CONFIG_FILE=$1
			export COROSYNC_DEFAULT_CONFIG_IFACE=xmlconfig:cmanpreconfig
			filetest=1
			if [ -n "$loaderoverride" ] || \
			   [ -n "$runtimetest" ] || \
			   [ -n "$noloadtest" ]; then
				echo "Error: invalid options. -l can not be set together with -r or -C or -f" >&2
				exit 255
			fi
		;;
		-f)
			shift
			export COROSYNC_CLUSTER_CONFIG_FILE=$1
			unset COROSYNC_DEFAULT_CONFIG_IFACE
			noloadtest=1
			if [ -n "$loaderoverride" ] || \
			   [ -n "$runtimetest" ] || \
			   [ -n "$filetest" ]; then
				echo "Error: invalid options. -f can not be set together with -r or -C or -l" >&2
				exit 255
			fi
		;;
		-r)
			unset COROSYNC_DEFAULT_CONFIG_IFACE
			runtimetest=1
			if [ -n "$noloadtest" ] || \
			   [ -n "$loaderoverride" ] || \
			   [ -n "$filetest" ]; then
				echo "Error: invalid options. -r can not be set together with -l or -C or -f" >&2
				exit 255
			fi
		;;
		-v)
			verbose=1
			if [ -n "$quiet" ]; then
				echo "Error: invalid options. -v can not be set together with -q" >&2
				exit 255
			fi
		;;
		-q)
			quiet=1
			if [ -n "$verbose" ]; then
				echo "Error: invalid options. -q can not be set together with -v" >&2
				exit 255
			fi
		;;
		-u)
			updaterelaxng=0
		;;
		esac
		shift
	done
}

lecho()
{
	[ -n "$verbose" ] && echo $@
	return 0
}

opts=$(getopt t:hVnC:f:l:rR:ovqu $@)
if [ "$?" != 0 ]; then
	print_usage >&2
	exit 255
fi
check_opts $opts

if [ -n "$tempfile" ]; then
	if [ -f "$tempfile" ] && [ -z "$overwritetempfile" ]; then
		echo "Selected temporary file $tempfile already exists" >&2
		echo "Use -o to force overwrite (dangerous)" >&2
		exit 255
	fi
else
	tempfile=$(mktemp)
	if [ -z "$tempfile" ]; then
		echo "Unable to create temporary file" >&2
		exit 255
	fi
fi
lecho "Creating temporary file: $tempfile"
lecho "Config interface set to: $COROSYNC_DEFAULT_CONFIG_IFACE"

if [ -n "$noloadtest" ]; then
	cp $COROSYNC_CLUSTER_CONFIG_FILE $tempfile
else
	export CMAN_PIPE=2
	if ! ccs_config_dump > $tempfile; then
		[ -z "$notempfilerm" ] && rm -f $tempfile
		echo
		echo "Unable to get the configuration" >&2
		exit 255
	fi
fi
lecho "Configuration stored in temporary file"

lecho "Updating relaxng schema"
if [ "$updaterelaxng" != 0 ]; then
	updateerr="$(ccs_update_schema 2>&1)"
	if [ $? != 0 ]; then
		echo "Unable to update relaxng schema: $updateerr" >&2
		exit 255
	fi
fi

if [ -f /var/lib/cluster/rng_update.lock ]; then
	echo "Relax-ng schema update in progress" >&2
	exit 255
fi

if [ ! -e /usr/share/cluster/cluster.rng ]; then
	echo "Unable to verify a configuration without relaxng schema" >&2
	exit 255
fi

lecho "Validating.."

xmlout=$(xmllint --noout \
	--relaxng /usr/share/cluster/cluster.rng \
	$tempfile 2>&1)
res=$?

if [ -n "$old_version" ] && [ $old_version -ne 0 ] && [ $res -eq 0 ]; then
	new_version=$(get_config_version $tempfile)
	if [ -z "$new_version" ]; then
		[ -z "$quiet" ] && \
			echo "Error: Unable to determine new config version!" >&2
		[ -z "$notempfilerm" ] && rm -f $tempfile
		exit 253
	fi
	lecho "Old version: $old_version   New version: $new_version"
	if [ $new_version -le $old_version ]; then
		[ -z "$quiet" ] && \
			echo "Error: Configuration version is older than running config!" >&2
		[ -z "$notempfilerm" ] && rm -f $tempfile
		exit 254
	fi
fi

if [ -z "$quiet" ] || [ "$res" != "0" ]; then
	echo "$xmlout" | sed \
		-e 's#.*validates$#Configuration validates#g' \
		-e 's#.*validate$#Configuration fails to validate#g' \
		-e 's#'$tempfile'#tempfile#g'
fi

lecho "Validation completed"

[ -z "$notempfilerm" ] && rm -f $tempfile
exit $res
