#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2017,2018,2019,2020,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r721 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_add_appmonitor.sh 1.14.1.1 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2006,2016 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_add_appmonitor.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM

#================================================
# The following, commented line enforces coding
# standards when this file is edited via vim.
#================================================
# vim:tabstop=4:shiftwidth=4:expandtab:smarttab
#================================================

# Start of POD-formatted documentation. Viewing suggestions:
#      perldoc <FILENAME>
#      pod2text -c <FILENAME>
#      pod2text -c --code <FILENAME>
#      pod2html <FILENAME>
function devDoc {
    : <<'=cut' >/dev/null 2>&1

=head1 NAME

 KLIB_HACMP_add_appmonitor

=head1 VERSION

 Version Number:  1.14.1.1
 Last Extracted:  7/28/16 19:30:36
 Last Changed:    7/27/16 05:18:05

 Path, Component, Release(, Level):
 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_add_appmonitor.sh, hacmp.assist, 61haes_r721, 1630B_hacmp721

=head1 SYNOPSIS

 clmgr add application_monitor <monitor> \
             TYPE=Process \
             MODE={longrunning|startup|both} \
             PROCESSES="pmon1,dbmon,..."  \
             OWNER="<processes_owner_name>" \
             [ APPLICATIONS=<appctlr#1>[,<appctlr#2>,<appctlr#n>,...] ] \
             [ STABILIZATION="1 .. 3600" ] \
             [ RESTARTCOUNT="0 .. 100" ] \
             [ FAILUREACTION={notify|fallover} ] \
             [ INSTANCECOUNT="1 .. 1024" ] \
             [ RESTARTINTERVAL="1 .. 3600" ] \
             [ NOTIFYMETHOD="</script/to/notify>" ] \
             [ CLEANUPMETHOD="</script/to/cleanup>" ] \
             [ RESTARTMETHOD="</script/to/restart>" ]

 clmgr add application_monitor <monitor> \
             TYPE=Custom \
             MODE={longrunning|startup|both} \
             MONITORMETHOD="/script/to/monitor" \
             [ APPLICATIONS=<appctlr#1>[,<appctlr#2>,<appctlr#n>,...] ] \
             [ STABILIZATION="1 .. 3600" ] \
             [ RESTARTCOUNT="0 .. 100" ] \
             [ FAILUREACTION={notify|fallover} ] \
             [ MONITORINTERVAL="1 .. 1024" ] \
             [ HUNGSIGNAL="1 .. 63" ] \
             [ RESTARTINTERVAL="1 .. 3600"  ] \
             [ NOTIFYMETHOD="</script/to/notify>" ] \
             [ CLEANUPMETHOD="</script/to/cleanup>" ] \
             [ RESTARTMETHOD="</script/to/restart>" ] \
             [ MONITORRETRYCOUNT="0 .. 10" ] \
             [ AMLOGGING={yes|no} ]

 NOTE: "STABILIZATION" defaults to 180
 NOTE: "RESTARTCOUNT" defaults to 3
 NOTE: "MONITORRETRYCOUNT" defaults to 0
 NOTE: "AMLOGGING" defaults to "N"
 NOTE: "appctlr" is an abbreviation for "application_controller".

 NOTE: the aliases for "application_monitor" are "am" and "mon".

=head1 DESCRIPTION

Attempts to add an application monitor that conforms to the
provided specifications.

=head1 ARGUMENTS

 1. properties [REQUIRED] [hash ref]
    An associative array within which data about the
    created object can be returned to the caller.

 2. monname [REQUIRED] [string]
    The label to apply to the new monitor.

 3. p [REQUIRED] [hash ref]
    An associative array within which configuration details
    for the new object are passed in to this function.

=head1 RETURN

 0: no errors were detected; the operation appears to have been successful
 1: a general error has occurred
 2: a specified resource does not exist, or could not be found
 3: some required input was missing
 4: some detected input was incorrect in some way
 5: a required dependency does not exist
 6: a specified search failed to match any data

=head1 COPYRIGHT

COPYRIGHT International Business Machines Corp. 2005,2010
All Rights Reserved

=cut
} # End of POD-formatted documentation.


#============================================================================
#
# Name:        KLIB_HACMP_add_appmonitor
#
# Description: This is the main, FPATH function that is invoked by clmgr
#              to add an application monitor to the cluster configuration.
#
# Inputs:      See the "devDoc()" function, above.
#
# Outputs:     The properties hash is populated. The only other outputs are
#              any error messages that might be needed.
#
# Returns:     Zero if no errors are detected. Otherwise, an appropriate
#              non-zero value is returned. Refer to the "RETURN" section
#              of the "devDoc()" function, above, for the standard return
#              code values/meanings for clmgr.
#
#============================================================================
function KLIB_HACMP_add_appmonitor {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_add_appmonitor.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
    : INPUTS: $*

    typeset -n properties=$1
    typeset monname=${2//\"/}
    shift; shift

    typeset -n p=$1

    [[ $CLMGR_LOGGING == 'med' ]] && set +x  # Only trace param values

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -A args monitormethod
    typeset -l monitorType=${p[TYPE]}
    typeset -i rc=$RC_UNKNOWN
    typeset -i i=0

    typeset existing
    CL=$LINENO KLIB_HACMP_list_appmonitors existing 2>>$CLMGR_TMPLOG

    typeset -l monitorMode="${p[MODE]}"
    case $monitorMode in
        s*) monitorMode="startup"     ;;
        b*) monitorMode="both"        ;;
         *) monitorMode="longrunning" ;;
    esac

    #================================================================
    : Check for a defined cluster. No need to continue without one.
    #================================================================
    CL=$LINENO isClusterDefined
    if (( $? != RC_SUCCESS )); then
        rc=$RC_MISSING_DEPENDENCY

    #=================
    : Validate input
    #=================
    elif [[ -z $monname ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT

    elif [[ " ${existing[*]} " == *\ $monname\ * ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 229 "\nERROR: the specified object already exists: \"%1\$s\"\n\n" "$monname" 1>&2
        rc=$RC_INCORRECT_INPUT

    elif [[ -n $monname && -n "${monname//[a-zA-Z0-9_]/}" ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 105 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid characters include letters, numbers, and underscores only.\n\n" "$monname" "${monname//[a-zA-Z0-9_]/}" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    typeset app=""
    typeset rg_name=""
    typeset -i appmon_per_app_count=0
    typeset -i appmon_count=0
    typeset all_apps_in_rg=""
    typeset app_in_rg=""
    typeset -i BAD_APPS=0
    for app in ${p[APPLICATIONS]//,/ }; do
        CL=$LINENO KLIB_HACMP_is_known_appserver $app
        if (( $? != RC_SUCCESS )); then
            BAD_APPS=1
            cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 '\nERROR: "%1$s" does not appear to exist!\n\n' "$app" 1>&2
        else
            rg_name=$(clodmget -q "name = APPLICATIONS and value = $app" -f group HACMPresource)
            if [[ -n $rg_name ]]; then
                appmon_count=0
                all_apps_in_rg=$(clodmget -q "name=APPLICATIONS AND group=$rg_name" -f value HACMPresource)
                for app_in_rg in $all_apps_in_rg; do
                    appmon_per_app_count=0
                    appmon_per_app_count=$(clodmget -q "name = RESOURCE_TO_MONITOR AND value = $app_in_rg" -f monitor HACMPmonitor | wc -l)
                    (( appmon_count += appmon_per_app_count ))
                done
                #===========================================================================
                : This check is added to stop the user if he adds more than specified limit
                : for application monitors in a resource group. The same code is used in
                : KLIB_HACMP_modify_appmonitor.sh. Any modifications here should also be
                : replicated in KLIB_HACMP_modify_appmonitor.sh.
                #===========================================================================
                if (( $appmon_count >= $MAX_USER_RESOURCES )); then
                    cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1449 "\nERROR: Cannot add more than %1\$d application monitors in a resource group.\n\
Application controller %2\$s is a part of resource group %3\$s and\n\
this resource group %3\$s already contains %1\$d application monitors.\n\n" "$MAX_USER_RESOURCES" "$app" "$rg_name"
                    rc=$RC_INCORRECT_INPUT 
                fi
            fi
        fi
    done
    if (( BAD_APPS )); then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 140 "Available Application Controllers:\n\n" 1>&2

        typeset available
        CL=$LINENO KLIB_HACMP_list_appservers available
        for (( i=0; i<${#available[*]}; i++ )); do
            if [[ ${available[$i]} != *([[:space:]]) ]]; then
                print -u2 "\t${available[$i]}"
            fi
        done
        print -u2 ""

        rc=$RC_MISSING_INPUT
    fi

    if [[ -z $monitorType ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 101 "\nERROR: this operation requires the \"%1\$s\" attribute.\n\n" TYPE 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "Process, Custom" 1>&2
        rc=$RC_MISSING_INPUT
    fi

    if [[ -n $monitorType && $monitorType != @(p|c|u)* ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" TYPE "$monitorType" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "Process, Custom" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[RESTARTCOUNT]} && \
         ${p[RESTARTCOUNT]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: \"%1\$s\" requires a positive, integer value.\n\n" RESTARTCOUNT 1>&2
        rc=$RC_INCORRECT_INPUT
    elif [[ -z ${p[RESTARTCOUNT]} ]]; then
        p[RESTARTCOUNT]=3
    fi

    if [[ -n ${p[MONITORMETHOD]} && ${p[MONITORMETHOD]} != /* ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 "\nERROR: the specified path does not appear to be in absolute format:\n%1\$s\n\n" "${p[MONITORMETHOD]}")
        MSG="$MSG (MONITORMETHOD @ $LOCAL_NODE)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[MONITORMETHOD]} && ! -e ${p[MONITORMETHOD]%% *} ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2$s": %1$s\n\n' "${p[MONITORMETHOD]}" "$LOCAL_NODE")
        MSG="$MSG (MONITORMETHOD)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_NOT_FOUND
    fi

    if [[ -n ${p[NOTIFYMETHOD]} && ${p[NOTIFYMETHOD]} != /* ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 "\nERROR: the specified path does not appear to be in absolute format:\n%1\$s\n\n" "${p[NOTIFYMETHOD]}")
        MSG="$MSG (NOTIFYMETHOD @ $LOCAL_NODE)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[NOTIFYMETHOD]} && ! -e ${p[NOTIFYMETHOD]%% *} ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2$s": %1$s\n\n' "${p[NOTIFYMETHOD]}" "$LOCAL_NODE")
        MSG="$MSG (NOTIFYMETHOD)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_NOT_FOUND
    fi

    if [[ -n ${p[CLEANUPMETHOD]} && ${p[CLEANUPMETHOD]} != /* ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 "\nERROR: the specified path does not appear to be in absolute format:\n%1\$s\n\n" "${p[CLEANUPMETHOD]}")
        MSG="$MSG (CLEANUPMETHOD @ $LOCAL_NODE)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[CLEANUPMETHOD]} && ! -e ${p[CLEANUPMETHOD]%% *} ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2$s": %1$s\n\n' "${p[CLEANUPMETHOD]}" "$LOCAL_NODE")
        MSG="$MSG (CLEANUPMETHOD)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_NOT_FOUND
    fi

    if [[ -n ${p[RESTARTMETHOD]} && ${p[RESTARTMETHOD]} != /* ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 106 "\nERROR: the specified path does not appear to be in absolute format:\n%1\$s\n\n" "${p[RESTARTMETHOD]}")
        MSG="$MSG (RESTARTMETHOD @ $LOCAL_NODE)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[RESTARTMETHOD]} && ! -e ${p[RESTARTMETHOD]%% *} ]]; then
        MSG=$(/usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 107 '\nERROR: the specified path/file does not appear to exist on "%2$s": %1$s\n\n' "${p[RESTARTMETHOD]}" "$LOCAL_NODE")
        MSG="$MSG (RESTARTMETHOD)"
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS -1 "${MSG//+([[:space:]])/ }" 1>&2
        rc=$RC_NOT_FOUND
    fi

    if [[ -z $monitorMode ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 101 "\nERROR: this operation requires the \"%1\$s\" attribute.\n\n" MODE 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "Continuous, Startup, Both" 1>&2
        rc=$RC_MISSING_INPUT

    elif [[ -n $monitorMode && \
            $monitorMode != @(longrunning|startup|both) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" MODE "$monitorMode" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "Continuous, Startup, Both" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[STABILIZATION]} && \
          ${p[STABILIZATION]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" STABILIZATION 1>&2
        rc=$RC_INCORRECT_INPUT
    elif [[ -n ${p[STABILIZATION]} ]] && (( ${p[STABILIZATION]} > 3600 )); then
         dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" STABILIZATION "${p[STABILIZATION]}" 1>&2
         dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "1 .. 3600" 1>&2
         rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[RESTART_COUNT]} && \
          ${p[RESTART_COUNT]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" RESTART_COUNT 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[MONITORINTERVAL]} && \
          ${p[MONITORINTERVAL]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" MONITORINTERVAL 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n ${p[HUNGSIGNAL]} && \
          ${p[HUNGSIGNAL]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" HUNGSIGNAL 1>&2
        rc=$RC_INCORRECT_INPUT
    elif [[ -n ${p[HUNGSIGNAL]} ]] && (( ${p[HUNGSIGNAL]} > 63 )); then
         dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" HUNGSIGNAL "${p[HUNGSIGNAL]}" 1>&2
         dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "1 .. 63" 1>&2
         rc=$RC_INCORRECT_INPUT
    fi
 
    if [[ -n ${p[RESTARTINTERVAL]} && \
          ${p[RESTARTINTERVAL]} != +([[:digit:]]) ]]
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" RESTARTINTERVAL 1>&2
        rc=$RC_INCORRECT_INPUT
    fi
    
    if [[ -n ${p[MONITORRETRYCOUNT]} && \
          ${p[MONITORRETRYCOUNT]} != +([[:digit:]]) ]]
    then
        dspmsg -s $CLMGR_SET $CLMGR_MSGS 111 "\nERROR: the \"%1\$s\" option requires a positive, integer value.\n\n" MONITORRETRYCOUNT 1>&2
        rc=$RC_INCORRECT_INPUT
    
    elif [[ -z ${p[MONITORRETRYCOUNT]} ]]; then
        p[MONITORRETRYCOUNT]=0
    elif [[ -n ${p[MONITORRETRYCOUNT]} ]] && (( ${p[MONITORRETRYCOUNT]} > 10 ));then
        dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" MONITORRETRYCOUNT "${p[MONITORRETRYCOUNT]}" 1>&2
        dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "0 .. 10" 1>&2
        rc=$RC_INCORRECT_INPUT

    fi

    if [[ -n ${p[AMLOGGING]} ]]
    then
        CL=$LINENO verify_in_set AMLOGGING "${p[AMLOGGING]}" "yes true enable 1 no false disable 0" result
        if (( $? == RC_SUCCESS )); then
            if [[ $result == @(y|t|e|1)* ]]; then
                p[AMLOGGING]="Y"
            else
                p[AMLOGGING]="N"
            fi
         else
             rc=$RC_INCORRECT_INPUT
         fi
    elif [[ -z ${p[AMLOGGING]} ]]; then
        p[AMLOGGING]=N
    fi
    
    #=======================================================================
    : Create the application monitor if no input errors have been detected
    #=======================================================================
    if (( $rc == RC_UNKNOWN )); then
        #===================================
        : Establish defaults, if necessary
        #===================================
        if [[ ${p[FAILUREACTION]} == *([[:space:]]) ]]; then
            p[FAILUREACTION]=notify
        fi
        if [[ ${p[STABILIZATION]} != +([[:digit:]]) ]]; then
            p[STABILIZATION]=180
        fi
        if [[ ${p[RESTART_COUNT]} != +([[:digit:]]) ]]; then
            p[RESTART_COUNT]=3
        fi
        if [[ ${p[MONITORRETRYCOUNT]} != +([[:digit:]]) ]]; then
            p[MONITORRETRYCOUNT]=0
        fi
        if [[ ${p[CLEANUPMETHOD]} == *([[:space:]]) ]]; then
            if [[ -n ${p[APPLICATIONS]} ]]
            then
                typeset stop_script=""
                print "$0()[$LINENO]($SECONDS): clodmget -q \"name=${p[APPLICATIONS]}\" -n -f stop HACMPserver">>$CLMGR_TMPLOG  # Always log commands
                stop_script=$(clodmget -q "name = ${p[APPLICATIONS]}" -n -f stop HACMPserver 2>>$CLMGR_TMPLOG)
                print "$0()[$LINENO]($SECONDS): clodmget RC: $?; stop_script == \"$stop_script\"" >>$CLMGR_TMPLOG  # Always log command result
                if [[ -n $stop_script ]]
                then
                    cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 99 '\nWarning: No cleanup method was specified for Application monitor "%1$s". The stop script "%2$s"\nfrom application server "%3$s" will be used as the cleanup method.\n' "$monname" "$stop_script" "${p[APPLICATIONS]}"
                    p[CLEANUPMETHOD]=$stop_script
                fi
            fi
        fi

        #===================================================
        : Begin constructing an appropriate command string
        #===================================================
        typeset cmd="$HAUTILS/claddappmon
                              name=$monname
                              RESOURCE_TO_MONITOR=\"${p[APPLICATIONS]//,/ }\"
                              INVOCATION=$monitorMode
                              FAILURE_ACTION=${p[FAILUREACTION]}
                              STABILIZATION_INTERVAL=${p[STABILIZATION]}
                              RESTART_COUNT=${p[RESTARTCOUNT]}"

        #===================================================================
        : Add the command parameters that are specific to process monitors
        #===================================================================
        typeset -i missing_args=0
        if [[ $monitorType == p* ]]; then

            cmd="$cmd MONITOR_TYPE=process"

            #==================================================================
            : Check for required arguments that have not already been checked
            #==================================================================
            requiredArgs="PROCESSES
                          OWNER
                          STABILIZATION
                          RESTARTCOUNT
                          FAILUREACTION"
            for arg in $requiredArgs; do
                if [[ -z ${p[$arg]} ]]; then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 200 "\nERROR: missing required argument:  %1\$s\n" "$arg" 1>&2
                    (( missing_args++ ))
                fi
            done

            cmd="$cmd PROCESS_OWNER=${p[OWNER]}"
            cmd="$cmd PROCESSES=\"${p[PROCESSES]//,/ }\""

            if [[ -n ${p[INSTANCECOUNT]} ]]; then
                cmd="$cmd INSTANCE_COUNT=${p[INSTANCECOUNT]}"
            fi
            if [[ -n ${p[INSTANCECOUNT]} ]] && (( ${p[INSTANCECOUNT]} > 1024 )); then
              dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" INSTANCECOUNT "${p[INSTANCECOUNT]}" 1>&2
              dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "1 .. 1024" 1>&2
              rc=$RC_INCORRECT_INPUT
            fi

        #==================================================================
        : Add the command parameters that are specific to custom monitors
        #==================================================================
        elif [[ $monitorType == @(c|u)* ]]; then

            cmd="$cmd MONITOR_TYPE=user"

            #=============================================================
            : Check for the arguments that have not already been checked
            #=============================================================
            requiredArgs="MONITORMETHOD
                          STABILIZATION
                          RESTARTCOUNT
                          FAILUREACTION"
            typeset -i missing=0
            for arg in $requiredArgs; do
                if [[ -z ${p[$arg]} ]]; then
                    /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 200 "\nERROR: missing required argument:  %1\$s\n" "$arg" 1>&2
                    (( missing_args++ ))
                fi
            done

            cmd="$cmd MONITOR_METHOD=\"${p[MONITORMETHOD]}\""

            if [[ -n ${p[MONITORINTERVAL]} ]]; then
                cmd="$cmd MONITOR_INTERVAL=${p[MONITORINTERVAL]}"
            fi
            if [[ -n ${p[HUNGSIGNAL]} ]]; then
                cmd="$cmd HUNG_MONITOR_SIGNAL=${p[HUNGSIGNAL]}"
            fi
            if [[ -n ${p[AMLOGGING]} ]]; then
                cmd="$cmd AM_LOGGING=${p[AMLOGGING]}"
            fi
            if [[  -n $monitorMode && $monitorMode == @(longrunning|both) ]]; then

                if [[ -n ${p[MONITORRETRYCOUNT]} ]]; then
                    cmd="$cmd MONITOR_RETRY_COUNT=${p[MONITORRETRYCOUNT]}"
                fi
            else 
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 1167 "\nWARNING: Monitor Retry Count cannot be tuned \
when Monitor Mode is StartUp. Hence Setting it to Default value 0.\n" 1>&2
                if [[ -n ${p[MONITORRETRYCOUNT]} ]]; then
                    cmd="$cmd MONITOR_RETRY_COUNT=0"
                fi
              
            fi  
        fi

        if (( missing_args )); then
            print -u2
            rc=$RC_MISSING_INPUT

        else
            #=========================================
            : Add any specified, optional parameters
            #=========================================
            if [[ -n ${p[RESTARTINTERVAL]} ]]; then
                cmd="$cmd RESTART_INTERVAL=${p[RESTARTINTERVAL]}"
            fi
            if [[ -n ${p[NOTIFYMETHOD]} ]]; then
                cmd="$cmd NOTIFY_METHOD=\"${p[NOTIFYMETHOD]}\""
            fi
            if [[ -n ${p[CLEANUPMETHOD]} ]]; then
                cmd="$cmd CLEANUP_METHOD=\"${p[CLEANUPMETHOD]}\""
            fi
            if [[ -n ${p[RESTARTMETHOD]} ]]; then
                cmd="$cmd RESTART_METHOD=\"${p[RESTARTMETHOD]}\""
            fi

            #================================================================
            : Execute the add monitor command. Check for execution symbols,
            : since we are using an eval. Improves our security posture.
            #================================================================
            if [[ $cmd != *@(\`|\$)* ]]; then
                print -- "$0()[$LINENO]($SECONDS): $cmd" >>$CLMGR_TMPLOG  # Always log commands
                eval $cmd
                rc=$?
                print -- "$(basename ${cmd%% *}) RC: $rc" >>$CLMGR_TMPLOG  # Always log command result
            else
                rc=$RC_ERROR
            fi

            if (( $rc != RC_SUCCESS )); then
                rc=$RC_ERROR
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 201 "\nERROR: failed to create \"%1\$s\".\n\n" "$monname" 1>&2
            fi

            #===========================================================
            : If output from this operation was requested, retrieve it
            #===========================================================
            if (( $rc == RC_SUCCESS )); then
                if (( CLMGR_VERBOSE )) || [[ -n $CLMGR_ATTRS ]]; then
                    CL=$LINENO KLIB_HACMP_get_appmonitor_attributes "$monname" properties
                fi
            fi
        fi
    fi

    #=======================================================================
    : If a user input error was detected, provide some helpful suggestions
    #=======================================================================
    if (( $rc == RC_MISSING_INPUT || $rc == RC_INCORRECT_INPUT )) && \
       [[ $CLMGR_GUI == *([[:space:]]) ]]
    then
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 104 "For more information about available options and syntax, try\n\"$HAUTILS/clmgr %1\$s\". As an\nalternative, if the PowerHA SystemMirror man pages have been installed, invoke\n\"$HAUTILS/clmgr -hv\" (or \"/usr/bin/man clmgr\"),\nsearching for \"%2\$s\" in the displayed text.\n\n" \
        "add application_monitor -h" "APPLICATION MONITOR:" "$CLMGR_PROGNAME" 1>&2
    fi

    log_return_msg "$rc" "$0()" "$LINENO"
    return $?
} # End of "KLIB_HACMP_add_appmonitor()"
