#!/bin/sh
#
#
# Confsync OCF Resource Agent.
#
# Copyright (c) 2006 Andrew Beekhof
# Copyright (c) 2012. Synology, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#

#######################################################################
# Initialization:

: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
. $prefix/etc.defaults/rc.subr

CRM_MASTER="${USR_BIN_DIR}/crm_master -l reboot"
HA_LUA="$prefix/etc.defaults/confsync/system_sync.lua"
LSYNCD_PROG="$prefix/sbin/lsyncd"
LSYNCD_PID="$prefix/var/run/ha/lsyncd.pid"
SYNOLSYNC="$prefix/sbin/synolsync"

#######################################################################

meta_data() {
	cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="Confsync" version="1.0">
<version>1.0</version>

<longdesc lang="en">
This is an example resource agent that impliments two states
</longdesc>
<shortdesc lang="en">Example confsync resource agent</shortdesc>

<parameters>

<parameter name="state" unique="1">
<longdesc lang="en">
Location to store the resource state in
</longdesc>
<shortdesc lang="en">State file</shortdesc>
<content type="string" default="${HA_RSCTMP}/Confsync-{OCF_RESOURCE_INSTANCE}.state" />
</parameter>

</parameters>

<actions>
<action name="start"   timeout="20s" />
<action name="stop"    timeout="20s" />
<action name="promote" timeout="20s" />
<action name="demote"  timeout="20s" />
<action name="monitor" timeout="20" interval="31" role="Slave" depth="0" />
<action name="monitor" timeout="20" interval="29" role="Master" depth="0" />
<action name="meta-data"  timeout="5" />
<action name="validate-all"  timeout="20s" />
</actions>
</resource-agent>
END
	exit $OCF_SUCCESS
}

#######################################################################

confsync_usage() {
	cat <<END
usage: $0 {start|stop|promote|demote|monitor|validate-all|meta-data}

Expects to have a fully populated OCF RA-compliant environment set.
END
	exit $1
}

confsync_update() {
	echo $1 > ${OCF_RESKEY_state}
}

confsync_check_state() {
	target=$1
	if [ -f ${OCF_RESKEY_state} ]; then
		state=`cat ${OCF_RESKEY_state}`
		if [ "x$target" = "x$state" ]; then
			return 0
		fi

	else
		if [ "x$target" = "x" ]; then
			return 0
		fi
	fi

	return 1
}

confsync_start() {
	confsync_check_state master
	if [ $? = 0 ]; then
		# CRM Error - Should never happen
		return $OCF_RUNNING_MASTER
	fi

	local pid=`cat "$LSYNCD_PID"`
	kill_proc_id $pid lsyncd
	rm ${LSYNCD_PID} &> /dev/null

	pid=`cat "$RSYNC_PID"`
	kill_proc_id "$pid" rsync
	${RSYNC_PROG} ${HA_RSYNC_OPTION} &> /dev/null

	$prefix/etc.defaults/ntpclient.sh start

	confsync_update slave
	$CRM_MASTER -v 5
	return 0
}

confsync_demote() {
	confsync_check_state
	if [ $? = 0 ]; then
		# CRM Error - Should never happen
		return $OCF_NOT_RUNNING
	fi

	local hasErr=`$SYNOLSYNC --get-status | grep "error" | cut -d ":" -f2`
	local isWait=`$SYNOLSYNC --get-status | grep "wait" | cut -d ":" -f2`
	local retry=0
	local retryMax=60   #total wait 60*2 s
	local numEvents=0
	local hasRemote=$(HAHasRemote)

	if [ -z "$hasRemote" ]; then
		synoha_log "remote not online, skip waiting confsync"
	elif [ 0 == $hasErr -a 0 == $isWait ]; then
		while [ 1 ];
		do
			numEvents=`$SYNOLSYNC --get-events | head -n 1`
			if [ $numEvents != "0" ]; then
				retry=`expr $retry + 1`
				if [ $retry -gt $retryMax ]; then
					synoha_log "waiting confsync timeout"
					break
				fi
				synoha_log "waiting confsync $retry:$retryMax"
				sleep 2 # delay 2s , since lsync's event aggregation time is 2s
			else
				break
			fi
		done
	fi

	local pid=`cat "$LSYNCD_PID"`
	kill_proc_id "$pid" lsyncd
	rm ${LSYNCD_PID} &> /dev/null

	pid=`cat "$RSYNC_PID"`
	if ! check_alive_id $pid rsync; then
		${RSYNC_PROG} ${HA_RSYNC_OPTION} &> /dev/null
	fi

	$prefix/etc.defaults/ntpclient.sh start

	confsync_update slave
	$CRM_MASTER -v 5
	return 0
}

confsync_promote() {
	confsync_check_state
	if [ $? = 0 ]; then
		return $OCF_NOT_RUNNING
	fi

	local pid=`cat "$RSYNC_PID"`
	kill_proc_id "$pid" rsync
	rm ${RSYNC_PID} &> /dev/null

	pid=`cat "$LSYNCD_PID"`
	if ! check_alive_id $pid lsyncd; then
		${LSYNCD_PROG} ${HA_LUA} &> /dev/null
	fi

	$prefix/etc.defaults/ntpclient.sh stop

	confsync_update master
	$CRM_MASTER -v 10
	return 0
}

confsync_stop() {
	$CRM_MASTER -D
	confsync_check_state master
	if [ $? = 0 ]; then
		# CRM Error - Should never happen
		return $OCF_RUNNING_MASTER
	fi

	local pid=`cat "$LSYNCD_PID"`
	kill_proc_id $pid lsyncd
	rm ${LSYNCD_PID} &> /dev/null

	pid=`cat "$RSYNC_PID"`
	kill_proc_id "$pid" rsync
	rm ${RSYNC_PID} &> /dev/null

	$prefix/etc.defaults/ntpclient.sh stop

	if [ -f ${OCF_RESKEY_state} ]; then
		rm ${OCF_RESKEY_state}
	fi
	return 0
}

## TODO, report real system configuration status
confsync_monitor() {
	confsync_check_state "master"
	if [ $? = 0 ]; then
		local pid=`cat "$LSYNCD_PID"`
		if ! check_alive_id $pid lsyncd; then
			synoha_log "lsyncd crashed, restart lsyncd"
			${LSYNCD_PROG} ${HA_LUA} &> /dev/null
		fi
		return $OCF_RUNNING_MASTER
	fi

	confsync_check_state "slave"
	if [ $? = 0 ]; then
		local pid=`cat "$RSYNC_PID"`
		if ! check_alive_id $pid rsync; then
			synoha_log "rsync daemon crashed, restart rsync daemon"
			${RSYNC_PROG} ${HA_RSYNC_OPTION} &> /dev/null
		fi
		return $OCF_SUCCESS
	fi

	if [ -f ${OCF_RESKEY_state} ]; then
		echo "File '${OCF_RESKEY_state}' exists but contains unexpected contents"
		cat ${OCF_RESKEY_state}
		return $OCF_ERR_GENERIC
	fi
	return 7
}

confsync_validate() {
	exit $OCF_SUCCESS
}

: ${OCF_RESKEY_state=${HA_RSCTMP}/Confsync-${OCF_RESOURCE_INSTANCE}.state}

case $__OCF_ACTION in
meta-data)    meta_data;;
start)        synoha_log "confsync start.";confsync_start;;
promote)      synoha_log "confsync promote.";confsync_promote;;
demote)       synoha_log "confsync demote";confsync_demote;;
stop)         synoha_log "confsync stop.";confsync_stop;;
monitor)      confsync_monitor;;
validate-all) confsync_validate;;
usage|help)   confsync_usage $OCF_SUCCESS;;
*)            confsync_usage $OCF_ERR_UNIMPLEMENTED;;
esac

exit $?

