#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG
#  This is an automatically generated prolog.
#
#  Copyright (C) Altran ACT S.A.S. 2017,2019,2021,2022.  All rights reserved.
#
#  ALTRAN_PROLOG_END_TAG
#
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r721 src/43haes/usr/sbin/cluster/events/utils/clcommonroha.sh 1.8 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2015,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 
###############################################################################
# @(#)  5881272 43haes/usr/sbin/cluster/events/utils/clcommonroha.sh, 61aha_r726, 2205A_aha726, May 16 2022 12:15 PM
###############################################################################

#########################################################################
#
#   COMPONENT_NAME: hacmp.events
#
#   FUNCTIONS:
#
#       usage
#       min
#       max
#
#########################################################################

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

export PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)"
export FPATH="$FPATH:/usr/es/sbin/cluster/events/utils2"
eval export $(cllsparam -x)
. /usr/es/sbin/cluster/events/utils/clsessionroha
. /usr/es/sbin/cluster/events/utils/clqueryroha
. /usr/es/sbin/cluster/events/utils/clcomputeroha
. /usr/es/sbin/cluster/events/utils/clidentifyroha
. /usr/es/sbin/cluster/events/utils/clapplyroha

#=======================================================
# Verbose logging is ignored here - no need to trace initiliazations
#=======================================================
# tunables
typeset -i ROHA_RELEASE_CPU_BEFORE_MEM=0
typeset TUNABLE_ROHA_SKIP_NODE=""

#=======================================================
# Dspmsg codes
#=======================================================
export ROHA_SET=38
export ROHA_MSGS="scripts.cat"
export ROHA_TAG="ROHALOG"

#=======================================================
# Global variables
#=======================================================
export LOCALNODENAME=${LOCALNODENAME:-$(get_local_nodename)}
export VERBOSE_LOGGING=${VERBOSE_LOGGING:-}

export CLODMGET_CMD=${CLODMGET_CMD:-clodmget}
export CLRGINFO_CMD=${CLRGINFO_CMD:-eval LC_ALL=C clRGinfo}
export CLLSSERV_CMD=${CLLSSERV_CMD:-cllsserv}
export CLRMUPDATE_CMD=${CLRMUPDATE_CMD:-cl_RMupdate}

#=======================================================
# Return codes
#=======================================================
typeset -ri RC_SUCCESS=0
typeset -ri RC_FAILURE=1
typeset -ri RC_PARAM_ERROR=1

# Query error codes
typeset -ri RC_QUERY_ERROR=2

# Compute error codes (range 10-14)
typeset -ri RC_COMPUTE_MEM_ERROR_LPAR_MAX=10
typeset -ri RC_COMPUTE_CPU_ERROR_LPAR_CPU_MAX=11
typeset -ri RC_COMPUTE_CPU_ERROR_LPAR_PU_MAX=11
typeset -ri RC_COMPUTE_CPU_ERROR_LPAR_VP_MAX=12
typeset -ri RC_COMPUTE_CPU_ERROR_SPP_SIZE=13
typeset -ri RC_COMPUTE_CPU_ERROR_RATIO=14

# Identify error codes (range 30-32)
typeset -ri RC_IDENTIFY_ERROR=30
typeset -ri RC_IDENTIFY_MEM_ERROR_RESOURCES=1
typeset -ri RC_IDENTIFY_CPU_ERROR_RESOURCES=2

# Apply error codes (mixed with clhmccmd)
# Example: A managed system busy error during an Enterprise
# Pool CoD operation will lead to error code 55 (50 + 5).
# Please ensure consistency with clhmccmd error codes.
typeset -ri RC_APPLY_DLPAR_ERROR=40
typeset -ri RC_APPLY_DLPAR_ERROR_PARAMETER=41
typeset -ri RC_APPLY_DLPAR_ERROR_PING=42
typeset -ri RC_APPLY_DLPAR_ERROR_SSH=43
typeset -ri RC_APPLY_DLPAR_ERROR_RES_BUSY=44
typeset -ri RC_APPLY_DLPAR_ERROR_CEC_BUSY=45
typeset -ri RC_APPLY_DLPAR_ERROR_NOT_ENOUGH=46
typeset -ri RC_APPLY_DLPAR_ERROR_OTHER=47
typeset -ri RC_APPLY_EPCOD_ERROR=50
typeset -ri RC_APPLY_EPCOD_ERROR_PARAMETER=51
typeset -ri RC_APPLY_EPCOD_ERROR_PING=52
typeset -ri RC_APPLY_EPCOD_ERROR_SSH=53
typeset -ri RC_APPLY_EPCOD_ERROR_RES_BUSY=54
typeset -ri RC_APPLY_EPCOD_ERROR_CEC_BUSY=55
typeset -ri RC_APPLY_EPCOD_ERROR_NOT_ENOUGH=56
typeset -ri RC_APPLY_EPCOD_ERROR_OTHER=57
typeset -ri RC_APPLY_ONOFF_ERROR=60
typeset -ri RC_APPLY_ONOFF_ERROR_PARAMETER=61
typeset -ri RC_APPLY_ONOFF_ERROR_PING=62
typeset -ri RC_APPLY_ONOFF_ERROR_SSH=63
typeset -ri RC_APPLY_ONOFF_ERROR_RES_BUSY=64
typeset -ri RC_APPLY_ONOFF_ERROR_CEC_BUSY=65
typeset -ri RC_APPLY_ONOFF_ERROR_NOT_ENOUGH=66
typeset -ri RC_APPLY_ONOFF_ERROR_OTHER=67

#=============================================================================
#
# Name:        usage
#
# Description: None
#
# Inputs:      None
#
# Outputs:     None
#
# Returns:     None
#
#=============================================================================
function usage
{
    print -u1 -- 'Usage: clmanageroha -o <acquire|release> -l list_of_apps [-c] [-s]'
    print -u1 -- '  -o <acquire|release> : '
    print -u1 -- '        -o acquire to perform an acquisition of resources for a list of '
    print -u1 -- '          application controllers.'
    print -u1 -- '        -o release to perform a release of resources for a list of '
    print -u1 -- '          application controllers.'
    print -u1 -- '  -l <list_of_apps> : list of application controllers to be taken into '
    print -u1 -- '         account at acquisition time, or at release time. '
    print -u1 -- '        At acquisition time (-o acquire), this list contains application '
    print -u1 -- '         controllers for which acquisition is to be done. '
    print -u1 -- '        At release time (-o release), this list contains application '
    print -u1 -- '         controllers for which release is to be done. '
    print -u1 -- '  -c    "compute only" mode : in this mode, the acquisition of resources '
    print -u1 -- '         or the release of resources is simulated, but not done.'
    print -u1 -- '        In this mode, the clmanageroha command performs "query", "compute", '
    print -u1 -- '         "identify" steps, but not the "apply" step. '
    print -u1 -- '  -s    "PowerHA SystemMirror" mode : in this mode, the clmanageroha command '
    print -u1 -- '         works by reporting status to PowerHA SystemMirror cluster manager. '
    print -u1 -- '        This is the mode when clmanageroha is automatically called by '
    print -u1 -- '         PowerHA SystemMirror. '
    print -u1 -- '        Without "-s" parameter, clmanageroha runs in isolation mode.'
    print -u1 -- '        Isolation mode is the default mode when the clmanageroha script is '
    print -u1 -- '         manually run, without "-s" option. '
    print -u1 -- '        In isolation mode, the clmanageroha command works without reporting '
    print -u1 -- '         status to cluster manager. Therefore, the acquisition of resources '
    print -u1 -- '         (if -o acquire) or the release of resources (if -o release) are done,'
    print -u1 -- '         but status are not changed.'
    print -u1 -- '        The "isolation" mode has no effect in "compute only" mode.'
} # End of "usage()"


#=============================================================================
#
# NAME common_hmc_cmd
#
# Function : Checks the connection type of the node from the odm
#            If the conncetion type is set to SSH then it returns "clhmccmd"
#            If the conncetion type is set to REST API then it returns "clrest"
#
# RETURNS : clhmccmd
#           clrest
#
#=============================================================================
function common_hmc_cmd {
    #Get the HMC connection type from ODM (0=ssh, 1=rest)
    typeset -i CONN_TYPE=$($CLODMGET_CMD -n -f connection_type HACMPhmcparam)

    if [[ -n $($CLODMGET_CMD -q "name=$LOCALNODENAME and object like POWERVS_*" -nf name HACMPnode 2>/dev/null) ]]; then
        CONN_TYPE=2
    fi
    export CONN_TYPE

    if (( $CONN_TYPE == 2 )); then
        print "eval LC_ALL=C clcloudroha"
    elif (( $CONN_TYPE == 1 )); then
        print "eval LC_ALL=C clrest"
    else
        print "eval LC_ALL=C clhmccmd"
    fi
}

export CLHMCCMD_CMD=${CLHMCCMD_CMD:-$(common_hmc_cmd)}


#=============================================================================
#
# Name:        min
#
# Description: Compare two values.
#
# Inputs:      param1 - first parameter to compare
#              param2 - second parameter to compare
#
# Outputs:     None
#
# Returns:     None
#
#=============================================================================
function min
{
    print -- $(( $1 > $2 ? $2 : $1 ))
} # End of "min()"

#=============================================================================
# Name:        read_tunables
# Description: to read tunable variables stored into /etc/environment
#   under the form key=value
#
# Description of TUNABLE_ROHA_SKIP_NODE tunable
#    This tunable decides whether to skip resource acquisition/release
#       for the specified cluster nodes
#
#    By default this new tunable is not set.
#    If it is not set then the resources acquisition/release
#       operation will be performed on every cluster node
#
#    If it is set then the resources acquisition/release will
#       be skipped for the specified cluster nodes
#
# Description of ROHA_RELEASE_CPU_BEFORE_MEM tunable
#    This tunable decides the order of releasing the CPU or Memory resources
#
#    By default this new tunable is not set.
#      If it is not set order of releasing the resources is
#                 memory followed by cpu
#      If it is set order of releasing the resources is
#                 cpu followed by memory
# Inputs:      None
# Outputs:     Environment variables are set to value retrieved
#          from /etc/environment
# Returns:     None
#=============================================================================
function read_tunables
{
    typeset environment_file="/etc/environment"
    typeset skip=""
    typeset roha_release_cpu_before_mem=""
    typeset roha_skip_nodes=""
    typeset tunable_roha_skip_nodes=""
    typeset wrong_nodes=""
    TUNABLE_ROHA_SKIP_NODE=""
    typeset cluster_nodes=""
    
    # For ROHA on Cloud feature
    export http_proxy=$(grep -w http_proxy $environment_file |cut -d"=" -f2)
    export https_proxy=$(grep -w https_proxy $environment_file |cut -d"=" -f2)

    grep -w "^ROHA_RELEASE_CPU_BEFORE_MEM" $environment_file | IFS='=' read skip roha_release_cpu_before_mem
    if [[ -n $roha_release_cpu_before_mem ]] && [[ $roha_release_cpu_before_mem == @(1|y|t|Y|T|e|E)* ]]
    then
        ROHA_RELEASE_CPU_BEFORE_MEM=1
    else
        ROHA_RELEASE_CPU_BEFORE_MEM=0
    fi
    export ROHA_RELEASE_CPU_BEFORE_MEM
    
    grep -w "^TUNABLE_ROHA_SKIP_NODE" $environment_file | IFS='=' read skip roha_skip_nodes
    roha_skip_nodes=${roha_skip_nodes//\"/}   #remove trialing/leading quotes if exist
    if [[ -n $roha_skip_nodes ]]
    then
        cluster_nodes=$(clnodename|tr '\n' ' ')    #Get the list of cluster nodes
        for node in ${roha_skip_nodes//,/ }
        do
            echo "$cluster_nodes" | grep -wq $node
            if (( $? != 0 )); then
                wrong_nodes="${wrong_nodes:+$wrong_nodes,}$node"
            else
                tunable_roha_skip_nodes="${tunable_roha_skip_nodes:+$tunable_roha_skip_nodes,}$node"
            fi
        done
        if [[ -n $wrong_nodes ]]; then
            cl_dspmsg -s 41 scripts.cat 89 "\nWARNING: The following specified nodes in /etc/environment for TUNABLE_ROHA_SKIP_NODE variable are not part of the cluster: %1\$s" $wrong_nodes
        fi
        if [[ -n $tunable_roha_skip_nodes ]]; then
            TUNABLE_ROHA_SKIP_NODE=$tunable_roha_skip_nodes
        fi
    fi
    export TUNABLE_ROHA_SKIP_NODE

} # End of "read_tunables()"


#=============================================================================
#
# Name:        max
#
# Description: Compare two values.
#
# Inputs:      param1 - first parameter to compare
#              param2 - second parameter to compare
#
# Outputs:     None
#
# Returns:     None
#
#=============================================================================
function max
{
    print -- $(( $1 < $2 ? $2 : $1 ))
} # End of "max()"
