#!/bin/sh
#
# Startup/shutdown script for services managed by xinetd.
#
#	Copyright (C) 2003 Charlie Brooks
#	Copyright (C) 2011 Ulrich Windl
#
# WARNING:	Tested ONLY on SLES11 SP1 at this time.
#
# Author:	Charlie Brooks <ha@HBCS.Org>
# Description:	given parameters of a service name and start|stop|status,
#		will enable, disable or report on a specified xinetd service
# Config:	all services must have a descriptor file in /etc/xinetd.d
# Support:	users@clusterlabs.org
# License:	GNU General Public License (GPL)
#
#	  OCF parameters are as below:
#		OCF_RESKEY_service

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

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

service=$OCF_RESKEY_service
SVCDEF=/etc/xinetd.d/$service

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

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

<longdesc lang="en">
Resource script for Xinetd. It starts/stops services managed
by xinetd by enabling or disabling them in the configuration file.

The xinetd daemon itself must be running: we are not going to start or
stop it ourselves.

All services should have a line saying either "disable=yes" or "disable=no".
The script just changes those settings before reloading xinetd.

Important: in case the services managed by the cluster are the
only ones enabled, you should specify the -stayalive option for
xinetd or it will exit on Heartbeat stop. Alternatively, you may
enable some internal service such as echo.
</longdesc>
<shortdesc lang="en">Manages a service of Xinetd</shortdesc>

<parameters>
<parameter name="service" unique="0" required="1">
<longdesc lang="en">
The name of the service managed by xinetd. 
</longdesc>
<shortdesc lang="en">service name</shortdesc>
<content type="string" default="" />
</parameter>
</parameters>

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

get_xinetd_pid() {
    ps -e -o pid,comm | $AWK '$2 == "xinetd" { print $1 }'
}

# force xinetd to reload the service descriptions
hup_inetd () {
    # don't rely on the pid file, but lookup xinetd in the list of
    # processes
    local pid
    pid=`get_xinetd_pid`
    if [ "$pid" ]; then
	if kill -s HUP $pid; then
            ocf_log info "asked xinetd to reload by sending SIGHUP to process $pid!"
	else
            ocf_exit_reason "could not send SIGHUP to process $pid!"
            exit $OCF_ERR_GENERIC
	fi
    else
	ocf_exit_reason "xinetd process not found!"
	exit $OCF_ERR_GENERIC
    fi
}

# check "disable = X", printing X
check_service()
{
    ocf_log "info" "checking \"disable\" in $1"
    local result=$(sed -nre 's/^[ 	]*disable[ 	]*=[ 	]*([^ 	]+)[# 	]*/\1/p' $1)
    echo "$result"
}

# change "disable = X" to desired value
change_service()
{
    ocf_log "info" "setting \"disable = $1\" in $2"
    if ! sed -i -re 's/^([ 	]*disable[ 	]*=[ 	]*)([^ 	]+)([# 	]*)/\1'"$1"'\3/' $2
    then
	ocf_log "err" "could not edit $2"
	return 1
    fi
    return 0
}

xup_status () {
    local disabled="$(check_service $SVCDEF)"
    if [ "${disabled:=no}" = no ]; then
	echo running
	return $OCF_SUCCESS
    elif [ "$disabled" = yes ]; then
	echo stopped
	return $OCF_NOT_RUNNING
    else
	echo unknown
	return $OCF_ERR_CONFIGURED
    fi
}

xup_start () {
    if [ "running" = "`xup_status`" ]; then
	ocf_log info "service $service already started"
	exit $OCF_SUCCESS
    fi
    ocf_log "info" "enabling in $SVCDEF"
    if change_service "no" $SVCDEF; then
        hup_inetd 
    fi
}

xup_stop () {
    if [ "stopped" = "`xup_status`" ]; then
	ocf_log info "service $service already stopped"
	exit $OCF_SUCCESS
    fi
    ocf_log "info" "disabling in $SVCDEF"
    if change_service "yes" $SVCDEF; then
        hup_inetd 
    fi
}

xup_usage () {
    echo "Usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}"
    return 0
}

xup_validate_all () {
    if [ ! -f "$SVCDEF" ]; then
        ocf_exit_reason "service $service missing $SVCDEF"
	return $OCF_ERR_INSTALLED
    fi
    return $OCF_SUCCESS
}

if [ $# -ne 1 ]; then
    xup_usage
    exit $OCF_ERR_ARGS
fi

# These operations do not require OCF instance parameters to be set
case "$1" in
    meta-data)
	meta_data
	exit $OCF_SUCCESS
	;;
    usage)
	xup_usage
	exit $OCF_SUCCESS
	;;
esac

if [ -z "$OCF_RESKEY_service" ]; then
    ocf_exit_reason "please define \"service\" parameter"
    if [ "$1" = "start" ]; then 
	exit $OCF_ERR_CONFIGURED
    else
	exit $OCF_NOT_RUNNING
    fi
fi

# Is xinetd running at all
if [ -z "`get_xinetd_pid`" ]; then
    case "$1" in
    stop) exit $OCF_SUCCESS;;
    start)
	ocf_exit_reason "xinetd not running, we manage just xinetd services, not the daemon itself"
	exit $OCF_ERR_INSTALLED
	;;
    status|monitor)
	if ocf_is_probe; then
	    exit $OCF_NOT_RUNNING
	else
	    ocf_exit_reason "xinetd stopped"
	    exit $OCF_ERR_GENERIC
	fi
	;;
    esac
fi

# Make sure the OCF_RESKEY_service is a valid xinetd service name
if [ ! -f $SVCDEF ]; then
    ocf_exit_reason "service definition $SVCDEF not found!"
    if [ "$1" = "start" ]; then 
	exit $OCF_ERR_INSTALLED
    else
	exit $OCF_NOT_RUNNING
    fi
fi

# See how we were called.
case "$1" in
    start)
	xup_start
	;;
    stop)
	xup_stop
	;;
    restart)
	$0 stop
	$0 start
	;;
    status)
	xup_status
	;;
    monitor)
	xup_status > /dev/null
	;;
    validate-all)
	xup_validate_all
	;;
    *)
	xup_usage
	exit $OCF_ERR_UNIMPLEMENTED
esac
exit $?
