#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG                                                    
#  This is an automatically generated prolog.                                  
#                                                                              
#  Copyright (C) Altran ACT S.A.S. 2019,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_run_discovery.sh 1.6 
#  
# 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_run_discovery.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_run_discovery

=head1 SYNOPSIS

 clmgr discover cluster
 clmgr discover interfaces
 clmgr discover volume_groups

=head1 DESCRIPTION

Runs discovery on the cluster, and returns the discovered IP
and volume group information to the caller.

=head1 ARGUMENTS

 1. vginfo [OPTIONAL] [hash ref]
    A reference to an associate array that will be used to return 
    all discovered volume group information.

 2. ipinfo [OPTIONAL] [hash ref]
    A reference to an associate array that will be used to return 
    all discovered IP information.

=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

=cut
} # End of POD-formatted documentation.


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

    typeset -u disc_type=$_CLASS

    if [[ -n $1 ]]; then
        typeset -n vginfo=$1
        if [[ -n $2 && $2 != $1 ]]; then
            typeset -n ipinfo=$2
        else
            typeset -A ipinfo
        fi
    else
        typeset -A vginfo ipinfo
    fi

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

    #===================================
    : Declare and initialize variables
    #===================================
    typeset -i rc=$RC_UNKNOWN
    typeset NO_CLUSTER=0
    typeset STDOUT_FILE=$TMPDIR/clmgr.KHrd.out.$$
    typeset STDERR_FILE=$TMPDIR/clmgr.KHrd.err.$$
    typeset NODES=""

    CL=$LINENO isClusterDefined >$STDOUT_FILE 2>&1
    NO_CLUSTER=$?

    if (( NO_CLUSTER )) && (( ! CLMGR_VERBOSE || ! CLMGR_FORCE )); then
        /usr/bin/cat $STDOUT_FILE 1>&2
        /usr/bin/rm -f $STDOUT_FILE
        log_return_msg "$RC_MISSING_DEPENDENCT" "$0()" "$LINENO"
        return $?

    elif (( NO_CLUSTER && CLMGR_VERBOSE && CLMGR_FORCE )); then
        NODES=${_ENV_ARGS[NODES]}
        [[ $NODES == *([[:space:]]) ]] && NODES=$(/usr/bin/hostname)

        #===================================================================
        # On the rare possibility that the host dies before this script
        # is done operating, meaning no HACMPnode cleanup would occur,
        # add an entry to the inittab to make sure that the cleanup takes
        # place when the host is brought back up. Note that if this script
        # completes normally, the inittab will be removed.
        #===================================================================
        typeset ODMFILE="$TMPDIR/odm_nodes.$$"
        rm -f $ODMFILE
        print '\
if [ -z `/usr/bin/odmget HACMPcluster` ]; then
    /usr/bin/odmdelete -o HACMPnode
fi
rmitab hadisccln
rm -f $ODMFILE
rm -f $0
' >$TMPDIR/hadisccln
        mkitab "hadisccln:2:once:/bin/ksh $TMPDIR/hadisccln >/dev/null 2>&1"

        typeset node="" host=""
        typeset cversion=$(grep CLUSTERVERSION= $HAETC/rc.cluster)
                cversion=${cversion##*=}
        for node in ${NODES//,/ }; do
            host $node | read host rest
            if (( $? != 0 )); then
                cl_dspmsg -s $CLVT_SET $CLVT_MSGS 9999 '\nERROR: "%1$s" could not be resolved via the /usr/bin/host command. Please make sure that "%1$s" is correctly defined in the /etc/hosts file.\n\n' "$node" 1>&2
                return $RC_INCORRECT_INPUT
            fi

            print "
HACMPnode:
${TAB}name = \"${node%%\.*}\"
${TAB}object = \"COMMUNICATION_PATH\"
${TAB}value = \"$host\"
${TAB}node_id = 0
${TAB}node_handle = 0
${TAB}version = $cversion" >>$ODMFILE
        done

        # Add the temporary HACMPnode entries
        odmadd <$ODMFILE
        rm -f $ODMFILE

        print "$0()[$LINENO]($SECONDS): $HADIAG/clver -Nv" >>$CLMGR_TMPLOG
        $HADIAG/clver -Nv >$STDOUT_FILE 2>$STDERR_FILE
        rc=$?
        print "clver RC: $rc" >>$CLMGR_TMPLOG

        print "$0()[$LINENO]($SECONDS): $HAUTILS/clharvest_vg -w" >>$CLMGR_TMPLOG
        $HAUTILS/clharvest_vg -w >$STDOUT_FILE 2>$STDERR_FILE
        rc=$?
        print "clharvest_vg RC: $rc" >>$CLMGR_TMPLOG

    elif [[ $disc_type == "INTERFACE" ]]; then
        print "$0()[$LINENO]($SECONDS): $HADIAG/clver -Nv" >>$CLMGR_TMPLOG  # Always log commands
        $HADIAG/clver -Nv >$STDOUT_FILE 2>$STDERR_FILE
        rc=$?
        print "clver RC: $rc" >>$CLMGR_TMPLOG  # Always log command result

    elif [[ $disc_type == "VOLUME_GROUP" ]]; then
        print "$0()[$LINENO]($SECONDS): $HAUTILS/clharvest_vg -w" >>$CLMGR_TMPLOG  # Always log commands
        $HAUTILS/clharvest_vg -w >$STDOUT_FILE 2>$STDERR_FILE
        rc=$?
        print "clharvest_vg RC: $rc" >>$CLMGR_TMPLOG  # Always log command result

    else
        print "$0()[$LINENO]($SECONDS): $HAUTILS/clmodclstr -K" >>$CLMGR_TMPLOG  # Always log commands
        $HAUTILS/clmodclstr -K >$STDOUT_FILE 2>$STDERR_FILE
        rc=$?
        print "clmodclstr RC: $rc" >>$CLMGR_TMPLOG  # Always log command result
    fi

    (( $rc != RC_SUCCESS )) && rc=$RC_ERROR

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

        if [[ $disc_type == "INTERFACE" ]]; then
            if [[ -r $HAETC/config/clip_config ]]; then
                typeset node="" interface_description="" iplabel="" ip_int=""
                typeset ip="" netmask_int="" netmask="" subnet_int="" subnet=""
                typeset logical_interface="" logical_adapter=""
                typeset hardware_address="" state="" nim_type="" attr_type=""
                typeset discoveredNet="" macaddr="" pair="" network="" rest=""

                while IFS='#' read node interface_description \
                    iplabel ip_int ip netmask_int netmask \
                    subnet_int subnet logical_interface logical_adapter \
                    hardware_address state nim_type attr_type discoveredNet \
                    rest
                do
                    [[ -z $ip ]] && continue

                    LC_ALL=C lscfg -vl $logical_adapter |\
                        grep -w "Address" | read hardware_address
                    hardware_address=${hardware_address##*\.}
                    macaddr=""
                    for (( i=0; i<${#hardware_address}; i+=2 )); do
                        pair=${hardware_address:$i:2}
                        [[ -n $macaddr ]] && macaddr="$macaddr:"
                        macaddr="$macaddr$pair"
                    done

                    if [[ $discoveredNet == +([[:digit:]]) ]]; then
                        (( $discoveredNet == 0 )) && discoveredNet=1
                        if (( $discoveredNet < 10 )); then
                            network="net_ether_0$discoveredNet"
                        else
                            network="net_ether_$discoveredNet"
                        fi
                    fi

                    ipinfo[${ip%%/*}]="${node//:*/}|$iplabel|$nim_type|$subnet|$netmask|$logical_interface|$logical_adapter|$macaddr|$state|$nim_type|$network|$attr_type"
                done < $HAETC/config/clip_config
            fi
        fi

        if [[ $disc_type == "VOLUME_GROUP" ]]; then
            if [[ -r $HAETC/config/clvg_config ]]; then
                typeset node="" pv="" pvid="" vg="" major="" ecm=""
                typeset status="" quorum="" local="" type="" size=""

                while IFS=':' read node pv pvid vg major ecm status \
                                   quorum local type size
                do
                    [[ -z $vg ]] && continue

                    pv=${pv# }
                    node=${node//:*/}
                    [[ $node != $LOCAL_NODE ]] && continue

                    [[ $quorum == "0" ]] && quorum="false" || quorum="true"
                    [[ $ecm == "0"    ]] && ecm="false"    || ecm="true"

                    [[ -n ${vginfo[$vg]} ]] && vginfo[$vg]="${vginfo[$vg]}$NL"
                    vginfo[$vg]="${vginfo[$vg]}$node|$pv|$pvid|$major|$ecm|$status|$quorum|$local|$type|$size"
                done < $HAETC/config/clvg_config

                for vg in ${!vginfo[*]}; do
                    vginfo[$vg]=$(print -- "${vginfo[$vg]}" | sort)
                done
            fi
        fi

        if (( CLMGR_VERBOSE )); then
            case $disc_type in
                INTERFACE)
                    typeset -A props
                    typeset -i INDEX=1

                    for ip in ${!ipinfo[*]}; do
                        print -- ${ipinfo[$ip]} | IFS=\| read node iplabel nim_type subnet netmask logical_interface logical_adapter macaddr state nim_type network attr_type rest
                        props[NAME$INDEX]=$iplabel
                        props[TYPE$INDEX]="boot"
                        props[INTERFACE$INDEX]=$logical_interface
                        props[IPADDR$INDEX]=${ip%%/*}
                        props[NETMASK$INDEX]=$netmask
                        props[NODE$INDEX]=${node//:*/}
                        props[STATE$INDEX]=$state
                        props[NETTYPE$INDEX]=$nim_type
                        props[NETWORK$INDEX]=$network
                        props[ATTR$INDEX]=$attr_type
                        props[STATE$INDEX]=$state
                        props[HADDR$INDEX]=$macaddr

                        (( INDEX++ ))
                    done # End of the IP address loop

                    CL=$LINENO SerializeAsAssociativeArray props interface
                ;;
                VOLUME_GROUP)
                    typeset -A props
                    typeset -u type=""
                    typeset VGS=""

                    for vg in ${!vginfo[*]}; do
                        [[ $vg == "None" ]] && continue
                        [[ " $VGS " != *\ $vg\ * ]] && VGS="$VGS $vg"
                    done

                    typeset -i INDEX=1
                    for vg in $VGS; do
                        typeset -i DISK_CNT=1

                        for vglabel in ${!vginfo[*]}; do
                            [[ $vglabel != $vg ]] && continue

                            print -- "${vginfo[$vg]}" |\
                            while read LINE; do
                                print -- "$LINE" |\
                                IFS=\| read node pv pvid major ecm status \
                                            quorum local type size rest

                            if (( DISK_CNT == 1 )); then
                                props[NAME$INDEX]=$vg
                                props[PHYSICAL_VOLUMES$INDEX]="$pv@$pvid"
                                props[CONCURRENT_ACCESS$INDEX]=$ecm
                                props[QUORUM$INDEX]=$quorum
                                props[MAJOR_NUMBER$INDEX]=$major
                                if [[ $type != "UNKNOWN" ]]; then
                                    props[TYPE$INDEX]=$type
                                fi
                            else
                                props[PHYSICAL_VOLUMES$INDEX]="${props[PHYSICAL_VOLUMES$INDEX]},$pv@$pvid"
                                if [[ $type != "UNKNOWN" ]]; then
                                    props[TYPE$INDEX]=$type
                                fi
                            fi

                            (( DISK_CNT++ ))
                            done
                        done

                        if [[ ${props[TYPE$INDEX]} == "" ]]; then
                            for pv in ${props[PHYSICAL_VOLUMES$INDEX]//,/ }; do

                                pv=${pv%%@*}
                                /usr/sbin/lqueryvg -Atp $pv |\
                                while IFS= read LINE; do
                                    if [[ $LINE == MAX\ PVs:* ]]; then
                                        LINE=${LINE##*+([[:space:]])}
                                        if [[ $LINE == +([[:digit:]]) ]]; then
                                            if (( $LINE < 128 )); then
                                                LINE="ORIGINAL"
                                            elif (( $LINE < 1024 )); then
                                                LINE="BIG"
                                            else
                                                LINE="SCALABLE"
                                            fi
                                        fi
                                        props[TYPE$INDEX]=$LINE
                                    fi
                                    [[ -n ${props[TYPE$INDEX]} ]] && break
                                done
                            done
                        fi

                        (( INDEX++ ))
                    done # End of the volume group loop

                    CL=$LINENO SerializeAsAssociativeArray props volume_group
                ;;
            esac
        fi
    fi

    if (( ! CLMGR_VERBOSE || $rc != RC_SUCCESS )); then
        [[ -s $STDOUT_FILE ]] && /usr/bin/cat $STDOUT_FILE
        [[ -s $STDERR_FILE ]] && /usr/bin/cat $STDERR_FILE 1>&2
    elif (( CLMGR_VERBOSE || $rc == RC_SUCCESS )); then
        [[ -s $STDOUT_FILE ]] && /usr/bin/cat $STDOUT_FILE >>$CLMGR_TMPLOG
        [[ -s $STDERR_FILE ]] && /usr/bin/cat $STDERR_FILE >>$CLMGR_TMPLOG
    fi
    [[ -f $STDOUT_FILE ]] && /usr/bin/rm -f $STDOUT_FILE
    [[ -f $STDERR_FILE ]] && /usr/bin/rm -f $STDERR_FILE

    if (( NO_CLUSTER && CLMGR_FORCE && CLMGR_VERBOSE )); then
        # Time to clean up
        odmdelete -o HACMPnode >>$CLMGR_TMPLOG 2>&1
        rmitab hadisccln >>$CLMGR_TMPLOG 2>&1
        rm -f $TMPDIR/hadisccln >>$CLMGR_TMPLOG 2>&1
        rm -f $HAETC/config/clip_config $HAETC/config/clvg_config
    fi

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