#!/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                                                      
#                                                                              
###############################################################################
# @(#)  5881272 43haes/usr/sbin/cluster/events/clmanageroha.sh, 61aha_r726, 2205A_aha726, May 16 2022 12:15 PM
###############################################################################

#########################################################################
#
#   COMPONENT_NAME: hacmp.events
#
#
#########################################################################

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

#=============================================================================
#
# NAME:        clmanageroha
#
# DESCRIPTION: Takes as arguments a list of application controllers on which
#              either acquisition of resources or release of resources is to be
#              performed.
#              A first step is considering the currently running application
#              controllers to determine what are the resources needed by them.
#              A second step is computing the resources needed by the application
#              controllers received as parameters.
#              A third step is considering the available resources on the managed
#              system by type, DLPAR resources, On/Off CoD resources, EPCoD
#              resources. Then, this script must identify how the needs as
#              expressed by the application controllers to be run can be matched
#              on the available resources.
#              The final step consists in performing the necessary allocations
#              or releases on the various types of resources (DLPAR resources,
#              On/Off CoD resources, EPCoD resources) matches the computed level
#              of resources.
#
# ARGUMENTS:
#   -c                     compute only
#   -o <acquire|release|adjust>  acquire or release or adjust of resources
#   -l list_of_apps        list of application controllers to bring on/off-line
#   -s                     PowerHA SystemMirror mode, to run command with reporting
#                          to PowerHA SystemMirror cluster manager.
#
# OUTPUT:
#   none
#
# EXAMPLE:
#   clmanageroha -o acquire -l AC_11,AC_12:AC_21,AC_22:AC_31,AC_32
#
# RETURN VALUE DESCRIPTION:
#   0  - Everything goes fine
#   1  - A wrong parameter has been passed as argument
#   2  - An error occured querying information
#
#   10 - DLPAR needed amount of memory exceeds LPAR maximum
#   11 - DLPAR needed processors or processing units exceeds LPAR maximum
#   12 - DLPAR needed virtual processors exceeds LPAR maximum
#   13 - DLPAR needed processing units exceeds SPP maximum
#   14 - DLPAR needed virtual processor and processing units will break the ratio
#   21 - DLPAR needed memory and processors or processing units exceeds LPAR maximum
#   22 - DLPAR needed memory and virtual processors exceeds LPAR maximum
#   23 - DLPAR needed memory exceeds LPAR maximum and processing units exceeds SPP maximum
#   24 - DLPAR needed memory exceeds LPAR maximum and virtual processor and processing units will break the ratio
#
#   31 - An error occured identifying CoD memory resources to acquire/release
#   32 - An error occured identifying CoD processor resources to acquire/release
#
#   41 - Wrong parameter error occured applying ROHA DLPAR resources
#   42 - Ping error occured applying ROHA DLPAR resources
#   43 - Ssh error occured applying ROHA DLPAR resources
#   44 - Resource busy error occured applying ROHA DLPAR resources
#   45 - Managed system busy error occured applying ROHA DLPAR resources
#   46 - Not enough resources error occured applying ROHA DLPAR resources
#   47 - Other error occured applying ROHA DLPAR resources
#
#   51 - Wrong parameter error occured applying ROHA Enterprise Pool COD resources
#   52 - Ping error occured applying ROHA Enterprise Pool COD resources
#   53 - Ssh error occured applying ROHA Enterprise Pool COD resources
#   54 - Resource busy error occured applying ROHA Enterprise Pool COD resources
#   55 - Managed system busy error occured applying ROHA Enterprise Pool COD resources
#   56 - Not enough resources error occured applying ROHA Enterprise Pool COD resources
#   57 - Other error occured applying ROHA Enterprise Pool COD resources
#
#   61 - Wrong parameter error occured applying ROHA On/Off resources
#   62 - Ping error occured applying ROHA On/Off resources
#   63 - Ssh error occured applying ROHA On/Off resources
#   64 - Resource busy error occured applying ROHA On/Off resources
#   65 - Managed system busy error occured applying ROHA On/Off resources
#   66 - Not enough resources error occured applying ROHA On/Off resources
#   67 - Other error occured applying ROHA On/Off resources
#
#   Questions? Comments? Expressions of Astonishment? mailto:hafeedbk@us.ibm.com
#
#=============================================================================

#=============================================================================
#
# Name:        roha_process_resources
#
# Description: Convenient encapsulation of the resources (cpu and memory)
#   acquisition and release process.
#
# Inputs:      $1 to indicate if we are in last loop of reassessment.
#              If set to 1, we are in last loop of reassessment.
#              If set to 0, we are in normal reassessment.
#
# Outputs:     None
#
# Returns:     RC_SUCCESS
#              or else an error code
#
#=============================================================================
function roha_process_resources
{
    [[ $VERBOSE_LOGGING == high ]] && set -x

    typeset -i LAST_LOOP_OF_FORCE_REASSESSMENT=$1

    #=================================================================
    : LAST_LOOP_OF_FORCE_REASSESSMENT=$LAST_LOOP_OF_FORCE_REASSESSMENT
    #=================================================================

    #=======================================================
    # Query step 1(HMC, LPAR and Applications)
    #=======================================================
    cl_query_roha
    rc=$?
    (( $rc > 0 )) && return $rc

    #=================================================================
    : Reset to 0 all variables used in clcomputeroha
    #=================================================================
    initialize_compute_globals

    #=======================================================
    # Compute step
    #=======================================================
    cl_compute_roha
    rc=$?
    (( $rc > 0 )) && return $rc

    #=======================================================
    # If no needed resources, return on success
    #=======================================================
    roha_compute_check_needed_resources
    (( $? > 0 )) && return $RC_SUCCESS

    #=======================================================
    # Check if any aync release is in progress
    #=======================================================
    if [[ ${roha_session.compute_only} == 0 || ${roha_session.systemmirror_mode} == 1 ]] ; then
        roha_session_wait_on_async_release
        rc=$?
        (( $rc > 0 )) && return $rc
    fi

  # This step is not required for ROHA on Cloud
  if (( CONN_TYPE != 2 )); then    
    #===============================================================
    # Query step 2(CEC, EPCoD, Trail CoD and On/Off CoD information)
    #===============================================================
    cl_query_roha_post_compute
    rc=$?
    (( $rc > 0 )) && return $rc
  fi

    #=================================================================
    : Reset to 0 all variables used in clidentifyroha
    #=================================================================
    initialize_identify_globals

    #=================================================================
    : Reset to 0 all variables used in clapplyroha
    #=================================================================
    initialize_apply_globals

  # This step is not required for ROHA on Cloud
  if (( CONN_TYPE != 2 )); then    
    #=======================================================
    # Identify step
    #=======================================================
    cl_identify_roha
    rc=$?
    (( $rc > 0 )) && return $rc
  fi

    #=======================================================
    # Apply step
    # During acquisition, in case of RC_*_ERROR_NOT_ENOUGH
    #  return code on clhmccmd command, return directly and
    #  try reassessment.
    # Do not perform apply step in case of compute_only mode
    #=======================================================
    if (( ${roha_session.compute_only} == 0 )); then
        cl_apply_roha $LAST_LOOP_OF_FORCE_REASSESSMENT

        rc=$?
        (( $rc > 0 )) && return $rc

        roha_session_report_success
    fi
    return $RC_SUCCESS
} # End of "roha_process_resources()"

#=============================================================================
#
# Name:        roha_process_operation
#
# Description: ROHA process operation(acquisition or release or adjustment of
#   resources.
#
# Inputs:      None
#
# Outputs:     None
#
# Returns:     RC_SUCCESS
#              or else an error code
#
#=============================================================================
function roha_process_operation
{
    #=============================================================
    # This variable to follow reassessments progression
    #=============================================================
    typeset -i CURRENT_REASSESSMENT=1
    typeset -i rc=$RC_SUCCESS

    amlog_trace $AM_ROHA_ASSESSMENT_BEGIN "Maximum Number of Reassessments $MAX_REASSESSMENT"
    while (( $CURRENT_REASSESSMENT <= $MAX_REASSESSMENT )); do
        #=======================================================
        : Process resources for CURRENT_REASSESSMENT=$CURRENT_REASSESSMENT
        #=======================================================
        if (( $CURRENT_REASSESSMENT != 1 )); then
            roha_session_log "Trying reassessment $(( $CURRENT_REASSESSMENT - 1 ))."
        fi
        if (( $CURRENT_REASSESSMENT == MAX_REASSESSMENT )); then
            LAST_LOOP_OF_FORCE_REASSESSMENT=1
        fi
        roha_process_resources $LAST_LOOP_OF_FORCE_REASSESSMENT


        rc=$?
        if (( rc == 0 )); then
            roha_session_log "INFO: received rc=$rc."
            roha_session_log "Success on $CURRENT_REASSESSMENT attempt(s)."
            break
        elif [[ ${roha_session.operation} == acquire && $rc == @($RC_APPLY_DLPAR_ERROR_NOT_ENOUGH|$RC_APPLY_ONOFF_ERROR_NOT_ENOUGH|$RC_APPLY_EPCOD_ERROR_NOT_ENOUGH) ]] ; then
            roha_session_log "INFO: received error code $rc."
            roha_session_log "Will try reassessment $CURRENT_REASSESSMENT."
            (( CURRENT_REASSESSMENT += 1 ))
        else
            roha_session_log "INFO: received error code $rc, no more reassessment."
            break
        fi
    done
 
    if (( rc == 0 )); then
        amlog_trace $AM_ROHA_ASSESSMENT_END "Number of Reassessments performed $CURRENT_REASSESSMENT"
    else
        amlog_trace $AM_ROHA_ASSESSMENT_FAILURE "Number of Reassessments performed $CURRENT_REASSESSMENT"
    fi 
    #========================================================
    # Acquisition or release failures need to be
    # transformed into a SUCCESS in some cases.
    #========================================================
    if (( rc > 0 )); then
        if [[ ${roha_session.operation} == acquire && $(roha_session_read_odm_rohaparam "always_start_rg") == 1 ]] ; then
            roha_session_log "A failure in acquisition should not prevent RG from starting if 'always_start_rg' is set."
            #==============================================================
            : Acquisition : As we have a 'always_start_rg' policy,
            :  transform the failure RC into a success RC so that Resource
            :  Groups can start.
            #==============================================================
            rc=$RC_SUCCESS
        elif [[ ${roha_session.operation} == release ]] ; then
            roha_session_log "A failure in release should not prevent takeover from occuring."
            roha_session_report_error
            #==============================================================
            : Release : transform the failure RC into a success RC so that
            :  takeover can normally continue.
            #==============================================================
            rc=$RC_SUCCESS
        else
            roha_session_report_error
        fi
    fi
    return $rc
} # End of "roha_process_operation()"

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

#=======================================================
# Export environment
#=======================================================
PROGNAME=${0##*/}
. /usr/es/sbin/cluster/events/utils/clcommonroha
#Include Availability Metrics library
. /usr/es/lib/ksh93/availability/cl_amlib

[[ $VERBOSE_LOGGING == high ]] && set -x
: version=@(#)  5881272 43haes/usr/sbin/cluster/events/clmanageroha.sh, 61aha_r726, 2205A_aha726, May 16 2022 12:15 PM

#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

#=======================================================
# Open the session
#=======================================================
roha_session_open "${@:-}"
(( $? > 0 )) && { roha_session_report_error; exit $RC_PARAM_ERROR ;}

#=============================================================
# Reassessment: in case of RC_*_ERROR_NOT_ENOUGH return code,
#  the whole process of acquisition or relase is retried from
#  the beginning.
#  A RC_*_ERROR_NOT_ENOUGH rc returned, means that a rollback
#   was done on the previous acquisition or relase, leaving
#   LPAR in same state than initially.
#=============================================================

#=============================================================
# This MAX_REASSESSMENT is set by default to 10, but is
#  auto-adjustable. It should depend on the number of clusters
#  deployed on the various LPARs of the frame, but as we cannot
#  access this value, we take the number of LPARs of the frame.
#=============================================================
typeset -i MAX_REASSESSMENT=10

# This step is not required for ROHA on Cloud
if (( CONN_TYPE != 2 )); then
    typeset SYS_LPAR_NAMES=""
    SYS_LPAR_NAMES=$(roha_query_sys_lpar_names)
    if [[ -n $SYS_LPAR_NAMES && "$SYS_LPAR_NAMES" == +([[:digit:]]) ]]; then
        MAX_REASSESSMENT=$(print $SYS_LPAR_NAMES)
    fi

    if (( $MAX_REASSESSMENT == 0 ));then
        MAX_REASSESSMENT=10
    fi
fi

#=============================================================
# This variable LAST_LOOP_OF_FORCE_REASSESSMENT
#  is set to 1, when we reach the last
#  loop of reassessments, as behaviour needs to change
#  in cl_apply_roha
#=============================================================
typeset -i LAST_LOOP_OF_FORCE_REASSESSMENT=0

#========================================================
# ROHA process Acquisition or Release or Adjustment of
# resources
#========================================================
if [[ ${roha_session.operation} == adjust ]] ; then
    #===================================
    # ROHA process Release of resources
    #===================================
    roha_session.operation="release"
    roha_process_operation
    #===================================
    # ROHA process Acquisition of resources
    #===================================    
    roha_session.operation="acquire"
    roha_process_operation
else
    #=================================================
    # ROHA process Acquisition or Release of resources
    #=================================================
    roha_process_operation
fi

rc=$?

#=======================================================
# Close the session
#=======================================================
roha_session_close

exit $rc
