#!/usr/bin/bash
#
# SAPCMControlZone
#
# Description: Manages SAP Convergent Mediation ControlZone
#
##############################################################################
#
# SAPCMControlZone (short mz)
# Author:       Fabian Herschel, October 2023
# Support:      linux@sap.com
# License:      GNU General Public License (GPL)
# Copyright:    (c) 2023-2024 SUSE LLC
#
# An example usage:
#      See usage() function below for more details.
#
# OCF instance parameters:
#   OCF_RESKEY_USER             - optional parameter, linux user to control the CM control-zone (default: mzadmin)
#   OCF_RESKEY_MZSHELL          - optional parameter, path to the mz-shell (default: /usr/bin/mzsh)
#                               - could take TWO paths separated by a colon. Then the first is the local, the second the central mzsh (like /usr/sap/$SID/CMP$InstNumber/CM/bin/mzsh)
#   OCF_RESKEY_SERVICE          - optional parameter, service/component name of mz (default: platform)
#
# OCF instance parameters currently not implemented:
#   OCF_RESKEY_SHUTDOWN_RETRIES - optional parameter, passed to mzsh (default: unset - use mzsh internal default)
#   OCF_RESKEY_CALL_TIMEOUT     - optional parameter, do not mix-up with RA action timeout => should be either per action type or for all actions (startup,shutdown,status))
#
# OCF instance parameters not planned to be implemented:
#   OCF_RESKEY_VERBOSE_STATUS   - optional parameter, call mz with "verbose output" (default no)
#
#######################################################################
SAPCMControlZoneVersion="0.3.5"
export myBASH="/usr/bin/bash"
#
# DONE: PRIO1: get RA_MZ_PLATFORM, RA_JAVA_HOME AND RA_MZ_HOME from cluster config
export RA_MZ_PLATFORM="http://localhost:9000"
export RA_JAVA_HOME="/usr/lib64/jvm/jre-17-openjdk"
export RA_MZ_HOME="/opt/cm"

export logger_pid="$$"
#
# all BASH-REGEX to be case insensitive (no case match)
shopt -s nocasematch
#
# Initialization:
#
raType="mz_"
#
# fallback, if OCF variables are not set (before sourcing the ocf-shellfuncts)
OCF_ROOT="${OCF_ROOT:-/usr/lib/ocf}"
OCF_FUNCTIONS_DIR="${OCF_FUNCTIONS_DIR:-${OCF_ROOT}/lib/heartbeat}"
OCF_SUCCESS=0
OCF_ERR_GENERIC=1
OCF_ERR_ARGS=2
OCF_ERR_UNIMPLEMENTED=3
OCF_ERR_PERM=4
# shellcheck disable=SC2034
OCF_ERR_INSTALLED=5
OCF_ERR_CONFIGURED=6
OCF_NOT_RUNNING=7
# shellcheck source=/dev/null
source "${OCF_FUNCTIONS_DIR}/ocf-shellfuncs"
ocf_log INFO "Version $SAPCMControlZoneVersion ($*)"
# init a minimum set of variables, if the variable are not initialized so far
OCF_SUCCESS="${OCF_SUCCESS:-0}"
#
#######################################################################
#

#
######################################################################
#
# mz-side of the RA
#

function mz_component_startup()
{
    local user="$1" component="$2" rid="$3" lid="$4" rc=0
    # DONE: set env for variables RA_JAVA_HOME and RA_MZ_HOME
    # DONE: output for already started component is "platform is already running" - implemented, checked with project
    # DONE: Output like "FAILED\nStartable platform exited unexpectedly"; interpreted as ERROR
    # DONE: Tested, but not committed API: RC==0 OK; committed by project
    while [[ "$#" -gt 0 ]]; do
        case "$1" in
            --user=* ) # user handling
                        user=${1#*=}
                       ;;
            --component=* ) # component name
                        component=${1#*=}
                            ;;
            --rid=* ) # resource id to log
                        rid=${1#*=}
                        ;;
            --lid=* ) # logger id to be used
                        lid=${1#*=}
                    ;;
            --mz_platform=* ) # set RA_MZ_PLATFORM for CM
                        RA_MZ_PLATFORM=${1#*=}
                        export RA_MZ_PLATFORM
                        ;;
            --java_home=* ) # set RA_JAVA_HOME for CM
                        RA_JAVA_HOME=${1#*=}
                        export RA_JAVA_HOME
                        ;;
            --mz_home=* ) # set mz_home for CM
                        RA_MZ_HOME=${1#*=}
                        export RA_MZ_HOME
                        ;;
        esac
        shift
    done
    # using option "-f" for startup following mail "Convergent Mediation SUSE HA Status 2024-04-15" from software vendor
    result=$(su -w RA_MZ_HOME,RA_MZ_PLATFORM,RA_JAVA_HOME - "$user" -c "$mz_shell_central startup -f $component"); rc_call="$?"
    # DONE: PRIO2: Try to get rid of "grep" (bash-regmap)
    regex_starting="Starting $component\.*done."
    regex_already="$component is already running"
    case "$rc_call" in
        0 ) # success
            rc=0
            ;;
        1 ) # failed
            rc=1
            ;;
        102 ) # failed (timeout on callback)
            rc=1
            ;;
        103 ) # interrupted
            rc=1
            ;;
        104 ) # failed critical
            rc=1
            ;;
        * ) # unknown
            rc=1
            ;;
    esac
    logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh startup $component with env: RA_MZ_HOME=$RA_MZ_HOME, RA_MZ_PLATFORM=$RA_MZ_PLATFORM, RA_JAVA_HOME=$RA_JAVA_HOME"
    if [[ ( "$rc" == "0" ) && (( "$result" =~ $regex_starting ) || ( "$result" =~ $regex_already )) ]]; then
        logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh startup $component ($mz_shell_central) OK - got rc_call=$rc_call"
    else
        if [[ "$rc" == "0" ]]; then
            logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh startup $component ($mz_shell_central) OK - got rc_call=$rc_call; result=$result"
        else
            logger -p err --id="$lid" -t "SAPCMControlZone($rid)" "ERROR: mzsh startup $component ($mz_shell_central) FAILED - got rc_call=$rc_call; result=$result"
        fi
    fi
    return "$rc"
}
export -f mz_component_startup

function mz_component_shutdown()
{
    local user="mzadmin" component="platform" rid="n/a" lid="$$" rc=0 RA_JAVA_HOME="" RA_MZ_HOME="" RA_MZ_PLATFORM=""
    # DONE: set env for variables RA_JAVA_HOME and RA_MZ_HOME
    # DONE: How to treat output like "Shutting down platform...\nShutdown failed. Trying kill instead.\ndone."
    # DONE: How to treat output with unequal 3 dots (Shutting down platform....done.)
    # DONE: Output fror already stopped component is "<component> is not running"
    # DONE: Output like "Starting ui...FAILED"; solved by rc of the command
    # DONE: Output like "platfoam: no such server process"; solved by rc of the command
    # DONE: Tested, but not committed API: RC==0 OK; committed by project
    while [[ "$#" -gt 0 ]]; do
        case "$1" in
            --user=* ) # user handling
                        user=${1#*=}
                       ;;
            --component=* ) # component name
                        component=${1#*=}
                            ;;
            --rid=* ) # resource id to log
                        rid=${1#*=}
                        ;;
            --lid=* ) # logger id to be used
                        lid=${1#*=}
                    ;;
            --mz_platform=* ) # set RA_MZ_PLATFORM for CM
                        RA_MZ_PLATFORM=${1#*=}
                        export RA_MZ_PLATFORM
                        ;;
            --java_home=* ) # set RA_JAVA_HOME for CM
                        RA_JAVA_HOME=${1#*=}
                        export RA_JAVA_HOME
                        ;;
            --mz_home=* ) # set mz_home for CM
                        RA_MZ_HOME=${1#*=}
                        export RA_MZ_HOME
                        ;;
        esac
        shift
    done
    logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh shutdown $component with env: RA_MZ_HOME=$RA_MZ_HOME, RA_MZ_PLATFORM=$RA_MZ_PLATFORM, RA_JAVA_HOME=$RA_JAVA_HOME"
    result=$(su -w RA_MZ_HOME,RA_MZ_PLATFORM,RA_JAVA_HOME - "$user" -c "$mz_shell_central shutdown $component"); rc_call="$?"
    regex_shuttingdown="Shutting down $component\.*done."
    regex_notrunning="$component is not running"; rc="$?"
    case "$rc_call" in
        0 ) # success
            rc=0
            ;;
        1 ) # not found
            rc=1
            ;;
        3 ) # interrupted
            rc=1
            ;;
        4 ) # failed
            rc=1
            ;;
        * ) # unknown
            rc=1
            ;;
    esac
    if [[ ( "$rc" == "0" ) && (( "$result" =~ $regex_shuttingdown ) || ( "$result" =~ $regex_notrunning )) ]]; then
        logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh shutdown $component ($mz_shell_central) OK - got rc_call=$rc_call"
    else
        if [[ "$rc" == "0" ]]; then
            logger -p err --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh shutdown $component ($mz_shell_central) OK - got rc_call=$rc_call; result=$result"
        else
            logger -p err --id="$lid" -t "SAPCMControlZone($rid)" "ERROR: mzsh shutdown $component ($mz_shell_central) FAILED - got rc_call=$rc_call; result=$result"
        fi
    fi
    return "$rc"
}
export -f mz_component_shutdown

function mz_component_status()
{
    # DONE: improved and more detailled parameter handling
    # TODO PRIO3: add --mz_shell in parameter handling
    local user="mzadmin" component="platform" rid="n/a" lid="$$" rc=0 RA_JAVA_HOME="" RA_MZ_HOME="" RA_MZ_PLATFORM="" timeout=60
    while [[ "$#" -gt 0 ]]; do
        case "$1" in
            --user=* ) # user handling
                        user=${1#*=}
                       ;;
            --component=* ) # component name
                        component=${1#*=}
                            ;;
            --timeout=* ) # timeout
                        timeout=${1#*=}
                        ;;
            --rid=* ) # resource id to log
                        rid=${1#*=}
                        ;;
            --lid=* ) # logger id to be used
                        lid=${1#*=}
                    ;;
            --mz_platform=* ) # set RA_MZ_PLATFORM for CM
                        RA_MZ_PLATFORM=${1#*=}
                        export RA_MZ_PLATFORM
                        ;;
            --java_home=* ) # set RA_JAVA_HOME for CM
                        RA_JAVA_HOME=${1#*=}
                        export RA_JAVA_HOME
                        ;;
            --mz_home=* ) # set mz_home for CM
                        RA_MZ_HOME=${1#*=}
                        export RA_MZ_HOME
                        ;;
        esac
        shift
    done
    # DONE: PRIO1: How to treat output like "platform is running without ..."; solved by rc of the command
    # DONE: set env for variables RA_JAVA_HOME and RA_MZ_HOME
    # DONE: PRIO1: Tested, but not committed API: status <component> does also work; committed by the project
    # DONE: Tested, but not committed API: RC==0 UP, RC==1 DEGRADED; RC==2 DOWN (one or multiple), OTHER: ERROR (FATAL)
    #             have been committed in a meeting that we could use the RCs
    logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh status $component with env: RA_MZ_HOME=$RA_MZ_HOME, RA_MZ_PLATFORM=$RA_MZ_PLATFORM, RA_JAVA_HOME=$RA_JAVA_HOME"
    result=$(timeout "$timeout" su -w RA_MZ_HOME,RA_MZ_PLATFORM,RA_JAVA_HOME - "$user" -c "$mz_shell_local status $component"); rc_call="$?"
    regex_isrunning="$component is running"
    regex_isnotrunning="$component is not running"
    case "$rc_call" in
        0 ) # success
            rc=0
            ;;
        1 ) # degraded
            rc=1
            ;;
        2 ) # down
            rc=1
            ;;
        * ) # unknown
            rc=1
            ;;
    esac
    if [[  "$rc" == "0" ]]; then
        if [[ "$result" =~ $regex_isrunning ]]; then
            #
            # rc UP, message OK
            logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh status $component ($mz_shell_local) OK - component running; got rc_call=$rc_call"
        else
            #
            # rc UP, message UNCLEAR
            logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh status $component ($mz_shell_local) OK - component running, but unexpected message; got rc_call=$rc_call; result=$result"
        fi
    elif [[ ( "$rc" == "1" ) && ( "$rc_call" == "2" ) ]]; then
        if [[ ( "$result" =~ $regex_isnotrunning ) ]]; then
            #
            # rc DOWN, message OK
            logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh ($mz_shell_local) OK - component not running; got rc_call=$rc_call;"
        else
            #
            # rc DOWN, message unclear
            logger --id="$lid" -t "SAPCMControlZone($rid)" "INFO: mzsh status $component ($mz_shell_local) OK component not running, but unexpected message; got rc_call=$rc_call; result=$result"
        fi
    else
        #
        # rc FAIL
        logger -p err --id="$lid" -t "SAPCMControlZone($rid)" "ERROR: mzsh status $component ($mz_shell_central) FAILED component status unclear - got rc_call=$rc_call; result=$result"
    fi
    return "$rc"
}
export -f mz_component_status


function mz_call()
{
    # TODO PRIO3: 'timeout' default value (non zero), see OCF_RESKEY_CALL_TIMEOUT?
    local rc="$OCF_ERR_GENERIC" timeout=60, user="$mz_user", action="status", component="platform" call_rc=0
    while [ $# -gt 0 ]; do
        case "$1" in
            --user=* )  user=${1#*=} ;;
            --action=* )  action=${1#*=} ;;
            --timeout=* )  timeout=${1#*=} ;;
            --component=* )  component=${1#*=} ;;
        esac
        shift
    done
    case "$action" in
        status )
                export mz_shell_local mz_shell_central component user
                retry_sleep=10
                max_retry=2
                retry_count=0
                # we might need 1-2 retries, lets check if we only need to retry, if the status runs into a timeout
                # needs to switch-user to <mzadmin>
                while [[ "$retry_count" -lt "$max_retry" ]]; do
                    (( retry_count++ ))
                    # DONE: improved and more detailled parameter handling
                    # TODO PRIO3: also add mz_shell
                    # DONE: also add java_home
                    mz_component_status --user="$user" --component="$component" --mz_platform="${mz_platform_local}" --mz_home="${mz_home_local}" --java_home="${java_home_local}" --rid="${OCF_RESOURCE_INSTANCE}" --lid="${logger_pid}" --timeout="$timeout"; call_rc="$?"
                    case "$call_rc" in
                        0 ) ocf_log INFO "mz_call: $component is running"
                            rc="$OCF_SUCCESS"
                            break;;
                        1 ) # also for clear "not running" we need to repeat the status call (have seen short outages with ui in the test cluster)
                            ocf_log INFO "mz_call: $component is NOT running"
                            rc="$OCF_NOT_RUNNING";;
                        * ) ocf_log INFO "mz_call: $component is unclear (call_rc=$call_rc)"
                            rc="$OCF_ERR_GENERIC";;
                    esac
                    sleep "$retry_sleep"
                done
                ;;
        startup )
                # needs to switch-user to <mzadmin>
                retry_sleep=10
                max_retry=2
                retry_count=0
                while [[ "$retry_count" -lt "$max_retry" ]]; do
                    (( retry_count++ ))
                    if mz_component_startup --user="$user" --component="$component" --mz_platform="${mz_platform_central}" --mz_home="${mz_home_central}" --java_home="${java_home_central}" --rid="${OCF_RESOURCE_INSTANCE}" --lid="${logger_pid}"; then
                        ocf_log INFO "mz_call: $component is started"
                        rc="$OCF_SUCCESS"
                        break
                    else
                        ocf_log INFO "mz_call: $component is NOT started"
                        rc="$OCF_NOT_RUNNING"
                    fi
                    sleep "$retry_sleep"
                done
                #
                # now just wait till status could catch the compoent as started (rc keeps unttached by the following waiting-code
                #
                while [[ "$retry_count" -lt "$max_retry" ]]; do
                    mz_component_status --user="$user" --component="$component" --mz_platform="${mz_platform_local}" --mz_home="${mz_home_local}" --java_home="${java_home_local}" --rid="${OCF_RESOURCE_INSTANCE}" --lid="${logger_pid}" --timeout="$timeout"; call_rc="$?"
                    case "$call_rc" in
                        0 ) # dont longer wait for started component
                            rc="$OCF_SUCCESS"
                            break;;
                        1 ) # also for clear "not running" we need to repeat the status call (have seen short outages with ui in the test cluster)
                            ocf_log INFO "mz_call: $component is NOT running (still wait to be started)"
                            ;;
                        * ) ocf_log INFO "mz_call: $component is unclear (call_rc=$call_rc)"
                            ;;
                    esac
                    sleep "$retry_sleep"
                done
                ;;
        shutdown )
                # needs to switch-user to <mzadmin>
                retry_sleep=10
                max_retry=2
                retry_count=0
                while [[ "$retry_count" -lt "$max_retry" ]]; do
                    (( retry_count++ ))
                    # second try to stop mz component
                    if mz_component_shutdown --user="$user" --component="$component" --mz_platform="${mz_platform_local}" --mz_home="${mz_home_central}" --java_home="${java_home_central}" --rid="${OCF_RESOURCE_INSTANCE}" --lid="${logger_pid}" ; then
                        ocf_log INFO "mz_call: $component is stopped"
                        rc="$OCF_SUCCESS"
                        break
                    else
                        ocf_log INFO "mz_call: $component is still NOT stopped"
                        rc="$OCF_ERR_GENERIC"
                    fi
                    sleep "$retry_sleep"
                done
                if [[ "$rc" == "$OCF_ERR_GENERIC" ]]; then
                    # compoent is still not stopped, try to escalate with pkill
                    pkill_pattern="${java_home_central}/bin/java.*OnOutOfMemoryError=oom ${component}"
                    ocf_log INFO "$component still not stopped, killing component process"
                    pkill -9 -f "${pkill_pattern}"
                    sleep 10
                    if pgrep -f "${pkill_pattern}"; then
                        ocf_log INFO "$component still not stopped, setting stop failure"
                        rc="$OCF_ERR_GENERIC"
                    else
                        ocf_log INFO "$component killed succesfully, setting stop success"
                        rc="$OCF_SUCCESS"
                    fi
                fi
                ;;
        * )
                # not implemented
                rc="$OCF_ERR_UNIMPLEMENTED"
    esac
    return "$rc"
}

#
######################################################################
#
# cluster-side of the RA
#
function mz_usage()
{
    echo "usage: $0 [start|stop|monitor|meta-data|reload|methods|usage]"
}

function mz_methods()
{
    echo "start stop monitor meta-data reload methods usage"
}

function mz_init()
{
    # DONE: init variables
    mz_user="${OCF_RESKEY_USER:-mzadmin}"
    mz_path_str="${OCF_RESKEY_MZSHELL:-/usr/bin/mzsh}"
    mz_home_str="${OCF_RESKEY_MZHOME:-/opt/cm/C11/CM}"
    java_home_str="${OCF_RESKEY_JAVAHOME:-/opt/cm/C11/CM}"
    mz_platform_str="${OCF_RESKEY_MZPLATFORM:-http://localhost:9000}"
    regex_seperator=";"
    regex_multivalue="^([^$regex_seperator]*)$regex_seperator(.*)$"
    ## mz_shell
    # cut string into a first part and an optional second part. parts are separated by $regex_seperator
    if [[ "$mz_path_str" =~ $regex_multivalue ]]; then
        # found first:second
        mz_shell_local="${BASH_REMATCH[1]}"
        mz_shell_central="${BASH_REMATCH[2]}"
    else
        mz_shell_local="$mz_path_str"
        mz_shell_central="$mz_path_str"
    fi
    ## mz_home
    # cut string into a first part and an optional second part. parts are separated by $regex_seperator
    if [[ "$mz_home_str" =~ $regex_multivalue ]]; then
        # found first:second
        mz_home_local="${BASH_REMATCH[1]}"
        mz_home_central="${BASH_REMATCH[2]}"
    else
        mz_home_local="$mz_home_str"
        mz_home_central="$mz_home_str"
    fi
    # DONE: also handle arraxs for java_home
    ## java_home
    # cut string into a first part and an optional second part. parts are separated by $regex_seperator
    if [[ "$java_home_str" =~ $regex_multivalue ]]; then
        # found first:second
        java_home_local="${BASH_REMATCH[1]}"
        java_home_central="${BASH_REMATCH[2]}"
    else
        java_home_local="$java_home_str"
        java_home_central="$java_home_str"
    fi
    ## mz_platform 
    # cut string into a first part and an optional second part. parts are separated by $regex_seperator
    if [[ "$mz_platform_str" =~ $regex_multivalue ]]; then
        # found first:second
        mz_platform_local="${BASH_REMATCH[1]}"
        mz_platform_central="${BASH_REMATCH[2]}"
    else
        mz_platform_local="$mz_platform_str"
        mz_platform_central="$mz_platform_str"
    fi
    
    # mz_search_list="/usr/bin:/usr/sap/[A-Z][A-Z0-9][A-Z0-9]/CMP[0-9][0-9]/CM/bin/"
    mz_component="${OCF_RESKEY_SERVICE:-platform}"
    # shellcheck disable=SC2034  # variable for future usage
    mz_shutdown_retries="${OCF_RESKEY_SHUTDOWN_RETRIES:+-r $OCF_RESKEY_SHUTDOWN_RETRIES}" # empty, if OCF_RESKEY_SHUTDOWN_RETRIES} is usnet, otherwise "-r $OCF_RESKEY_SHUTDOWN_RETRIES"
    # shellcheck disable=SC2034  # variable for future usage
    mz_call_timeout="${OCF_RESKEY_CALL_TIMEOUT:-60}"
}

function mz_meta_data()
{
   # shellcheck disable=SC2016
   echo '<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="SAPCMControlZone" version="$raVersion">
<version>1.1</version>
<shortdesc lang="en">Manages SAP Convergent Mediation ControlZone.</shortdesc>
<longdesc lang="en">The SAPCMControlZone RA manages SAP Convergent Mediation ControlZone services platform or UI as active/passive resources.</longdesc>
<parameters>
<parameter name="CALL_TIMEOUT" unique="0" required="0">
   <shortdesc lang="en">Currently not implemented: How long calls to the ControlZone platform can take.</shortdesc>
   <longdesc lang="en">How long calls to the ControlZone platform for checking the status can take. If you increase this timeout, you should also adjust the operation timeouts of your Linux cluster resources.</longdesc>
    <content type="string" default="60" />
</parameter>
<parameter name="JAVAHOME" unique="0" required="0">
    <shortdesc lang="en">ControlZone specific JAVA_HOME directory</shortdesc>
    <longdesc lang="en">TBD</longdesc>
    <content type="string" default="TBD" />
</parameter>
<parameter name="MZHOME" unique="0" required="0">
    <shortdesc lang="en">ControlZone home directory</shortdesc>
    <longdesc lang="en">TBD</longdesc>
    <content type="string" default="TBD" />
</parameter>
<parameter name="MZPLATFORM" unique="0" required="0">
    <shortdesc lang="en">ControlZone connection URL</shortdesc>
    <longdesc lang="en">ControlZone connection URL</longdesc>
    <content type="string" default="http://localhost:9000" />
</parameter>
<parameter name="MZSHELL" unique="0" required="0">
    <shortdesc lang="en">ControlZone shell</shortdesc>
    <longdesc lang="en">Path to the CM ControlZone commandline shell to be called. Values: full path to the shell. The parameter could also take two different paths separarated by colon (:). In that case the first path must be the path of the "local" mzsh and the second must be the path of the "central/shared" mzsh. Format: PATH-LOCAL:PATH-CENTRAL</longdesc>
    <content type="string" default="/usr/bin/mzsh" />
</parameter>
<parameter name="SERVICE" unique="0" required="0">
    <shortdesc lang="en">Convergent Mediation ControlZone service to manage.</shortdesc>
    <longdesc lang="en">Convergent Mediation ControlZone service to manage. Either platform or UI.</longdesc>
    <content type="string" default="platform" />
</parameter>
<parameter name="SHUTDOWN_RETRIES" unique="0" required="0">
    <shortdesc lang="en">Number of retries to check for process shutdown. Not yet implemented.</shortdesc>
    <longdesc lang="en">Number of retries to check for process shutdown. If you increase the number of shutdown retries, you should also adjust the stop operation timeout of your Linux cluster resource.</longdesc>
    <content type="string" default="" />
</parameter>
<parameter name="USER" unique="0" required="0">
    <shortdesc lang="en">Linux user to control the CM component.</shortdesc>
    <longdesc lang="en">Linux user to control the CM component.</longdesc>
    <content type="string" default="mzadmin" />
</parameter>
<parameter name="VERBOSE_STATUS" unique="0" required="0">
    <shortdesc lang="en">Currently not implemented: Verbose status output.</shortdesc>
    <longdesc lang="en">Verbose status output.</longdesc>
    <content type="string" default="" />
</parameter>
</parameters>
<actions>
    <action name="start"   timeout="120" />
    <action name="stop"    timeout="150" />
    <action name="monitor" timeout="120" interval="120" />
    <action name="meta-data" timeout="5" />
    <action name="methods" timeout="5" />
    <action name="usage" timeout="5" />
    <action name="reload" timeout="5" />
</actions>
</resource-agent>'
}


# shellcheck disable=SC2120
function mz_check_params()
{
    local rc="$OCF_SUCCESS"
    if [[ -n "$OCF_RESKEY_USER" ]]; then
        if id "$OCF_RESKEY_USER" 1>/dev/null 2>/dev/null; then
            ocf_log INFO "User '$OCF_RESKEY_USER' exists"
        else
            ocf_log ERROR "User '$OCF_RESKEY_USER' does NOT exist"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    if [[ -n "$mz_shell_local" ]]; then
        if [[ -x "$mz_shell_local" ]]; then
            ocf_log INFO "mz_shell_local '$mz_shell_local' exists and is executable"
        else
            ocf_log ERROR "mz_shell_local '$mz_shell_local' either does NOT exist or is NOT executable"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    if [[ -n "$mz_shell_central" ]]; then
        if [[ -x "$mz_shell_central" ]]; then
            ocf_log INFO "mz_shell_central '$mz_shell_central' exists and is executable"
        else
            ocf_log ERROR "mz_shell_central '$mz_shell_central' either does NOT exist or is NOT executable"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
# mz_home_local=
    if [[ -n "$mz_home_local" ]]; then
        if [[ -e "$mz_home_local" ]]; then
            ocf_log INFO "mz_home_local '$mz_home_local' exists"
        else
            ocf_log ERROR "mz_home_local '$mz_home_local' does NOT exist"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    if [[ -n "$mz_home_central" ]]; then
        if [[ -e "$mz_home_central" ]]; then
            ocf_log INFO "mz_home_central '$mz_home_central' exists"
        else
            ocf_log ERROR "mz_home_central '$mz_home_central' does NOT exist"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    ###
    # java_home_local=
    if [[ -n "$java_home_local" ]]; then
        if [[ -e "$java_home_local" ]]; then
            ocf_log INFO "java_home_local '$java_home_local' exists"
        else
            ocf_log ERROR "java_home_local '$java_home_local' does NOT exist"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    if [[ -n "$java_home_central" ]]; then
        if [[ -e "$java_home_central" ]]; then
            ocf_log INFO "java_home_central '$java_home_central' exists"
        else
            ocf_log ERROR "java_home_central '$java_home_central' does NOT exist"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    # DONE: Request from project to also controlling services like "wdX"
    regex_platformorui="^(platform|ui|wd.*)$"
    if [[ -n "$OCF_RESKEY_SERVICE" ]]; then
        if [[ "$OCF_RESKEY_SERVICE" =~ $regex_platformorui ]]; then
            ocf_log INFO "Service '$OCF_RESKEY_SERVICE' matches list ['platform', 'ui', 'wd']"
        else
            ocf_log INFO "Service '$OCF_RESKEY_SERVICE' does NOT match list ['platform', 'ui', 'wd']"
            rc="$OCF_ERR_CONFIGURED"
        fi
    fi
    return "$rc"
}

function mz_validate()
{
    local rc="$OCF_SUCCESS"
    # shellcheck disable=SC2119
    mz_check_params; rc="$?"
    return "$rc"
}

function mz_start()
{
    local rc="$OCF_SUCCESS"
    mz_call --timeout=60 --action=startup --component="$mz_component" --user="$mz_user"; rc="$?"
    # DONE: map to cluster return code (OCF_*)
    return "$rc"
}

function mz_stop()
{
    local rc="$OCF_SUCCESS"
    # DONE: retry
    mz_call --timeout=60 --action=shutdown --component="$mz_component" --user="$mz_user"; rc="$?"
    # DONE: map to cluster return code (OCF_*)
    return "$rc"
}

function mz_reload()
{
    local rc="$OCF_SUCCESS"
    return "$rc"
}

function mz_monitor()
{
    local rc="$OCF_SUCCESS"
    # DONE: retry
    mz_call --timeout=60 --action=status --component="$mz_component" --user="$mz_user"; rc="$?"
    # DONE: map to cluster return code (OCF_*)
    return "$rc"
}

# function: main - main function to operate
# params:   ACTION
# globals:  OCF_*(r), ra_rc(rw), $0(r)
#
ra_rc="$OCF_SUCCESS"

if [ "$#" != "1" ]
then
    mz_usage
    exit "$OCF_ERR_ARGS"
fi

ACTION="$1"
if [ "$ACTION" = "status" ]; then
    ACTION=monitor
fi

# These operations don't require OCF parameters to be set
ocf_log INFO "begin action $ACTION"
case "$ACTION" in
    usage)          mz_usage
                    ocf_log INFO "end action $ACTION rc=${ra_rc}"
                    exit "$OCF_SUCCESS";;
    methods)        mz_methods
                    ocf_log INFO "end action $ACTION rc=${ra_rc}"
                    exit "$OCF_SUCCESS";;
    meta-data)      mz_meta_data
                    ocf_log INFO "end action $ACTION rc=${ra_rc}"
                    exit "$OCF_SUCCESS";;
    notify)         # just ignore
                    ocf_log INFO "end action $ACTION rc=${ra_rc}"
                    exit "$OCF_SUCCESS";;
    validate-all)
        mz_init
        mz_validate; ra_rc="$?"
        ocf_log INFO "end action $ACTION rc=${ra_rc}"
        exit "$ra_rc"
        ;;
esac
mz_init

# check for root user
if ! ocf_is_root
then
    ocf_log err "ACT: $0 must be run as root"
    exit "$OCF_ERR_PERM"
fi

# TODO PRIO2: Maybe add 'light' parameter check later e.g. not checking availability of files and directory but checking for parameter syntax
ra_rc="$OCF_ERR_UNIMPLEMENTED"
case "$ACTION" in
    start)
        mz_check_params
        mz_start;
        ra_rc="$?"
        ;;
    stop)
        mz_stop; ra_rc="$?";;
    monitor)
        mz_monitor; ra_rc="$?";;
    promote)
        mz_promote; ra_rc="$?";;
    demote)
        mz_demote; ra_rc="$?";;
    reload)
        mz_reload
        ra_rc="$OCF_SUCCESS";;
    validate)
        mz_validate
        ra_rc="$OCF_SUCCESS";;
    *)  # seems to be an unknown request
        "${raType}"methods
        ra_rc="$OCF_ERR_UNIMPLEMENTED"
        ;;
esac
ocf_log INFO "end action $ACTION rc=${ra_rc} (${SECONDS}s)"
exit "${ra_rc}"
# set ts=4 sw=4 sts=4 et
