#!/bin/sh
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# Support: www.windriver.com
#
# Purpose: This resource agent manages
#
#     .... the Inventory Conductor Service
#
# RA Spec:
#
# http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt?rev=HEAD
#
#######################################################################
# Initialization:

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

process="inventory"
service="-conductor"
binname="${process}${service}"

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

# Fill in some defaults if no values are specified
OCF_RESKEY_binary_default=${binname}
OCF_RESKEY_dbg_default="false"
OCF_RESKEY_pid_default="/var/run/${binname}.pid"
OCF_RESKEY_config_default="/etc/inventory/inventory.conf"


: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
: ${OCF_RESKEY_dbg=${OCF_RESKEY_dbg_default}}
: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}

mydaemon="/usr/bin/${OCF_RESKEY_binary}"

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

usage() {
    cat <<UEND

usage: $0 (start|stop|status|reload|monitor|validate-all|meta-data)

$0 manages the Platform's Inventory Conductor (inventory-conductor) process as an HA resource

   The 'start' .....  operation starts the inventory-conductor service in the active state.
   The 'stop' ......  operation stops the inventory-conductor service.
   The 'reload' ....  operation stops and then starts the inventory-conductor service.
   The 'status' ....  operation checks the status of the inventory-conductor service.
   The 'monitor' .... operation indicates the in-service status of the inventory-conductor service.
   The 'validate-all' operation reports whether the parameters are valid.
   The 'meta-data' .. operation reports the inventory-conductor's meta-data information.

UEND
}

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

meta_data() {
   if [ ${OCF_RESKEY_dbg} = "true" ] ; then
      ocf_log info "${binname}:meta_data"
   fi

cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="inventory-conductor">
<version>1.0</version>

<longdesc lang="en">
This 'inventory-conductor' is an OCF Compliant Resource Agent that manages start, stop and in-service monitoring of the Inventory Conductor
</longdesc>

<shortdesc lang="en">
Manages the Config (inventory-conductor) process.
</shortdesc>


<parameters>

<parameter name="dbg" unique="0" required="0">
<longdesc lang="en">
dbg = false  ... info, warn and err logs sent to output stream (default)
dbg = true   ... Additional debug logs are also sent to the output stream
</longdesc>
<shortdesc lang="en">Service Debug Control Option</shortdesc>
<content type="boolean" default="${OCF_RESKEY_dbg_default}"/>
</parameter>

</parameters>


<actions>
<action name="start"        timeout="10s" />
<action name="stop"         timeout="10s" />
<action name="monitor"      timeout="10s" interval="10m" />
<action name="meta-data"    timeout="10s" />
<action name="validate-all" timeout="10s" />
</actions>
</resource-agent>
END
   return ${OCF_SUCCESS}
}

inventory_conductor_validate() {

    local rc

    proc="${binname}:validate"
    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    check_binary ${OCF_RESKEY_binary}

    if [ ! -f ${OCF_RESKEY_config} ] ; then
        ocf_log err "${OCF_RESKEY_binary} ini file missing (${OCF_RESKEY_config})"
        return ${OCF_ERR_CONFIGURED}
    fi

    return ${OCF_SUCCESS}
}

inventory_conductor_status() {
    local pid
    local rc

    proc="${binname}:status"
    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    if [ ! -f $OCF_RESKEY_pid ]; then
        ocf_log info "${binname}:Inventory Conductor (inventory-conductor) is not running"
        return $OCF_NOT_RUNNING
    else
        pid=`cat $OCF_RESKEY_pid`
    fi

    ocf_run -warn kill -s 0 $pid
    rc=$?
    if [ $rc -eq 0 ]; then
        return $OCF_SUCCESS
    else
        ocf_log info "${binname}:Old PID file found, but Inventory Conductor (inventory-conductor)is not running"
        rm -f $OCF_RESKEY_pid
        return $OCF_NOT_RUNNING
    fi
}

inventory_conductor_monitor () {
    local rc
    proc="${binname}:monitor"

    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    inventory_conductor_status
    rc=$?
    return ${rc}
}

inventory_conductor_start () {
    local rc

    proc="${binname}:start"
    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    # If running then issue a ping test
    if [ -f ${OCF_RESKEY_pid} ] ; then
        inventory_conductor_status
        rc=$?
        if [ $rc -ne ${OCF_SUCCESS} ] ; then
            ocf_log err "${proc} ping test failed (rc=${rc})"
            inventory_conductor_stop
        else
            return ${OCF_SUCCESS}
        fi
    fi

    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        RUN_OPT_DEBUG="--debug"
    else
        RUN_OPT_DEBUG=""
    fi

    su ${OCF_RESKEY_user} -s /bin/sh -c "${OCF_RESKEY_binary} --config-file=${OCF_RESKEY_config} ${RUN_OPT_DEBUG}"' >> /dev/null 2>&1 & echo $!' > $OCF_RESKEY_pid
    rc=$?
    if [ ${rc} -ne ${OCF_SUCCESS} ] ; then
        ocf_log err "${proc} failed ${mydaemon} daemon (rc=$rc)"
        return ${OCF_ERR_GENERIC}
    else
        if [ -f ${OCF_RESKEY_pid} ] ; then
            pid=`cat ${OCF_RESKEY_pid}`
            ocf_log info "${proc} running with pid ${pid}"
        else
            ocf_log info "${proc} with no pid file"
        fi
    fi

    # Record success or failure and return status
    if [ ${rc} -eq $OCF_SUCCESS ] ; then
        ocf_log info "Inventory Conductor Service (${OCF_RESKEY_binary}) started (pid=${pid})"
    else
        ocf_log err "Config Service (${OCF_RESKEY_binary}) failed to start (rc=${rc})"
        rc=${OCF_NOT_RUNNING}
    fi

    return ${rc}
}

inventory_conductor_confirm_stop() {
    local my_bin
    local my_processes

    my_binary=`which ${OCF_RESKEY_binary}`
    my_processes=`pgrep -l -f "^(python|/usr/bin/python|/usr/bin/python2) ${my_binary}([^\w-]|$)"`

    if [ -n "${my_processes}" ]
    then
        ocf_log info "About to SIGKILL the following: ${my_processes}"
        pkill -KILL -f "^(python|/usr/bin/python|/usr/bin/python2) ${my_binary}([^\w-]|$)"
    fi
}

inventory_conductor_stop () {
    local rc
    local pid

    proc="${binname}:stop"
    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    inventory_conductor_status
    rc=$?
    if [ $rc -eq $OCF_NOT_RUNNING ]; then
        ocf_log info "${proc} Inventory Conductor (inventory-conductor) already stopped"
        inventory_conductor_confirm_stop
        return ${OCF_SUCCESS}
    fi

    # Try SIGTERM
    pid=`cat $OCF_RESKEY_pid`
    ocf_run kill -s TERM $pid
    rc=$?
    if [ $rc -ne 0 ]; then
        ocf_log err "${proc} Inventory Conductor (inventory-conductor) couldn't be stopped"
        inventory_conductor_confirm_stop
        exit $OCF_ERR_GENERIC
    fi

    # stop waiting
    shutdown_timeout=15
    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
        shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
    fi
    count=0
    while [ $count -lt $shutdown_timeout ]; do
        inventory_conductor_status
        rc=$?
        if [ $rc -eq $OCF_NOT_RUNNING ]; then
            break
        fi
        count=`expr $count + 1`
        sleep 1
        ocf_log info "${proc} Inventory Conductor (inventory-conductor) still hasn't stopped yet. Waiting ..."
    done

    inventory_conductor_status
    rc=$?
    if [ $rc -ne $OCF_NOT_RUNNING ]; then
        # SIGTERM didn't help either, try SIGKILL
        ocf_log info "${proc} Inventory Conductor (inventory-conductor) failed to stop after ${shutdown_timeout}s \
          using SIGTERM. Trying SIGKILL ..."
        ocf_run kill -s KILL $pid
    fi
    inventory_conductor_confirm_stop

    ocf_log info "${proc} Inventory Conductor (inventory-conductor) stopped."

    rm -f $OCF_RESKEY_pid

    return $OCF_SUCCESS

}

inventory_conductor_reload () {
    local rc

    proc="${binname}:reload"
    if [ ${OCF_RESKEY_dbg} = "true" ] ; then
        ocf_log info "${proc}"
    fi

    inventory_conductor_stop
    rc=$?
    if [ $rc -eq ${OCF_SUCCESS} ] ; then
        #sleep 1
        inventory_conductor_start
        rc=$?
        if [ $rc -eq ${OCF_SUCCESS} ] ; then
            ocf_log info "Inventory (${OCF_RESKEY_binary}) process restarted"
        fi
    fi

    if [ ${rc} -ne ${OCF_SUCCESS} ] ; then
        ocf_log info "Inventory (${OCF_RESKEY_binary}) process failed to restart (rc=${rc})"
    fi

    return ${rc}
}

case ${__OCF_ACTION} in
    meta-data)   meta_data
                 exit ${OCF_SUCCESS}
                 ;;
    usage|help)  usage
                 exit ${OCF_SUCCESS}
                 ;;
esac

# Anything except meta-data and help must pass validation
inventory_conductor_validate || exit $?

if [ ${OCF_RESKEY_dbg} = "true" ] ; then
    ocf_log info "${binname}:${__OCF_ACTION} action"
fi

case ${__OCF_ACTION} in

    start)        inventory_conductor_start
                  ;;
    stop)         inventory_conductor_stop
                  ;;
    status)       inventory_conductor_status
                  ;;
    reload)       inventory_conductor_reload
                  ;;
    monitor)      inventory_conductor_monitor
                  ;;
    validate-all) inventory_conductor_validate
                  ;;
    *)            usage
                  exit ${OCF_ERR_UNIMPLEMENTED}
                  ;;
esac
