#!/bin/bash
#
#   Hulft OCF Resource Agent
#
# Copyright (c) 2014 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#######################################################################
# Initialization:

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

# Defaults
OCF_RESKEY_hulexep_default=/usr/local/HULFT/bin
OCF_RESKEY_hulpath_default=/mnt/shareddisk/HULFT/etc
OCF_RESKEY_huluser_default=root
OCF_RESKEY_start_opts_default=""
OCF_RESKEY_huldname_default=""
OCF_RESKEY_sync_stop_default=10

: ${OCF_RESKEY_hulexep=${OCF_RESKEY_hulexep_default}}
: ${OCF_RESKEY_hulpath=${OCF_RESKEY_hulpath_default}}
: ${OCF_RESKEY_huluser=${OCF_RESKEY_huluser_default}}
: ${OCF_RESKEY_start_opts=${OCF_RESKEY_start_opts_default}}
: ${OCF_RESKEY_sync_stop=${OCF_RESKEY_sync_stop_default}}

usage() {
    cat <<EOF
    usage: $0 start|stop|status|monitor|meta-data|validate-all|methods
EOF
  return $OCF_ERR_ARGS
}

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

<longdesc lang="en">
This is a HULFT Resource Agent.
</longdesc>
<shortdesc lang="en">HULFT Resource Agent</shortdesc>

<parameters>
<parameter name="hulexep" unique="0" required="0">
<longdesc lang="en">
HULEXEP path
</longdesc>
<shortdesc lang="en">HULEXEP</shortdesc>
<content type="string" default="${OCF_RESKEY_hulexep_default}" />
</parameter>

<parameter name="hulpath" unique="0" required="0">
<longdesc lang="en">
HULPATH path
</longdesc>
<shortdesc lang="en">HULPATH</shortdesc>
<content type="string" default="${OCF_RESKEY_hulpath_default}" />
</parameter>

<parameter name="huluser" unique="0" required="0">
<longdesc lang="en">
HULFT user who start, monitor, stop HULFT.

This parameter is only supported on HULFT8 or later.
DO NOT SET this parameter on HULFT 7 or less.
</longdesc>
<shortdesc lang="en">HULFT user</shortdesc>
<content type="string" default="${OCF_RESKEY_huluser_default}" />
</parameter>

<parameter name="sync_stop" unique="0" required="0">
<longdesc lang="en">
timeout(sec) of synchronous stop.
required more than 10 seconds.
</longdesc>
<shortdesc lang="en">timeout of synchronous stop</shortdesc>
<content type="integer" default="${OCF_RESKEY_sync_stop_default}" />
</parameter>

<parameter name="huldname" unique="0" required="1">
<longdesc lang="en">
HULFT daemon name (snd/rcv/obs)
</longdesc>
<shortdesc lang="en">huldname</shortdesc>
<content type="string" default="${OCF_RESKEY_huldname_default}" />
</parameter>

<parameter name="start_opts" unique="0" required="0">
<longdesc lang="en">
start options.
Example : "-o -l /mnt/shareddisk/HULFT/log/hullog"
DO NOT USE "-mutual" and "-endwait".
</longdesc>
<shortdesc lang="en">start options</shortdesc>
<content type="string" default="${OCF_RESKEY_start_opts_default}" />
</parameter>
</parameters>

<actions>
<action name="start" timeout="60" />
<action name="stop" timeout="80" />
<action name="status" timeout="60" />
<action name="monitor" depth="0" timeout="30" interval="30"/>
<action name="meta-data" timeout="5" />
<action name="validate-all" timeout="5" />
<action name="methods" timeout="5" />
</actions>
</resource-agent>
EOF
}

hulft_methods() {
  cat <<EOF
    start
    stop
    status
    monitor
    methods
    meta-data
    validate-all
EOF
}

exec_command() {
    local command=$1

    if [ "$OCF_RESKEY_huluser" = "root" ]; then
        $command
    else
        su -l $OCF_RESKEY_huluser -c "export HULPATH=\"$HULPATH\"; \
                                      export HULEXEP=\"$HULEXEP\"; \
                                      export PATH=\"$PATH\"; \
                                      $command"
    fi

    return $?
}

hulft_start() {
    local rc

    hulft_status
    rc=$?

    if [ $rc -eq 0 ]; then
        ocf_log info "HULFT($OCF_RESKEY_huldname) already running."
        return $OCF_SUCCESS
    fi

    ocf_log info "starting HULFT($OCF_RESKEY_huldname) : $HULBIN -start $OCF_RESKEY_start_opts"
    exec_command "$HULBIN -start $OCF_RESKEY_start_opts"
    rc=$?
    if [ $rc -ne 0 ]; then
        ocf_exit_reason "cannot start HULFT($OCF_RESKEY_huldname):$rc"
        return $OCF_ERR_GENERIC
    fi

    return $OCF_SUCCESS
}

hulft_stop() {
    local rc

    hulft_status
    rc=$?

    if [ $rc -eq $OCF_NOT_RUNNING ]; then
        ocf_log info "HULFT($OCF_RESKEY_huldname) already stopped"
        return $OCF_SUCCESS
    fi

    ocf_log info "stopping HULFT($OCF_RESKEY_huldname) synchronously."
    exec_command "$HULBIN -stop -t -timeout $OCF_RESKEY_sync_stop"
    rc=$?
    if [ $rc -ne 0 ]; then
        ocf_log info "cannot stop HULFT($OCF_RESKEY_huldname):$rc synchronously. escalate to a forced stop"
        exec_command "$HULBIN -stop -f -timeout 10"
        rc=$?
        if [ $rc -ne 0 ]; then
            ocf_exit_reason "cannot stop HULFT($OCF_RESKEY_huldname):$rc"
            return $OCF_ERR_GENERIC
        fi
    fi
    return $OCF_SUCCESS
}

hulft_status() {
    local timeout
    local process_path

    case "$OCF_RESKEY_huldname" in
        snd)    process_path="$OCF_RESKEY_hulexep/hulsndd";;
        rcv)    process_path="$OCF_RESKEY_hulexep/hulrcvd";;
        obs)    process_path="$OCF_RESKEY_hulexep/hulobsd";;
    esac

    # The value of -timeout must set between 10 and 60.
    # NOTICE:
    # Timeout option (-timeout) is set ONLY for monitor action.
    # In case of start and stop action, the status of hulft process
    # is handle adequately by the action.
    if [ "$__OCF_ACTION" = "monitor" ]; then
        timeout=$(((OCF_RESKEY_CRM_meta_timeout/1000) - 10))

        if [ $timeout -gt 60 ]; then
            timeout=60
        elif [ $timeout -lt 10 ]; then
            timeout=10
        fi

        exec_command "$HULBIN -status -timeout $timeout"
    else
        exec_command "$HULBIN -status"
    fi
    rc=$?

    # Confirm whether the process is alive or stopped or hanged .
    # return value:
    # 0: Success
    # 100: Timed Out
    # 111 or 112 or 113: processes may be not running.
    # 118: Invalid HULPATH, but this is valid at probe.
    if [ $rc -eq 0 ]; then
        return 0
    elif [ $rc -eq 100 ]; then
        return 100
    elif [ $rc -eq 111 ] || [ $rc -eq 112 ] || [ $rc -eq 113 ]; then
        pgrep -f $process_path > /dev/null 2>&1

        if [ $? -ne 0 ]; then
            return $OCF_NOT_RUNNING
        else
            return $rc
        fi
    elif ocf_is_probe && [ $rc -eq 118 ]; then
        return $OCF_NOT_RUNNING
    else
        return $rc
    fi
}

hulft_monitor() {
    local rc

    hulft_status
    rc=$?

    if [ $rc -eq 0 ]; then
        return $OCF_SUCCESS
    elif [ $rc -eq $OCF_NOT_RUNNING ]; then
        ocf_log info "HULFT($OCF_RESKEY_huldname) is down"
        return $OCF_NOT_RUNNING
    elif [ $rc -eq 100 ]; then
        ocf_exit_reason "Time out has been occured to get HULFT($OCF_RESKEY_huldname) status."
        return $OCF_ERR_GENERIC
    else
        ocf_exit_reason "unknown error is occured. Please check hulft status. (error code: $?)"
        return $OCF_ERR_GENERIC
    fi
}

hulft_validate_all() {
    if [ ! -d $OCF_RESKEY_hulexep ]; then
    ocf_exit_reason "hulexep parameter is invalid : $OCF_RESKEY_hulexep"
        return $OCF_ERR_PERM
    fi

    if ! ocf_is_probe; then
        if [ ! -d $OCF_RESKEY_hulpath ]; then
            ocf_exit_reason "hulpath parameter is invalid : $OCF_RESKEY_hulpath"
            return $OCF_ERR_PERM
        fi
    fi

    if [ "$OCF_RESKEY_huluser" != "root" ]; then
        getent passwd $OCF_RESKEY_huluser > /dev/null 2>&1
        rc=$?
        if [ $rc -ne 0 ]; then
            ocf_exit_reason "There is no user : $OCF_RESKEY_huluser."
            return $OCF_ERR_PERM
        fi
    fi

    return $OCF_SUCCESS
}

###### MAIN #######

if [ $# -ne 1 ]
then
    usage
    exit $OCF_ERR_GENERIC
fi

case "$1" in
    methods)    hulft_methods
                exit $?;;

    meta-data)  meta_data
                exit $OCF_SUCCESS;;
esac

hulft_validate_all
rc=$?
[ "$1" == "validate-all" ] && exit $rc

export HULEXEP=$OCF_RESKEY_hulexep
export HULPATH=$OCF_RESKEY_hulpath
export PATH=$HULEXEP:$PATH

# check HULFT daemon name (snd/rcv/obs)
HULBIN=""
case "$OCF_RESKEY_huldname" in
    snd)    HULBIN="$OCF_RESKEY_hulexep/hulclustersnd";;
    rcv)    HULBIN="$OCF_RESKEY_hulexep/hulclusterrcv";;
    obs)    HULBIN="$OCF_RESKEY_hulexep/hulclusterobs";;
    *)      ocf_exit_reason "huldname parameter is invalid : $OCF_RESKEY_huldname"
            exit $OCF_ERR_CONFIGURED;;
esac

# What kind of method was invoked?
case "$1" in
    status)     if hulft_status
                then
                    ocf_log info "HULFT($OCF_RESKEY_huldname) is up"
                    exit $OCF_SUCCESS
                else
                    ocf_log info "HULFT($OCF_RESKEY_huldname) is down"
                    exit $OCF_NOT_RUNNING
                fi;;
    monitor)    hulft_monitor
                exit $?;;
    start)      hulft_start
                exit $?;;
    stop)       hulft_stop
                exit $?;;
    *)          usage
                exit $OCF_ERR_UNIMPLEMENTED;;
esac

