#!/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_modify_hmc.sh 1.4.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_modify_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_modify_hmc

=head1 SYNOPSIS

 clmgr modify 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 modify the specified HMC object within the PowerHA SystemMirror
  configuration.
 When modifying 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.

 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.

 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.

 6. NODES [OPTIONAL] [string]
 The list of nodes that will use this HMC.
 By using NODES="" the user can reset the list of nodes using this HMC.

 7. SITES [OPTIONAL] [string]
 The list of sites that will use this HMC.
 By using SITES="" the user can reset the list of sites using 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_modify_hmc {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_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 CHECK_HMC_ERROR=
    typeset -i rc=$RC_UNKNOWN
    typeset -i checkRC=$RC_SUCCESS

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

    #======================================================
    # To distinguish the two following cases
    #  clmgr modify hmc myhmc TIMEOUT=15
    #  clmgr modify hmc myhmc TIMEOUT=15 NODES=""
    #======================================================
    typeset -i resetNodes=0
    if [[ -z $nodelist && " ${!_ENV_ARGS[*]} " == *\ NODES\ * ]]; then
        resetNodes=1
    fi

    #======================================================
    # To distinguish the two following cases
    #  clmgr modify hmc myhmc TIMEOUT=15
    #  clmgr modify hmc myhmc TIMEOUT=15 SITES=""
    #======================================================
    typeset -i resetSites=0
    if [[ -z $sitelist && " ${!_ENV_ARGS[*]} " == *\ SITES\ * ]]; then
        resetSites=1
    fi

    #=================
    : Validate input
    #=================
    # hmc_label
    typeset HMC_LABEL=
    if [[ -z $hmc_label ]]; then
        CL=$LINENO 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 dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$hmc_label" 1>&2
            dspmsg -s $CLMGR_SET $CLMGR_MSGS 810 "Available HMCs:\n\n" 1>&2

            typeset available
            CL=$LINENO KLIB_HACMP_list_hmcs 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
        else
            HMC_LABEL=$hmc_label
        fi
    fi


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


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

        #===================
        : 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' NAME "[-+~@]" 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
        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" "$timeout" "[-1|[0-9]*}" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                RETRY_COUNT=$retry_count
            fi
        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" "$timeout" "[-1|[0-9]*}" 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                RETRY_DELAY=$retry_delay
            fi
        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" "CHECK_HMC" "$CHECK_HMC" 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 [[ -n $username && -z $password ]]; then
                PASSWORD=$(clodmget -q name=$HMC_LABEL -f passwd -n HACMPhmc)
                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
            if [[ -z $username && -z $password ]]; then
                PASSWORD=$(clodmget -q name=$HMC_LABEL -f passwd -n HACMPhmc)
                USER_NAME=$(clodmget -q name=$HMC_LABEL -f user -n HACMPhmc)
            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 "\"%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_ERRROR=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
                    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 [[ -z $nodelist && -z $sitelist ]]; then
            #==========================================================
            : If nodelist or sitelist is empty, but we must check at 
            : least connectivity between the current node and this hmc
            #==========================================================
            if (( $CHECK_HMC == 1 )); then
                #LOCAL_NODE is always set by the clmgr framework, and can be used
                print -- "check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL NODES=$NODES" >>$CLMGR_TMPLOG
                check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL NODES $USER_NAME $PASSWORD
                checkRC=$?
                print -- "check_hmc_connectivity_with_node $LOCAL_NODE $HMC_LABEL NODES=$NODES 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=" " || tOpt=" -t $TIMEOUT"
            [[ -z $RETRY_COUNT ]] && rOpt=" " || rOpt=" -c $RETRY_COUNT"
            [[ -z $RETRY_DELAY ]] && dOpt=" " || dOpt=" -d $RETRY_DELAY"
            [[ -z $username ]] && uOpt=" " || uOpt=" -u $username"
            [[ -z $password ]] && pOpt=" " || pOpt=" -p $PASSWORD"

            print -- "$0()[$LINENO]($SECONDS): clchhmc $nOpt$tOpt$rOpt$dOpt$uOpt$pOpt" >>$CLMGR_TMPLOG # Always log command
            clchhmc $nOpt$tOpt$rOpt$dOpt$uOpt$pOpt
            rc=$?
            print -- "$0()[$LINENO]($SECONDS): clchhmc $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 modify \"%1\$s\".\n\n" "$HMC_LABEL" 1>&2
                rc=$RC_ERROR
            else
                #==========================================================
                : Now update the nodes objects
                :  - For the nodes given in parameter one per one, i.e we loop around the nodes
                :  -- we look to see if the hmc is already here or if it must be added
                :  - For all other nodes, .i.e all nodes not given in parameter
                :  -- we must remove the hmc if it was there
                #==========================================================

                if [[ -n $NODES ]]; then
                    #==========================================================
                    :  - for the nodes given in parameter one per one, i.e. we loop around the nodes
                    :  -- we look to see if the hmc is already here or if it must be added
                    #==========================================================
                    for NODE in $NODES; do
                        typeset NOpt= kvOpt=
                        typeset UPDATED_HMCS=
                        typeset -i hmcFound=0
                        typeset HMCNAMES=
                        print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n $NODE -o" >>$CLMGR_TMPLOG # Always log command
                        HMCNAMES=$(cllshmcparam -n $NODE -o)
                        rc=$?
                        print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n $NODE -o rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                        for HMCNAME in $HMCNAMES; do
                            #==========================================================
                            : We search if the hmc is already here for this node or not
                            #==========================================================
                            if [[ $HMCNAME == $HMC_LABEL ]]; then
                                hmcFound=1
                            fi
                            #==========================================================
                            : In any case, we build the new list of HMCs
                            #==========================================================
                            UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMCNAME
                        done

                        #==========================================================
                        : If the hmc was not already set, then add it on this node
                        #==========================================================
                        if (( $hmcFound == 0 )); then
                            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 # Always log command
                            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 link \"%1\$s\" NODE and \"%2\$s\" HMC.\n\n" "$NODE" "$UPDATED_HMCS" 1>&2
                                rc=$RC_ERROR
                                break
                            fi
                        fi
                    done
                fi

                ## Now reset NODES to its original value
                NODES=$nodelist
                if [[ -n $NODES || $resetNodes == 1 ]]; then
                    #==========================================================
                    :  - for all other nodes, i.e all nodes not given in parameter
                    :  -- we must remove the hmc if it was there
                    #==========================================================
                    typeset available
                    CL=$LINENO KLIB_HACMP_list_nodes available
                    for (( i=0; i<${#available[*]}; i++ )); do
                                typeset nodeFound=0
                                if (( $resetNodes == 0 )); then
                                    for NODE in $NODES; do
                                        #=================================
                                        : Exclude nodes given as parameter
                                        #=================================
                                        if [[ ${available[$i]} == $NODE ]]; then
                                            nodeFound=1
                                            break
                                        fi
                                    done
                                else
                                    nodeFound=0
                                fi

                                if (( $nodeFound == 0 )); then
                                    typeset UPDATED_HMCS=
                                    typeset hmcFound=0
                                    typeset HMCNAMES=
                                    print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n ${available[$i]} -o" >>$CLMGR_TMPLOG # Always log command
                                    HMCNAMES=$(cllshmcparam -n ${available[$i]} -o)
                                    print -- "$0()[$LINENO]($SECONDS): cllshmcparam -n ${available[$i]} -o rc=$rc" >>$CLMGR_TMPLOG  # Always log command result
                                    for HMCNAME in $HMCNAMES; do
                                        #=================================
                                        : We search if the hmc is already there for this node or not
                                        #=================================
                                        if [[ $HMCNAME == $HMC_LABEL ]]; then
                                            hmcFound=1
                                        else
                                            #=================================
                                            : We build the list of HMCs to be passed to clchhmcparam
                                            #=================================
                                            UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMCNAME
                                        fi
                                    done

                                    #=================================
                                    : If the hmc was found, we must update the link
                                    #=================================
                                    if (( $hmcFound == 1 )) ; then
                                        kvOpt="-c HMC_IP=$UPDATED_HMCS"
                                        NOpt=" -n ${available[$i]}"
                                        print -- "$0()[$LINENO]($SECONDS): clchhmcparam $NOpt $kvOpt" >>$CLMGR_TMPLOG # Always log command
                                        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 link \"%1\$s\" NODE and \"%2\$s\" HMC.\n\n" "${available[$i]}" "$UPDATED_HMCS" 1>&2
                                            rc=$RC_ERROR
                                        fi
                                    fi
                                fi
                    done
                fi


                #==========================================================
                : Now update the sites objects
                : - For the sites given as parameter, we must add the hmc if
                :    it were not already set
                : - For the site not given as parameter, we must remove the
                :    hmc if it was set.
                : - If empty site string was given as parameter, we must remove
                :    the hmc  for all sites if it was set
                #==========================================================
                if [[ -n $SITES ]]; then
                    #=================================
                    : Loop on sites given as parameter
                    #=================================
                    for SITE in $SITES; do
                        typeset pOpt= HOpt=
                        typeset UPDATED_HMCS=
                        typeset -i hmcFound=0
                        typeset HMCNAMES=
                        print -- "$0()[$LINENO]($SECONDS): cllssite -S $SITE" >>$CLMGR_TMPLOG # Always log command
                        HMCNAMES=$(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 HMCNAME in $HMCNAMES; do
                                #=================================
                                : We search if the hmc is already here for this site or not
                                #=================================
                                if [[ $HMCNAME == $HMC_LABEL ]]; then
                                    hmcFound=1
                                fi
                                #=================================
                                : In any case, we build the new list of HMCs
                                #=================================
                                UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMCNAME
                            done

                            #=================================
                            : If the hmc was not already set, then add it on this site
                            #=================================
                            if (( $hmcFound == 0 )); then
                                UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMC_LABEL
                            fi

                            pOpt=" -p $SITE"
                            if [[ -z $UPDATED_HMCS ]]; then
                                HOpt=" -H \"\" ";
                            else
                                HOpt=" -H $UPDATED_HMCS"
                            fi

                            print -- "$0()[$LINENO]($SECONDS): clchgsite $pOpt $HOpt" >>$CLMGR_TMPLOG # Always log command
                            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 link \"%1\$s\" SITE and \"%2\$s\" HMC.\n\n" "$SITENODE" "$UPDATED_HMCS" 1>&2
                                rc=$RC_ERROR
                            fi
                        fi

                    done
                fi

                if [[ -n $SITES || $resetSites == 1 ]]; then
                    #=================================
                    : Loop on sites not given as parameter
                    #=================================
                    typeset SITENAMES=
                    print -- "$0()[$LINENO]($SECONDS): cllssite -l" >>$CLMGR_TMPLOG # Always log command
                    SITENAMES=$(cllssite -l)
                    rc=$?
                    print -- "$0()[$LINENO]($SECONDS): cllssite -l rc=$rc" >>$CLMGR_TMPLOG # Always log command result
                    for SITENAME in $SITENAMES; do
                        typeset siteFound=0
                        if (( $resetSites == 0 )); then
                            for SITE in $SITES; do
                                #=================================
                                : Exclude sites given as parameter
                                #=================================
                                if [[ $SITENAME == $SITE ]]; then
                                    siteFound=1
                                    break
                                fi
                            done
                        else
                            siteFound=0;
                        fi

                        if (( $siteFound == 0 )); then
                            #=================================
                            : We must remove this hmc from this site, it it was set
                            #=================================
                            typeset UPDATED_HMCS=
                            typeset pOpt= HOpt=
                            typeset bFound=0
                            typeset HMCNAMES=
                            print -- "$0()[$LINENO]($SECONDS): cllssite -S $SITENAME" >>$CLMGR_TMPLOG # Always log command
                            HMCNAMES=$(cllssite -S $SITENAME)
                            rc=$?
                            print -- "$0()[$LINENO]($SECONDS): cllssite -S $SITENAME rc=$?" >>$CLMGR_TMPLOG # Always log command result
                            for HMCNAME in $HMCNAMES; do
                                if [[ $HMCNAME == $HMC_LABEL ]]; then
                                    bFound=1
                                else
                                    UPDATED_HMCS=${UPDATED_HMCS:+$UPDATED_HMCS,}$HMCNAME
                                fi
                            done
                            #=================================
                            : If the hmc was set, remove it from this site
                            #=================================
                            if (( $bFound == 1 )); then
                                pOpt=" -p $SITENAME"
                                if [[ -z $UPDATED_HMCS ]]; then
                                    HOpt=" -H \"\" ";
                                else
                                    HOpt=" -H $UPDATED_HMCS"
                                fi
                                print -- "$0()[$LINENO]($SECONDS): clchgsite $pOpt $HOpt" >>$CLMGR_TMPLOG # Always log command
                                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 link \"%1\$s\" SITE and \"%2\$s\" HMC.\n\n" "$SITENODE" "$UPDATED_HMCS" 1>&2
                                    rc=$RC_ERROR
                                fi
                            fi
                        fi
                    done
                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
            fi
        else
            CL=$LINENO cl_dspmsg -s $CLMGR_SET $CLMGR_MSGS 818 "\tChecking HMC connectivity failed : you can use the -f option to force, or use the CHECK_HMC=no option to skip the check.\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" "modify hmc -h" "HMC:" 1>&2
    fi

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