#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2017,2019,2020,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
###############################################################################
# @(#)  64438b3 43haes/usr/sbin/cluster/events/utils/clhmccmd.sh, 726, 2147A_aha726, Oct 13 2021 08:38 AM
###############################################################################

#########################################################################
#
#   COMPONENT_NAME: hacmp.events
#
#   FUNCTIONS:
#
#       usage
#       parse_cmd_line
#       format_list
#       get_local_partition
#       get_local_hmc_list
#       check_enterprise_pool
#       check_partition
#       check_managed_system
#       check_profile
#       check_shared_processor_pool
#       get_enterprise_pool
#       get_local_managed_system
#       get_lpars_state
#       get_managed_system
#       get_profile
#       get_shared_processor_pool
#       get_free_sys_mem
#       get_free_sys_proc_units
#       get_free_pool_proc_units
#       gather_and_convert
#       execute_cmds
#       sort_and_output
#       process_query
#       process_change
#       process_acquire
#       process_release
#       get_hmc_param
#       update_hmc_list
#       get_effective_version
#       hmccmdexec
#       clhmcexec
#
#########################################################################

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

#=============================================================================
#
# NAME
#   clhmccmd - perform HMC commands on cluster ROHA resources
#
# SYNOPSIS
#   To query configuration information for current LPAR/Managed System/EPCoD/etc:
#   clhmccmd -o query -a {ALL|GEN|PROC|MEM|HMC|CEC|LPAR|PROF|SPP|TRIAL|ONOFF|EPCOD|<attribute1:attribute2:...>}
#       [-E <epcod>] [-M <cec>] [-L <lpar>] [-P <prof>] [-S <procpool>] [-h] [-H <hmcs>]
#
#   To change configuration parameter:
#   clhmccmd -o change -a "attr_name1=value:attr_name2=value:..." [-H <hmcs>]
#
#   To acquire resources (allocate DLPAR resources, activate On/Off resources, acquire EPCoD resources)
#    or release these resources:
#   clhmccmd -o {acquire|release} [-f] -r {dlpar|onoff|epcod} [-m <mem>] [-p <proc_units>]
#       [-q <procs>] [-d <days>] [-t <timeout>] [-H <hmcs>]
#
#   To halt current partition:
#   clhmccmd -o halt [-L <lpar>] [-H <hmcs>]
#
# DESCRIPTION
#   This clhmccmd command line interfaces HMC to perform HMC commands for the
#   account of PowerHA SystemMirror 'Resource Optimized High Availability'
#   (ROHA) functionality.
#
#   This clhmccmd command line is the common pipe for PowerHA SystemMirror to
#   interface HMCs.
#
#   This clhmccmd command line can run on any node of the cluster.
#
#   PowerHA SystemMirror configuration must be done as far as HMCs are concerned:
#       - HMCs have to be configured either
#           at the cluster level,
#           or at the site level,
#           or at the node level.
#       - But this is always possible to use the [-H hmcs] option otherwise.
#
#   This clhmccmd command line encapsulates with ssh all commands run on HMCs,
#   but the ssh link has to be properly configured first.
#
#   This clhmccmd command line encapsulates a retry mechanism, and is able to
#   takeover on an other HMC (the next in the list) in case of repeated failure.
#
#   This clhmccmd command line translates applicative level request to commands
#   comprehensible by the HMC, taking into account the version of HMC, and is
#   able to perform the following types of operations:
#       - Query operation on configuration attributes.
#       - Change operation on configuration attributes.
#       - Allocation of  memory and processor DLPAR resources (in shared and dedicated processing modes).
#       - Activation of  memory and processor On/Off CoD resources.
#       - Acquisition of memory and processor EPCoD resources.
#       - Release of memory and processor DLPAR resources (in shared and dedicated processing modes),
#         On/Off resources, EPCoD resources.
#       - Administrative actions on CEC to immediately halt LPARs.
#
# OPTIONS
#   -a      The colon-separated list of attributes. Only valid and mandatory with
#           -o {query|change} option.
#           Valid values for -o query option are:
#               hmc_list,                       hmc_version.
#               local_sys_name,                 sys_name,
#               sys_lpar_names,                 sys_state,
#               sys_type_model,                 cod_mem_capable,
#               cod_proc_capable,               mem_region_size,
#               installed_sys_mem,              configurable_sys_mem,
#               sys_firmware_mem,               curr_avail_sys_mem,
#               curr_free_sys_mem,              deconfig_sys_mem,
#               installed_sys_proc_units,       deconfig_sys_proc_units,
#               configurable_sys_proc_units,    curr_avail_sys_proc_units,
#               curr_free_sys_proc_units,       min_proc_units_per_virtual_proc.
#               local_lpar_name,                lpar_name,
#               lpar_id,                        uuid,
#               lpar_state,                     curr_profile,
#               lpar_avail_priority,            curr_proc_mode,
#               curr_min_mem,                   curr_mem,
#               curr_max_mem,                   curr_min_procs,
#               curr_procs,                     curr_max_procs,
#               curr_min_proc_units,            curr_proc_units,
#               curr_max_proc_units,            curr_shared_proc_pool_name.
#               local_prof_name,                prof_name,
#               prof_proc_mode,                 prof_sharing_mode,
#               prof_shared_procpool,           prof_minimum_procs,
#               prof_desired_procs,             prof_maximum_procs,
#               prof_minimum_proc_units,        prof_desired_proc_units,
#               prof_maximum_prof_units,        prof_minimum_mem,
#               prof_desired_mem,               prof_maximum_mem.
#               local_procpool_name,            procpool_name,
#               max_pool_proc_units,            curr_free_pool_proc_units,
#               curr_reserved_pool_proc_units.
#               mem_trial_state,                activated_trial_mem,
#               mem_trial_days_left,            mem_trial_hours_left,
#               proc_trial_state,               activated_trial_procs,
#               proc_trial_days_left,           proc_trial_hours_left.
#               proc_onoff_state,               activated_onoff_procs,
#               avail_procs_for_onoff,          unreturned_onoff_procs,
#               onoff_request_proc_days_left,   onoff_proc_day_hours_left,
#               onoff_proc_days_avail,
#               mem_onoff_state,                activated_onoff_mem,
#               avail_mem_for_onoff,            unreturned_onoff_mem,
#               onoff_request_mem_days_left,    onoff_mem_day_hours_left,
#               onoff_mem_days_avail.
#               local_codpool_name,             codpool_name,
#               codpool_sys_names,              mobile_state,
#               master_mc_name,                 backup_master_mc_name,
#               mobile_mem,                     unreturned_mobile_mem,
#               avail_mobile_mem,               sys_inactive_mem,
#               sys_mobile_mem,                 sys_unreturned_mobile_mem,
#               mobile_procs,                   unreturned_mobile_procs,
#               avail_mobile_procs,             sys_inactive_procs,
#               sys_mobile_procs,               sys_unreturned_mobile_procs.
#           Valid values for -o change option are:
#               max_pool_proc_units             reserved_pool_proc_units.
#   -d      The number of days for On/Off CoD request. Only valid and mandatory
#           with -o acquire and -l onoff.
#   -E      The EPCoD name. May be specified if information from another
#           EPCoD than the one the Managed System the LPAR belongs to are needed.
#   -f      Force allocation/release of resources to the best effort even if failure.
#   -h      Display help usage.
#   -H      The space-separated list of HMCs to interrogate.
#   -l      Display labels.
#   -L      The LPAR name. May be specified if information from another LPAR
#           than the one on which the command is issued are needed.
#   -m      The amount of memory (in MBytes). Only valid with -o acquire and -o release.
#   -M      The Managed System name. May be specified if information from another Managed System
#           than the one the LPAR belongs to are needed.
#   -o      The operation to perform. Valid values are query, change, acquire and release.
#               The query operation displays information about configuration by
#                   interrogating the first HMC in the list. Option -a is mandatory.
#               The change operation sets attributes to new values. Option -a is
#                   mandatory.
#               The acquire operation tries to allocate/activate/acquire/ resources for the account
#                   of the LPAR. If no -m, -p or -q option are set, acquire all possible
#                   resources. If -l option is set to onoff, -d option is mandatory.
#               The release operation tries to release resources for the account of
#                   the LPAR. If no -m, -p or -q option is set, release all possible
#                   resources.
#               The halt operation tries to immediately shutdown the LPAR.
#   -p      The decimal number of processing units. Only valid with -o acquire and -o release.
#   -P      The profile name. May be specified if information from another profile than
#           the one on which the command is issued are needed.
#   -q      The number of processors. Only valid with -o acquire and -o release.
#   -r      The type of resources. Only valid and mandatory with -o acquire and -o release.
#           Valid values are dlpar for Dynamic LPAR resources, onoff for On/Off CoD resources,
#           epcod for Enterprise Pool CoD resources.
#   -s      Safe option to tell that no check is to be done on parameter.
#   -S      The shared processor pool name. May be specified if information from another
#           shared processor pool than the one the partition belongs to are needed.
#   -t      The timeout for operation on DLPAR memory and processors. Only valid with
#           -o acquire and -o release and -r dlpar. This timeout will automatically be
#           incremented by the maximum resources value.
#
# EXIT STATUS
#   This command has the following return codes:
#       0   Success
#       1   Error - Wrong parameter
#       2   Error - Last HMC tried cannot be pinged
#       3   Error - Remote command cannot be ssh'ed on the last HMC tried
#       4   Error - Remote command returned a resource busy error on the last HMC tried
#       5   Error - Remote command returned a managed system busy error on the last HMC tried
#       6   Error - Remote command returned a not enough resources error on the last HMC tried
#       7   Error - Remote command returned an other type of error on the last HMC tried
#
# EXAMPLES
#   To query multiple configuration information:
#   clhmccmd -o query -a hmc_version:curr_proc_mode:activated_onoff_mem:lpar_state
#
#   To query all configuration information with labels:
#   clhmccmd -o query -a ALL -l
#
#   To query multiple configuration information for a specific Managed System:
#   clhmccmd -o query -a sys_state:sys_type_model -M 3node-9117-MMB-100082P
#
#   To change maximum size of shared processor pool:
#   clhmccmd -o change -a "max_pool_proc_units=8.5"
#
#   To allocate 9.75 GBytes of memory, 2.2 processing units and 4 virtual CPUs of DLPAR resources:
#   clhmccmd -o acquire -m 9984 -p 2.2 -q 4 -r dlpar
#
#   To activate 32 GBytes of On/Off CoD memory resources for 18 days:
#   clhmccmd -o acquire -m 32768 -d 18 -r onoff
#
#   To acquire 32 GBytes of EPCoD memory resources for 18 days:
#   clhmccmd -o acquire -m 32768 -r epcod
#
#   To release 100 GBytes of DLPAR memory resources with a 50 minutes timeout:
#   clhmccmd -o release -m 102400 -r dlpar -t 50
#
#   To release 7 Enterprise Pool CoD processors:
#   clhmccmd -o release -r epcod -q 7
#
#   To shutdown current partition:
#   clhmccmd -o halt
#
#   Questions?  Comments?  Expressions of Astonishment?  mailto:hafeedbk@us.ibm.com
#
#=============================================================================

#=============================================================================
#
# Name:        usage
#
# Description: Prints usage.
#
# Arguments:   None
#
# Returns:     None
#
#=============================================================================
function usage
{
    printf "%s: Usage:\n" "$PROGNAME"
    printf "\tclhmccmd -o query -a {ALL|GEN|PROC|MEM|HMC|CEC|LPAR|PROF|SPP|TRIAL|ONOFF|EPCOD|<attribute1:attribute2:...>} [-l] [-H <hmcs>] [-E <epcod>] [-M <cec>] [-L <lpar>] [-P <prof>] [-S <procpool>]\n"
    printf "\tclhmccmd -o change -a \"attr_name1=value:attr_name2=value:...\" [-H <hmcs>]\n"
    printf "\tclhmccmd -o {acquire|release} [-f] -r {dlpar|onoff|epcod} [-m <mem>] [-p <proc_units>] [-q <procs>] [-d <days>] [-t <timeout>] [-H <hmcs>]\n"
    printf "\tclhmccmd -o halt [-L <lpar>] [-H <hmcs>]\n"
    printf "\n"
    printf "Note: -m <mem> must be passed in MB, 1GB=1024MB.\n"
    printf "Note: verbose output is shown by setting VERBOSE_LOGGING=high.\n"
    printf "Note: to display output messages, run clhmccmd with \" 3>&2\""
} # End of "usage()"

#=============================================================================
#
# Name:        parse_cmd_line
#
# Description: Parse and check the command line arguments.
#
# Arguments:   $@ [IN]       list of arguments
#
# Environment: g_attributes
#              g_duration
#              g_enterprise_pool
#              g_hmc_list
#              g_labels
#              g_partition
#              g_memory
#              g_managed_system
#              g_operation
#              g_proc_units
#              g_profile
#              g_quantity
#              g_resource
#              g_shared_proc_pool
#              g_timeout
#
# Returns:     RC_SUCCESS
#              RC_PARAM_ERROR
#
#=============================================================================
function parse_cmd_line
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS

    duplicate_args=$(echo $* | tr ' ' '\n' | grep "^-" | uniq -d)
    if [[ -n $duplicate_args ]]; then
    	echo ERROR: $duplicate_args option is duplicate.
   	exit $RC_PARAM_ERROR
    fi

    #=======================================================
    # Get options
    #=======================================================
    while getopts ":a:d:E:fhH:lL:m:M:o:p:P:q:r:sS:t:" opt ; do
        case $opt in
        a)  g_attributes=$OPTARG ;;         # attributes to list
        d)  g_duration=$OPTARG ;;           # number of days for onoff requests
        E)  g_enterprise_pool=$OPTARG ;;    # enterprise pool name
        f)  g_force=1 ;;                    # force allocation/release
        h)  usage ; exit $RC_SUCCESS ;;     # usage
        H)  if [[ -z $g_hmc_list ]] ; then  # list of HMCs
                g_hmc_list=${g_hmc_list:+${g_hmc_list} }${OPTARG//[,:]/ }
            fi
            ;;
        l)  g_labels=1 ;;                   # display labels
        L)  g_partition=$OPTARG ;;          # partition name
        m)  g_memory=$OPTARG ;;             # MBytes of memory
        M)  g_managed_system=$OPTARG ;;     # managed system name
        o)  g_operation=$OPTARG ;;          # operation {query|change|acquire|release}
        p)  g_proc_units=$OPTARG ;;         # processing units for shared proc LPARs
        P)  g_profile=$OPTARG ;;            # profile name
        q)  g_quantity=$OPTARG ;;           # quantity of CPUs
        r)  g_resource=$OPTARG ;;           # resource type {dlpar|onoff|epcod}
        s)  g_safe_option=1 ;; 
        S)  g_shared_proc_pool=$OPTARG ;;   # shared processor pool name
        t)  g_timeout=$OPTARG ;;            # timeout for DLPAR operations
       \?)  dspmsg $ROHA_MSGS -s $ROHA_SET 400 \
            "%1\$s: ERROR: unknown -%2\$s parameter.\n" \
            "$PROGNAME" "$OPTARG" >&3
            exit $RC_PARAM_ERROR
            ;;
        :)  dspmsg $ROHA_MSGS -s $ROHA_SET 401 \
            "%1\$s: ERROR: -%2\$s option requires an argument.\n" \
            "$PROGNAME" "$OPTARG" >&3
            exit $RC_PARAM_ERROR
            ;;
        esac
    done

    shift $((OPTIND-1))
    if [[ -n $1 ]]; then
    	echo "WARNING: Unknown extra parameter $1 \n"
    fi

    #=======================================================
    # Check operation
    #=======================================================
    if [[ -z $g_operation ]] ; then
        dspmsg $ROHA_MSGS -s $ROHA_SET 402 \
        "%1\$s: ERROR: missing operation.\n" \
        "$PROGNAME" "$g_operation" >&3
        dspmsg $ROHA_MSGS -s $ROHA_SET 404 \
        "\tSupported operations for -o flag are: %1\$s.\n" \
        "$OPERATION_LIST" >&3
        exit $RC_PARAM_ERROR
    fi
    case $g_operation in
        q*)
            #=======================================================
            # Check query options
            #=======================================================
            g_operation="query"

            if [[ -z $g_attributes ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 405 \
                "%1\$s: ERROR: missing attribute for %2\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 407 \
                "\tSupported attributes for -a flag are:\n%1\$s\n" \
                "$(format_list "$QUERY_ATTR_LIST")" >&3
                exit $RC_PARAM_ERROR
            fi

            for attribute in ${g_attributes//:/ } ; do
                #=======================================================
                # Convert generic g_attributes
                #=======================================================
                case $attribute in
                  ALL)  g_attributes=${g_attributes/ALL/${QUERY_ATTR_LIST// /:}}            ;;
                  HMC)  g_attributes=${g_attributes/HMC/${HMC_ATTRS// /:}}                  ;;
                  CEC)  g_attributes=${g_attributes/CEC/${MANAGED_SYSTEM_ATTRS// /:}}       ;;
                 LPAR)  g_attributes=${g_attributes/LPAR/${PARTITION_ATTRS// /:}}           ;;
                 PROF)  g_attributes=${g_attributes/PROF/${PROFILE_ATTRS// /:}}             ;;
                  SPP)  g_attributes=${g_attributes/SPP/${SHARED_PROC_POOL_ATTRS// /:}}     ;;
                TRIAL)  g_attributes=${g_attributes/TRIAL/${TRIAL_COD_ATTRS// /:}}          ;;
                ONOFF)  g_attributes=${g_attributes/ONOFF/${ONOFF_COD_ATTRS// /:}}          ;;
                EPCOD)  g_attributes=${g_attributes/EPCOD/${ENTERPRISE_POOL_ATTRS// /:}}    ;;
                  GEN)  g_attributes=${g_attributes/GEN/${GENERAL_ATTRS// /:}}              ;;
                 PROC)  g_attributes=${g_attributes/PROC/${PROCESSOR_ATTRS// /:}}           ;;
                  MEM)  g_attributes=${g_attributes/MEM/${MEMORY_ATTRS// /:}}               ;;
                AVAIL)  g_attributes=${g_attributes/AVAIL/${AVAIL_ATTRS// /:}}              ;;
              CURRENT)  g_attributes=${g_attributes/CURRENT/${CURRENT_ATTRS// /:}}          ;;
                    *)  if [[ $attribute != @(${QUERY_ATTR_LIST// /\|}) ]] ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 406 \
                            "%1\$s: ERROR: unsupported %2\$s attribute for %3\$s operation.\n" \
                            "$PROGNAME" "$attribute" "$g_operation" >&3
                            dspmsg $ROHA_MSGS -s $ROHA_SET 407 \
                            "\tSupported attributes for -a flag are:\n%1\$s\n" \
                            "$(format_list "$QUERY_ATTR_LIST")" >&3
                            exit $RC_PARAM_ERROR
                        fi
                esac
            done
            ;;

        c*)
            #=======================================================
            # Check change options
            #=======================================================
            g_operation="change"

            if [[ -z $g_attributes ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 405 \
                "%1\$s: ERROR: missing attribute for %2\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 407 \
                "\tSupported attributes for -a flag are:\n%1\$s\n" \
                "$(format_list "$CHANGE_ATTR_LIST")" >&3
                exit $RC_PARAM_ERROR
            fi

            for attribute in ${g_attributes//:/ } ; do
                print -- $attribute | IFS='=' read key value
                if [[ $key != @(${CHANGE_ATTR_LIST// /\|}) ]] ; then
                    dspmsg $ROHA_MSGS -s $ROHA_SET 406 \
                    "%1\$s: ERROR: unsupported %2\$s attribute for %3\$s operation.\n" \
                    "$PROGNAME" "$key" "$g_operation" >&3
                    dspmsg $ROHA_MSGS -s $ROHA_SET 407 \
                    "\tSupported attributes for -a flag are:\n%1\$s\n" \
                    "$(format_list "$CHANGE_ATTR_LIST")" >&3
                    exit $RC_PARAM_ERROR
                fi
            done
            ;;

        a*)
            #=======================================================
            # Check acquire options
            #=======================================================
            g_operation="acquire"

            if [[ -z $g_resource ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 408 \
                "%1\$s: ERROR: missing resource type for %2\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 410 \
                "\tSupported resource types for -r flag are: %1\$s.\n" \
                "$RESOURCE_LIST" >&3
                exit $RC_PARAM_ERROR
            fi

            if [[ $g_resource != @(dlpar|onoff|epcod) ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 409 \
                "%1\$s: ERROR: unsupported %2\$s resource type for %3\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 410 \
                "\tSupported resource types for -r flag are: %1\$s.\n" \
                "$RESOURCE_LIST" >&3
                exit $RC_PARAM_ERROR
            fi

            if (( $g_memory == 0 && $g_quantity == 0 && $g_proc_units == 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 411 \
                "%1\$s: ERROR: missing resource quantity for %2\$s operation. Provide -m, -q or -p option.\n" \
                "$PROGNAME" "$g_operation" >&3
                exit $RC_PARAM_ERROR
            fi

            if [[ $g_resource == onoff ]] && (( $g_duration == -1 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 412 \
                "%1\$s: ERROR: missing request duration for On/Off CoD acquire operation. Provide -d option.\n" \
                "$PROGNAME" >&3
                exit $RC_PARAM_ERROR
            fi
            ;;

        r*)
            #=======================================================
            # Check release options
            #=======================================================
            g_operation="release"

            if [[ -z $g_resource ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 408 \
                "%1\$s: ERROR: missing resource type for %2\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 410 \
                "\tSupported resource types for -r flag are: %1\$s.\n" \
                "$RESOURCE_LIST" >&3
                exit $RC_PARAM_ERROR
            fi

            if [[ $g_resource != @(dlpar|onoff|epcod) ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 409 \
                "%1\$s: ERROR: unsupported %2\$s resource type for %3\$s operation.\n" \
                "$PROGNAME" "$g_operation" >&3
                dspmsg $ROHA_MSGS -s $ROHA_SET 410 \
                "\tSupported resource types for -r flag are: %1\$s.\n" \
                "$RESOURCE_LIST" >&3
                exit $RC_PARAM_ERROR
            fi

            if (( $g_memory == 0 && $g_quantity == 0 && $g_proc_units == 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 411 \
                "%1\$s: ERROR: missing resource quantity for %2\$s operation. Provide -m, -q or -p option.\n" \
                "$PROGNAME" "$g_operation" >&3
                exit $RC_PARAM_ERROR
            fi
            ;;

        h*)
            #=======================================================
            # Check halt options
            #=======================================================
            g_operation="halt"
            ;;

        *)  dspmsg $ROHA_MSGS -s $ROHA_SET 403 \
            "%1\$s: ERROR: unsupported %2\$s operation.\n" \
            "$PROGNAME" "$g_operation" >&3
            dspmsg $ROHA_MSGS -s $ROHA_SET 404 \
            "\tSupported operations for -o flag are: %1\$s.\n" \
            "$OPERATION_LIST" >&3
            exit $RC_PARAM_ERROR
    esac

    #=======================================================
    # Check HMC list & partition
    #=======================================================
    if [[ -n $g_hmc_list ]] ; then
        if [[ -n $g_partition ]] ; then
            if (( g_safe_option == 0)); then 
                check_partition $g_partition
                if (( $? > 0 )) ; then
                    dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                        "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                        "$PROGNAME" "$g_partition" >&3
                    exit $RC_PARAM_ERROR
                fi
            fi
        else
            get_local_partition g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                "$PROGNAME" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    else
        #=======================================================
        # cl_get_hmc_list needs a node name as argument.
        #=======================================================
        if [[ -n $g_partition ]] ; then
            #=======================================================
            # nodename/lparname match and nodename/cecname match are
            #   stored into HACMPdynresop ODM
            #  We use cl_dynresop to retrieve match between lparname
            #   and nodename into HACMPdynresop ODM
            #=======================================================
            nodename=$(LC_ALL=C cl_dynresop -l $g_partition -N)
            rc=$?
            if (( rc != 0 )) || [[ -z $nodename ]] ; then
                #
                : best can do, nodename is set to g_partition $g_partition
                #
                nodename=$g_partition
                rc=$RC_SUCCESS
            fi

            g_hmc_list=$(cl_get_hmc_list -n $nodename 2>/dev/null)
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 413 \
                    "%1\$s: ERROR: no list of HMC defined for %2\$s node. Provide -H option.\n" \
                    "$PROGNAME" "$nodename" >&3
                exit $RC_PARAM_ERROR
            fi

            check_partition $g_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                    "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                    "$PROGNAME" "$g_partition" >&3
                exit $RC_PARAM_ERROR
            fi

        else
            get_local_hmc_list g_hmc_list
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 413 \
                "%1\$s: ERROR: no list of HMC defined for %2\$s node. Provide -H option.\n" \
                "$PROGNAME" "$(get_local_nodename)" >&3
                exit $RC_PARAM_ERROR
            fi

            get_local_partition g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                "$PROGNAME" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check managed system
    #=======================================================
    if [[ -n $g_managed_system && -z $g_enterprise_pool ]] ; then
        if (( g_safe_option == 0)); then 
            check_managed_system $g_managed_system
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 416 \
                    "%1\$s: ERROR: unknown %2\$s Managed System. Provide valid name through -M option.\n" \
                    "$PROGNAME" "$g_managed_system" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check enterprise pool
    #=======================================================
    if [[ -n $g_enterprise_pool ]] ; then
        if (( g_safe_option == 0)); then 
            check_enterprise_pool $g_enterprise_pool
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 415 \
                    "%1\$s: ERROR: unknown %2\$s Enterprise Pool CoD. Provide valid name through -E option.\n" \
                    "$PROGNAME" "$g_enterprise_pool" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check profile
    #=======================================================
    if [[ -n $g_profile ]] ; then
        if [[ -n $g_partition ]] ; then
            if (( g_safe_option == 0)); then 
                check_profile $g_profile $g_partition
                if (( $? > 0 )) ; then
                    dspmsg $ROHA_MSGS -s $ROHA_SET 417 \
                        "%1\$s: ERROR: unknown %2\$s Profile for %3\$s LPAR. Provide valid name through -P option.\n" \
                        "$PROGNAME" "$g_profile" "$g_partition" "$prof_name" >&3
                    exit $RC_PARAM_ERROR
                fi
            fi
        else
            get_local_partition g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                "$PROGNAME" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
            check_profile $g_profile $g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 417 \
                "%1\$s: ERROR: unknown %2\$s Profile for %3\$s LPAR. Provide valid name through -P option.\n" \
                "$PROGNAME" "$g_profile" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check shared processor pool
    #=======================================================
    if [[ -n $g_shared_proc_pool ]] ; then
        if [[ -n $g_partition ]] ; then
            if (( g_safe_option == 0)); then 
                check_shared_processor_pool $g_shared_proc_pool $g_partition
                if (( $? > 0 )) ; then
                    dspmsg $ROHA_MSGS -s $ROHA_SET 418 \
                        "%1\$s: ERROR: unknown %2\$s Shared Processor Pool for %3\$s LPAR. Provide valid name through -S option.\n" \
                        "$PROGNAME" "$g_shared_proc_pool" "$g_partition" >&3
                    exit $RC_PARAM_ERROR
                fi
            fi
        else
            get_local_partition g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
                "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
                "$PROGNAME" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
            check_shared_processor_pool $g_shared_proc_pool $g_local_partition
            if (( $? > 0 )) ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 418 \
                "%1\$s: ERROR: unknown %2\$s Shared Processor Pool for %3\$s LPAR. Provide valid name through -S option.\n" \
                "$PROGNAME" "$g_shared_proc_pool" "$g_local_partition" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check consistency when -L and -M options are provided
    #=======================================================
	if (( g_safe_option == 0)); then 
        if [[ -n $g_managed_system && -n $g_partition ]] ; then
            # partition should belong to managed system
            typeset sys_name=
            get_managed_system sys_name $g_partition
            if [[ $sys_name != $g_managed_system ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 419 \
                    "%1\$s: ERROR: %2\$s LPAR does not belong to %3\$s Managed System but $4\$s. Provide valid name through -L or -M option.\n" \
                    "$PROGNAME" "$g_partition" "$g_managed_system" "$sys_name" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    #=======================================================
    # Check consistency when -E and -M options are provided
    #=======================================================
    if (( g_safe_option == 0)); then 
        if [[ -n $g_enterprise_pool && -n $g_managed_system ]] ; then
            # enterprise pool should belong to managed system
            typeset epcod_name=
            get_enterprise_pool epcod_name $g_managed_system
            if [[ $epcod_name != $g_enterprise_pool ]] ; then
                dspmsg $ROHA_MSGS -s $ROHA_SET 420 \
                    "%1\$s: ERROR: %2\$s Managed System does not belong to %3\$s Enterprise Pool CoD but %4\$s. Provide valid name through -M or -E option.\n" \
                    "$PROGNAME" "$g_managed_system" "$g_enterprise_pool" "$epcod_name" >&3
                exit $RC_PARAM_ERROR
            fi
        fi
    fi

    return $rc
} # End of "parse_cmd_line()"

#=============================================================================
#
# Name:        format_list
#
# Description: Prints format_list.
#
# Arguments:   $1 [IN]       list of elements
#
# Returns:     None
#
#=============================================================================
function format_list
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x
    typeset list=$1
    list="$(print "${list// /\\n}" | sort -u)"
    print $list | read -A array
    for (( i=0; i<${#array[@]}; i+=2 )) ; do
        printf "\t%-32s %-32s\n" "${array[$i]}" "${array[$((i+1))]}"
    done
} # End of "format_list()"

#=============================================================================
#
# Name:        get_local_partition
#
# Description: Obtain local partition name. The partition name is got from
#              'uname -L'.
#
# Arguments:   $1 [INOUT] lpar_name - reference to the local partition name.
#
# Environment: HOSTNAME
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_local_partition
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n lpar_name=$1

    if [[ -z $lpar_name ]] ; then
        #=======================================================
        : It refers to this one. Get it from uname.
        #=======================================================
        lpar_name=$(uname -L | cut -d \  -f2 2>/dev/null)
        if [[ -z $lpar_name ]] ; then
            #=======================================================
            : If failed, return failure.
            #=======================================================
            rc=$RC_FAILURE
        fi

    fi

    return $rc
} # End of "get_local_partition()"

#=============================================================================
#
# Name:        get_local_hmc_list
#
# Description: Obtain HMC list of the current partition. The HMC list is either
#              retrieved from HACMPdynresop ODM where it was previously saved,
#              or default to null.
#
# Arguments:   $1 [INOUT] hmc_list  - reference to a space-separated list of HMCs.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_local_hmc_list
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n hmc_list=$1

    if [[ -z $hmc_list ]] ; then
        #=======================================================
        : First, look into HACMPdynresop ODM.
        #=======================================================
        hmc_list=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=PREFERRED_HMC_LIST" -nf value HACMPdynresop 2>/dev/null)
        rc=$?

        if (( $rc > 0 )) || [[ -z $hmc_list ]] ; then
            #=======================================================
            : Then, look at node, site or cluster level ODM. If no
            : partition are provided, it will look by default for
            : the local partition.
            #=======================================================
            hmc_list=$(cl_get_hmc_list 2>/dev/null)
            rc=$?

            if (( $rc > 0 )) || [[ -z $hmc_list ]] ; then
                #=======================================================
                : Then, unset and return failure.
                #=======================================================
                hmc_list=""
                rc=$RC_FAILURE
            fi

        fi

    fi

    return $rc
} # End of "get_local_hmc_list()"

#=============================================================================
#
# Name:        check_enterprise_pool
#
# Description: Check enterprise pool name by asking HMC.
#
# Arguments:   $1 [IN] epcod_name - enterprise pool name to check for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function check_enterprise_pool
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset epcod_name=$1

    #=======================================================
    : Check enterprise pool name
    #=======================================================
    clhmcexec "lscodpool --level pool -p $epcod_name -F name" res
    if (( $? > 0 )) ; then
        rc=$RC_FAILURE
    fi

    return $rc
} # End of "check_enterprise_pool()"

#=============================================================================
#
# Name:        check_partition
#
# Description: Check partition name by asking HMC.
#
# Arguments:   $1 [IN] lpar_name - partition name to check for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function check_partition
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset lpar_name=$1
    typeset sys_name_ref=""
    typeset res=""

    #===================================================
    # nodename/lparname match and nodename/cecname match
    #  are stored into HACMPdynresop ODM
    # we use cl_dynresop to retrieve match between
    #  lparname and cecname into HACMPdynresop ODM
    #===================================================

    [[ -z $lpar_name ]] && get_local_partition lpar_name
    sys_name_ref=$(LC_ALL=C cl_dynresop -l $lpar_name -C)

    if (( $? != 0 )) ; then
        #
        : If ever not possible to retrieve partition using cl_dynresop,
        : try to loop against all cecs of hmc
        #
        typeset -i found=0

        clhmcexec "lssyscfg -r sys -F name" res
        if (( $? == $RC_SUCCESS )) ; then

            #=======================================================
            # Ask HMC if the partition belongs to the managed system.
            #=======================================================
            print "$res" | \
                while read sys_name_ref ; do {
                    clhmcexec "lssyscfg -r lpar -m $sys_name_ref -F name" res
                    rc=$?
                    if (( rc == $RC_SUCCESS )) ; then
                        print "$res" | \
                            while read lpar_name_ref ; do
                            if [[ $lpar_name == $lpar_name_ref ]] ; then
                                found=1
                                break 2
                            fi
                        done
                    fi
                } < /dev/null ; done # Avoid ssh to break while loop by redirecting standard input
        fi

        if (( found == 0 )) ; then
            rc=$RC_FAILURE
        fi
    else
        #
        : Retrieve complete sys_name_ref $sys_name_ref against HMC
        #
        clhmcexec "lssyscfg -r sys -m $sys_name_ref -F name" sys_name_ref
        if (( $? > 0 )) ; then
            rc=$RC_FAILURE
        else
            #
            : Check lpar_name $lpar_name against HMC
            #
            clhmcexec "lssyscfg -r lpar -m $sys_name_ref --filter lpar_names=$lpar_name -F name" res
            if (( $? > 0 )) ; then
                rc=$RC_FAILURE
            fi
        fi
    fi

    return $rc
} # End of "check_partition()"

#=============================================================================
#
# Name:        check_managed_system
#
# Description: Check managed system name by asking HMC.
#
# Arguments:   $1 [IN] sys_name - managed system name to check for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function check_managed_system
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset sys_name=$1

    #=======================================================
    : Check managed system name
    #=======================================================
    clhmcexec "lssyscfg -r sys -m $sys_name -F name" res
    if (( $? > 0 )) ; then
        rc=$RC_FAILURE
    fi

    return $rc
} # End of "check_managed_system()"

#=============================================================================
#
# Name:        check_profile
#
# Description: Check profile name is valid for the partition by asking HMC.
#
# Arguments:   $1 [IN] prof_name - profile name to check for.
#              $2 [IN] lpar_name - lpar name to check for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function check_profile
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset prof_name=$1
    typeset lpar_name=$2
    typeset sys_name=""

    #=======================================================
    : Obtain managed system of the partition
    #=======================================================
    get_managed_system sys_name $lpar_name
    if (( $? > 0 )) ; then
        rc=$RC_FAILURE
    else
        #=======================================================
        : Check profile name
        #=======================================================
        clhmcexec "lssyscfg -r prof -m $sys_name --filter lpar_names=$lpar_name,profile_names=$prof_name -F name" res
        if (( $? > 0 )) ; then
            rc=$RC_FAILURE
        fi
    fi

    return $rc
} # End of "check_profile()"

#=============================================================================
#
# Name:        check_shared_processor_pool
#
# Description: Check shared processor pool name is valid for the partition by asking HMC.
#
# Arguments:   $1 [IN] spp_name  - shared processor pool name to check for.
#              $2 [IN] lpar_name - lpar name to check for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function check_shared_processor_pool
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset spp_name=$1
    typeset lpar_name=$2
    typeset sys_name=""

    #=======================================================
    : Obtain managed system of the partition
    #=======================================================
    get_managed_system sys_name $lpar_name
    if (( $? > 0 )) ; then
        rc=$RC_FAILURE
    else
        #=======================================================
        : Check shared processor pool name
        #=======================================================
        clhmcexec "lshwres -r procpool -m $sys_name --filter pool_names=$spp_name -F name" res
        if (( $? > 0 )) ; then
            rc=$RC_FAILURE
        fi
    fi

    return $rc
} # End of "check_shared_processor_pool()"

#=============================================================================
#
# Name:        get_managed_system
#
# Description: Obtain managed system name of a partition. The name is gotten
#              from the ODM, or from HMC, or default to null.
#
# Arguments:   $1 [INOUT] sys_name  - reference to the managed system name.
#              $2 [IN]    lpar_name - partition name to search managed system for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_managed_system
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n sys_name=$1
    typeset    lpar_name=$2
    typeset    local_lpar_name=""


    #===================================================
    # nodename/lparname match and nodename/cecname match
    #  are stored into HACMPdynresop ODM
    # we use cl_dynresop to retrieve match between
    #  lparname and cecname into HACMPdynresop ODM
    #===================================================
    [[ -z $lpar_name ]] && get_local_partition lpar_name
    sys_name=$(LC_ALL=C cl_dynresop -l $lpar_name -C)
    rc=$?
    if (( rc == 0 )); then
        clhmcexec "lssyscfg -r sys -m $sys_name -F name" sys_name
        if (( $? != 0 )) ; then
            rc=$RC_FAILURE
        fi
    fi
    if [[ -z $sys_name || $rc != 0 ]]; then
        #
        : If ever not possible to retrieve cec name using cl_dynresop,
        : try to loop against all cecs of hmc
        #
        typeset    sys_name_ref=""
        typeset    res=""
        typeset -i found=0

        #=======================================================
        : Check if lpar_name is the local one
        #=======================================================
        get_local_partition local_lpar_name
        rc=$?
        if (( rc == $RC_SUCCESS )) && [[ $local_lpar_name == $lpar_name ]] ; then
            #=======================================================
            : If looking for local MS name, use dedicated function
            #=======================================================
            get_local_managed_system sys_name
            rc=$?
        else
            #=======================================================
            : If any error while getting local_lpar_name, go through
            : the long process anyway
            #=======================================================
            rc=$RC_SUCCESS
        fi

        if [[ -z $sys_name ]] ; then
            #=======================================================
            : Then, ask the HMC and go through all lpars from all
            : managed system to find our partition. Break when found.
            #=======================================================
            typeset -i found=0

            clhmcexec "lssyscfg -r sys -F name" res
            rc=$?
            if (( rc == $RC_SUCCESS )) ; then

                #=======================================================
                # Ask HMC if the partition belongs to the managed system.
                #=======================================================
                print "$res" | \
                    while read sys_name_ref ; do {
                        clhmcexec "lssyscfg -r lpar -m $sys_name_ref -F name" res
                        rc=$?
                        if (( rc == $RC_SUCCESS )) ; then
                            print "$res" | \
                                while read lpar_name_ref ; do
                                if [[ $lpar_name == $lpar_name_ref ]] ; then
                                    sys_name=$sys_name_ref
                                    found=1
                                    break 2
                                fi
                            done
                        fi
                    } < /dev/null ; done # Avoid ssh to break while loop by redirecting standard input
            fi

            if (( found == 0 )) || [[ -z $sys_name ]] ; then
                #=======================================================
                : Then, unset and return failure.
                #=======================================================
                sys_name=""
                rc=$RC_FAILURE
            fi
        else
            clhmcexec "lssyscfg -r sys -m $sys_name -F name" sys_name
            if (( $? != 0 )) ; then
                rc=$RC_FAILURE
            fi
       fi
    fi
    #
    : returning sys_name=$sys_name
    #
    return $rc
} # End of "get_managed_system()"


#=============================================================================
#
# Name:        get_local_managed_system
#
# Description: Obtain local managed system name. The name is gotten
#              from the ODM, or from HMC, or default to null.
#
# Arguments:   $1 [INOUT] sys_name reference to the managed system name.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_local_managed_system
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n sys_name=$1
    typeset LOCAL_MANAGED_SYSTEM_MTM=""
    typeset LOCAL_MANAGED_SYSTEM_SN=""

    #=======================================================
    : First, look into ODM if it has been persisted
    #=======================================================
    sys_name=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=MANAGED_SYSTEM" -nf value HACMPdynresop 2>/dev/null)
    rc=$?

    if (( rc != $RC_SUCCESS )) || [[ -z $sys_name ]] ; then

	    LOCAL_MANAGED_SYSTEM_MTM=$(uname -M)
	    (( $? == 0 )) && LOCAL_MANAGED_SYSTEM_MTM=${LOCAL_MANAGED_SYSTEM_MTM#*,}
	    LOCAL_MANAGED_SYSTEM_SN=$(uname -u)
	    (( $? == 0 )) && LOCAL_MANAGED_SYSTEM_SN=${LOCAL_MANAGED_SYSTEM_SN#*,}
	    if [[ -n $LOCAL_MANAGED_SYSTEM_MTM && -n $LOCAL_MANAGED_SYSTEM_SN ]]; then
	        #=======================================================
	        : Two first characters of SN need to be stripped
	        #=======================================================
	        sys_name=${LOCAL_MANAGED_SYSTEM_MTM}*${LOCAL_MANAGED_SYSTEM_SN:2}
	    fi
	    if [[ -n $sys_name ]]; then
	        clhmcexec "lssyscfg -r sys -m $sys_name -F name" sys_name
	        rc=$?
	        if (( $? != 0 )) ; then
	            rc=$RC_FAILURE
	        fi
	    fi
	fi

    (( rc != $RC_SUCCESS )) && sys_name=""

    #
    : returning sys_name=$sys_name
    #
    return $rc
} # End of "get_local_managed_system()"

#=============================================================================
#
# Name:        get_enterprise_pool
#
# Description: Obtain Enterprise Pool name. The name is gotten from the HMC,
#              or default to null.
#
# Arguments:   $1 [INOUT] epcod_name - reference to the enterprise pool name.
#              $2 [IN]    sys_name   - managed system name to search enterprise pool for.
#
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_enterprise_pool
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n epcod_name=$1
    typeset    sys_name=$2
    typeset    ms_filter=""
    typeset    out_str=""

    if [[ -z $epcod_name ]] ; then
        #=======================================================
        : First, look into ODM if the lpar name corresponds.
        #=======================================================
        if [[ $(ODMDIR="/etc/es/objrepos" clodmget -q "key=MANAGED_SYSTEM" -nf value HACMPdynresop 2>/dev/null) == $sys_name ]] ; then
            epcod_name=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=ENTERPRISE_POOL" -nf value HACMPdynresop 2>/dev/null)
            rc=$?
        fi

        if (( rc == $RC_SUCCESS )) && [[ -z $epcod_name ]] ; then
            #=======================================================
            : Then, ask the HMC to check for each enterprise pools
            : if it contains the managed system.
            #=======================================================

            [[ -z $ms_filter && $sys_name == +([a-z]|[A-Z]|[0-9])-+([a-z]|[A-Z]|[0-9])\*+([a-z]|[A-Z]|[0-9]) ]] \
                && ms_filter="mtms"
            [[ -z $ms_filter && -n $sys_name ]] \
                && ms_filter="names"

            if [[ -n $ms_filter ]] ; then
                clhmcexec "$func_HMCEXEC_managed_system_to_enterprise_pool ; HMCEXEC_managed_system_to_enterprise_pool $ms_filter $sys_name" out_str
                rc=$?
                if (( rc == $RC_SUCCESS )) && [[ $out_str != "No results were found." ]] ; then
                    epcod_name=$out_str
                else
                    epcod_name=""
                fi
            fi

            [[ -z $epcod_name ]] \
                && rc=$RC_FAILURE

        fi

    fi
    #
    : returning epcod_name=$epcod_name
    #
    return $rc
} # End of "get_enterprise_pool()"

#=============================================================================
#
# Name:        get_profile
#
# Description: Obtain partition profile name. The name is gotten from the HMC,
#              or default to null.
#
# Arguments:   $1 [INOUT] prof_name - reference to the profile name.
#              $2 [IN]    lpar_name - partition name to search profile for.
#              $3 [IN]    sys_name  - managed system name matching lpar name
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_profile
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n prof_name=$1
    typeset    lpar_name=$2
    typeset    sys_name=$3

    if [[ -z $prof_name ]] ; then
        #=======================================================
        : Ask the HMC.
        #=======================================================
        clhmcexec "lssyscfg -m $sys_name -r lpar --filter lpar_names=$lpar_name -F curr_profile" prof_name
        rc=$?

        if (( rc == $RC_SUCCESS )) && [[ -z $prof_name ]] ; then
            #=======================================================
            : Unset and return failure.
            #=======================================================
            prof_name=""
            rc=$RC_FAILURE
        fi

    fi
    #
    : returning prof_name=$prof_name
    #
    return $rc
} # End of "get_profile()"

#=============================================================================
#
# Name:        get_shared_processor_pool
#
# Description: Obtain shared processor pool name. The name is gotten from the
#              HMC, or default to null.
#
# Arguments:   $1 [INOUT] spp_name  - reference to the shared processor pool name.
#              $2 [IN]    lpar_name - partition name to search shared processor pool for.
#              $3 [IN]    sys_name  - managed system name matching lpar name
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_shared_processor_pool
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n spp_name=$1
    typeset    lpar_name=$2
    typeset    sys_name=$3

    if [[ -z $spp_name ]] ; then
        #=======================================================
        : First, ask the HMC.
        #=======================================================
        clhmcexec "lshwres -m $sys_name -r proc --level lpar --filter lpar_names=$lpar_name -F curr_shared_proc_pool_name" spp_name
        rc=$?

        if (( rc == $RC_SUCCESS )) && [[ -z $spp_name || $spp_name == "null" ]] ; then
            #=======================================================
            : Then, unset and return failure.
            : The previous command may return null string on
            : dedicated lpars.
            #=======================================================
            spp_name=""
            rc=$RC_FAILURE
        fi

    fi
    #
    : returning spp_name=$spp_name
    #
    return $rc
} # End of "get_shared_processor_pool()"

#=============================================================================
#
# Name:        get_lpars_state
#
# Description: Obtain state of partitions in order to apply different behavior for
#              several functions.
#
# Arguments:   $1 [IN]    sys_name  - managed system name on which we parse lpars.
#
# Globals:     g_not_act_lpars_list - List of lpars in state Not Activated.
#              g_running_lpars_list - List of lpars in any other state.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_lpars_state
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset sys_name=$1
    typeset lpar_name= lpar_state=
    typeset res=

    g_not_act_lpars_list=""
    g_running_lpars_list=""

    clhmcexec "lssyscfg -m $sys_name -r lpar -F name:state" res
    rc=$?
    (( rc == $RC_SUCCESS )) && print "$res" | \
        while IFS=: read lpar_name lpar_state ; do
            [[ $lpar_state == "Not Activated" ]] \
                && g_not_act_lpars_list="${g_not_act_lpars_list}${g_not_act_lpars_list:+,}${lpar_name}" \
                || g_running_lpars_list="${g_running_lpars_list}${g_running_lpars_list:+,}${lpar_name}"
        done

    return $rc
}

#=============================================================================
#
# Name:        get_free_sys_mem
#
# Description: Obtain available amount of memory by considering shutdowned
#              partitions, and by considering shared memory pool.
#
# Arguments:   $1 [INOUT] mem_avail - reference to the available memory.
#              $2 [IN]    sys_name  - managed system name to search available memory for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_free_sys_mem
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n mem_avail=$1
    typeset sys_name=$2
    typeset configurable_sys_mem= sys_firmware_mem= run_mem= curr_mem=
    typeset lpar_name= lpar_state=
    typeset curr_pool_mem=
    typeset res=

    #=======================================================
    : Get configurable memory
    #=======================================================
    clhmcexec "lshwres -m $sys_name --level sys -r mem -F configurable_sys_mem:sys_firmware_mem" res
    rc=$?

    #=======================================================
    : Substract memory used by other partitions
    #   First separate lpars depending on their state
    #=======================================================
    if (( rc == $RC_SUCCESS )) ; then
        print "$res" | IFS=: read configurable_sys_mem sys_firmware_mem
        (( mem_avail = configurable_sys_mem - sys_firmware_mem ))

        [[ -z $g_not_act_lpars_list ]] && [[ -z $g_running_lpars_list ]] \
            && get_lpars_state $sys_name

    fi
    #=======================================================
    #   For Not Activated ones, consider run_mem
    #=======================================================
    if (( rc == $RC_SUCCESS )) && [[ -n $g_not_act_lpars_list ]] ; then
        clhmcexec "lshwres -m $sys_name -r mem --level lpar --filter \"\\\"lpar_names=$g_not_act_lpars_list\\\"\" -F run_mem" res
        rc=$?
        (( rc == $RC_SUCCESS )) && print "$res" | \
            while read run_mem ; do
                (( mem_avail -= run_mem ))
            done
    fi
    #=======================================================
    #   For other ones, consider curr_mem
    #=======================================================
    if (( rc == $RC_SUCCESS )) && [[ -n $g_running_lpars_list ]] ; then
        clhmcexec "lshwres -m $sys_name -r mem --level lpar --filter \"\\\"lpar_names=$g_running_lpars_list\\\"\" -F curr_mem" res
        rc=$?
        (( rc == $RC_SUCCESS )) && print "$res" | \
            while read curr_mem ; do
                (( mem_avail -= curr_mem ))
            done
    fi

    #=======================================================
    : Substract memory used by shared memory pool.
    #=======================================================
    if (( rc == $RC_SUCCESS )) ; then
        clhmcexec "lshwres -m $sys_name -r mempool -F curr_pool_mem" curr_pool_mem
        rc=$?
        if (( rc == $RC_SUCCESS )) && [[ $curr_pool_mem != "No results were found." ]] ; then
            (( mem_avail -= curr_pool_mem ))
        fi
    fi
	
    #=============================================
    : Available memory should be a positive value.
    #=============================================
    if (( mem_avail < 0.00 )); then 
        mem_avail=0.00
    fi

    return $rc
} # End of "get_free_sys_mem()"

#=============================================================================
#
# Name:        get_free_sys_proc_units
#
# Description: Provide computed available processing units by considering
#              shutdowned partitions, and by considering reserved of shared processor pools.
#
# Arguments:   $1 [INOUT] proc_units_avail - reference to the available processing units.
#              $2 [IN]    sys_name         - managed system name to search available processing units for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_free_sys_proc_units
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n proc_units_avail=$1
    typeset sys_name=$2
    typeset configurable_sys_proc_units= curr_proc_mode= run_proc_units= curr_proc_units= run_procs= curr_procs=
    typeset lpar_name= lpar_state=
    typeset procpool_name= procpool_reserved=
    typeset res=

    #=======================================================
    : Get configurable processing units
    #=======================================================
    clhmcexec "lshwres -m $sys_name --level sys -r proc -F configurable_sys_proc_units" configurable_sys_proc_units
    rc=$?

    #=======================================================
    : Substract processing units used by other partition
    #   First separate lpars depending on their state
    #=======================================================
    if (( rc == $RC_SUCCESS )) ; then
        (( proc_units_avail = configurable_sys_proc_units ))

        [[ -z $g_not_act_lpars_list ]] && [[ -z $g_running_lpars_list ]] \
            && get_lpars_state $sys_name

    fi
    #=======================================================
    #   For Not Activated ones, consider run_procs
    #=======================================================
    if (( rc == $RC_SUCCESS )) && [[ -n $g_not_act_lpars_list ]] ; then
        clhmcexec "lshwres -m $sys_name -r proc --level lpar --filter \"\\\"lpar_names=$g_not_act_lpars_list\\\"\" -F curr_proc_mode:run_proc_units:run_procs" res
        rc=$?
        (( rc == $RC_SUCCESS )) && print "$res" | \
            while IFS=: read curr_proc_mode run_proc_units run_procs ; do
                if [[ $curr_proc_mode == "shared" ]] ; then
                    (( proc_units_avail -= run_proc_units ))
                elif [[ $curr_proc_mode == "ded" ]] ; then
                    (( proc_units_avail -= run_procs ))
                fi
            done
    fi
    #=======================================================
    #   For other ones, consider curr_procs
    #=======================================================
    if (( rc == $RC_SUCCESS )) && [[ -n $g_running_lpars_list ]] ; then
        clhmcexec "lshwres -m $sys_name -r proc --level lpar --filter \"\\\"lpar_names=$g_running_lpars_list\\\"\" -F curr_proc_mode:curr_proc_units:curr_procs" res
        rc=$?
        (( rc == $RC_SUCCESS )) && print "$res" | \
            while IFS=: read curr_proc_mode curr_proc_units curr_procs ; do
                if [[ $curr_proc_mode == "shared" ]] ; then
                    (( proc_units_avail -= curr_proc_units ))
                elif [[ $curr_proc_mode == "ded" ]] ; then
                    (( proc_units_avail -= curr_procs ))
                fi
            done
    fi

    #=======================================================
    : Substract processing units used by shared pool. Do not
    : consider DefaultPool which has no reserved.
    #=======================================================
    if (( rc == $RC_SUCCESS )) ; then
        clhmcexec "lshwres -m $sys_name -r procpool -F name:curr_reserved_pool_proc_units" res
        rc=$?
        if (( rc == $RC_SUCCESS )) ; then
            print "$res"  | grep -wv DefaultPool | \
            while IFS=: read procpool_name procpool_reserved ; do
                (( proc_units_avail -= procpool_reserved ))
            done
        fi
    fi

    #=========================================
    : Available Proc units should be positive.
    #=========================================
    if (( proc_units_avail < 0.00 )); then 
        proc_units_avail=0.00
    fi

    return $RC_SUCCESS
} # End of "get_free_sys_proc_units()"

#=============================================================================
#
# Name:        get_free_pool_proc_units
#
# Description: Obtain current available processing units in shared processor
#              pool
#
# Arguments:   $1 [INOUT] proc_units_avail - reference to the available processing units.
#              $2 [IN]    sys_name         - managed system name of the shared processor pool.
#              $3 [IN]    procpool_name    - shared processor pool name to search available processing units for.
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=============================================================================
function get_free_pool_proc_units
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS

    typeset -n proc_units_avail=$1
    typeset sys_name=$2
    typeset procpool_name=$3

    typeset -F4 max=0.00 reserved=0.00 curr_proc_units=0.00
    typeset lpar_list="" lpar_name="" res=""

    if [[ $procpool_name != "DefaultPool" ]] ; then

        #=======================================================
        : Get attributes for shared processor pool
        #=======================================================
        clhmcexec "lshwres -m $sys_name -r procpool --filter pool_names=$procpool_name -F max_pool_proc_units:curr_reserved_pool_proc_units:lpar_names" res
        rc=$?
        if (( rc == $RC_SUCCESS )) ; then

            print "$res" | IFS=: read max reserved lpar_list

            (( proc_units_avail = max - reserved ))

            #=======================================================
            : Substract processing units used by other partitions
            : in the shared processor pool
            #=======================================================
            clhmcexec "lshwres -m $sys_name -r proc --level lpar --filter \"\\\"lpar_names=$lpar_list\\\"\" -F curr_proc_units" res
            rc=$?
            (( rc == $RC_SUCCESS )) && print "$res" | \
                while read curr_proc_units ; do
                    (( proc_units_avail -= curr_proc_units ))
                done

            #=========================================
            : Available Proc Units should be positive.
            #=========================================
            if (( proc_units_avail < 0.00 )); then 
                proc_units_avail=0.00
            fi
        fi

    else

        proc_units_avail="unknown"

    fi

    return $RC_SUCCESS
} # End of "get_free_pool_proc_units()"

#=============================================================================
#
# Name:        gather_and_convert
#
# Description: Gather together attributes that should be executed by the same
#              HMC command. Also convert attributes to be HMC compatible.
#
# Arguments:   $1 [IN]    attrs - space-separated list of attributes.
#              $2 [INOUT] cmds  - reference to the array of attributes for each command.
#
# Environment: g_convtabHMC78
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function gather_and_convert
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset attrs=$1
    typeset -n cmds=$2

    for attr in $attrs ; do
        case $attr in

        #=======================================================
        # 0. local
        #=======================================================
        hmc_list|hmc_version|local_sys_name|local_lpar_name|local_prof_name|local_procpool_name|local_codpool_name)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;

        #=======================================================
        # 1. cec_sys (lssyscfg -m $g_managed_system -r sys)
        #=======================================================
        sys_name|sys_state|sys_type_model|cod_mem_capable|cod_proc_capable)
            cmds.cec_sys=${cmds.cec_sys:+"${cmds.cec_sys}:"}${g_convtabHMC78[$attr]}
            ;;
        sys_lpar_names)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;

        #=======================================================
        # 2. cec_mem (lshwres -m $g_managed_system --level sys -r mem)
        #=======================================================
        mem_region_size|installed_sys_mem|configurable_sys_mem|sys_firmware_mem|curr_avail_sys_mem|deconfig_sys_mem)
            cmds.cec_mem=${cmds.cec_mem:+"${cmds.cec_mem}:"}${g_convtabHMC78[$attr]}
            ;;
        curr_free_sys_mem)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;

        #=======================================================
        # 3. cec_proc (lshwres -m $g_managed_system --level sys -r proc)
        #=======================================================
        installed_sys_proc_units|configurable_sys_proc_units|curr_avail_sys_proc_units|min_proc_units_per_virtual_proc|deconfig_sys_proc_units)
            cmds.cec_proc=${cmds.cec_proc:+"${cmds.cec_proc}:"}${g_convtabHMC78[$attr]}
            ;;
        curr_free_sys_proc_units)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;

        #=======================================================
        # 4. lpar_sys (lssyscfg -m $g_managed_system -r lpar --filter lpar_names=$g_partition)
        #=======================================================
        lpar_name|lpar_id|uuid|lpar_state|curr_profile|lpar_avail_priority)
            cmds.lpar_sys=${cmds.lpar_sys:+"${cmds.lpar_sys}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 5. lpar_prof (lssyscfg -m $g_managed_system -r prof --filter profile_names=$g_profile,lpar_names=$g_partition)
        #=======================================================
        prof_name|prof_proc_mode|prof_sharing_mode|prof_shared_procpool|prof_minimum_mem|prof_minimum_procs|prof_minimum_proc_units|prof_desired_mem|prof_desired_procs|prof_desired_proc_units|prof_maximum_mem|prof_maximum_procs|prof_maximum_proc_units)
            cmds.lpar_prof=${cmds.lpar_prof:+"${cmds.lpar_prof}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 6. lpar_mem (lshwres -m $g_managed_system -r mem --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_min_mem|curr_mem|curr_max_mem)
            cmds.lpar_mem=${cmds.lpar_mem:+"${cmds.lpar_mem}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 7. lpar_proc (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_proc_mode|curr_min_procs|curr_procs|curr_max_procs|curr_min_proc_units|curr_proc_units|curr_max_proc_units)
            cmds.lpar_proc=${cmds.lpar_proc:+"${cmds.lpar_proc}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 8. lpar_procpool (lshwres -m $g_managed_system -r procpool --filter pool_names=$g_shared_proc_pool)
        #=======================================================
        procpool_name|max_pool_proc_units|curr_reserved_pool_proc_units)
            cmds.lpar_procpool=${cmds.lpar_procpool:+"${cmds.lpar_procpool}:"}${g_convtabHMC78[$attr]}
            ;;
        curr_free_pool_proc_units)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;

        #=======================================================
        # 9. trial_mem (lscod -t cap -m $g_managed_system -c trial -r mem)
        #=======================================================
        mem_trial_state|activated_trial_mem|mem_trial_days_left|mem_trial_hours_left)
            cmds.trial_mem=${cmds.trial_mem:+"${cmds.trial_mem}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 10. trial_proc (lscod -t cap -m $g_managed_system -c trial -r proc)
        #=======================================================
        proc_trial_state|activated_trial_procs|proc_trial_days_left|proc_trial_hours_left)
            cmds.trial_proc=${cmds.trial_proc:+"${cmds.trial_proc}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 11. onoff_mem (lscod -t cap -m $g_managed_system -c onoff -r mem)
        #=======================================================
        mem_onoff_state|activated_onoff_mem|avail_mem_for_onoff|unreturned_onoff_mem|onoff_request_mem_days_left|onoff_mem_day_hours_left|onoff_mem_days_avail)
            cmds.onoff_mem=${cmds.onoff_mem:+"${cmds.onoff_mem}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 12. onoff_proc (lscod -t cap -m $g_managed_system -c onoff -r proc)
        #=======================================================
        proc_onoff_state|activated_onoff_procs|avail_procs_for_onoff|unreturned_onoff_procs|onoff_request_proc_days_left|onoff_proc_day_hours_left|onoff_proc_days_avail)
            cmds.onoff_proc=${cmds.onoff_proc:+"${cmds.onoff_proc}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 13. epcod_pool (lscodpool -p $g_enterprise_pool --level pool)
        #=======================================================
        codpool_name|mobile_state|master_mc_name|backup_master_mc_name|mobile_mem|avail_mobile_mem|unreturned_mobile_mem|mobile_procs|avail_mobile_procs|unreturned_mobile_procs)
            cmds.epcod_pool=${cmds.epcod_pool:+"${cmds.epcod_pool}:"}${g_convtabHMC78[$attr]}
            ;;

        #=======================================================
        # 14. epcod_sys (lscodpool -p $g_enterprise_pool --level sys --filter names=$g_managed_system)
        #=======================================================
        sys_mobile_mem|sys_unreturned_mobile_mem|sys_inactive_mem|sys_mobile_procs|sys_unreturned_mobile_procs|sys_inactive_procs)
            cmds.epcod_sys=${cmds.epcod_sys:+"${cmds.epcod_sys}:"}${g_convtabHMC78[$attr]}
            ;;
        codpool_sys_names)
            # Do nothing here. it will be added to the output list in sort_and_output
            ;;
        #=======================================================
        # 15. lpar_cspp (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_shared_proc_pool_name)
            cmds.lpar_cspp=${cmds.lpar_cspp:+"${cmds.lpar_cspp}:"}${g_convtabHMC78[$attr]}
            ;;
        esac
    done

    return $RC_SUCCESS
} # End of "gather_and_convert()"

#=============================================================================
#
# Name:        execute_query_cmds
#
# Description: Execute sequentially at most 14 HMC commands, if needed among
#              'lssyscfg', 'lshwres', 'lscod', and 'lscodpool'. If the command
#              can not be issued or returns an error, the corresponding
#              attributes are default to null and the function succeeds.
#
# Arguments:   $1 [IN]    cmds - reference to the array of attributes for each command.
#              $2 [INOUT] res  - reference to the array of results for each command.
#
# Environment: g_partition
#              g_managed_system
#              g_profile
#              g_shared_proc_pool
#              g_enterprise_pool
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function execute_query_cmds
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n cmd=$1
    typeset -n res=$2
    typeset attrs_list= list_out=

    #=======================================================
    # This function sets all fields from input to unknown.
    # It has to be defined as func() to allow compound
    # variable res.xxx to be known inside this embedded
    # function, or else a 'no parent' error will occur.
    #=======================================================
    fill_with_unknown()
    {
        typeset -n out=$2
        for attr in ${1//:/ } ; do
            out=${out:+"$out:"}"unknown"
        done
    } # End of "fill_with_unknown()"

    #=======================================================
    # 1. cec_sys
    #=======================================================
    if [[ -n ${cmd.cec_sys} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.cec_sys} res.cec_sys
        else
            clhmcexec "lssyscfg -m $g_managed_system -r sys -F ${cmd.cec_sys}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.cec_sys} res.cec_sys
            else
                res.cec_sys=$list_out
            fi
        fi
    fi

    #=======================================================
    # 2. cec_mem
    #=======================================================
    if [[ -n ${cmd.cec_mem} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.cec_mem} res.cec_mem
        else
            clhmcexec "lshwres -m $g_managed_system --level sys -r mem -F ${cmd.cec_mem}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.cec_mem} res.cec_mem
            else
                res.cec_mem=$list_out
            fi
        fi
    fi

    #=======================================================
    # 3. cec_proc
    #=======================================================
    if [[ -n ${cmd.cec_proc} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.cec_proc} res.cec_proc
        else
            clhmcexec "lshwres -m $g_managed_system --level sys -r proc -F ${cmd.cec_proc}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.cec_proc} res.cec_proc
            else
                res.cec_proc=$list_out
            fi
        fi
    fi

    #=======================================================
    # 4. lpar_sys
    #=======================================================
    if [[ -n ${cmd.lpar_sys} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_partition || -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.lpar_sys} res.lpar_sys
        else
            clhmcexec "lssyscfg -m $g_managed_system -r lpar --filter lpar_names=$g_partition -F ${cmd.lpar_sys}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_sys} res.lpar_sys
            else
                res.lpar_sys=$list_out
            fi
        fi
    fi

    #=======================================================
    # 5. lpar_prof
    #=======================================================
    if [[ -n ${cmd.lpar_prof} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        [[ -z $g_profile ]] && get_profile g_profile $g_partition $g_managed_system
        if [[ -z $g_partition || -z $g_managed_system || -z $g_profile ]] ; then
            fill_with_unknown ${cmd.lpar_prof} res.lpar_prof
        else
            clhmcexec "lssyscfg -m $g_managed_system -r prof --filter profile_names=$g_profile,lpar_names=$g_partition -F ${cmd.lpar_prof}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_prof} res.lpar_prof
            else
                res.lpar_prof=$list_out
            fi
        fi
    fi

    #=======================================================
    # 6. lpar_mem
    #=======================================================
    if [[ -n ${cmd.lpar_mem} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_partition || -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.lpar_mem} res.lpar_mem
        else
            clhmcexec "lshwres -m $g_managed_system -r mem --level lpar --filter lpar_names=$g_partition -F ${cmd.lpar_mem}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_mem} res.lpar_mem
            else
                res.lpar_mem=$list_out
            fi
        fi
    fi

    #=======================================================
    # 7. lpar_proc
    #=======================================================
    if [[ -n ${cmd.lpar_proc} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_partition || -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.lpar_proc} res.lpar_proc
        else
            clhmcexec "lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition -F ${cmd.lpar_proc}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_proc} res.lpar_proc
            else
                res.lpar_proc=$list_out
            fi
        fi
    fi

    #=======================================================
    # 8. lpar_procpool
    #=======================================================
    if [[ -n ${cmd.lpar_procpool} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        [[ -z $g_shared_proc_pool ]] && get_shared_processor_pool g_shared_proc_pool $g_partition $g_managed_system
        if [[ -z $g_managed_system || -z $g_shared_proc_pool ]] ; then
            fill_with_unknown ${cmd.lpar_procpool} res.lpar_procpool
        else
            clhmcexec "lshwres -m $g_managed_system -r procpool --filter pool_names=$g_shared_proc_pool -F ${cmd.lpar_procpool}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_procpool} res.lpar_procpool
            else
                res.lpar_procpool=$list_out
            fi
        fi
    fi

    #=======================================================
    # 9. trial_mem
    #=======================================================
    if [[ -n ${cmd.trial_mem} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.trial_mem} res.trial_mem
        else
            clhmcexec "lscod -t cap -m $g_managed_system -c trial -r mem -F ${cmd.trial_mem}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.trial_mem} res.trial_mem
            else
                res.trial_mem=$list_out
            fi
        fi
    fi

    #=======================================================
    # 10. trial_proc
    #=======================================================
    if [[ -n ${cmd.trial_proc} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.trial_proc} res.trial_proc
        else
            clhmcexec "lscod -t cap -m $g_managed_system -c trial -r proc -F ${cmd.trial_proc}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.trial_proc} res.trial_proc
            else
                res.trial_proc=$list_out
            fi
        fi
    fi

    #=======================================================
    # 11. onoff_mem
    #=======================================================
    if [[ -n ${cmd.onoff_mem} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.onoff_mem} res.onoff_mem
        else
            clhmcexec "lscod -t cap -m $g_managed_system -c onoff -r mem -F ${cmd.onoff_mem}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.onoff_mem} res.onoff_mem
            else
                res.onoff_mem=$list_out
            fi
        fi
    fi

    #=======================================================
    # 12. onoff_proc
    #=======================================================
    if [[ -n ${cmd.onoff_proc} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.onoff_proc} res.onoff_proc
        else
            clhmcexec "lscod -t cap -m $g_managed_system -c onoff -r proc -F ${cmd.onoff_proc}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.onoff_proc} res.onoff_proc
            else
                res.onoff_proc=$list_out
            fi
        fi
    fi

    #=======================================================
    # 13. epcod_pool
    #=======================================================
    if [[ -n ${cmd.epcod_pool} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
        if [[ -z $g_enterprise_pool ]] ; then
            fill_with_unknown ${cmd.epcod_pool} res.epcod_pool
        else
            #=======================================================
            # Query operation on ENterprise Pool does not care
            # about Master HMC.
            #=======================================================
            g_epcod_modify_operation=0
            if [[ ${cmd.epcod_pool} == "name" ]] ; then
                list_out=$g_enterprise_pool
                rc=$RC_SUCCESS
            else
                clhmcexec "lscodpool -p $g_enterprise_pool --level pool -F ${cmd.epcod_pool}" list_out
                rc=$?
            fi
            if (( rc != $RC_SUCCESS )) ; then
                fill_with_unknown ${cmd.epcod_pool} res.epcod_pool
            else
                res.epcod_pool=$list_out
            fi
        fi
    fi

    #=======================================================
    # 14. epcod_sys
    #=======================================================
    if [[ -n ${cmd.epcod_sys} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
        if [[ -z $g_enterprise_pool ]] ; then
            fill_with_unknown ${cmd.epcod_sys} res.epcod_sys
        else
            #=======================================================
            # Query operation on Enterprise Pool does not care
            # about Master HMC.
            #=======================================================
            g_epcod_modify_operation=0
            clhmcexec "lscodpool -p $g_enterprise_pool --level sys --filter names=$g_managed_system -F ${cmd.epcod_sys}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.epcod_sys} res.epcod_sys
            else
                res.epcod_sys=$list_out
            fi
        fi
    fi

    #=======================================================
    # 15. lpar_cspp
    #=======================================================
    # Retrieving shared processor pool inforation. Though it can be queried with LPAR attributes, 
    # but you may get incorrect data for all the process related attributes when shared processor
    # pool capability is not enabled. 
    if [[ -n ${cmd.lpar_cspp} ]] ; then
        [[ -z $g_partition ]] && get_local_partition g_partition
        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -z $g_partition || -z $g_managed_system ]] ; then
            fill_with_unknown ${cmd.lpar_cspp} res.lpar_cspp
        else
            clhmcexec "lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition -F ${cmd.lpar_cspp}" list_out
            rc=$?
            if (( rc > 0 )) ; then
                fill_with_unknown ${cmd.lpar_cspp} res.lpar_cspp
            else
                res.lpar_cspp=$list_out
            fi
        fi
    fi

    return $RC_SUCCESS
} # End of "execute_query_cmds()"

#=============================================================================
#
# Name:        sort_and_output
#
# Description: Sort results from hmc commands to match input order of
#              attributes.
#
# Arguments:   $1 [IN]    res      - reference to the array of results for each command.
#              $2 [IN]    list_in  - space-separated list of attributes.
#              $3 [INOUT] list_out - colon-separated list of value for each attributes.
#
# Environment: g_partition
#              g_managed_system
#              g_local_partition
#              g_local_managed_system
#              g_local_profile
#              g_local_shared_processor_pool
#              g_local_enterprise_pool
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function sort_and_output
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n res=$1
    typeset list_in=$2
    typeset -n list_out=$3
    typeset -i cec_sys_idx=0
    typeset -i cec_mem_idx=0
    typeset -i cec_proc_idx=0
    typeset -i lpar_sys_idx=0
    typeset -i lpar_prof_idx=0
    typeset -i lpar_mem_idx=0
    typeset -i lpar_proc_idx=0
    typeset -i lpar_proc_idx2=0
    typeset -i lpar_procpool_idx=0
    typeset -i trial_mem_idx=0
    typeset -i trial_proc_idx=0
    typeset -i onoff_mem_idx=0
    typeset -i onoff_proc_idx=0
    typeset -i epcod_pool_idx=0
    typeset -i epcod_sys_idx=0

    for attr in $list_in ; do
        case $attr in

        #=======================================================
        # 0. local
        #=======================================================
        hmc_list)
            if [[ -n $g_hmc_list ]] ; then
                hmc_list=$g_hmc_list
            else
                hmc_list=$(cl_get_hmc_list)
            fi
            list_out=${list_out:+"$list_out:"}${hmc_list:-unknown}
            ;;
        hmc_version)
            clhmcexec "lshmc -v" hmc_version
            hmc_version=$(print "$hmc_version" | sed -n 's/.*\*RM \([^ ]\)/\1/p')
            list_out=${list_out:+"$list_out:"}${hmc_version:-unknown}
            ;;
        local_sys_name)
            [[ -z $g_local_partition ]] && get_local_partition g_local_partition
            [[ -z $g_local_managed_system ]] && get_managed_system g_local_managed_system $g_local_partition
            list_out=${list_out:+"$list_out:"}${g_local_managed_system:-unknown}
            ;;
        local_lpar_name)
            [[ -z $g_local_partition ]] && get_local_partition g_local_partition
            list_out=${list_out:+"$list_out:"}${g_local_partition:-unknown}
            ;;
        local_prof_name)
            [[ -z $g_local_partition ]] && get_local_partition g_local_partition
            [[ -z $g_local_managed_system ]] && get_managed_system g_local_managed_system $g_local_partition
            [[ -z $g_local_profile ]] && get_profile g_local_profile $g_local_partition $g_local_managed_system
            list_out=${list_out:+"$list_out:"}${g_local_profile:-unknown}
            ;;
        local_procpool_name)
            [[ -z $g_local_partition ]] && get_local_partition g_local_partition
            [[ -z $g_local_managed_system ]] && get_managed_system g_local_managed_system $g_local_partition
            [[ -z $g_local_shared_processor_pool ]] && get_shared_processor_pool g_local_shared_processor_pool $g_local_partition $g_local_managed_system
            list_out=${list_out:+"$list_out:"}${g_local_shared_processor_pool:-unknown}
            ;;
        local_codpool_name)
            [[ -z $g_local_partition ]] && get_local_partition g_local_partition
            [[ -z $g_local_managed_system ]] && get_managed_system g_local_managed_system $g_local_partition
            [[ -z $g_local_enterprise_pool ]] && get_enterprise_pool g_local_enterprise_pool $g_local_managed_system
            list_out=${list_out:+"$list_out:"}${g_local_enterprise_pool:-unknown}
            ;;

        #=======================================================
        # 1. cec_sys (lssyscfg -m $g_managed_system -r sys)
        #=======================================================
        sys_name|sys_state|sys_type_model|cod_mem_capable|cod_proc_capable)
            print "${res.cec_sys}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$cec_sys_idx]}
            (( cec_sys_idx += 1 ))
            ;;
        sys_lpar_names)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            if [[ -n $g_managed_system ]] ; then
                clhmcexec "lssyscfg -m $g_managed_system -r lpar -F name" sys_lpar_names
            fi
            sys_lpar_names=$(print $sys_lpar_names|wc -w)
            list_out=${list_out:+"$list_out:"}${sys_lpar_names:-unknown}
            ;;

        #=======================================================
        # 2. cec_mem (lshwres -m $g_managed_system --level sys -r mem)
        #=======================================================
        mem_region_size|installed_sys_mem|configurable_sys_mem|sys_firmware_mem|curr_avail_sys_mem|deconfig_sys_mem)
            print "${res.cec_mem}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$cec_mem_idx]}
            (( cec_mem_idx += 1 ))
            ;;
        curr_free_sys_mem)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            if [[ -n $g_managed_system ]] ; then
                get_free_sys_mem value $g_managed_system
            fi
            list_out=${list_out:+"$list_out:"}${value:-unknown}
            ;;

        #=======================================================
        # 3. cec_proc (lshwres -m $g_managed_system --level sys -r proc)
        #=======================================================
        installed_sys_proc_units|configurable_sys_proc_units|curr_avail_sys_proc_units|min_proc_units_per_virtual_proc|deconfig_sys_proc_units)
            print "${res.cec_proc}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$cec_proc_idx]}
            (( cec_proc_idx += 1 ))
            ;;
        curr_free_sys_proc_units)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            if [[ -n $g_managed_system ]] ; then
                get_free_sys_proc_units value $g_managed_system
            fi
            list_out=${list_out:+"$list_out:"}${value:-unknown}
            ;;

        #=======================================================
        # 4. lpar_sys (lssyscfg -m $g_managed_system -r lpar --filter lpar_names=$g_partition)
        #=======================================================
        lpar_name|lpar_id|uuid|lpar_state|curr_profile|lpar_avail_priority)
            print "${res.lpar_sys}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_sys_idx]}
            (( lpar_sys_idx += 1 ))
            ;;

        #=======================================================
        # 5. lpar_prof (lssyscfg -m $g_managed_system -r prof --filter profile_names=$g_profile,lpar_names=$g_partition)
        #=======================================================
        prof_name|prof_proc_mode|prof_sharing_mode|prof_shared_procpool|prof_minimum_mem|prof_minimum_procs|prof_minimum_proc_units|prof_desired_mem|prof_desired_procs|prof_desired_proc_units|prof_maximum_mem|prof_maximum_procs|prof_maximum_proc_units)
            print "${res.lpar_prof}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_prof_idx]}
            (( lpar_prof_idx += 1 ))
            ;;

        #=======================================================
        # 6. lpar_mem (lshwres -m $g_managed_system -r mem --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_min_mem|curr_mem|curr_max_mem)
            print "${res.lpar_mem}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_mem_idx]}
            (( lpar_mem_idx += 1 ))
            ;;

        #=======================================================
        # 7. lpar_proc (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_proc_mode|curr_min_procs|curr_procs|curr_max_procs|curr_min_proc_units|curr_proc_units|curr_max_proc_units)
            print "${res.lpar_proc}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_proc_idx]}
            (( lpar_proc_idx += 1 ))
            ;;

        #=======================================================
        # 8. lpar_procpool (lshwres -m $g_managed_system -r procpool --filter pool_names=$g_shared_proc_pool)
        #=======================================================
        procpool_name|max_pool_proc_units|curr_reserved_pool_proc_units)
            print "${res.lpar_procpool}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_procpool_idx]}
            (( lpar_procpool_idx += 1 ))
            ;;
        curr_free_pool_proc_units)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            [[ -z $g_shared_proc_pool ]] && get_shared_processor_pool g_shared_proc_pool $g_partition $g_managed_system
            if [[ -n $g_managed_system && -n $g_shared_proc_pool ]] ; then
                get_free_pool_proc_units value $g_managed_system $g_shared_proc_pool
            fi
            list_out=${list_out:+"$list_out:"}${value:-unknown}
            ;;

        #=======================================================
        # 9. trial_mem (lscod -t cap -m $g_managed_system -c trial -r mem)
        #=======================================================
        mem_trial_state|activated_trial_mem|mem_trial_days_left|mem_trial_hours_left)
            print "${res.trial_mem}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$trial_mem_idx]}
            (( trial_mem_idx += 1 ))
            ;;

        #=======================================================
        # 10. trial_proc (lscod -t cap -m $g_managed_system -c trial -r proc)
        #=======================================================
        proc_trial_state|activated_trial_procs|proc_trial_days_left|proc_trial_hours_left)
            print "${res.trial_proc}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$trial_proc_idx]}
            (( trial_proc_idx += 1 ))
            ;;

        #=======================================================
        # 11. onoff_mem (lscod -t cap -m $g_managed_system -c onoff -r mem)
        #=======================================================
        mem_onoff_state|activated_onoff_mem|avail_mem_for_onoff|unreturned_onoff_mem|onoff_request_mem_days_left|onoff_mem_day_hours_left|onoff_mem_days_avail)
            print "${res.onoff_mem}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$onoff_mem_idx]}
            (( onoff_mem_idx += 1 ))
            ;;

        #=======================================================
        # 12. onoff_proc (lscod -t cap -m $g_managed_system -c onoff -r proc)
        #=======================================================
        proc_onoff_state|activated_onoff_procs|avail_procs_for_onoff|unreturned_onoff_procs|onoff_request_proc_days_left|onoff_proc_day_hours_left|onoff_proc_days_avail)
            print "${res.onoff_proc}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$onoff_proc_idx]}
            (( onoff_proc_idx += 1 ))
            ;;

        #=======================================================
        # 13. epcod_pool (lscodpool -p $g_enterprise_pool --level pool)
        #=======================================================
        codpool_name|mobile_state|master_mc_name|backup_master_mc_name|mobile_mem|avail_mobile_mem|unreturned_mobile_mem|mobile_procs|avail_mobile_procs|unreturned_mobile_procs)
            print "${res.epcod_pool}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$epcod_pool_idx]}
            (( epcod_pool_idx += 1 ))
            ;;

        #=======================================================
        # 14. epcod_sys (lscodpool -p $g_enterprise_pool --level sys --filter names=$g_managed_system)
        #=======================================================
        sys_mobile_mem|sys_unreturned_mobile_mem|sys_inactive_mem|sys_mobile_procs|sys_unreturned_mobile_procs|sys_inactive_procs)
            print "${res.epcod_sys}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$epcod_sys_idx]}
            (( epcod_sys_idx += 1 ))
            ;;
        codpool_sys_names)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
            if [[ -n $g_enterprise_pool ]] ; then
                clhmcexec "lscodpool -p $g_enterprise_pool --level sys -F name" codpool_sys_names
            fi
            codpool_sys_names=$(print $codpool_sys_names)
            list_out=${list_out:+"$list_out:"}${codpool_sys_names:-unknown}
            ;;
        #=======================================================
        # 15. lpar_cspp (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
        #=======================================================
        curr_shared_proc_pool_name)
            print "${res.lpar_cspp}" | IFS=: read -A tab
            list_out=${list_out:+"$list_out:"}${tab[$lpar_proc_idx2]}
            (( lpar_proc_idx2 += 1 ))
            ;;
        esac
    done

    return $RC_SUCCESS
} # End of "sort_and_output()"

#=============================================================================
#
# Name:        process_query
#
# Description: Process a 'query' operation on some attributes.
#
# Arguments:   None
#
# Environment: g_attributes
#              g_labels
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function process_query
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset attr_list=${g_attributes//:/ }
    typeset lbl_str="" out_str=""

    if (( g_labels == 1 )) ; then
        #=======================================================
        : Display header
        #=======================================================
        lbl_str="$g_attributes\n"
    fi

    typeset commands=( # colon-separated list of attributes
        typeset cec_sys
        typeset cec_mem
        typeset cec_proc
        typeset lpar_sys
        typeset lpar_prof
        typeset lpar_mem
        typeset lpar_proc
        typeset lpar_cspp
        typeset lpar_procpool
        typeset trial_mem
        typeset trial_proc
        typeset onoff_mem
        typeset onoff_proc
        typeset epcod_pool
        typeset epcod_sys
    )

    typeset results=( # colon-separated list of results
        typeset cec_sys
        typeset cec_mem
        typeset cec_proc
        typeset lpar_sys
        typeset lpar_prof
        typeset lpar_mem
        typeset lpar_proc
        typeset lpar_cspp
        typeset lpar_procpool
        typeset trial_mem
        typeset trial_proc
        typeset onoff_mem
        typeset onoff_proc
        typeset epcod_pool
        typeset epcod_sys
    )

    #=======================================================
    : First, gather attributes together by HMC commands and
    : convert them to comprehensible ones.
    #=======================================================
    gather_and_convert "$attr_list" commands

    #=======================================================
    : Then, execute all commands on HMC and obtain results.
    #=======================================================
    execute_query_cmds commands results

    #=======================================================
    : Finally, sort results to match attributes order and
    : format output.
    #=======================================================
    sort_and_output results "$attr_list" out_str

    print -- "${lbl_str}${out_str}"
    return $RC_SUCCESS
} # End of "process_query()"

#=============================================================================
#
# Name:        process_change
#
# Description: Process a 'change' operation on some attributes.
#
# Arguments:   None
#
# Environment: g_attributes
#              g_managed_system
#              g_shared_proc_pool
#
# Returns:     RC_SUCCESS
#              RC_PARAM_ERROR
#              or clhmcexec error code if an error occurs.
#
#=============================================================================
function process_change
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -i chg_rc=
    typeset out_str=

    print "${g_attributes//:/\\n}" | \
    while IFS='=' read key value ; do {
        case $key in
        max_pool_proc_units|reserved_pool_proc_units)
            [[ -z $g_partition ]] && get_local_partition g_partition
            [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
            [[ -z $g_shared_proc_pool ]] && get_shared_processor_pool g_shared_proc_pool $g_partition $g_managed_system
            if [[ -n $g_shared_proc_pool ]] ; then
                clhmcexec "chhwres -m $g_managed_system -r procpool --poolname $g_shared_proc_pool -o s -a $key=$value" out_str
                chg_rc=$?
                if (( chg_rc > 0 )) ; then
                    rc=$chg_rc
                fi
            else
                dspmsg $ROHA_MSGS -s $ROHA_SET 421 \
                "%\1$s: ERROR: %\2$s Shared Processor Pool does not belong to %\3$s LPAR. Provide valid name through -S or -L option.\n" \
                "$PROGNAME" "$g_shared_proc_pool" "$g_partition" >&3
                rc=$RC_PARAM_ERROR
                break
            fi
            ;;
        esac
    } < /dev/null ; done # Avoid ssh to break while loop by redirecting standard input

    return $rc
} # End of "process_change()"

#=============================================================================
#
# Name:        process_acquire
#
# Description: Process an 'acquire' operation of DLPAR, On/Off CoD or
#              Enterprise Pool CoD memory, processing unit(s) and/or CPU(s)
#              for the partition. Memory is acquired first, then CPU.
#
# Arguments:   None
#
# Environment: g_resource
#              g_memory
#              g_quantity
#              g_proc_units
#              g_force
#              g_partition
#              g_managed_system
#              g_enterprise_pool
#
# Returns:     RC_SUCCESS
#              RC_PARAM_ERROR
#              or clhmcexec error code if an error occurs.
#
#=============================================================================
function process_acquire
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset out_str=

    [[ -z $g_partition ]] && get_local_partition g_partition
    if [[ -n $g_partition ]] ; then

        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -n $g_managed_system ]] ; then

            case $g_resource in
            dlpar)
                g_enable_timeout=1

                if (( $g_force == 1 )) ; then
                    #=======================================================
                    : case where g_force = 1
                    #=======================================================

                    #=======================================================
                    : mem and procs are separately done
                    #=======================================================

                    typeset mem_rc=$RC_UNKNOWN
                    typeset procs_rc=$RC_UNKNOWN

                    #=======================================================
                    : Compute timeout dynamically by adding to the default
                    : timeout, the greatest from memory, processor and
                    : processing units.
                    #=======================================================
                    (( g_timeout += g_memory/1024 > g_proc_units ? $(( g_memory/1024 > g_quantity ? g_memory/1024 : g_quantity )) : g_proc_units ))

                    #=======================================================
                    : Acquire memory.
                    #=======================================================
                    if (( $g_memory > 0 )) ; then
                        clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o a -q $g_memory" out_str
                        mem_rc=$?
                        if (( $mem_rc == $RC_SUCCESS )) ; then
                            typeset -F4 mem_gb=$g_memory
                            (( mem_gb /= 1024 ))
                            dspmsg $ROHA_MSGS -s $ROHA_SET 537 \
                                "%1\$s: %2\$d GB of DLPAR resources have been allocated.\n" \
                                "$PROGNAME" "$mem_gb"
                        else
                            rc=$mem_rc
                        fi
                    fi

                    #=======================================================
                    : Acquire processors.
                    #=======================================================
                    if (( $g_quantity > 0 || $g_proc_units > 0 )) ; then
                        typeset opt_procs= opt_proc_units=
                        (( $g_quantity > 0 ))   && opt_procs="--procs $g_quantity"
                        (( $g_proc_units > 0 )) && opt_proc_units="--procunits $g_proc_units"
                        clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o a $opt_procs $opt_proc_units" out_str
                        procs_rc=$?
                        if (( $procs_rc == $RC_SUCCESS )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 538 \
                                "%1\$s: %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources have been allocated.\n" \
                                "$PROGNAME" "$g_quantity" "$g_proc_units"
                        else
                            rc=$procs_rc
                        fi
                    fi

                    #=======================================================
                    # in case of force, and for last loop of reassment,
                    #  we do not undo was was potentially done
                    #=======================================================
                    g_enable_timeout=0
                    return $rc
                fi

                #
                : case where g_force = 0
                #

                #=======================================================
                : Compute timeout dynamically by adding to the default
                : timeout, the greatest from memory, processor and
                : processing units.
                #=======================================================
                (( g_timeout += g_memory/1024 > g_proc_units ? $(( g_memory/1024 > g_quantity ? g_memory/1024 : g_quantity )) : g_proc_units ))

                #=======================================================
                : Acquire memory.
                #=======================================================
                if (( $g_memory > 0 )) ; then
                    clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o a -q $g_memory" out_str
                    rc=$?
                    if (( $rc == $RC_SUCCESS )) ; then
                        typeset -F4 mem_gb=$g_memory
                        (( mem_gb /= 1024 ))
                        dspmsg $ROHA_MSGS -s $ROHA_SET 537 \
                        "%1\$s: %2\$d GB of DLPAR resources have been allocated.\n" \
                        "$PROGNAME" "$mem_gb"
                    fi
                fi

                if (( $rc == $RC_SUCCESS )) ; then

                    #=======================================================
                    : Acquire processors.
                    #=======================================================
                    if (( $g_quantity > 0 || $g_proc_units > 0 )) ; then
                        typeset opt_procs= opt_proc_units=
                        (( $g_quantity > 0 ))   && opt_procs="--procs $g_quantity"
                        (( $g_proc_units > 0 )) && opt_proc_units="--procunits $g_proc_units"
                        clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o a $opt_procs $opt_proc_units" out_str
                        rc=$?
                        if (( $rc == $RC_SUCCESS )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 538 \
                            "%1\$s: %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources have been allocated.\n" \
                            "$PROGNAME" "$g_quantity" "$g_proc_units"
                        fi
                    fi

                    if (( $rc != $RC_SUCCESS )) ; then

                        #=======================================================
                        : Error while acquiring processors. The operation may
                        : have completed partially. Undo what has been acquired.
                        #=======================================================
                        typeset substr=$out_str
                        substr=${substr##*Amount of processors removed: }
                        substr=${substr%% *}
                        typeset -i cpu=$substr
                        typeset -F4 pu=$substr
                        if (( $cpu > 0 || $pu > 0 )) ; then
                            typeset opt_procs= opt_proc_units=
                            (( $cpu > 0 )) && opt_procs="--procs $cpu"
                            (( $pu  > 0 )) && opt_proc_units="--procunits $pu"
                            clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o r $opt_procs $opt_proc_units" out_str
                            if (( $? == $RC_SUCCESS )) ; then
                                dspmsg $ROHA_MSGS -s $ROHA_SET 539 \
                                "%1\$s: WARNING: allocation of %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources has been undone.\n" \
                                "$PROGNAME" "$pu" "$vp" >&3
                            fi
                        fi

                        #=======================================================
                        : Also, despite memory has succeeded, undo what has been
                        : acquired.
                        #=======================================================
                        if (( $g_memory > 0 )) ; then
                            clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o r -q $g_memory" out_str
                            if (( $? == $RC_SUCCESS )) ; then
                                typeset -F4 mem_gb=$g_memory
                                (( mem_gb /= 1024 ))
                                dspmsg $ROHA_MSGS -s $ROHA_SET 540 \
                                "%1\$s: WARNING: allocation of %2\$d GB of DLPAR resources has been undone.\n" \
                                "$PROGNAME" "$mem_gb" >&3
                            fi
                        fi

                    fi

                else

                    #=======================================================
                    : Error while acquiring memory. The operation may have
                    : completed partially. Undo what has been acquired.
                    #=======================================================
                    typeset substr=$out_str
                    print $substr | grep -q -i "Attention: Operation completed partially."
                    if (( $? == 0 )) ; then
                        substr=${substr##*Amount of memory added: }
                        substr=${substr%% *}
                        typeset -F4 mem_mb=$substr
                        if (( $mem_mb > 0 )) ; then
                            clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o r -q $mem_mb" out_str
                            if (( $? == $RC_SUCCESS )) ; then
                                typeset -F4 mem_gb=$mem_mb
                                (( mem_gb /= 1024 ))
                                dspmsg $ROHA_MSGS -s $ROHA_SET 540 \
                                "%1\$s: WARNING: allocation of %2\$d GB of DLPAR resources has been undone.\n" \
                                "$PROGNAME" "$mem_gb" >&3
                            fi
                        fi
                    fi

                fi
                g_enable_timeout=0
                ;;

            onoff)
                if (( $g_force == 1 )) ; then

                    #
                    : mem and procs are separately done
                    #

                    typeset mem_rc=$RC_UNKNOWN
                    typeset procs_rc=$RC_UNKNOWN

                    #=======================================================
                    : Acquire memory.
                    #=======================================================
                    if (( $g_memory > 0 )) ; then
                        clhmcexec "chcod -m $g_managed_system -r mem -c onoff -o a -q $g_memory -d $g_duration" out_str
                        mem_rc=$?
                        if (( $mem_rc == $RC_SUCCESS )) ; then
                            typeset -F4 mem_gb=$g_memory
                            (( mem_gb /= 1024 ))
                            dspmsg $ROHA_MSGS -s $ROHA_SET 320 \
                                "%1\$s: %2\$d GB of On/Off CoD resources have been activated for %3\$d days.\n" \
                                "$PROGNAME" "$mem_gb" "$g_duration"
                        fi
                    fi


                    #=======================================================
                    : Acquire processors.
                    #=======================================================
                    if (( $g_quantity > 0 )) ; then
                        clhmcexec "chcod -m $g_managed_system -r proc -c onoff -o a -q $g_quantity -d $g_duration" out_str
                        procs_rc=$?
                        if (( $procs_rc == $RC_SUCCESS )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 321 \
                                "%1\$s: %2\$d CPU(s) of On/Off CoD resources have been activated for %3\$d days.\n" \
                                "$PROGNAME" "$g_quantity" "$g_duration"
                        fi
                    fi

                    # in case of force, and for last loop of reassment,
                    #  we do not undo was was potentially done
                    return $rc
                fi


                #=======================================================
                : Acquire memory.
                #=======================================================
                if (( $g_memory > 0 )) ; then
                    clhmcexec "chcod -m $g_managed_system -r mem -c onoff -o a -q $g_memory -d $g_duration" out_str
                    rc=$?
                    if (( $rc == $RC_SUCCESS )) ; then
                        typeset -F4 mem_gb=$g_memory
                        (( mem_gb /= 1024 ))
                        dspmsg $ROHA_MSGS -s $ROHA_SET 320 \
                        "%1\$s: %2\$d GB of On/Off CoD resources have been activated for %3\$d days.\n" \
                        "$PROGNAME" "$mem_gb" "$g_duration"
                    fi
                fi


                if (( $rc == $RC_SUCCESS )) ; then

                    #=======================================================
                    : Acquire processors.
                    #=======================================================
                    if (( $g_quantity > 0 )) ; then
                        clhmcexec "chcod -m $g_managed_system -r proc -c onoff -o a -q $g_quantity -d $g_duration" out_str
                        rc=$?
                        if (( $rc == $RC_SUCCESS )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 321 \
                            "%1\$s: %2\$d CPU(s) of On/Off CoD resources have been activated for %3\$d days.\n" \
                            "$PROGNAME" "$g_quantity" "$g_duration"
                        fi
                    fi

                    if (( $rc != $RC_SUCCESS )) ; then

                        #=======================================================
                        : Also, despite memory has succeeded, undo what has been
                        : acquired.
                        #=======================================================
                        if (( $g_memory > 0 )) ; then
                            clhmcexec "chcod -m $g_managed_system -r mem -c onoff -o d" out_str
                            if (( $? == $RC_SUCCESS )) ; then
                                typeset -F4 mem_gb=$g_memory
                                (( mem_gb /= 1024 ))
                                dspmsg $ROHA_MSGS -s $ROHA_SET 541 \
                                "%1\$s: WARNING: activation of %2\$d GB of On/Off CoD resources has been undone.\n" \
                                "$PROGNAME" "$mem_gb" >&3
                            fi
                        fi

                    fi

                fi
                ;;

            epcod)
                if (( $g_force == 1 )) ; then
                     #
                     : mem and procs are separately done
                     #

                    [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
                    if [[ -n $g_enterprise_pool ]] ; then

                        g_epcod_modify_operation=1

                        #=======================================================
                        : Acquire memory.
                        #=======================================================
                        if (( $g_memory > 0 )) ; then
                            clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r mem -o add -q $g_memory" out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                typeset -F4 mem_gb=$g_memory
                                (( mem_gb /= 1024 ))
                                dspmsg $ROHA_MSGS -s $ROHA_SET 542 \
                                    "%1\$s: %2\$d GB of Enterprise Pool CoD have been acquired.\n" \
                                    "$PROGNAME" "$mem_gb"
                            fi
                        fi


                        #=======================================================
                        : Acquire processors.
                        #=======================================================
                        if (( $g_quantity > 0 )) ; then
                            clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r proc -o add -q $g_quantity" out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                dspmsg $ROHA_MSGS -s $ROHA_SET 543 \
                                    "%1\$s: %2\$d CPU(s) of Enterprise Pool CoD have been acquired.\n" \
                                    "$PROGNAME" "$g_quantity"
                            fi
                        fi

                        g_epcod_modify_operation=0

                        # in case of force, and for last loop of reassment,
                        #  we do not undo was was potentially done
                        return $rc
                    else

                        dspmsg $ROHA_MSGS -s $ROHA_SET 415 \
                            "%1\$s: ERROR: unknown %2\$s Enterprise Pool CoD. Provide valid name through -E option.\n" \
                            "$PROGNAME" "$g_enterprise_pool" >&3
                        rc=$RC_PARAM_ERROR

                    fi
                    return $rc
                fi


                [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
                if [[ -n $g_enterprise_pool ]] ; then

                    g_epcod_modify_operation=1

                    #=======================================================
                    : Acquire memory.
                    #=======================================================
                    if (( $g_memory > 0 )) ; then
                        clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r mem -o add -q $g_memory" out_str
                        rc=$?
                        if (( $rc == $RC_SUCCESS )) ; then
                            typeset -F4 mem_gb=$g_memory
                            (( mem_gb /= 1024 ))
                            dspmsg $ROHA_MSGS -s $ROHA_SET 330 \
                            "%1\$s: %2\$d GB of Enterprise Pool CoD have been acquired.\n" \
                            "$PROGNAME" "$mem_gb"
                        fi
                    fi

                    if (( $rc == $RC_SUCCESS )) ; then

                        #=======================================================
                        : Acquire processors.
                        #=======================================================
                        if (( $g_quantity > 0 )) ; then
                            clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r proc -o add -q $g_quantity" out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                dspmsg $ROHA_MSGS -s $ROHA_SET 331 \
                                "%1\$s: %2\$d CPU(s) of Enterprise Pool CoD have been acquired.\n" \
                                "$PROGNAME" "$g_quantity"
                            fi
                        fi

                        if (( $rc != $RC_SUCCESS )) ; then

                            #=======================================================
                            : Also, despite memory has succeeded, undo what has been
                            : acquired.
                            #=======================================================
                            if (( $g_memory > 0 )) ; then
                                clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r mem -o remove -q $g_memory" out_str
                                if (( $? == $RC_SUCCESS )) ; then
                                    typeset -F4 mem_gb=$g_memory
                                    (( mem_gb /= 1024 ))
                                    dspmsg $ROHA_MSGS -s $ROHA_SET 517 \
                                    "%1\$s: WARNING: acquisition of %2\$d GB of Enterprise Pool CoD resources has been undone.\n" \
                                    "$PROGNAME" "$mem_gb" >&3
                                fi
                            fi

                        fi

                    fi

                    g_epcod_modify_operation=0

                else

                    dspmsg $ROHA_MSGS -s $ROHA_SET 415 \
                    "%1\$s: ERROR: unknown %2\$s Enterprise Pool CoD. Provide valid name through -E option.\n" \
                    "$PROGNAME" "$g_enterprise_pool" >&3
                    rc=$RC_PARAM_ERROR

                fi
                ;;
            esac

        else

            dspmsg $ROHA_MSGS -s $ROHA_SET 416 \
            "%1\$s: ERROR: unknown %2\$s Managed System. Provide valid name through -M option.\n" \
            "$PROGNAME" "$g_managed_system" >&3
            rc=$RC_PARAM_ERROR

        fi

    else

        dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
        "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
        "$PROGNAME" "$g_partition" >&3
        rc=$RC_PARAM_ERROR

    fi

    return $rc
} # End of "process_acquire()"

#=============================================================================
#
# Name:        process_release
#
# Description: Process a 'release' operation of some DLPAR, On/Off CoD or
#              Enterprise Pool CoD memory, processing unit(s) and/or CPU(s)
#              for the partition.
#
# Arguments:   None
#
# Environment: g_resource
#              g_memory
#              g_quantity
#              g_proc_units
#              g_force
#              g_partition
#              g_managed_system
#              g_enterprise_pool
#
# Returns:     RC_SUCCESS
#              RC_PARAM_ERROR
#              or clhmcexec error code if an error occurs.
#
#=============================================================================
function process_release
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset out_str=
    typeset proc_out_str=

    typeset release_order="memory cpu"
    typeset -i memory_released=0
    typeset -i cpu_released=0

    # 
    : Release order should be based on the tunable $ROHA_RELEASE_CPU_BEFORE_MEM,
    : use default one if tunable is not updated
    #
    if (( ROHA_RELEASE_CPU_BEFORE_MEM == 1 )); then
        release_order="cpu memory"
    fi

    [[ -z $g_partition ]] && get_local_partition g_partition
    if [[ -n $g_partition ]] ; then

        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -n $g_managed_system ]] ; then

            case $g_resource in
            dlpar)
                g_enable_timeout=1

                #=======================================================
                : Compute timeout dynamically by adding to the default
                : timeout, the greatest from memory, processor and
                : processing units.
                #=======================================================
                (( g_timeout += ( g_memory/1024 > g_proc_units ) ? $(( ( g_memory/1024 > g_quantity ) ? g_memory/1024 : g_quantity )) : g_proc_units ))

                for resourceloop in $release_order
                do
                    case $resourceloop in
                    memory)
                        typeset -i CHUNK_SIZE=10240
                        #=======================================================
                        : Release memory by chunk of $CHUNK_SIZE MB.
                        #=======================================================
                        if (( $g_memory > 0 )) ; then
                            typeset -i qty=0 tmp=0
                            while (( qty < g_memory )) ; do
                                tmp=$(( g_memory - qty ))
                                mem_mb=$(( CHUNK_SIZE < tmp ? CHUNK_SIZE : tmp ))
                                clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o r -q $mem_mb" out_str
                                rc=$?
                                if (( $rc == $RC_SUCCESS )) ; then
                                    (( qty += $mem_mb ))
                                    typeset -F4 mem_gb=$qty
                                    (( mem_gb /= 1024 ))
                                    dspmsg $ROHA_MSGS -s $ROHA_SET 304 \
                                    "%1\$s: %2\$d GB of DLPAR resources have been released.\n" \
                                    "$PROGNAME" "$mem_gb"
                                elif (( $rc == $RC_REM_RES_BUSY_ERROR )) ; then
                                    #=======================================================
                                    : Error while releasing memory. The operation may have
                                    : completed partially. Also, undo what has been released.
                                    #=======================================================
                                    typeset substr=$out_str
                                    print $substr | grep -q -i "Attention: Operation completed partially."
                                    if (( $? == 0 )) ; then
                                        substr=${substr##*Amount of memory removed: }
                                        substr=${substr%% *}
                                        (( qty += $substr ))
                                    fi
                                    # Continue by releasing CHUNK smaller
                                    if (( $CHUNK_SIZE == 10240 )) ; then
                                        CHUNK_SIZE=5120
                                    elif (( $CHUNK_SIZE == 5120 )) ; then
                                        CHUNK_SIZE=2048
                                    elif (( $CHUNK_SIZE == 2048 )) ; then
                                        CHUNK_SIZE=1024
                                    elif (( $CHUNK_SIZE == 1024 )) ; then
                                        CHUNK_SIZE=256
                                    else
                                        break
                                    fi
                                else
                                    break
                                fi
                            done
                        fi
                        if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then
                            #=======================================================
                            : Force return code to success.
                            #=======================================================
                            rc=$RC_SUCCESS
                            memory_released=1
                        else
                            #=======================================================
                            : Error while releasing memory. Undo what have already
                            : been released.
                            #=======================================================
                            if (( $qty > 0 )) ; then
                                clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o a -q $qty" out_str
                                if (( $? == $RC_SUCCESS )) ; then
                                    typeset -F4 mem_gb=$qty
                                    (( mem_gb /= 1024 ))
                                    dspmsg $ROHA_MSGS -s $ROHA_SET 511 \
                                    "%1\$s: WARNING: release of %2\$d GB of DLPAR resources has been undone.\n" \
                                    "$PROGNAME" "$mem_gb" >&3
                                fi
                            fi

                            if (( $cpu_released == 1 )); then
                                #=======================================================
                                : Also, despite CPU has succeeded, undo what has been
                                : released.
                                #=======================================================
                                typeset substr=$proc_out_str
                                substr=${substr##*Amount of processors removed: }
                                substr=${substr%% *}
                                typeset -i cpu=$substr
                                typeset -F4 pu=$substr
                                if (( $cpu > 0 || $pu > 0 )) ; then
                                    typeset opt_procs= opt_proc_units=
                                    (( $cpu > 0 )) && opt_procs="--procs $cpu"
                                    (( $pu  > 0 )) && opt_proc_units="--procunits $pu"
                                    clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o a $opt_procs $opt_proc_units" out_str
                                    if (( $? == $RC_SUCCESS )) ; then
                                        dspmsg $ROHA_MSGS -s $ROHA_SET 512 \
                                        "%1\$s: WARNING: release of %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources has been undone.\n" \
                                        "$PROGNAME" "$pu" "$vp" >&3
                                    fi
                                fi
                            fi
                            # come out of case and for loop to avoid processing further
                            break
                        fi
                        ;;
                    cpu)
                        #=======================================================
                        : Release processors.
                        #=======================================================
                        if (( $g_quantity > 0 || $g_proc_units > 0 )) ; then
                            typeset opt_procs= opt_proc_units=
                            (( $g_quantity > 0 ))   && opt_procs="--procs $g_quantity"
                            (( $g_proc_units > 0 )) && opt_proc_units="--procunits $g_proc_units"
                            clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o r $opt_procs $opt_proc_units" proc_out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                dspmsg $ROHA_MSGS -s $ROHA_SET 306 \
                                "%1\$s: %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources have been released.\n" \
                                "$PROGNAME" "$g_quantity" "$g_proc_units"
                            fi
                        fi

                        if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then

                            #=======================================================
                            : Force return code to success.
                            #=======================================================
                            rc=$RC_SUCCESS
                            cpu_released=1
                        else

                            #=======================================================
                            : Error while releasing processors. The operation may
                            : have completed partially. Undo what has been released.
                            #=======================================================
                            typeset substr=$proc_out_str
                            substr=${substr##*Amount of processors removed: }
                            substr=${substr%% *}
                            typeset -i cpu=$substr
                            typeset -F4 pu=$substr
                            if (( $cpu > 0 || $pu > 0 )) ; then
                                typeset opt_procs= opt_proc_units=
                                (( $cpu > 0 )) && opt_procs="--procs $cpu"
                                (( $pu  > 0 )) && opt_proc_units="--procunits $pu"
                                clhmcexec "chhwres -m $g_managed_system -p $g_partition -r proc -o a $opt_procs $opt_proc_units" out_str
                                if (( $? == $RC_SUCCESS )) ; then
                                    dspmsg $ROHA_MSGS -s $ROHA_SET 512 \
                                    "%1\$s: WARNING: release of %2\$d VP(s) or CPU(s) and %3\$d PU(s) of DLPAR resources has been undone.\n" \
                                    "$PROGNAME" "$pu" "$vp" >&3
                                fi
                            fi

                            #=======================================================
                            : Also, despite memory has succeeded, undo what has been
                            : released.
                            #=======================================================
                            if (( $g_memory > 0 && $memory_released == 1)) ; then
                                clhmcexec "chhwres -m $g_managed_system -p $g_partition -r mem -o a -q $g_memory" out_str
                                if (( $? == $RC_SUCCESS )) ; then
                                    typeset -F4 mem_gb=$g_memory
                                    (( mem_gb /= 1024 ))
                                    dspmsg $ROHA_MSGS -s $ROHA_SET 511 \
                                    "%1\$s: WARNING: release of %2\$d GB of DLPAR resources has been undone.\n" \
                                    "$PROGNAME" "$mem_gb" >&3
                                fi
                            fi
                            # come out of case and for loop to avoid processing further
                            break
                        fi
                        ;;
                    esac
                done
                g_enable_timeout=0
                ;;
            onoff)
                for resourceloop in $release_order
                do
                    case $resourceloop in
                    memory)

                        #=======================================================
                        : Release memory.
                        #=======================================================
                        if (( $g_memory > 0 )) ; then
                            clhmcexec "chcod -m $g_managed_system -r mem -c onoff -o d" out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                typeset -F4 mem_gb=$g_memory
                                (( mem_gb /= 1024 ))
                                dspmsg $ROHA_MSGS -s $ROHA_SET 322 \
                                "%1\$s: All %2\$d GB of On/Off CoD resources have been released.\n" \
                                "$PROGNAME" "$mem_gb"
                            fi
                        fi

                        if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then
                            #=======================================================
                            : Force return code to success.
                            #=======================================================
                            memory_released=1
                            rc=$RC_SUCCESS
                        else
                            # come out of case and for loop to avoid processing further
                            break
                        fi
                        ;; 
                    cpu)    
                        #=======================================================
                        : Release processors.
                        #=======================================================
                        if (( $g_quantity > 0 )) ; then
                            clhmcexec "chcod -m $g_managed_system -r proc -c onoff -o d" out_str
                            rc=$?
                            if (( $rc == $RC_SUCCESS )) ; then
                                dspmsg $ROHA_MSGS -s $ROHA_SET 323 \
                                "%1\$s: All %2\$d CPU(s) of On/Off CoD resources have been released.\n" \
                                "$PROGNAME" "$g_quantity"
                            fi
                        fi

                        if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then
                            #=======================================================
                            : Force return code to success.
                            #=======================================================
                            rc=$RC_SUCCESS
                            cpu_released=1
                        else
                            if (( $memory_released == 1)) ; then
                                #=======================================================
                                : Also, despite memory has succeeded, undo what has been
                                : released.
                                #=======================================================
                                if (( $g_memory > 0 )) ; then
                                    clhmcexec "chcod -m $g_managed_system -r mem -c onoff -o a -d $g_duration" out_str
                                    if (( $? == $RC_SUCCESS )) ; then
                                        typeset -F4 mem_gb=$g_memory
                                        (( mem_gb /= 1024 ))
                                        dspmsg $ROHA_MSGS -s $ROHA_SET 515 \
                                        "%1\$s: WARNING: release of %2\$d GB of On/Off CoD resources has been undone.\n" \
                                        "$PROGNAME" "$mem_gb" >&3
                                    fi
                                fi
                            fi
                            # come out of case and for loop to avoid processing further
                            break
                         fi
                        ;;
                    esac
                done

                ;;

            epcod)
                [[ -z $g_enterprise_pool ]] && get_enterprise_pool g_enterprise_pool $g_managed_system
                if [[ -n $g_enterprise_pool ]] ; then

                    g_epcod_modify_operation=1

                    for resourceloop in $release_order
                    do
                        case $resourceloop in
                            memory)

                                #=======================================================
                                : Release memory.
                                #=======================================================
                                while (( $g_memory > 0 )); do
                                    typeset -i mem_quantity=0
                                    clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r mem -o remove -q $g_memory --force" out_str
                                    rc=$?
                                    if (( $rc == $RC_SUCCESS )) ; then
                                        typeset -F4 mem_gb=$g_memory
                                        (( mem_gb /= 1024 ))
                                        dspmsg $ROHA_MSGS -s $ROHA_SET 332 \
                                        "%1\$s: %2\$d GB of Enterprise Pool CoD have been returned.\n" \
                                        "$PROGNAME" "$mem_gb"
                                    elif [[ -n $(echo $out_str | grep "to remove cannot exceed") ]]; then
                                        typeset substr=$out_str
                                        substr=${out_str% GB*}
                                        mem_quantity=${substr##*[!0-9]}
                                        #========================================================================
                                        : The amount of mobile memory to be released cannot exceed $mem_quantity
                                        #========================================================================
                                        (( mem_quantity *= 1024 ))
                                        if (( $mem_quantity > 0 )); then
                                            #========================================================
                                            : Resetting mobile memory to be released to $mem_quantity
                                            #========================================================
                                            g_memory=$mem_quantity
                                            continue
                                        else
                                            #===================================================
                                            : No mobile memory currently assigned to this server
                                            #===================================================
                                            rc=$RC_SUCCESS
                                        fi
                                    fi
                                    #================================
                                    : Nothing to do break from loop
                                    #================================
                                    break
                                done

                                if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then
                                    #=======================================================
                                    : Force return code to success.
                                    #=======================================================
                                    rc=$RC_SUCCESS 
                                    memory_released=1
                                else
                                    # come out of case and for loop to avoid processing further
                                    break
                                fi

                                ;;
                            cpu)
                                #=======================================================
                                : Release processors.
                                #=======================================================
                                while (( $g_quantity > 0 )); do
                                    typeset -i proc_quantity=0
                                    clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r proc -o remove -q $g_quantity --force" out_str
                                    rc=$?
                                    if (( $rc == $RC_SUCCESS )) ; then
                                        dspmsg $ROHA_MSGS -s $ROHA_SET 333 \
                                        "%1\$s: %2\$d CPU(s) of Enterprise Pool CoD have been returned.\n" \
                                        "$PROGNAME" "$g_quantity"
                                    elif [[ -n $(echo $out_str | grep "to remove cannot exceed") ]]; then
                                        typeset substr=$out_str
                                        substr=${out_str%,*}
                                        proc_quantity=${substr##*[!0-9]}
                                        #======================================================================
                                        : The amount of mobile proc to be released cannot exceed $proc_quantity
                                        #======================================================================
                                        if (( $proc_quantity > 0 )); then
                                            #=========================================================
                                            : Resetting mobile procs to be released to $proc_quantity
                                            #=========================================================
                                            g_quantity=$proc_quantity
                                            continue
                                        else
                                            #================================================================
                                            : No mobile procs currently assigned to this server
                                            #================================================================
                                            rc=$RC_SUCCESS
                                        fi
                                    fi
                                    #================================
                                    : Nothing to do break from loop
                                    #================================
                                    break
                                done

                                if (( $rc == $RC_SUCCESS || $g_force == 1 )) ; then

                                    #=======================================================
                                    : Force return code to success.
                                    #=======================================================
                                    rc=$RC_SUCCESS
                                    cpu_released=1

                                else
                                    if (( $memory_released == 1 )) ; then
                                        #=======================================================
                                        : Also, despite memory has succeeded, undo what has been
                                        : released.
                                        #=======================================================
                                        if (( $g_memory > 0 )) ; then
                                            clhmcexec "chcodpool -p $g_enterprise_pool -m $g_managed_system -r mem -o add -q $g_memory" out_str
                                            if (( $? == $RC_SUCCESS )) ; then
                                                typeset -F4 mem_gb=$g_memory
                                                (( mem_gb /= 1024 ))
                                                dspmsg $ROHA_MSGS -s $ROHA_SET 519 \
                                                "%1\$s: WARNING: release of %2\$d GB of Enterprise Pool CoD resources has been undone.\n" \
                                                "$PROGNAME" "$mem_gb" >&3
                                            fi
                                        fi

                                    fi
                                    # come out of case and for loop to avoid processing further
                                    break
                                fi
                            ;;
                        esac
                    done
                    g_epcod_modify_operation=0

                else

                    dspmsg $ROHA_MSGS -s $ROHA_SET 415 \
                    "%1\$s: ERROR: unknown %2\$s Enterprise Pool CoD. Provide valid name through -E option.\n" \
                    "$PROGNAME" "$g_enterprise_pool" >&3
                    rc=$RC_PARAM_ERROR

                fi
                ;;
            esac

        else

            dspmsg $ROHA_MSGS -s $ROHA_SET 416 \
            "%1\$s: ERROR: unknown %2\$s Managed System. Provide valid name through -M option.\n" \
            "$PROGNAME" "$g_managed_system" >&3
            rc=$RC_PARAM_ERROR

        fi

    else

        dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
        "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
        "$PROGNAME" "$g_partition" >&3
        rc=$RC_PARAM_ERROR

    fi

    return $rc
} # End of "process_release()"

#=============================================================================
#
# Name:        process_halt
#
# Description: Process a 'halt' operation for the partition.
#
# Arguments:   None
#
# Environment: g_partition
#              g_managed_system
#
# Returns:     RC_SUCCESS
#              RC_PARAM_ERROR
#              or clhmcexec error code if an error occurs.
#
#=============================================================================
function process_halt
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset out_str=

    [[ -z $g_partition ]] && get_local_partition g_partition
    if [[ -n $g_partition ]] ; then

        [[ -z $g_managed_system ]] && get_managed_system g_managed_system $g_partition
        if [[ -n $g_managed_system ]] ; then

            clhmcexec "chsysstate -m $g_managed_system -r lpar -o shutdown --immed -n $g_partition" out_str
            rc=$?

        else

            dspmsg $ROHA_MSGS -s $ROHA_SET 416 \
            "%1\$s: ERROR: unknown %2\$s Managed System. Provide valid name through -M option.\n" \
            "$PROGNAME" "$g_managed_system" >&3
            rc=$RC_PARAM_ERROR

        fi

    else
        dspmsg $ROHA_MSGS -s $ROHA_SET 414 \
        "%1\$s: ERROR: unknown %2\$s LPAR. Provide valid name through -L option.\n" \
        "$PROGNAME" "$g_partition" >&3
        rc=$RC_PARAM_ERROR
    fi

    return $rc
} # End of "process_halt()"

#=============================================================================
#
# Name:        get_hmc_param
#
# Description: Obtain HMC parameter by looking into HACMPhmc ODM object. Then,
#              if not found or default is set, look into HACMPhmcparam ODM
#              object. Otherwise set to default value.
#
# Arguments:   $1 [INOUT] - output_value  reference to the parameter
#              $2 [IN]    - hmc           HMC to get parameter from
#              $3 [IN]    - attribute     name of the HMC parameter to set
#              $4 [IN]    - default_value default value to be set
#
# Environment: None
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function get_hmc_param
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset -n output_value=$1
    typeset hmc=$2
    typeset attribute=$3
    typeset -i default_value=$4

    #=======================================================
    : First, look into HACMPhmc ODM.
    #=======================================================
    output_value=$(clodmget -q name=$hmc -f $attribute -n HACMPhmc 2>/dev/null)
    rc=$?

    if (( $rc > 0 || output_value == -1 || output_value == 0 )) ; then
        #==========================================================================
        : Then, look into HACMPhmcparam ODM, which stores the default for all HMCs.
        #==========================================================================
        output_value=$(clodmget -f default_$attribute -n HACMPhmcparam 2>/dev/null)
        rc=$?

        if (( $rc > 0 || output_value == 0 )) ; then
            #=======================================================
            : Then, set to default value received in parameter.
            #=======================================================
            output_value=$default_value
            rc=$RC_SUCCESS
        fi
    fi

    return $rc
} # End of "get_hmc_param()"

#=============================================================================
#
# Name:        update_hmc_list
#
# Description: Update list of HMCs to fit the precedence order.
#
# Arguments:   $@ [IN]       first valid hmc
#
# Environment: g_hmc_list
#
# Returns:     RC_SUCCESS
#
#=============================================================================
function update_hmc_list
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset valid_hmc=$1
    typeset param=

    #=======================================================
    # Build new HMC list.
    #=======================================================
    if echo $g_hmc_list | grep -q "[[:space:]]" ; then
        if [[ $valid_hmc == ${g_hmc_list%% *} ]] ; then
            g_hmc_list="$valid_hmc ${g_hmc_list#*$valid_hmc }"
        elif [[ $valid_hmc == ${g_hmc_list##* } ]] ; then
            g_hmc_list="$valid_hmc ${g_hmc_list% $valid_hmc*}"
        else
            g_hmc_list="$valid_hmc ${g_hmc_list#*$valid_hmc } ${g_hmc_list% $valid_hmc*}"
        fi
    fi

    #=======================================================
    # Persist new HMC list in HACMPdynresop ODM.
    #=======================================================
    param=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=PREFERRED_HMC_LIST" HACMPdynresop 2>/dev/null)
    if [[ -n $param ]] ; then
        print -- "HACMPdynresop:\\nvalue=\"$g_hmc_list\"" | ODMDIR="/etc/es/objrepos" odmchange -o HACMPdynresop -q "key=PREFERRED_HMC_LIST"
    else
        print -- "HACMPdynresop:\\nkey=\"PREFERRED_HMC_LIST\"\\nvalue=\"$g_hmc_list\"" | ODMDIR="/etc/es/objrepos" odmadd
    fi

    return $RC_SUCCESS
} # End of "update_hmc_list()"

#=============================================================================
#
# Name:        get_effective_version
#
# Description: Update the current effective HMC version for enterprise pool 
#              operations to work with HMC levels 8.4/8.5 and above.
#
# Arguments:   None
#
# Environment: g_hmc_list
#
# Returns:     version
#
#=============================================================================
function get_effective_version
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset ping_output=""
    typeset ping_cmd="ping -c 1 -w 3"
    typeset -i ping_rc=0
    typeset param=
    typeset -i hmc_version=0
    typeset version=""
	
    #=========================================================
    # Get the current effetive version from HACMPdynresop ODM.
    #=========================================================
    param=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=EFFECTIVE_HMC_VERSION" -f value -n HACMPdynresop 2>/dev/null)
    if [[ -n $param ]] ; then
        return $param
    else
        for hmc in $g_hmc_list ; do
            #============================================
            : Try to ping the HMC at address $hmc.
            #============================================
            ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
            ping_rc=$?
            if (( $ping_rc > 0 )) ; then
                #=====================================================
                : Cannot contact this HMC. Ask following HMC in list.
                #=====================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                "$PROGNAME" "$hmc" >&3
                continue
            fi
            hmccmdexec $hmc "lshmc -v" version

            rc=$?
            if (( $rc != 0 )) ; then
                continue
            else
                version=$(print "$version" | sed -n 's/.*\*RM \([^ ]\)/\1/p')
				version=$(print "$version" | cut -c 4,6)
                if (( $hmc_version == 0 || $hmc_version < $version )); then
                    hmc_version=$version
                fi
            fi
        done
    fi

    #========================================================
    # Persist the effective HMC version in HACMPdynresop ODM.
    #========================================================
    if (( $hmc_version != 0 )) ; then
        param=$(ODMDIR="/etc/es/objrepos" clodmget -q "key=EFFECTIVE_HMC_VERSION" HACMPdynresop 2>/dev/null)
        if [[ -n $param ]] ; then
            print -- "HACMPdynresop:\\nvalue=\"$hmc_version\"" | ODMDIR="/etc/es/objrepos" odmchange -o HACMPdynresop -q "key=EFFECTIVE_HMC_VERSION"
        else
            print -- "HACMPdynresop:\\nkey=\"EFFECTIVE_HMC_VERSION\"\\nvalue=\"$hmc_version\"" | ODMDIR="/etc/es/objrepos" odmadd
        fi
    fi

    return $hmc_version
} # End of "get_effective_version()"

#=============================================================================
#
# Name:        hmccmdexec
#
# Description: Execute the specified command on an HMC. The command run via a 
#              password-less remote ssh connection, thus the HMC must have the
#              public key of the local node in its authorized keys list. Retry
#              delay and retry count are obtained from HACMPhmcparam ODM.
#
#              The "-o StrictHostKeyChecking=no" tells ssh to automatically
#              add new host keys to the host key database file, without user
#              confirmation, for all first-time connection.
#              The "-o LogLevel=quiet" tells ssh to disable the display of the
#              warning message 'Warning: Permanently added 'host,ip' (RSA) to
#              the list of known hosts.'.
#              The "-o AddressFamily=any" tells ssh to work with both
#              IPv4 and IPv6.
#              The "-o BatchMode=yes" option forces ssh to not prompt for a
#              password. In order to run commands remotely via ssh the target
#              ssh machine must have the public key of this client machine.
#              If the target ssh machine does not have the public key of this
#              machine, then normally ssh prompts for a password, and
#              that causes this script to hang. But by using BatchMode,
#              if the target does not have our public key, then ssh
#              immediately returns an error.
#              The "-o ConnectTimeout=3" and "-o ConnectionAttempts=3"
#              tells ssh to wait for a maximum timeout of 9 seconds if
#              connection with the target machine cannot be established.
#              The "-o TCPKeepAlive=yes" tells ssh to send an empty TCP ACK
#              packet in order to keep the connection with remote target
#              opened.
#
# Arguments:   $1 [IN]  hmc       - HMC to run the given commad
#              $2 [IN]  cmd       - command to run on the HMC.
#              $3 [OUT] ssh_ouput - reference to the output of the ssh command.
#
# Environment: g_hmc_list
#              g_enable_timeout
#              g_timeout
#              g_enterprise_pool
#
# Returns:     RC_SUCCESS
#              RC_PING_ERROR
#              RC_SSH_ERROR
#              RC_REM_RES_BUSY_ERROR
#              RC_REM_CEC_BUSY_ERROR
#              RC_REM_NOT_ENOUGH_RES_ERROR
#              RC_REM_OTHER_ERROR
#
#=============================================================================
function hmccmdexec
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset hmc=$1 cmd=$2 ccmd=""
    typeset -n ssh_output=$3
    typeset ssh_cmd="eval LC_ALL=C ssh -o StrictHostKeyChecking=no -o LogLevel=quiet -o AddressFamily=any -o BatchMode=yes -o ConnectTimeout=3 -o ConnectionAttempts=3 -o TCPKeepAlive=no"
    typeset -i ssh_rc=0
    typeset res=""
    typeset hmcuser=""

    # Get HMC User from HACMPhmc
    hmcuser=$(clodmget -n -q name=$hmc -f user HACMPhmc 2>/dev/null)
    if [[ -z "$hmcuser" ]]; then
         # Use FQDN and try again from HACMPhmc
         typeset fqdn_hmc=$(host $hmc | awk '{print $1}')
         [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
         if [[ -z "$hmcuser" ]];then
              # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
              typeset cust_hmcuser=$hmc"_user"
              hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
              if [[ -z "$hmcuser" ]];then
                   cust_hmcuser=$fqdn_hmc"_user"
                   [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                   if [[ -z "$hmcuser" ]];then
                        # None of methods works to get HMC user name, hence use hscroot
                        hmcuser="hscroot"
                   fi
              fi
         fi
    fi
    #
    : g_enable_timeout=$g_enable_timeout
    #
    if (( g_enable_timeout == 1 )) ; then
        #
        : g_enable_timeout is set on acquire/release dlpar operation.
        : g_timeout has been computed accordingly to the amount of
        : resources to be acquired/released : g_timeout=$g_timeout.
        #
        get_hmc_param hmc_timeout "$hmc" timeout 5
        #
        : We add to the g_timeout, the default timeout set on this hmc : $hmc_timeout
        #
        (( hmc_timeout = $g_timeout + $hmc_timeout ))
        #
        : hmc_timeout=$hmc_timeout
        : Timeout value is expressed in minutes.
        #
        ccmd="$cmd -w $hmc_timeout"
    else
        ccmd="$cmd"
    fi

    #=======================================================
    : Get retry count and retry delay.
    #=======================================================
    typeset -i hmc_retry_cnt=0 hmc_retry_dly=0
    get_hmc_param hmc_retry_cnt "$hmc" retry_count 5
    get_hmc_param hmc_retry_dly "$hmc" retry_delay 10

    for (( i=1 ; i <= hmc_retry_cnt ; i++ )) ; do
        #=======================================================
        : Try to ssh the command on HMC at address $hmc.
        #=======================================================
        : Start ssh command at $(LC_ALL=C date)
        ssh_output=$($ssh_cmd "$hmcuser@$hmc '$ccmd 2>&1'")
        ssh_rc=$?
        : Return from ssh command at $(LC_ALL=C date)
        if (( $ssh_rc == 255 )) ; then
            #=======================================================
            : Cannot ssh the command. Do not retry. Break out from
            : the retry loop.
            #=======================================================
            dspmsg $ROHA_MSGS -s $ROHA_SET 501 \
            "%1\$s: WARNING: unable to ssh HMC at address %2\$s.\n" \
            "$PROGNAME" "$hmc" >&3
            rc=$RC_SSH_ERROR
            g_enable_update_hmc=1
            break
        elif (( $ssh_rc > 0 )) ; then
            ssh_output=$(print -n $ssh_output | sed -e "s/\-q/\-m/g")
            typeset code=${ssh_output%% *}
            case $code in
            "HSCL2932"|"HSCL294F") # "Operation completed partially" condition
                #=======================================================
                : The remote command fails acquiring/releasing busy
                : resources or timed out. The operation may have
                : completed partially. Break out from the retry loop.
                #=======================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 430 \
                "%1\$s: ERROR: HMC %2\$s returns %3\$s error code when running command \"%4\$s\":\n%5\$s\n" \
                "$PROGNAME" "$hmc" "$code" "$ccmd" "$ssh_output" >&3
                rc=$RC_REM_RES_BUSY_ERROR
                break
                ;;
            "HSCL3205") # "Managed System busy" condition
                #=======================================================
                : The remote command fails because managed system is
                : busy. Retry asking this same HMC or the following HMC
                : in the list.
                #=======================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 504 \
                "%1\$s: WARNING: HMC %2\$s returns %3\$s error code when running command \"%4\$s\" (attempt %5\$d/%6\$d):\n%7\$s\n" \
                "$PROGNAME" "$hmc" "$code" "$ccmd" "$i" "$hmc_retry_cnt" "$ssh_output" >&3
                rc=$RC_REM_CEC_BUSY_ERROR
                ;;
            "HSCL03F9"|"HSCL2914"|"HSCL1453"|"HSCL90A4"|"HSCL909F"|"HSCL9028"\
|"HSCL9029"|"HSCL90E7"|"HSCL90E8"|"HSCL9026"|"HSCL9027"|"HSCL9052"|"HSCL9053") # "Not enough resources" condition
                # http://www.ibm.com/support/knowledgecenter/POWER5/ipha5_p5/hscl_9xxx.htm
                #=======================================================
                : The remote command fails beacuse there are not enough
                : available resources. Break out from the retry loop.
                #=======================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 430 \
                "%1\$s: ERROR: HMC %2\$s returns %3\$s error code when running command \"%4\$s\":\n%5\$s\n" \
                "$PROGNAME" "$hmc" "$code" "$ccmd" "$ssh_output" >&3
                rc=$RC_REM_NOT_ENOUGH_RES_ERROR
                break
                ;;
            "HSCL90A8"|"HSCL900B"|"HSCL900C")
                # HSCL90A8 The number of Mobile CoD processors to remove cannot exceed 4,
                #  which is the number of Mobile CoD processors that are currently assigned to the managed system.
                # HSCL900B This operation is not allowed because On/Off Capacity on Demand for processors is not
                #  supported on the managed system.
                # HSCL900C This operation is not allowed because On/Off Capacity on Demand for memory is not
                #  supported on the managed system.
                #=======================================================
                : Break out from the retry loop.
                #=======================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 430 \
                "%1\$s: ERROR: HMC %2\$s returns %3\$s error code when running command \"%4\$s\":\n%5\$s\n" \
                "$PROGNAME" "$hmc" "$code" "$ccmd" "$ssh_output" >&3
                rc=$RC_REM_OTHER_ERROR
                break
                ;;
            "HSCL8018")
                # HSCL8018 The managed system was not found.
                #=======================================================
                : Break out from the retry loop.
                #=======================================================
                rc=$RC_CEC_NOT_FOUND
                break
                ;;
            *)
                if [[ $code != HSCL* ]] ; then
                    code="unknown"
                fi
                #=======================================================
                : Error executing the remote command. Break out from the
                : retry loop.
                #=======================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 430 \
                "%1\$s: ERROR: HMC %2\$s returns %3\$s error code when running command \"%4\$s\":\n%5\$s\n" \
                "$PROGNAME" "$hmc" "$code" "$ccmd" "$ssh_output" >&3
                rc=$RC_REM_OTHER_ERROR
                break
                ;;
            esac
        else
            #=======================================================
            : Success. Break out from the retry loop and HMC loop,
            : except if we still have to search for a new backup HMC
            #=======================================================
            rc=$RC_SUCCESS
            break
        fi

        sleep $hmc_retry_dly
    done

    return $rc
} # End of "hmccmdexec()"

#=============================================================================
#
# Name:        clhmcexec
#
# Description: Execute the specified command on an HMC. Each HMC defined on
#              the local node will be contacted until one responds. The
#              command is run via a password-less remote ssh connection, thus
#              the HMC must have the public key of the local node in its
#              authorized keys list. Retry delay and retry count are obtained
#              from ODM object HACMPhmcparam.
#
#              The "-o StrictHostKeyChecking=no" tells ssh to automatically
#              add new host keys to the host key database file, without user
#              confirmation, for all first-time connection.
#              The "-o LogLevel=quiet" tells ssh to disable the display of the
#              warning message 'Warning: Permanently added 'host,ip' (RSA) to
#              the list of known hosts.'.
#              The "-o AddressFamily=any" tells ssh to work with both
#              IPv4 and IPv6.
#              The "-o BatchMode=yes" option forces ssh to not prompt for a
#              password. In order to run commands remotely via ssh the target
#              ssh machine must have the public key of this client machine.
#              If the target ssh machine does not have the public key of this
#              machine, then normally ssh prompts for a password, and
#              that causes this script to hang. But by using BatchMode,
#              if the target does not have our public key, then ssh
#              immediately returns an error.
#              The "-o ConnectTimeout=3" and "-o ConnectionAttempts=3"
#              tells ssh to wait for a maximum timeout of 9 seconds if
#              connection with the target machine cannot be established.
#              The "-o TCPKeepAlive=yes" tells ssh to send an empty TCP ACK
#              packet in order to keep the connection with remote target
#              opened.
#
# Arguments:   $1 [IN]  cmd       - command line to run on the HMC.
#              $2 [OUT] ssh_ouput - reference to the output of the ssh command.
#
# Environment: g_hmc_list
#              g_epcod_modify_operation
#              g_enable_timeout
#              g_timeout
#              g_enterprise_pool
#
# Returns:     RC_SUCCESS
#              RC_PING_ERROR
#              RC_SSH_ERROR
#              RC_REM_RES_BUSY_ERROR
#              RC_REM_CEC_BUSY_ERROR
#              RC_REM_NOT_ENOUGH_RES_ERROR
#              RC_REM_OTHER_ERROR
#
#=============================================================================
function clhmcexec
{
    [[ ${VERBOSE_LOGGING:-} == high ]] && set -x

    typeset -i rc=$RC_SUCCESS
    typeset cmd=$1 ccmd=""
    typeset ping_output=""
    typeset ping_cmd="ping -c 1 -w 3"
    typeset -i ping_rc=0
    typeset -n ssh_output=$2
    typeset ssh_output_bkupchange=""
    typeset ssh_cmd="eval LC_ALL=C ssh -o StrictHostKeyChecking=no -o LogLevel=quiet -o AddressFamily=any -o BatchMode=yes -o ConnectTimeout=3 -o ConnectionAttempts=3 -o TCPKeepAlive=no"
    typeset -i ssh_rc=0
    typeset -i loop_hmc_counter=0;
    typeset -i looking_for_new_backup=0;
    typeset res=""
    typeset hmcuser=""
    typeset -i version=0
    typeset -i release=0
    typeset -i service_pack=0
    typeset set_type="setmaster"
    version=$(echo $hmc_version | awk -F[\V\R] '{print $2}')
    release=$(echo $hmc_version | awk -F[\R\.] '{print $2}')
    service_pack=$(echo $hmc_version | awk -F[\.\.] '{print $2}')
    # For HMC version 10 or higher, setcontroller should be used to set one of the HMC as primary HMC.
    if [[ -n $version && -n $release && -n $service_pack ]] && (( $version > 10 )) || (( $version >= 10 && (( $release > 0 ) || ( $release >= 0 && $service_pack >= 1010 ))  )) ; then
        set_type="setcontroller"
    fi

    if (( g_epcod_modify_operation == 0 )) ; then
        for hmc in $g_hmc_list ; do
            #============================================
            : Try to ping the HMC at address $hmc.
            #============================================
            ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
            ping_rc=$?
            if (( $ping_rc > 0 )) ; then
                #=====================================================
                : Cannot contact this HMC. Ask following HMC in list.
                #=====================================================
                dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                "$PROGNAME" "$hmc" >&3
                rc=$RC_PING_ERROR
                g_enable_update_hmc=1
                continue
            fi
            hmccmdexec $hmc "$cmd" ssh_output
            rc=$?
            if (( rc == RC_SSH_ERROR || rc == RC_CEC_NOT_FOUND )); then
                continue
            else
                break
            fi
        done
        if (( rc == $RC_SUCCESS && g_enable_update_hmc == 1 )) ; then
            update_hmc_list "$hmc"
            g_enable_update_hmc=0
        elif (( rc == RC_CEC_NOT_FOUND )) ; then
            dspmsg $ROHA_MSGS -s $ROHA_SET 521 \
            "%1\$s: ERROR: Failed to get the Managed System when running command \"%2\$s\":\n%3\$s\n" \
            "$PROGNAME" "$cmd" "$ssh_output" >&3
        fi
    else
        #===================================================
        : Get the Effective HMC level for EPCOD operations
        #==================================================
        get_effective_version
        typeset -i version=$?
        if (( $version < $CROSS_HMC_VERSION )); then
            #=======================================================
            : If working on an EPCoD Operation, we need master and
            : backup_master hmcs, read only once
            #=======================================================
            if [[ -z $g_master_hmc ]] ; then
                for hmc in $g_hmc_list ; do
                    ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
                    ping_rc=$?
                    if (( $ping_rc > 0 )) ; then
                        dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                        "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                        "$PROGNAME" "$hmc" >&3
                        rc=$RC_PING_ERROR
                        g_enable_update_hmc=1
                    else
                        # Get HMC User from HACMPhmc
                        hmcuser=$(clodmget -n -q name=$hmc -f user HACMPhmc 2>/dev/null)
                        if [[ -z "$hmcuser" ]]; then
                             # Use FQDN and try again from HACMPhmc
                             typeset fqdn_hmc=$(host $hmc | awk '{print $1}')
                             [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                             if [[ -z "$hmcuser" ]];then
                                  # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                                  typeset cust_hmcuser=$hmc"_user"
                                  hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                  if [[ -z "$hmcuser" ]];then
                                       cust_hmcuser=$fqdn_hmc"_user"
                                       [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                       if [[ -z "$hmcuser" ]];then
                                            # None of methods works to get HMC user name, hence use hscroot
                                            hmcuser="hscroot"
                                       fi
                                  fi
                             fi
                        fi
                        res=$($ssh_cmd "$hmcuser@$hmc 'lscodpool -p $g_enterprise_pool --level pool -F master_mc_name:backup_master_mc_name 2>&1'")
                        ssh_rc=$?
                        if (( ssh_rc > 0 )) ; then
                            #=======================================================
                            : If an error occured, ask the following HMC in the list.
                            #=======================================================
                            dspmsg $ROHA_MSGS -s $ROHA_SET 502 \
                            "%1\$s: WARNING: unable to query Master HMC at address %2\$s from HMC at address %3\$s for %4\$s Enterprise Pool CoD.\n" \
                            "$PROGNAME" "$master_hmc" "$hmc" "$g_enterprise_pool" >&3
                            rc=$RC_PARAM_ERROR
                            #=======================================================
                            : Do not update HMC list if it is because HMC does not
                            : know the pool
                            #=======================================================
                            [[ ${res%% *} != "HSCL8029" ]] && g_enable_update_hmc=1
                            continue
                        else
                            print "$res" | IFS=: read g_master_hmc g_backup_hmc
                            rc=$RC_SUCCESS;
                            break;
                        fi
                    fi
                done
    
                if (( rc == $RC_SUCCESS && g_enable_update_hmc == 1 )) ; then
                    update_hmc_list "$hmc"
                    g_enable_update_hmc=0
                fi

                if (( rc != $RC_SUCCESS )) || [[ -z $g_master_hmc ]] ; then
                    return $rc
                fi
            fi

            #=======================================================
            : Priority to use master or backup hmc in case of epcod
            : modify operation
            #=======================================================
            if (( g_epcod_modify_operation == 1 )) ; then
                loop_hmc_list="$g_master_hmc $g_backup_hmc $g_hmc_list"
            fi

            #=======================================================
            : Loop through HMC list in case of ping or ssh failure.
            #=======================================================
            for hmc in $loop_hmc_list ; do
                #=======================================================
                : In case of epcod modify operation, loop_hmc_counter
                : value will be 1 for master hmc, 2 for backup_master
                : hmc and greater than 2 for other hmcs, also
                : re-including master and backup. We may just compare
                : string but it would cost more expensive
                #=======================================================
                (( loop_hmc_counter++ ))

                #=======================================================
                : For epcod modify op, if there was no backup_hmc, skip
                : loop_hmc_counter value 2
                #=======================================================
                (( loop_hmc_counter == 2 )) && [[ -z $g_backup_hmc ]] \
                    && (( loop_hmc_counter++ ))

                if (( loop_hmc_counter > 2 )) ; then
                    #=======================================================
                    : Either g_backup_hmc contains the hmc which was master at begin
                    : g_master_hmc contains the hmc which was backup at begin
                    : those have both already been tested.
                    : Or g_backup_hmc was empty
                    #=======================================================
                    if (( looking_for_new_backup == 1 )) ; then
                        #=======================================================
                        # Executed only if
                        #    Master was unreachable
                        #    Backup setted as new master
                        #    Command already executed on the new master
                        # If an HMC is found for being set as new backup, its
                        # connectivity has to be checked before doing the change
                        #=======================================================
                        [[ $(LC_ALL=C host $hmc | awk '{print $3}') == $(LC_ALL=C host $g_backup_hmc | awk '{print $3}') ]] \
                            || [[ $(LC_ALL=C host $hmc | awk '{print $3}') == $(LC_ALL=C host $g_master_hmc | awk '{print $3}') ]] \
                            && continue
                    else
                        #=======================================================
                        : Neither master_hmc nor backup_master_hmc is reachable
                        : EPCoD modify operation cannot be done
                        #=======================================================
                        break
                    fi
                fi

                #============================================
                : Try to ping the HMC at address $hmc.
                #============================================
                ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
                ping_rc=$?
                if (( $ping_rc > 0 )) ; then
                    #=====================================================
                    : Cannot contact this HMC. Ask following HMC in list.
                    #=====================================================
                    dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                    "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                    "$PROGNAME" "$hmc" >&3
                    if (( looking_for_new_backup == 0 )) ; then
                        rc=$RC_PING_ERROR
                        g_enable_update_hmc=1
                    fi
                    continue
                fi
                #=======================================================
                : If executing an epcod modify operation, make sure that
                : the hmc is the master_hmc
                #=======================================================
                if (( loop_hmc_counter != 1 )) ; then
                    #=======================================================
                    : If not, we need to change master_hmc, we also try to
                    : set a backup_master_hmc
                    : Change only on HMC failure, so do not use --force
                    #=======================================================
                    if (( loop_hmc_counter == 2 )) ; then
                        # Get HMC User from HACMPhmc
                        hmcuser=$(clodmget -n -q name=$hmc -f user HACMPhmc 2>/dev/null)
                        if [[ -z "$hmcuser" ]]; then
                             # Use FQDN and try again from HACMPhmc
                             typeset fqdn_hmc=$(host $hmc | awk '{print $1}')
                             [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                             if [[ -z "$hmcuser" ]];then
                                  # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                                  typeset cust_hmcuser=$hmc"_user"
                                  hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                  if [[ -z "$hmcuser" ]];then
                                       cust_hmcuser=$fqdn_hmc"_user"
                                       [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                       if [[ -z "$hmcuser" ]];then
                                            # None of methods works to get HMC user name, hence use hscroot
                                            hmcuser="hscroot"
                                       fi
                                  fi
                             fi
                        fi
                        ssh_output=$($ssh_cmd "$hmcuser@$hmc 'chcodpool -p $g_enterprise_pool -o $set_type --mc this 2>&1'")
                        ssh_rc=$?
                        if (( ssh_rc > 0 )) ; then
                            #=======================================================
                            : If an error occured, then both master and backup_master
                            : hmc were unable to be accessed. Cannot execute command
                            #=======================================================
                            dspmsg $ROHA_MSGS -s $ROHA_SET 503 \
                            "%1\$s: WARNING: unable to change Master HMC from %2\$s to %3\$s for %4\$s Enterprise Pool CoD.\n%5\$s\n" \
                            "$PROGNAME" "$g_master_hmc" "$g_backup_hmc" "$g_enterprise_pool" "$ssh_output" >&3
                            rc=$RC_PARAM_ERROR
                            return $rc
                        else # ! (ssh_rc > 0)
                            dspmsg $ROHA_MSGS -s $ROHA_SET 505 \
                            "%1\$s: WARNING: Master HMC has been changed from %2\$s to %3\$s for %4\$s Enterprise Pool CoD.\n" \
                            "$PROGNAME" "$g_master_hmc" "$g_backup_hmc" "$g_enterprise_pool" >&3
                            sleep 15 # give time for new master to be updated
                            #=======================================================
                            : Next steps are to execute operation and then to find
                            : and set a new backup master hmc. If no valid hmc can
                            : be found then the old master hmc is tried
                            #=======================================================
                            g_backup_hmc=$g_master_hmc
                            g_master_hmc=$hmc
                            looking_for_new_backup=1
                        fi # (ssh_rc > 0)
                    else # ! (loop_hmc_counter == 2)
                        #=======================================================
                        : When g_epcod_modify_operation value is 1, we only go
                        : beyond loop_hmc_counter value 2 if we are looking for
                        : a new backup master hmc
                        #=======================================================
                        # Get Master HMC User from HACMPhmc
                        typeset master_hmc_user=$(clodmget -n -q name=$g_master_hmc -f user HACMPhmc 2>/dev/null)
                        if [[ -z "$master_hmc_user" ]]; then
                             # Use FQDN and try again from HACMPhmc
                             typeset fqdn_hmc=$(host $g_master_hmc | awk '{print $1}')
                             [[ ${fqdn_hmc} != $g_master_hmc ]] && master_hmc_user=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                             if [[ -z "$master_hmc_user" ]];then
                                  # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                                  typeset masteruser=$g_master_hmc"_user"
                                  master_hmc_user=$(clodmget -q " type=verify_dlpar AND description=$masteruser " -nf value HACMPcustom 2>/dev/null)
                                  if [[ -z "$master_hmc_user" ]];then
                                       masteruser=$fqdn_hmc"_user"
                                       [[ ${fqdn_hmc} != $g_master_hmc ]] && master_hmc_user=$(clodmget -q " type=verify_dlpar AND description=$masteruser " -nf value HACMPcustom 2>/dev/null)
                                       if [[ -z "$master_hmc_user" ]];then
                                            # None of methods works to get Master HMC user name, hence use hscroot
                                            master_hmc_user="hscroot"
                                       fi
                                  fi
                             fi
                        fi
                        ssh_output_bkupchange=$($ssh_cmd "$master_hmc_user@$g_master_hmc 'chcodpool -p $g_enterprise_pool -o update -a \"backup_master_mc_name=${hmc%%.*}\" 2>&1'")
                        ssh_rc=$?
                        if (( ssh_rc > 0 )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 0 \
                            "%1\$s: WARNING: unable to set new Backup HMC %2\$s for %3\$s Enterprise Pool CoD.\n%4\$s\n" \
                            "$PROGNAME" "$hmc" "$g_enterprise_pool" "$ssh_output_bkupchange" >&3
                            continue
                        else
                            g_backup_hmc=$hmc
                            looking_for_new_backup=0
                            break
                        fi
                    fi # (loop_hmc_counter == 2)
                fi # ( loop_hmc_counter != 1 )
            
                #=======================================================
                : When the correct hmc is found, execute operation
                #=======================================================
                hmccmdexec $hmc "$cmd" ssh_output
                rc=$?
                if (( rc == RC_SSH_ERROR )) ; then
                    continue
                elif (( looking_for_new_backup == 1 )) ; then
                    #=======================================================
                    : Success. Break out from the HMC loop, except if we
                    : still have to search for a new backup HMC
                    #=======================================================
                    continue
                else
                    break
                fi
            done
            if (( looking_for_new_backup == 1 )) ; then
                #=======================================================
                : We were unable to find a new backup HMC, so we
                : will try to set the old master as the new backup
                #=======================================================

                # Get Master HMC User from HACMPhmc
                typeset master_hmc_user=$(clodmget -n -q name=$g_master_hmc -f user HACMPhmc 2>/dev/null)
                if [[ -z "$master_hmc_user" ]]; then
                     # Use FQDN and try again from HACMPhmc
                     typeset fqdn_hmc=$(host $g_master_hmc | awk '{print $1}')
                     [[ ${fqdn_hmc} != $g_master_hmc ]] && master_hmc_user=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                       if [[ -z "$master_hmc_user" ]];then
                            # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                            typeset masteruser=$g_master_hmc"_user"
                            master_hmc_user=$(clodmget -q " type=verify_dlpar AND description=$masteruser " -nf value HACMPcustom 2>/dev/null)
                            if [[ -z "$master_hmc_user" ]];then
                                 masteruser=$fqdn_hmc"_user"
                                 [[ ${fqdn_hmc} != $g_master_hmc ]] && master_hmc_user=$(clodmget -q " type=verify_dlpar AND description=$masteruser " -nf value HACMPcustom 2>/dev/null)
                                 if [[ -z "$master_hmc_user" ]];then
                                      # None of methods works to get Master HMC user name, hence use hscroot
                                      master_hmc_user="hscroot"
                                 fi
                            fi
                        fi
                fi
                ssh_output_bkupchange=$($ssh_cmd "$master_hmc_user@$g_master_hmc 'chcodpool -p $g_enterprise_pool -o update -a \"backup_master_mc_name=${hmc%%.*}\" 2>&1'")
                ssh_rc=$?
                if (( ssh_rc > 0 )) ; then
                    dspmsg $ROHA_MSGS -s $ROHA_SET 0 \
                    "%1\$s: WARNING: unable to set new Backup HMC %2\$s for %3\$s Enterprise Pool CoD.\n%4\$s\n" \
                    "$PROGNAME" "$hmc" "$g_enterprise_pool" "$ssh_output_bkupchange" >&3
                    g_backup_hmc=""
                fi
                looking_for_new_backup=0
            fi
        else
            #======================================================
            : If working on an EPCoD Operation, we need master hmc 
            #======================================================
            if [[ -z $g_master_hmc ]] ; then
                for hmc in $g_hmc_list ; do
                    ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
                    ping_rc=$?
                    if (( $ping_rc > 0 )) ; then
                        dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                        "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                        "$PROGNAME" "$hmc" >&3
                        rc=$RC_PING_ERROR
                        g_enable_update_hmc=1
                    else
                        # Get HMC User from HACMPhmc
                        hmcuser=$(clodmget -n -q name=$hmc -f user HACMPhmc 2>/dev/null)
                        if [[ -z "$hmcuser" ]]; then
                             # Use FQDN and try again from HACMPhmc
                             typeset fqdn_hmc=$(host $hmc | awk '{print $1}')
                             [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                             if [[ -z "$hmcuser" ]];then
                                  # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                                  typeset cust_hmcuser=$hmc"_user"
                                  hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                  if [[ -z "$hmcuser" ]];then
                                       cust_hmcuser=$fqdn_hmc"_user"
                                       [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                       if [[ -z "$hmcuser" ]];then
                                            # None of methods works to get HMC user name, hence use hscroot
                                            hmcuser="hscroot"
                                       fi
                                  fi
                              fi
                        fi
                        res=$($ssh_cmd "$hmcuser@$hmc 'lscodpool -p $g_enterprise_pool --level pool -F master_mc_name 2>&1'")
                        ssh_rc=$?
                        if (( ssh_rc > 0 )) ; then
                            #=======================================================
                            : If an error occured, ask the following HMC in the list.
                            #=======================================================
                            dspmsg $ROHA_MSGS -s $ROHA_SET 502 \
                            "%1\$s: WARNING: unable to query Master HMC at address %2\$s from HMC at address %3\$s for %4\$s Enterprise Pool CoD.\n" \
                            "$PROGNAME" "$master_hmc" "$hmc" "$g_enterprise_pool" >&3
                            rc=$RC_PARAM_ERROR
                            #=======================================================
                            : Do not update HMC list if it is because HMC does not
                            : know the pool
                            #=======================================================
                            [[ ${res%% *} != "HSCL8029" ]] && g_enable_update_hmc=1
                            continue
                        else
                            print "$res" | IFS=: read g_master_hmc
                            rc=$RC_SUCCESS;
                            break;
                        fi
                    fi
                done
    
                if (( rc == $RC_SUCCESS && g_enable_update_hmc == 1 )) ; then
                    update_hmc_list "$hmc"
                    g_enable_update_hmc=0
                fi

                if (( rc != $RC_SUCCESS )) || [[ -z $g_master_hmc ]] ; then
                    return $rc
                fi
            fi

            #=======================================================
            : Priority to use master or backup hmc in case of epcod
            : modify operation
            #=======================================================
            if (( g_epcod_modify_operation == 1 )) ; then
                loop_hmc_list="$g_master_hmc $g_hmc_list"
            fi

            #=======================================================
            : Loop through HMC list in case of ping or ssh failure.
            #=======================================================
            for hmc in $loop_hmc_list ; do
                #=======================================================
                : In case of epcod modify operation, loop_hmc_counter
                : value will be 1 for master hmc
                #=======================================================
                (( loop_hmc_counter++ ))

                #=======================================================
                : Try to ping the HMC at address $hmc.
                #=======================================================
                ping_output=$($ping_cmd $hmc >/dev/null 2>&1)
                ping_rc=$?
                if (( $ping_rc > 0 )) ; then
                    #=======================================================
                    : Cannot contact this HMC. Ask following HMC in list.
                    #=======================================================
                    dspmsg $ROHA_MSGS -s $ROHA_SET 500 \
                    "%1\$s: WARNING: unable to ping HMC at address %2\$s.\n" \
                    "$PROGNAME" "$hmc" >&3
                    continue
                fi

                #=======================================================
                : If executing an epcod modify operation, make sure that
                : the hmc is the master_hmc
                : HMC should be part of EPCoD before changing as master
                #=======================================================
                if (( loop_hmc_counter != 1 )) ; then
                    #=======================================================
                    : If not, we need to change master_hmc
                    : Change only on HMC failure, so do not use --force
                    #=======================================================
                   # Get HMC User from HACMPhmc
                   hmcuser=$(clodmget -n -q name=$hmc -f user HACMPhmc 2>/dev/null)
                   if [[ -z "$hmcuser" ]]; then
                        # Use FQDN and try again from HACMPhmc
                        typeset fqdn_hmc=$(host $hmc | awk '{print $1}')
                        [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -n -q name=${fqdn_hmc} -f user HACMPhmc 2>/dev/null)
                        if [[ -z "$hmcuser" ]];then
                             # If we are here means, either we are running clhmccmd very first time or no hmc user is configured to PowerHA.
                             typeset cust_hmcuser=$hmc"_user"
                             hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                             if [[ -z "$hmcuser" ]];then
                                  cust_hmcuser=$fqdn_hmc"_user"
                                  [[ ${fqdn_hmc} != $hmc ]] && hmcuser=$(clodmget -q " type=verify_dlpar AND description=$cust_hmcuser " -nf value HACMPcustom 2>/dev/null)
                                  if [[ -z "$hmcuser" ]];then
                                       # None of methods works to get HMC user name, hence use hscroot
                                       hmcuser="hscroot"
                                  fi
                             fi
                         fi
                    fi
                    ssh_output=$($ssh_cmd "$hmcuser@$hmc 'chcodpool -p $g_enterprise_pool -o $set_type --mc this 2>&1'")
                    ssh_rc=$?
                    if (( ssh_rc > 0 )) ; then
                        print $ssh_output | grep -q -i "specify the --force option"
                        if (( $? == 0 )) ; then
                            dspmsg $ROHA_MSGS -s $ROHA_SET 536 \
                            "%1\$s: WARNING: unable to change Master HMC from %2\$s to %3\$s for %4\$s Enterprise Pool CoD.\n%5\$s.. Now trying with force option.\n" \
                            "$PROGNAME" "$g_master_hmc" "$hmc" "$g_enterprise_pool" "$ssh_output" >&3
                            #=======================================================
                            : Change master returns failure, try with --force option
                            #=======================================================
                            ssh_output=$($ssh_cmd "$hmcuser@$hmc 'chcodpool -p $g_enterprise_pool -o $set_type --force --mc this 2>&1'")
                            ssh_rc=$?
                            if (( ssh_rc > 0 )) ; then
                                res=$($ssh_cmd "$hmcuser@$hmc 'lscodpool -p $g_enterprise_pool --level pool -F master_mc_name 2>&1'")
                                if (( $? == 0 )) && [[ -n $res && $res != $g_master_hmc ]]; then
                                    ssh_rc=0
                                fi
                            fi
                        fi
                    fi

                    if (( ssh_rc > 0 )) ; then
                        #=======================================================
                        : If an error occured, then master hmc were unable to be
                        : accessed. Cannot execute command
                        #=======================================================
                        dspmsg $ROHA_MSGS -s $ROHA_SET 503 \
                        "%1\$s: WARNING: unable to change Master HMC from %2\$s to %3\$s for %4\$s Enterprise Pool CoD.\n%5\$s\n" \
                        "$PROGNAME" "$g_master_hmc" "$hmc" "$g_enterprise_pool" "$ssh_output" >&3
                        rc=$RC_PARAM_ERROR
                        return $rc
                    else # ! (ssh_rc > 0)
                        dspmsg $ROHA_MSGS -s $ROHA_SET 505 \
                        "%1\$s: WARNING: Master HMC has been changed from %2\$s to %3\$s for %4\$s Enterprise Pool CoD.\n" \
                        "$PROGNAME" "$g_master_hmc" "$hmc" "$g_enterprise_pool" >&3
                        sleep 15 # give time for new master to be updated
                        g_master_hmc=$hmc
                    fi # (ssh_rc > 0)
                fi # ( loop_hmc_counter != 1 )

                #=======================================================
                : When the correct hmc is found, execute operation
                #=======================================================
                hmccmdexec $hmc "$cmd" ssh_output
                rc=$?
                if (( rc == RC_SSH_ERROR )) ; then
                    continue
                else
                    break
                fi
            done
        fi
    fi

    return $rc
} # End of "clhmcexec()"

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

#=============================================================================
# Attributes
#=============================================================================
typeset -r HMC_ATTRS="\
hmc_list \
hmc_version"

typeset -r MANAGED_SYSTEM_ATTRS="\
local_sys_name \
sys_name \
sys_lpar_names \
sys_state \
sys_type_model \
cod_mem_capable \
cod_proc_capable \
mem_region_size \
installed_sys_mem \
configurable_sys_mem \
deconfig_sys_mem \
sys_firmware_mem \
curr_avail_sys_mem \
curr_free_sys_mem \
installed_sys_proc_units \
configurable_sys_proc_units \
curr_avail_sys_proc_units \
curr_free_sys_proc_units \
deconfig_sys_proc_units \
min_proc_units_per_virtual_proc"

typeset -r PARTITION_ATTRS="\
local_lpar_name \
lpar_name \
lpar_id \
uuid \
lpar_state \
curr_profile \
lpar_avail_priority \
curr_proc_mode \
curr_min_mem \
curr_mem \
curr_max_mem \
curr_min_procs \
curr_procs \
curr_max_procs \
curr_min_proc_units \
curr_proc_units \
curr_max_proc_units \
curr_shared_proc_pool_name"

typeset -r PROFILE_ATTRS="\
local_prof_name \
prof_name \
prof_proc_mode \
prof_sharing_mode \
prof_shared_procpool \
prof_minimum_mem \
prof_minimum_procs \
prof_minimum_proc_units \
prof_desired_mem \
prof_desired_procs \
prof_desired_proc_units \
prof_maximum_mem \
prof_maximum_procs \
prof_maximum_proc_units"

typeset -r SHARED_PROC_POOL_ATTRS="\
local_procpool_name \
procpool_name \
max_pool_proc_units \
curr_free_pool_proc_units \
curr_reserved_pool_proc_units"

typeset -r TRIAL_COD_ATTRS="\
mem_trial_state \
activated_trial_mem \
mem_trial_days_left \
mem_trial_hours_left \
proc_trial_state \
activated_trial_procs \
proc_trial_days_left \
proc_trial_hours_left"

typeset -r ONOFF_COD_ATTRS="\
proc_onoff_state \
activated_onoff_procs \
avail_procs_for_onoff \
unreturned_onoff_procs \
onoff_request_proc_days_left \
onoff_proc_day_hours_left \
onoff_proc_days_avail \
mem_onoff_state \
activated_onoff_mem \
avail_mem_for_onoff \
unreturned_onoff_mem \
onoff_request_mem_days_left \
onoff_mem_day_hours_left \
onoff_mem_days_avail"

typeset -r ENTERPRISE_POOL_ATTRS="\
local_codpool_name \
codpool_name \
codpool_sys_names \
mobile_state \
master_mc_name \
backup_master_mc_name \
mobile_mem \
avail_mobile_mem \
unreturned_mobile_mem \
sys_mobile_mem \
sys_unreturned_mobile_mem \
sys_inactive_mem \
mobile_procs \
avail_mobile_procs \
unreturned_mobile_procs \
sys_mobile_procs \
sys_unreturned_mobile_procs \
sys_inactive_procs"

typeset -r GENERAL_ATTRS="\
hmc_list \
hmc_version \
local_sys_name \
sys_name \
sys_lpar_names \
sys_state \
sys_type_model \
local_lpar_name \
lpar_name \
lpar_id \
uuid \
lpar_state \
curr_profile \
local_prof_name \
prof_name \
local_procpool_name \
procpool_name \
local_codpool_name \
codpool_name \
codpool_sys_names \
mobile_state \
master_mc_name \
backup_master_mc_name"

typeset -r PROCESSOR_ATTRS="\
cod_proc_capable \
installed_sys_proc_units \
configurable_sys_proc_units \
deconfig_sys_proc_units \
curr_avail_sys_proc_units \
curr_free_sys_proc_units \
min_proc_units_per_virtual_proc \
prof_minimum_procs \
prof_minimum_proc_units \
prof_desired_procs \
prof_desired_proc_units \
prof_maximum_procs \
prof_maximum_proc_units \
prof_proc_mode \
prof_sharing_mode \
prof_shared_procpool \
curr_proc_mode \
curr_min_procs \
curr_procs \
curr_max_procs \
curr_min_proc_units \
curr_proc_units \
curr_max_proc_units \
curr_shared_proc_pool_name \
max_pool_proc_units \
curr_free_pool_proc_units \
curr_reserved_pool_proc_units \
proc_trial_state \
activated_trial_procs \
proc_trial_days_left \
proc_trial_hours_left \
proc_onoff_state \
activated_onoff_procs \
avail_procs_for_onoff \
unreturned_onoff_procs \
onoff_request_proc_days_left \
onoff_proc_day_hours_left \
onoff_proc_days_avail \
mobile_procs \
avail_mobile_procs \
unreturned_mobile_procs \
sys_mobile_procs \
sys_unreturned_mobile_procs \
sys_inactive_procs"

typeset -r MEMORY_ATTRS="\
cod_mem_capable \
mem_region_size \
installed_sys_mem \
configurable_sys_mem \
deconfig_sys_mem \
sys_firmware_mem \
curr_avail_sys_mem \
curr_free_sys_mem \
prof_minimum_mem \
prof_desired_mem \
prof_maximum_mem \
curr_min_mem \
curr_mem \
curr_max_mem \
mem_trial_state \
activated_trial_mem \
mem_trial_days_left \
mem_trial_hours_left \
mem_onoff_state \
activated_onoff_mem \
avail_mem_for_onoff \
unreturned_onoff_mem \
onoff_request_mem_days_left \
onoff_mem_day_hours_left \
onoff_mem_days_avail \
mobile_mem \
avail_mobile_mem \
unreturned_mobile_mem \
sys_mobile_mem \
sys_unreturned_mobile_mem \
sys_inactive_mem"

typeset -r AVAIL_ATTRS="\
curr_free_sys_mem \
onoff_mem_days_avail \
avail_mobile_mem \
curr_free_sys_proc_units \
onoff_proc_days_avail \
avail_mobile_procs"

typeset -r CURRENT_ATTRS="\
curr_mem \
curr_procs \
curr_proc_units \
activated_onoff_mem \
onoff_request_mem_days_left \
activated_onoff_procs \
onoff_request_proc_days_left \
sys_mobile_mem \
sys_mobile_procs"

typeset -r QUERY_ATTR_LIST="\
$HMC_ATTRS \
$MANAGED_SYSTEM_ATTRS \
$PARTITION_ATTRS \
$PROFILE_ATTRS \
$SHARED_PROC_POOL_ATTRS \
$TRIAL_COD_ATTRS \
$ONOFF_COD_ATTRS \
$ENTERPRISE_POOL_ATTRS"

typeset -r CHANGE_ATTR_LIST="\
max_pool_proc_units \
reserved_pool_proc_units"

typeset -r OPERATION_LIST="\
query \
change \
acquire \
release \
halt"

typeset -r RESOURCE_LIST="\
dlpar \
onoff \
epcod"

#=============================================================================
# Conversion tables
#   intended to convert attributes to be comprehensible by a specific version
#   of HMC.
# Key used in g_convtabHMC78 is the attribute passed to clhmccmd, while value
#  is the attribute passed to hmc command.
#=============================================================================
typeset -A g_convtabHMC78
#=======================================================
# 0. local
#=======================================================
g_convtabHMC78[hmc_list]=""                                   # Not supported by HMC - internally computed
g_convtabHMC78[hmc_version]=""                                # Not supported by HMC - internally computed
g_convtabHMC78[local_sys_name]=""                             # Not supported by HMC - internally computed
g_convtabHMC78[local_lpar_name]=""                            # Not supported by HMC - internally computed
g_convtabHMC78[local_prof_name]=""                            # Not supported by HMC - internally computed
g_convtabHMC78[local_procpool_name]=""                        # Not supported by HMC - internally computed
g_convtabHMC78[local_codpool_name]=""                         # Not supported by HMC - internally computed
#=======================================================
# 1. cec_sys (lssyscfg -m $g_managed_system -r sys)
#=======================================================
g_convtabHMC78[sys_name]="name"
g_convtabHMC78[sys_state]="state"
g_convtabHMC78[sys_lpar_names]=""                             # Not supported by HMC - internally computed
g_convtabHMC78[sys_type_model]="type_model"
g_convtabHMC78[cod_mem_capable]="cod_mem_capable"
g_convtabHMC78[cod_proc_capable]="cod_proc_capable"
#=======================================================
# 2. cec_mem (lshwres -m $g_managed_system --level sys -r mem)
#=======================================================
g_convtabHMC78[mem_region_size]="mem_region_size"
g_convtabHMC78[installed_sys_mem]="installed_sys_mem"
g_convtabHMC78[configurable_sys_mem]="configurable_sys_mem"
g_convtabHMC78[deconfig_sys_mem]="deconfig_sys_mem"
g_convtabHMC78[sys_firmware_mem]="sys_firmware_mem"
g_convtabHMC78[curr_avail_sys_mem]="curr_avail_sys_mem"
g_convtabHMC78[curr_free_sys_mem]=""                          # Not supported by HMC - internally computed
#=======================================================
# 3. cec_proc (lshwres -m $g_managed_system --level sys -r proc)
#=======================================================
g_convtabHMC78[installed_sys_proc_units]="installed_sys_proc_units"
g_convtabHMC78[configurable_sys_proc_units]="configurable_sys_proc_units"
g_convtabHMC78[deconfig_sys_proc_units]="deconfig_sys_proc_units"
g_convtabHMC78[curr_avail_sys_proc_units]="curr_avail_sys_proc_units"
g_convtabHMC78[min_proc_units_per_virtual_proc]="min_proc_units_per_virtual_proc"
g_convtabHMC78[curr_free_sys_proc_units]=""                   # Not supported by HMC - internally computed
#=======================================================
# 4. lpar_sys (lssyscfg -m $g_managed_system -r lpar --filter lpar_names=$g_partition)
#=======================================================
g_convtabHMC78[lpar_name]="name"
g_convtabHMC78[lpar_state]="state"
g_convtabHMC78[lpar_id]="lpar_id"
g_convtabHMC78[uuid]="uuid"
g_convtabHMC78[curr_profile]="curr_profile"
g_convtabHMC78[lpar_avail_priority]="lpar_avail_priority"
#=======================================================
# 5. lpar_prof (lssyscfg -m $g_managed_system -r prof --filter profile_names=$g_profile,lpar_names=$g_partition)
#=======================================================
g_convtabHMC78[prof_name]="name"
g_convtabHMC78[prof_proc_mode]="proc_mode"
g_convtabHMC78[prof_sharing_mode]="sharing_mode"
g_convtabHMC78[prof_shared_procpool]="shared_proc_pool_name"
g_convtabHMC78[prof_minimum_mem]="min_mem"
g_convtabHMC78[prof_minimum_procs]="min_procs"
g_convtabHMC78[prof_minimum_proc_units]="min_proc_units"
g_convtabHMC78[prof_desired_mem]="desired_mem"
g_convtabHMC78[prof_desired_procs]="desired_procs"
g_convtabHMC78[prof_desired_proc_units]="desired_proc_units"
g_convtabHMC78[prof_maximum_mem]="max_mem"
g_convtabHMC78[prof_maximum_procs]="max_procs"
g_convtabHMC78[prof_maximum_proc_units]="max_proc_units"
#=======================================================
# 6. lpar_mem (lshwres -m $g_managed_system -r mem --level lpar --filter lpar_names=$g_partition)
#=======================================================
g_convtabHMC78[curr_min_mem]="curr_min_mem"
g_convtabHMC78[curr_mem]="curr_mem"
g_convtabHMC78[curr_max_mem]="curr_max_mem"
#=======================================================
# 7. lpar_proc (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
#=======================================================
g_convtabHMC78[curr_proc_mode]="curr_proc_mode"
g_convtabHMC78[curr_min_procs]="curr_min_procs"
g_convtabHMC78[curr_procs]="curr_procs"
g_convtabHMC78[curr_max_procs]="curr_max_procs"
g_convtabHMC78[curr_min_proc_units]="curr_min_proc_units"
g_convtabHMC78[curr_proc_units]="curr_proc_units"
g_convtabHMC78[curr_max_proc_units]="curr_max_proc_units"
#=======================================================
# 8. lpar_proc_procpool (lshwres -m $g_managed_system -r procpool --filter pool_names=$g_shared_proc_pool)
#=======================================================
g_convtabHMC78[procpool_name]="name"
g_convtabHMC78[max_pool_proc_units]="max_pool_proc_units"
g_convtabHMC78[curr_free_pool_proc_units]=""                   # Not supported by HMC - internally computed
g_convtabHMC78[curr_reserved_pool_proc_units]="curr_reserved_pool_proc_units"
#=======================================================
# 9. trial_mem (lscod -t cap -m $g_managed_system -c trial -r mem)
#=======================================================
g_convtabHMC78[mem_trial_state]="mem_trial_state"
g_convtabHMC78[activated_trial_mem]="activated_trial_mem"
g_convtabHMC78[mem_trial_days_left]="mem_trial_days_left"
g_convtabHMC78[mem_trial_hours_left]="mem_trial_hours_left"
#=======================================================
# 10. trial_proc (lscod -t cap -m $g_managed_system -c trial -r proc)
#=======================================================
g_convtabHMC78[proc_trial_state]="proc_trial_state"
g_convtabHMC78[activated_trial_procs]="activated_trial_procs"
g_convtabHMC78[proc_trial_days_left]="proc_trial_days_left"
g_convtabHMC78[proc_trial_hours_left]="proc_trial_hours_left"
#=======================================================
# 11. onoff_mem (lscod -t cap -m $g_managed_system -c onoff -r mem)
#=======================================================
g_convtabHMC78[mem_onoff_state]="mem_onoff_state"
g_convtabHMC78[activated_onoff_mem]="activated_onoff_mem"
g_convtabHMC78[avail_mem_for_onoff]="avail_mem_for_onoff"
g_convtabHMC78[unreturned_onoff_mem]="unreturned_onoff_mem"
g_convtabHMC78[onoff_request_mem_days_left]="onoff_request_mem_days_left"
g_convtabHMC78[onoff_mem_day_hours_left]="onoff_mem_day_hours_left"
g_convtabHMC78[onoff_mem_days_avail]="onoff_mem_days_avail"
#=======================================================
# 12. onoff_proc (lscod -t cap -m $g_managed_system -c onoff -r proc)
#=======================================================
g_convtabHMC78[proc_onoff_state]="proc_onoff_state"
g_convtabHMC78[activated_onoff_procs]="activated_onoff_procs"
g_convtabHMC78[avail_procs_for_onoff]="avail_procs_for_onoff"
g_convtabHMC78[unreturned_onoff_procs]="unreturned_onoff_procs"
g_convtabHMC78[onoff_request_proc_days_left]="onoff_request_proc_days_left"
g_convtabHMC78[onoff_proc_day_hours_left]="onoff_proc_day_hours_left"
g_convtabHMC78[onoff_proc_days_avail]="onoff_proc_days_avail"
#=======================================================
# 13. epcod_pool (lscodpool -p $g_enterprise_pool --level pool)
#=======================================================
g_convtabHMC78[codpool_name]="name"
g_convtabHMC78[mobile_state]="state"
g_convtabHMC78[master_mc_name]="master_mc_name"
g_convtabHMC78[backup_master_mc_name]="backup_master_mc_name"
g_convtabHMC78[mobile_mem]="mobile_mem"
g_convtabHMC78[avail_mobile_mem]="avail_mobile_mem"
g_convtabHMC78[unreturned_mobile_mem]="unreturned_mobile_mem"
g_convtabHMC78[mobile_procs]="mobile_procs"
g_convtabHMC78[avail_mobile_procs]="avail_mobile_procs"
g_convtabHMC78[unreturned_mobile_procs]="unreturned_mobile_procs"
#=======================================================
# 14. epcod_sys (lscodpool -p $g_enterprise_pool --level sys --filter names=$g_managed_system)
#=======================================================
g_convtabHMC78[codpool_sys_names]=""                          # Not supported by HMC - internally computed
g_convtabHMC78[sys_mobile_mem]="mobile_mem"
g_convtabHMC78[sys_unreturned_mobile_mem]="unreturned_mobile_mem"
g_convtabHMC78[sys_inactive_mem]="inactive_mem"
g_convtabHMC78[sys_mobile_procs]="mobile_procs"
g_convtabHMC78[sys_unreturned_mobile_procs]="unreturned_mobile_procs"
g_convtabHMC78[sys_inactive_procs]="inactive_procs"
#=======================================================
# 15. lpar_cspp (lshwres -m $g_managed_system -r proc --level lpar --filter lpar_names=$g_partition)
#=======================================================
g_convtabHMC78[curr_shared_proc_pool_name]="curr_shared_proc_pool_name"

#=======================================================
# Return codes
#=======================================================
typeset -ri RC_SUCCESS=0
typeset -ri RC_FAILURE=1
typeset -ri RC_PARAM_ERROR=1
typeset -ri RC_PING_ERROR=2
typeset -ri RC_SSH_ERROR=3
typeset -ri RC_REM_RES_BUSY_ERROR=4
typeset -ri RC_REM_CEC_BUSY_ERROR=5
typeset -ri RC_REM_NOT_ENOUGH_RES_ERROR=6
typeset -ri RC_REM_OTHER_ERROR=7
typeset -ri RC_CEC_NOT_FOUND=8
#=======================================================
# HMC version to support cross HMC
#=======================================================
typeset -ri CROSS_HMC_VERSION=85
#=======================================================
# Dspmsg codes
#=======================================================
typeset ROHA_SET=38
typeset ROHA_MSGS="scripts.cat"

#=======================================================
# Global variables
#=======================================================
typeset g_operation=""
typeset g_hmc_list=""
typeset g_partition=""
typeset g_local_partition=""
typeset g_profile=""
typeset g_local_profile=""
typeset g_managed_system=""
typeset g_local_managed_system=""
typeset g_shared_proc_pool=""
typeset g_local_shared_processor_pool=""
typeset g_enterprise_pool=""
typeset g_local_enterprise_pool=""
typeset g_resource=""
typeset g_safe_option=0
typeset g_running_lpars_list=""
typeset g_not_act_lpars_list=""
typeset -i g_force=0
typeset -i g_timeout=0
typeset -i g_memory=0
typeset -i g_quantity=0
typeset -F4 g_proc_units=0.00
typeset g_attributes=""
typeset -i g_duration=-1
typeset -i g_labels=0
typeset -i g_enable_timeout=0
typeset -i g_enable_update_hmc=0
typeset -i g_epcod_modify_operation=0

#=======================================================
# HMC functions
#
# The function is written in a string and will be copied
# over ssh to the HMC to be executed in the HMC env.
# This allows to avoid many ssh operations in case of
# loops on HMC commands that cannot be avoided
#
# This require several special coding rules
#    Use \$ and \" if they are interpreted at HMC level.
#    Use $ and " not escaped if they are interpreted in current env when string is built
#    Use semicolon at end of each line (except for do and then) as the function string will be inlined
#=======================================================

#=======================================================
# Name:        HMCEXEC_managed_system_to_enterprise_pool
#
# Description:
#    Finds the EPCoD pool associated to a managed system
#    First need to list all EPCoD pools known by the HMC
#    Then for each pool, check if the managed system is
#    in the list of managed system for this pool
#
#    All unexpected behavior needs to be reported to be logged
#    HMC commands executed and their return code handling :
#      (once)     : lscodpool --level pool -F name
#          - success : we can pursue, looping on the discovered pools
#          - any error : return from the function with an error state and propagate the error message
#      (multiple) : lscodpool --level sys -p [pool] --filter [names|mtms]=[sys_name] -F name
#          - success : the correct pool is found, we can exit with success
#          - error with HSCL908C : the managed system is not in this pool, don't propagate this error and try next pool
#          - any other error : return from the function with an error state and propagate the error message
#    About HSCL908C agregated HSCL908C codes :
#          If all lscodpool --level sys ... commands in the loop returns which message :
#               HSCL908C Managed system [sys_name] is not in Power enterprise pool [pool_name].
#          Then we agregate these HSCL908C messages to a single HSCL908C message stating that no
#          Power enterprise pool on this HMC knows the Managed system :
#               HSCL908C (SystemMirror agregated HSCL908C codes) Managed system [sys_name] is not in any Power enterprise pool known by the HMC
#
# Arguments:   $1 [IN]    Filter type to query with lscodpool (describes $2 format) :
#                         Value can be "mtms" if $2 is like tttt-mmmm*ssss (machine type / model / serial number)
#                                   or "names" if $2 is the real managed_system name
#              $2 [IN]    Either real managed system name or managed system mtms depending on $1
#
# Environment: (Not escaped so they are interpreted at string initialization with current env values)
#              RC_SUCCESS
#              RC_FAILURE
#
# Output :     In case of error (different from HSCL908C) : error message from HMC
#              In case of HSCL908C for all lscodpool in the loop : agregated HSCL908C message
#              In case of success : Enterprise pool name
#
# Returns:     RC_SUCCESS
#              RC_FAILURE
#
#=======================================================
typeset func_HMCEXEC_managed_system_to_enterprise_pool="
    function HMCEXEC_managed_system_to_enterprise_pool
    {
        typeset ms_filter=\$1;
        typeset sys_name=\$2;
        typeset res=\"\";
        typeset -i rc=0;

        res=\$(LC_ALL=C lscodpool --level pool -F name);
        rc=\$?;
        if (( \$rc != $RC_SUCCESS )) || [[ \$res == \"No results were found.\" ]] ; then
            echo \$res;
            return \$rc;
        fi;
        for pool in \$res ; do
            res=\$(lscodpool --level sys -p \$pool --filter \$ms_filter=\$sys_name -F name);
            rc=\$?;
            if (( \$rc != $RC_SUCCESS )) && [[ \$(echo \$res | LC_ALL=C grep -v \"^HSCL908C\") != \"\" ]] ; then
                echo \$res;
                return \$rc;
            fi;
            if (( \$rc == $RC_SUCCESS )) ; then
                echo \$pool;
                return $RC_SUCCESS;
            fi;
        done;
        echo \"HSCL908C (SystemMirror agregated HSCL908C codes) Managed system \$sys_name is not in any Power enterprise pool known by the HMC\";
        return $RC_FAILURE;
    }"

#=======================================================
# Minimize function to avoid extra data on ssh
# This removes all extra spaces and newlines
#=======================================================
func_HMCEXEC_managed_system_to_enterprise_pool=$(echo $func_HMCEXEC_managed_system_to_enterprise_pool)

#=======================================================
# Export environment
#=======================================================
PROGNAME=${0##*/}
export PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)"
eval export $(cllsparam -x)
[[ ${VERBOSE_LOGGING:-} == high ]] && set -x
: version=@(#)  64438b3 43haes/usr/sbin/cluster/events/utils/clhmccmd.sh, 726, 2147A_aha726, Oct 13 2021 08:38 AM

#=======================================================
: Parse and check command line arguments
#=======================================================
parse_cmd_line "${@:-}" ; rc=$?
(( $rc > 0 )) && exit $rc

#=======================================================
: Execute operation $g_operation
#=======================================================
case $g_operation in
"query")
    process_query
    rc=$?
    ;;
"change")
    process_change
    rc=$?
    ;;
"acquire")
    process_acquire
    rc=$?
    ;;
"release")
    process_release
    rc=$?
    ;;
"halt")
    process_halt
    rc=$?
    ;;
esac
(( $rc > 0 )) && exit $rc

exit 0
