#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG
#  This is an automatically generated prolog.
#
#  Copyright (C) Altran ACT S.A.S. 2017,2019,2021.  All rights reserved.
#
#  ALTRAN_PROLOG_END_TAG
#
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# 61haes_r721 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_add_hmc.sh 1.3.1.10
#
# Licensed Materials - Property of IBM
#
# COPYRIGHT International Business Machines Corp. 2011
# All Rights Reserved
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
# IBM_PROLOG_END_TAG
# @(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_add_hmc.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
#================================================
# The following, commented line enforces coding
# standards when this file is edited via vim.
#================================================
# vim:tabstop=4:shiftwidth=4:expandtab:smarttab
#================================================

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

=head1 NAME

 KLIB_HACMP_add_hmc

=head1 SYNOPSIS

 clmgr add hmc <HMC> \
 [ TIMEOUT=<###> ] \
 [ RETRY_COUNT=<###> ] \
 [ RETRY_DELAY=<###> ] \
 [ NODES=<node>[,<node#2>,...] ] \
 [ SITES=<site>[,<site#2>,...] ] \
 [ CHECK_HMC=<Yes|No> ] \
 [ USER_NAME=<###> ] \
 [ PASSWORD=<###> ]

=head1 DESCRIPTION

 Attempts to create the specified HMC object within the PowerHA SystemMirror
  configuration.
 When creating an HMC into PowerHA SystemMirror configuration, it can be associated
  with nodes and/or sites. By default a newly created HMC is always added into
  default HMCs list of the cluster.
 An HMC is associated by default with all nodes of the cluster, but it can be
  associated with all nodes of a site by performing association at the site level,
  or can be associated with one specific node by performing association at the
  node level.
 If the association is done at different levels, the association done at the node
  level overrides the one done at the site level, which overrides the one done at
  the cluster level.
 Each node will try to communicate with its own HMCs to perform Resource
  Optimized High Availability operations.

=head1 ARGUMENTS

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

 2. HMC [REQUIRED] [string]
 Either hostname or IP address for the HMC.
 IPv4 and IPv6 format address are supported.

 3. TIMEOUT [OPTIONAL] [int]
 Timeout set on HMC operations.
 This value is expressed in minutes.
 You can choose the -1 value to indicate you want to use
  the default timeout value set at the HMC tunables parameters, or you can
  set your own value. No value means you use the default.

 4. RETRY_COUNT [OPTIONAL] [int]
 Number of retries set on HMC operations.
 The HMC operation which timeouts will be retried this number of times.
 You can choose the -1 value to indicate you want to use
  the default retry count value set at the HMC tunables parameters, or you can
  set your own value. No value means you use the default.

 5. RETRY_DELAY [OPTIONAL] [int]
 Duration of delay between two retries set on HMC operations.
 This value is expressed in seconds.
 The HMC operation which timeouts will be retried 'RETRY_COUNT' number
  of times, with 'RETRY_DELAY' seconds between each retry.
 You can choose the -1 value to indicate you want to use
  the default retry delay value set at the HMC tunables parameters, or you can
  set your own value. No value means you use the default.

 6. NODES [OPTIONAL] [string]
 The list of nodes that will use this HMC.

 7. SITES [OPTIONAL] [string]
 The list of sites that will use this HMC. 
 This SITES option is not valid for a Standard Cluster (aka a No-Site Cluster).

 8. CHECK_HMC [OPTIONAL] ['Yes'|'No']
 If check connectivity between nodes and HMC must be done, or must be avoided,
  at configuration time. By default the check is done.
 The connectivity check is done as well at  cluster synchronization time.

 9. USER_NAME [OPTIONAL] [string]
 User name for HMC. 
  This USER_NAME option is mandatory for REST API based communication with HMC.
  This USER_NAME option is not valid for SSH based communication with HMC.

 10. PASSWORD [OPTIONAL] [string]
 Password for HMC.
  This PASSWORD option is valid for REST API based communication with HMC.
  If PASSWORD is not specified for REST, will be prompted for password. 
  User need to enter the password.
  This PASSWORD option is not valid for SSH based communication with HMC.

=head1 CONFIGURATION/SETUP

1. If necessary, generate the SSH keys for your AIX node:

 1. cd ~/.ssh/
 2. ssh-keygen -t rsa

 This will create the private key (id_rsa) and public key (id_rsa.pub).

2. Add your node's public key to the HMC's SSH "allow" list:

 1. scp hscroot@<HMC>:.ssh/authorized_keys2 /tmp/HMC_PUB_KEYS
 2. cat ~/.ssh/id_rsa.pub >> /tmp/HMC_PUB_KEYS
 3. scp /tmp/HMC_PUB_KEYS hscroot@<HMC>:.ssh/authorized_keys2
 4. rm -f /tmp/HMC_PUB_KEYS
 5. Test it (i.e. ssh hscroot@<HMC> date). No password should be required.

=head1 RETURN

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

=head1 COPYRIGHT

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

=cut
} # End of POD-formatted documentation.

function KLIB_HACMP_add_hmc {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_add_hmc.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
    : INPUTS: $*

    typeset -n properties=$1
    typeset hmc_label=${2//\"/}
    typeset timeout=${3//\"/}
    typeset retry_count=${4//\"/}
    typeset retry_delay=${5//\"/}
    typeset nodelist=${6//\"/}
    nodelist=${nodelist//,/ }
    typeset sitelist=${7//\"/}
    sitelist=${sitelist//,/ }
    typeset -l check_hmc=${8//\"/}
    typeset username=${9//\"/}
    typeset password=${10//\"/}

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

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset -i CHECK_HMC_ERROR=
    typeset -i checkRC=$RC_SUCCESS

    CL=$LINENO isClusterDefined
    if (( $? != RC_SUCCESS )); then
        rc=$RC_MISSING_DEPENDENCY
    fi

    #===============
    : Validate input
    #===============
    : hmc_label
    typeset HMC_LABEL=
    if [[ -z $hmc_label ]]; then
        CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: an hostname or an IP address must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT
    else
        CL=$LINENO KLIB_HACMP_is_known_hmc hmc_label
        if (( $? == RC_SUCCESS )); then
            CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 229 "\nERROR: the specified object already exists: \"%1\$s\"\n\n" "$hmc_label" 1>&2
            rc=$RC_INCORRECT_INPUT
        else
            HMC_LABEL=$hmc_label
        fi
    fi

    typeset -i CONN_TYPE=
    CONN_TYPE=$(clodmget -n -f connection_type HACMPhmcparam)

    #================================================================
    : Check for a defined cluster. No need to continue without one.
    #================================================================
    if (( $rc == RC_UNKNOWN )); then
	#=========================================================
        : username parameter is mandatory for connection type rest
        #=========================================================
        if (( $CONN_TYPE == 1 )); then
            if [[ -z $username ]]; then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 1132 \
"\nERROR: USER_NAME must be provided for HMC connection type \"REST API\".\n\n" 1>&2
                rc=$RC_MISSING_INPUT
            fi
        fi

        #===================
        : username parameter
        #===================
        typeset USER_NAME=
        if [[ -n $username ]]; then
            if [[ $username == [\-\+\~\@]* ]]; then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 103 \
'\nERROR: one or more invalid characters were detected in "%1$s":  "%2$s".\n\n' $username "[-+~@]" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                USER_NAME=$username
            fi
        fi
    
        #===================
        : password parameter
        #===================
        typeset PASSWORD=
        if [[ -n $password ]]; then
            PASSWORD=$(print $password | clencodearg)
        fi

        if (( $CONN_TYPE == 0 )); then
            if [[ -n $username || -n $password ]]; then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 1137 \
"\nWARNING: Specified USER_NAME or PASSWORD will not be used for HMC connection type \"ssh\".\n\n" 1>&2
            fi
        fi  


        #==================
        : timeout parameter
        #==================
        typeset TIMEOUT=
        if [[ -n $timeout ]]; then
            if [[ $timeout == "-1" ]]; then
                TIMEOUT=-1
            elif [[ $timeout != +([[:digit:]]) ]];  then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 809 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid input include either \"-1\" or a positive integer value.\n\n" "$timeout" "[-1|[0-9]*}" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                TIMEOUT=$timeout
            fi
        else
            TIMEOUT=-1
        fi

        #======================
        : retry count parameter
        #======================
        typeset RETRY_COUNT=
        if [[ -n $retry_count ]]; then
            if [[ $retry_count == "-1" ]]; then
                RETRY_COUNT=-1
            elif [[ $retry_count != +([[:digit:]]) ]] then
                    dspmsg -s $CLMGR_SET $CLMGR_MSGS 809 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid input include either \"-1\" value or a positive integer value.\n\n" "$retry_count" "[-1|[0-9]*}" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                RETRY_COUNT=$retry_count
            fi
        else
            RETRY_COUNT=-1
        fi

        #======================
        : retry delay parameter
        #======================
        typeset RETRY_DELAY=
        if [[ -n $retry_delay ]]; then
            if [[ $retry_delay == "-1" ]]; then
                RETRY_DELAY=-1
            elif [[ $retry_delay != +([[:digit:]]) ]] then
                dspmsg -s $CLMGR_SET $CLMGR_MSGS 809 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid input include either \"-1\" value or a positive integer value.\n\n" "$retry_delay" "[-1|[0-9]*}" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                RETRY_DELAY=$retry_delay
            fi
        else
            RETRY_DELAY=-1
        fi

        #=================================
        : check HMC connectivity parameter
        #=================================
        typeset -i CHECK_HMC=
        if [[ -z $check_hmc ]]; then
            CHECK_HMC=1
        elif [[ $check_hmc != @(0|1|y|t|n|f)* ]]; then
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" "$ATTR" "$VALUE" 1>&2
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "Yes, No" 1>&2
            rc=$RC_INCORRECT_INPUT
        else
            if [[ $check_hmc == @(1|y|t)* ]]; then
                CHECK_HMC=1
            elif [[ $check_hmc == @(0|n|f)* ]]; then
                CHECK_HMC=0
            fi 
        fi


        #==========================================================
        : HMC password should be available for connection_type rest
        #==========================================================
        if (( $rc == RC_UNKNOWN && $CONN_TYPE == 1 )); then
            CHECK_HMC=1
            #==================================================================
            : Get the password from user if not provide for rest api connection
            #==================================================================
            if [[ -z $password ]]; then   
                print -- "$0()[$LINENO]($SECONDS): clhmcpasswd " >>$CLMGR_TMPLOG
                password=$(clhmcpasswd )
                checkRC=$?
                print -- "$0()[$LINENO]($SECONDS): clhmcpasswd rc=$checkRC" >>$CLMGR_TMPLOG #log command result 
                if (( $checkRC != RC_SUCCESS )); then
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1134 "\nERROR: failed to set PASSWORD for \"%1\$s\" HMC.\n\n" "$HMC_LABEL" 1>&2
                    rc=$RC_ERROR
                elif [[ -z $password || $password == *([[:space:]]) ]]; then
                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 1134 "\nERROR: failed to set PASSWORD for \"%1\$s\" HMC.\n\n" "$HMC_LABEL" 1>&2
                    rc=$RC_INCORRECT_INPUT
                else
                    PASSWORD=$(print $password | clencodearg)
                fi
            fi
        fi
    fi

    #==============================================================================
    : Sitelist parameter only valid for SC and LC 
    #==============================================================================
    if (( $rc == RC_UNKNOWN )); then
        if [[ $sitelist != *([[:space:]]) ]]; then
            if [[ $CLUSTER_TYPE == "NSC" ]]; then
                CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 821 '\nERROR: the SITE option is not appropriate for a no-site cluster.\n\n' 1>&2
                rc=$RC_INCORRECT_INPUT
            fi
        fi
    fi
    
    if (( $rc == RC_UNKNOWN )); then
        #==============================================================================
        : Sitelist parameter
        :  What must be done here :
        :    - check sites given in parameter exist, if not propose a list of existing sites
        :    - verify that all nodes of all sites can communicate with the hmc, and build
        :       the list of sites to be kept
        :    - if any error during the connectivity check, just break unless we ask to force
        : This variable SITES only to hold the list of sites whose nodes connect ok to the hmc
        #==============================================================================
        typeset SITES=
        if [[ -n $sitelist ]]; then
            for site in $sitelist; do
                CL=$LINENO KLIB_HACMP_is_known_site "${site%%\.*}" >/dev/null 2>&1
                if (( $? != RC_SUCCESS )); then
                    CL=$LINENO dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$site" 1>&2
                    dspmsg -s $CLMGR_SET $CLMGR_MSGS 157 "Available Sites:\n\n" 1>&2

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

            if (( $rc == RC_UNKNOWN )); then
                if (( $CHECK_HMC == 1 )); then
                    for site in $sitelist; do
                        CHECK_HMC_ERROR=0
                        typeset site_nodes=""
                        if [[ -n $site ]]; then
                           typeset -A siteAttrs
                           CL=$LINENO KLIB_HACMP_get_site_attributes $site siteAttrs
                           site_nodes="${siteAttrs[NODES]//,/ }"
                           unset siteAttrs
                        fi

                        if [[ -n $site_nodes ]]; then
                            #==============================
                            : this variable SITENODES to hold the nodes
                            :  which connect ok to the hmc, only for debug
                            #==============================
                            typeset SITENODES=
                            for site_node in $site_nodes; do
                                print -- "check_hmc_connectivity_with_node $site_node $HMC_LABEL SITENODES=$SITENODES" >>$CLMGR_TMPLOG
                                check_hmc_connectivity_with_node $site_node $HMC_LABEL SITENODES $USER_NAME $PASSWORD
                                checkRC=$?
                                print -- "check_hmc_connectivity_with_node $site_node $HMC_LABEL SITENODES=$SITENODES rc=$checkRC" >>$CLMGR_TMPLOG
                                if (( $checkRC != 0 )); then
                                    CHECK_HMC_ERRROR=1;
                                    break
                                fi
                            done
                        fi
                        if (( $CHECK_HMC_ERROR == 1 )); then
                            break
                        else
                            SITES=${SITES:+$SITES }$site
                        fi
                    done
                else
                    #==============================
                    : we do not check connectivity, we take all sites
                    #==============================
                    SITES="$sitelist"
                fi
            fi
        fi
    fi

    if (( $rc == RC_UNKNOWN )); then
        #==============================================================================
        : Nodelist parameter
        :  What must be done here :
        :    - check nodes given in parameter exist, if not propose a list of existing nodes
        :    - verify that all nodes can communicate with the hmc, and build
        :       the list of nodes to be kept
        :    - if any error during the connectivity check, just break unless we ask to force
        :
        : This variable NODES only to hold the list of nodes connect ok to the hmc
        #==============================================================================
        typeset NODES=

        if [[ -n $nodelist ]]; then
            for node in $nodelist; do
                CL=$LINENO KLIB_HACMP_is_known_node "${node%%\.*}" >/dev/null 2>&1
                if (( $? != RC_SUCCESS )); then
                    CL=$LINENO dspmsg -s $CLMGR_SET $CLMGR_MSGS 208 "\nERROR: this node does not exist \"%1\$s\".\n\n" "$node" 1>&2
                    dspmsg -s $CLMGR_SET $CLMGR_MSGS 151 "Available Nodes:\n\n" 1>&2

                    typeset available
                    CL=$LINENO KLIB_HACMP_list_nodes available
                    for (( i=0; i<${#available[*]}; i++ )); do
                        if [[ ${available[$i]} != *([[:space:]]) ]]; then
                            print -u2 "\t${available[$i]}"
                        fi
                    done
                    print -u2 ""
                    rc=$RC_NOT_FOUND
                fi
            done
            if (( $rc == RC_UNKNOWN )); then
                if (( $CHECK_HMC == 1 )); then
                    typeset -i checkRC=
                    for node in $nodelist; do
                        print -- "check_hmc_connectivity_with_node $node $HMC_LABEL NODES=$NODES" >>$CLMGR_TMPLOG
                        check_hmc_connectivity_with_node $node $HMC_LABEL NODES $USER_NAME $PASSWORD
                        checkRC=$?
                        print -- "check_hmc_connectivity_with_node $node $HMC_LABEL NODES=$NODES rc=$checkRC" >>$CLMGR_TMPLOG
                        if (( $checkRC != 0 )); then
                            CHECK_HMC_ERROR=1
                            break
                        fi
                    done
                else
                    #==============================
                    : we do not check connectivity, we take all nodes
                    #==============================
                    NODES=$nodelist
                fi
            fi
        fi
    fi

    if (( $rc == RC_UNKNOWN )); then
        #==========================================================
        : If nodelist or sitelist is empty, but we must check at 
        : least connectivity between the current node and this hmc
        #==========================================================
        if [[ -z $nodelist && -z $sitelist ]]; then
            if (( $CHECK_HMC == 1 )); then
                typeset CHECKED_NODE=
                #LOCAL_NODE is always set by the clmgr framework, and can be used
                print -- "check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL CHECKED_NODE=$CHECKED_NODE" >>$CLMGR_TMPLOG
                check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL CHECKED_NODE $USER_NAME $PASSWORD
                checkRC=$?
                print -- "check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL NODES=$CHECKED_NODE rc=$checkRC" >>$CLMGR_TMPLOG
                if (( $checkRC != 0 )); then
                    CHECK_HMC_ERROR=1
                fi
            fi
        fi
    fi


    if (( $rc == RC_UNKNOWN )); then
        #===========================================================
        : Define the HMC if no input errors have been detected
        #===========================================================
        if (( $CHECK_HMC_ERROR != 1 )); then
            #===========================================================
            : Define the HMC if no connectivity errors have been detected
            #===========================================================

            #===========================================================
            : Firstly, update the HMC object
            #===========================================================
            typeset nOpt= tOpt= rOpt= dOpt= uOpt= pOpt=
            [[ -z $HMC_LABEL ]]   && nOpt=" "     || nOpt=" -n $HMC_LABEL"
            [[ -z $TIMEOUT ]]     && tOpt=" -t 0" || tOpt=" -t $TIMEOUT"
            [[ -z $RETRY_COUNT ]] && rOpt=" -c 0" || rOpt=" -c $RETRY_COUNT"
            [[ -z $RETRY_DELAY ]] && dOpt=" -d 0" || dOpt=" -d $RETRY_DELAY"
            [[ -z $username ]] && uOpt="" || uOpt=" -u $username"
            [[ -z $PASSWORD ]] && pOpt="" || pOpt=" -p $PASSWORD"

            print -- "$0()[$LINENO]($SECONDS): claddhmc $nOpt$tOpt$rOpt$dOpt$uOpt$pOpt" >>$CLMGR_TMPLOG
            claddhmc $nOpt$tOpt$rOpt$dOpt$uOpt$pOpt
            rc=$?
            print -- "$0()[$LINENO]($SECONDS): claddhmc $nOpt$tOpt$rOpt$dOpt$uOpt$pOpt rc=$rc" >>$CLMGR_TMPLOG # Always log command result

            if (( $rc != RC_SUCCESS )); then
                CL=$LINENO dspmsg -s $CLMGR_SET $CLMGR_MSGS 201 "\nERROR: failed to add \"%1\$s\".\n\n" "$HMC_LABEL" 1>&2
                rc=$RC_ERROR
            else
                #===========================================================
                : Now update the nodes objects
                :  - for each node, we must update the list of hmcs already set
                #===========================================================
                if (( $rc == RC_SUCCESS )); then
                    if [[ -n $NODES ]]; then
                        #==============
                        : Loop on nodes
                        #==============
                        for NODE in $NODES; do
                            typeset NOpt= kvOpt=
                            typeset UPDATED_HMCS=
                            typeset CURRENT_HMCS=
                            print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n $NODE -o " >>$CLMGR_TMPLOG # Always log command
                            CURRENT_HMCS=$(cllshmcparam -n $NODE -o)
                            rc=$?
                            print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n $NODE -o rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                            if (($rc==RC_SUCCESS)); then
                                for CURRENT_HMC in $CURRENT_HMCS; do
                                    UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$CURRENT_HMC
                                done
                                UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMC_LABEL
                                kvOpt="-c HMC_IP=$UPDATED_HMCS"
                                NOpt=" -n $NODE"
                                print -- "$0()[$LINENO]($SECONDS): clchhmcparam $NOpt $kvOpt" >>$CLMGR_TMPLOG
                                clchhmcparam $NOpt $kvOpt
                                rc=$?
                                print -- "$0()[$LINENO]($SECONDS): clchhmcparam $NOpt $kvOpt rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                                if (( $rc != RC_SUCCESS )); then
                                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 860 "\nERROR: failed to associate \"%1\$s\" NODE and \"%2\$s\" HMC.\n\n" "$NODE" "$HMC_LABEL" 1>&2
                                    rc=$RC_ERROR
                                    break
                                fi
                            fi
                        done
                    fi
                fi

                if (( $rc == RC_SUCCESS )); then
                    #===========================================================
                    : Now update the sites objects
                    :  - for each site we consider the list of existing hmcs.
                    #===========================================================
                    #===========================================================
                    : Loop on sites given as parameter
                    #===========================================================
                    if [[ -n $SITES ]]; then
                        #==============
                        : Loop on sites
                        #==============
                        for SITE in $SITES; do
                            typeset pOpt= HOpt=
                            typeset UPDATED_HMCS=
                            typeset CURRENT_HMCS=
                            print -- "$0()[$LINENO]($SECONDS): cllssite -S $SITE " >>$CLMGR_TMPLOG # Always log command
                            CURRENT_HMCS=$(cllssite -S $SITE)
                            rc=$?
                            print -- "$0()[$LINENO]($SECONDS): cllssite -S $SITE rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                            if (( $rc == RC_SUCCESS)); then
                                for CURRENT_HMC in $CURRENT_HMCS; do
                                    UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$CURRENT_HMC
                                done
                                UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMC_LABEL
                                pOpt=" -p $SITE"
                                HOpt=" -H $UPDATED_HMCS"
                                print -- "$0()[$LINENO]($SECONDS): clchgsite $pOpt $HOpt" >>$CLMGR_TMPLOG
                                clchgsite $pOpt $HOpt
                                rc=$?
                                print -- "$0()[$LINENO]($SECONDS): clchgsite $pOpt $HOpt rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                                if (( $rc != RC_SUCCESS )); then
                                    CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 861 "\nERROR: failed to associate \"%1\$s\" SITE and \"%2\$s\" HMC.\n\n" "$SITENODE" "$UPDATED_HMCS" 1>&2
                                    rc=$RC_ERROR
                                    break
                                fi
                            fi
                        done
                    fi
                fi

                #==============================
                : Now update the cluster tunables object
                #==============================
                if (( $rc == RC_SUCCESS )); then
                    #==============================
                    : Get current default_hmcs_list
                    #==============================
                    typeset default_hmcs_list=$(clodmget -n -f default_hmcs_list HACMPhmcparam)
                    #==============================
                    : Modify default_hmcs_list
                    #==============================
                    default_hmcs_list=${default_hmcs_list:+$default_hmcs_list }$hmc_label
                    #==============================
                    : Persist default_hmcs_list=$default_hmcs_list to ODM
                    #==============================
                    print "HACMPhmcparam:
default_hmcs_list=$default_hmcs_list" | /usr/bin/odmchange -o HACMPhmcparam
                    rc=$?
                    if (( $rc != RC_SUCCESS )); then
                        dspmsg -s $CLMGR_SET $CLMGR_MSGS 819 "\nERROR: failed to add the \"%1\$s\" HMC to HACMPhmcparam.\n\n" "$hmc" 1>&2
                        rc=$RC_ERROR
                    else
                        typeset CHECK_VAL=$(clodmget -n -f default_hmcs_list HACMPhmcparam)
                        [[ $CHECK_VAL == $default_hmcs_list ]] && rc=$RC_SUCCESS || rc=$RC_ERROR
                    fi
                fi
            fi

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

        else
            CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 818 "\tChecking HMC connectivity failed : it is possible to skip the connectivity check (CHECK_HMC=no) to force the hmc creation or modification.\n" 1>&2
            rc=$RC_INCORRECT_INPUT
        fi
    fi

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

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