#!/bin/bash
#
# Description:  Manages a rsyslog instance, provided by NTT OSSC as an 
#               OCF High-Availability resource under Heartbeat/LinuxHA control
#
# Copyright (c) 2011 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##############################################################################
# OCF parameters:
#   OCF_RESKEY_rsyslog_binary   : Path to rsyslog binary.
#                                 Default is "/sbin/rsyslogd"
#   OCF_RESKEY_configfile       : Configuration file
#   OCF_RESKEY_start_opts       : Startup options
#
#   Only OCF_RESKEY_configfile must be specified. Each of the rests 
#   has its default value or refers OCF_RESKEY_configfile to make
#   its value when no explicit value is given.
#
# Further infomation for setup:
#   There are sample configurations at the end of this file.
#
###############################################################################

: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs

usage() 
{
	cat <<-!
usage: $0 action

action:
        start       : start a new rsyslog instance

        stop        : stop the running rsyslog instance

        status      : return the status of rsyslog, run or down

        monitor     : return TRUE if the rsyslog appears to be working.

        meta-data   : show meta data message

        validate-all: validate the instance parameters
!
	return $OCF_ERR_UNIMPLEMENTED
}

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

<longdesc lang="en">
This script manages a rsyslog instance as an HA resource.
</longdesc>
<shortdesc lang="en">rsyslog resource agent</shortdesc>

<parameters>

<parameter name="configfile" unique="1" required="1">
<longdesc lang="en">
This parameter specifies a configuration file 
for a rsyslog instance managed by this RA.
</longdesc>
<shortdesc>Configuration file</shortdesc>
<content type="string" default=""/>
</parameter>

<parameter name="rsyslog_binary" unique="0">
<longdesc lang="en">
This parameter specifies rsyslog's executable file.
</longdesc>
<shortdesc>rsyslog executable</shortdesc>
<content type="string" default="/sbin/rsyslogd"/>
</parameter>

<parameter name="start_opts" unique="0">
<longdesc lang="en">
This parameter specifies startup options for a 
rsyslog instance managed by this RA. When no value is given, no startup 
options is used. Don't use option '-F'. It causes a stuck of a start action.
</longdesc>
<shortdesc>Start options</shortdesc>
<content type="string" default=""/>
</parameter>

</parameters>

<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="60s" />
<action name="status" timeout="20s" />
<action name="monitor" depth="0" timeout="20s" interval="20s" />
<action name="meta-data" timeout="5s" />
<action name="validate-all"  timeout="5"/>
</actions>
</resource-agent>
END
	return $OCF_SUCCESS
}

monitor_rsyslog()
{
	set -- $(pgrep -f "$PROCESS_PATTERN" 2>/dev/null)
	case $# in
		0) ocf_log debug "No rsyslog process for $CONFIGFILE"
		   return $OCF_NOT_RUNNING;;
		1) return $OCF_SUCCESS;;
	esac
	ocf_log warn "Multiple rsyslog process for $CONFIGFILE"
	return $OCF_SUCCESS
}

start_rsyslog()
{
	local ocf_status
	monitor_rsyslog
	if [ $? = "$OCF_SUCCESS" ]; then
		return $OCF_SUCCESS
	fi

	$RSYSLOG_EXE -f $CONFIGFILE $START_OPTS 2>&1
	ocf_status=$?
	if [ "$ocf_status" != "$OCF_SUCCESS" ]; then
		return $OCF_ERR_GENERIC
	fi

	while true; do
		monitor_rsyslog
		if [ $? = "$OCF_SUCCESS" ]; then
			return $OCF_SUCCESS
		fi
		sleep 1
	done
}

stop_rsyslog()
{
	pkill -TERM -f "$PROCESS_PATTERN"

	typeset lapse_sec=0
	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
		sleep 1
		lapse_sec=$(( lapse_sec + 1 ))
		ocf_log debug "stop_rsyslog[${OCF_RESOURCE_INSTANCE}]: stop NORM $lapse_sec/$OCF_RESKEY_CRM_meta_timeout"
		if [ $lapse_sec -ge $OCF_RESKEY_CRM_meta_timeout ]; then
			break
		fi
	done

	lapse_sec=0
	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
		pkill -KILL -f "$PROCESS_PATTERN"
		sleep 1
		lapse_sec=$(( lapse_sec + 1 ))
		ocf_log debug "stop_rsyslog[${OCF_RESOURCE_INSTANCE}]: suspend rsyslog by SIGKILL ($lapse_sec/@@@)"
	done

	return $OCF_SUCCESS
}

status_rsyslog()
{
	monitor_rsyslog
	rc=$?
	if [ $rc = $OCF_SUCCESS ]; then
		echo "rsyslog service is running."
	elif [ $rc = $OCF_NOT_RUNNING ]; then
		echo "rsyslog service is stopped."
	fi
	return $rc
}

validate_all_rsyslog()
{
	ocf_log info "validate_all_rsyslog[${OCF_RESOURCE_INSTANCE}]"
	return $OCF_SUCCESS
}

if [[ "$1" = "meta-data" ]]; then
	metadata_rsyslog
	exit $?
fi

CONFIGFILE="${OCF_RESKEY_configfile}"
if [[ -z "$CONFIGFILE" ]]; then
	ocf_log err "undefined parameter:configfile"
	exit $OCF_ERR_CONFIGURED
fi
if [[ ! -f "$CONFIGFILE" ]]; then
	ocf_log err "Config file $CONFIGFILE does not exist."
	exit $OCF_ERR_CONFIGURED
fi

RSYSLOG_EXE="${OCF_RESKEY_rsyslog_binary-/sbin/rsyslogd}"
if [[ ! -x "$RSYSLOG_EXE" ]]; then
	ocf_log err "Invalid value:rsyslog_binary:$RSYSLOG_EXE"
	exit $OCF_ERR_CONFIGURED
fi

START_OPTS=${OCF_RESKEY_start_opts}
PROCESS_PATTERN="$RSYSLOG_EXE -f $CONFIGFILE"

COMMAND=$1

case "$COMMAND" in
	start)
		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Enter rsyslog start"
		start_rsyslog
		func_status=$?
		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Leave rsyslog start $func_status"
		exit $func_status
		;;
	stop)
		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Enter rsyslog stop"
		stop_rsyslog
		func_status=$?
		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Leave rsyslog stop $func_status"
		exit $func_status
		;;
	status)
		status_rsyslog
		exit $?
		;;
	monitor)
		monitor_rsyslog
		func_status=$?
		exit $func_status
		;;
	validate-all)
		validate_all_rsyslog
		exit $?
		;;
	*)
		usage
		;;
esac
