#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2020,2021.  All rights reserved.  
#                                                                              
#  ALTRAN_PROLOG_END_TAG                                                      
#                                                                              
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_interface.sh 1.4 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2006,2013 
# 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_interface.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_interface

=head1 VERSION

 Version Number:  1.4
 Last Extracted:  1/31/14 04:40:46
 Last Changed:    8/6/13 16:56:50

 Path, Component, Release(, Level):
 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_modify_interface.sh, hacmp.assist, 61haes_r714

=head1 SYNOPSIS

 clmgr modify interface <interface> \
             NETWORK=<network>

 NOTE: the "interface" may be either an IP address or label
 NOTE: the aliases for "interface" are "in" and "if".

=head1 DESCRIPTION

Attempts to modify the specified PowerHA interface
to conform to the provided specifications.

=head1 ARGUMENTS

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

 2. interface [REQUIRED] [string]
    The address/label of the interface that is to be modified.

 3. network [REQUIRED] [string]
    The label of the network to assign this interface to.

=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,2010
All Rights Reserved

=cut
} # End of POD-formatted documentation.


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

    typeset -n properties=$1
    typeset interface=${2//\"/}
    shift; shift

    typeset network=${1//\"/}

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

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

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset nodename=
    typeset -i i=0

    #================================================================
    : Assuming an object was specified, see if it is a known object
    #================================================================
    if [[ $interface != *([[:space:]]) ]]; then
        CL=$LINENO KLIB_HACMP_is_known_interface "$interface"
        (( $? != RC_SUCCESS )) && rc=$RC_NOT_FOUND
    fi

    #=================
    : Validate input
    #=================
    if [[ -z $interface ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT

    elif (( $rc == RC_NOT_FOUND )); then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$interface" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 146 "Available Interfaces:\n\n" 1>&2

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

    if [[ -z $network ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 101 "\nERROR: this operation requires the \"%1\$s\" attribute.\n\n" NETWORK 1>&2
        rc=$RC_MISSING_INPUT

    else
        CL=$LINENO KLIB_HACMP_is_known_network "$network" >/dev/null 2>&1
        if (( $? != RC_SUCCESS )); then
            rc=$RC_INCORRECT_INPUT
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 102 "\nERROR: \"%1\$s\" does not appear to exist!\n\n" "$network" 1>&2

            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 150 "Available Networks:\n\n" 1>&2
            typeset available
            CL=$LINENO KLIB_HACMP_list_networks available
            for (( i=0; i<${#available[*]}; i++ )); do
                if [[ ${available[$i]} != *([[:space:]]) ]]; then
                    print -u2 "\t${available[$i]}"
                fi
            done
            print -u2 ""
        fi
    fi

    #=============================================================
    : Modify the interface if no input errors have been detected
    #=============================================================
    if (( $rc == RC_UNKNOWN )); then
        #=============================================================
        : Retrieve the cllsif data to first, obtain a node name, and
        : second, convert any IP addresses to its matching the name.
        #=============================================================
        print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsif -pcS" >>$CLMGR_TMPLOG  # Always log commands
        $HAUTILS/cllsif -pcS |\
        while read LINE; do

            : Handle possible IPv6 address
            typeset IPv6=
            if [[ $LINE == *\[* ]]; then
                IPv6=${LINE##*\[}
                IPv6=${IPv6%%\]*}
                LINE=${LINE/\[$IPv6\]/[${IPv6//:/_}]}
            fi

            print -- "$LINE" | IFS=: read name type nw nettype attr node ipaddr haddr if gname netmask hb_addr site prefix family remainder

            : Handle possible IPv6 address
            ipaddr=${ipaddr//_/:}
            ipaddr=${ipaddr/\[/}
            ipaddr=${ipaddr/\]/}

            if [[ $interface == @($name|$ipaddr) ]]; then
                typeset new_interface=${LINE%%:*}
                [[ -n $new_interface ]] && interface=$new_interface
                nodename=$(print -- "$LINE" | /usr/bin/head -1 | /usr/bin/cut -d: -f6)
                break
            fi
        done
        print "cllsif RC: $?" >>$CLMGR_TMPLOG  # Always log command result

        if [[ -z $nodename ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 406 "\nERROR: could not determine the node name for interface \"%1\$s\".\n\n" "$interface" 1>&2
            rc=$RC_MISSING_INPUT
        else
            : First see if the network was changed. If not, do nothing.
            print "$0()[$LINENO]($SECONDS): $HAUTILS/cllsif -ci $nodename | /usr/bin/grep ^$interface | /usr/bin/cut -d\":\" -f3" >>$CLMGR_TMPLOG  # Always log commands
            typeset NW=$($HAUTILS/cllsif -ci $nodename |\
                         /usr/bin/grep ^$interface |\
                         /usr/bin/cut -d":" -f3)
            print "cllsif RC: $?; NW == \"$NW\"" >>$CLMGR_TMPLOG  # Always log command result
            if [[ $NW == $network ]]; then
                : Nothing to do
                rc=$RC_SUCCESS
            else
                #=======================================================================
                # If a network holding a service IP with only one network interface
                # then exiting with error message.
                #=======================================================================
                service_function=$(cllsif -pcS | grep -w "service:$NW" | wc -l | sed 's/ //g')
                if (( $service_function != 0 )); then
                    boot_function_value=$(cllsif -pcS | grep -w "boot:$NW" | wc -l | sed 's/ //g')
                    if (( $boot_function_value == 1 )); then
                        rc=$RC_ERROR
                        dspmsg -s $CLVT_SET $CLVT_MSGS 1461 "\nERROR: Modifying or removing last network interface '%1\$s' not allowed\n\
as the network '%2\$s' holds a service IP.\n\
You can remove the service IP from the network, then try the operation again.\n" $interface $NW
                    fi
                fi
                if (( $rc != $RC_ERROR )); then
                    print "$0()[$LINENO]($SECONDS): $HAUTILS/clchnode -n \"$nodename\" -l \"$interface\" -w \"$network\"" >>$CLMGR_TMPLOG  # Always log commands
                    $HAUTILS/clchnode -n "$nodename" \
                                      -l "$interface" \
                                      -w "$network"
                    rc=$?
                    print "clchnode RC: $?" >>$CLMGR_TMPLOG  # Always log command result
                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_interface_attributes "$interface" properties
                fi
            else
                rc=$RC_ERROR
            fi
        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 interface -h" "INTERFACE:" "$CLMGR_PROGNAME" 1>&2
    fi

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