#!/bin/ksh93
#  ALTRAN_PROLOG_BEGIN_TAG
#  This is an automatically generated prolog.
#
#  Copyright (C) Altran ACT S.A.S. 2017,2018,2019,2020,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_network.sh 1.13 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2006,2016 
# 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_network.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM

# 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_network

=head1 SYNOPSIS

 clmgr add network <network> \
             [ TYPE={ether|XD_data|XD_ip} ] \
             [ {NETMASK=<255.255.255.0> | PREFIX=1..128} ] \
             [ PUBLIC={true|false} ] \
             [ UNSTABLE_THRESHOLD=<1...99> ] \
             [ UNSTABLE_PERIOD=<1...120> ]

 NOTE: the TYPE defaults to "ether" if not specified.
 NOTE: when adding, the default is to construct an IPv4
       network using a netmask of "255.255.255.0". To
       create an IPv6 network, specify a valid prefix.
 NOTE: the aliases for "network" are "ne" and "nw".

=head1 DESCRIPTION

Attempts to add a network object that conforms to the
provided specifications.

=head1 ARGUMENTS

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

 2. name [REQUIRED] [string]
    The label to apply to the new network.

 3. type [OPTIONAL] [string]
    The type of network to create, defaulting to Ethernet
    (i.e. "ether"; see the HACMPnim ODM for all types).

 4. netmask [OPTIONAL] [string]
    The netmask to enforce within this network, defaulting
    to 255.255.0.0. IPv4 only.

 5. prefix [OPTIONAL] [string]
    The IPv6 prefix length to enforce within this network.

 6. public [OPTIONAL] [string]
    A Boolean-like flag indicating is this network is public
    or private.

 7. unstable_theshold [OPTIONAL] [integer]
    Integer specifying the event threshold for network stability.

 8. unstable_period [OPTIONAL] [integer]
    Integer specifying the event period for network stability.

=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_add_network {
    . $HALIBROOT/log_entry "$0()" "$CL"
    : version=@(#)  7d4c34b 43haes/lib/ksh93/hacmp/KLIB_HACMP_add_network.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM
    : INPUTS: $*

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

    typeset type=${1//\"/}
    typeset netmask=${2//\"/} # optional
    typeset prefix=${3//\"/}  # optional
    typeset -l public=${4//\"/}  # optional
    typeset unstable_threshold=${5//\"/}  # optional
    typeset unstable_period=${6//\"/}  # optional

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

    #===================================
    : Declare and initialize variables
    #===================================
    typeset args=
    typeset -i rc=$RC_UNKNOWN
    typeset -i i=0
    typeset -u typeUC=$type

    typeset existing
    CL=$LINENO KLIB_HACMP_list_networks existing 2>>$CLMGR_TMPLOG

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

    #=================
    : Validate input
    #=================
    elif [[ -z $name ]]; 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 [[ " ${existing[*]} " == *\ $name\ * ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 229 "\nERROR: the specified object already exists: \"%1\$s\"\n\n" "$name" 1>&2
        rc=$RC_INCORRECT_INPUT

    elif [[ -n $name && -n "${name//[a-zA-Z0-9_]/}" ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 105 "\nERROR: one or more invalid characters were detected in \"%1\$s\" (\"%2\$s\").\n\nValid characters include letters, numbers, and underscores only.\n\n" "$name" "${name//[a-zA-Z0-9_]/}" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    #=========================================================
    : Check for maximum limit of networks allowed in a cluster
    #=========================================================
    if (( ${#existing[*]} == $MAX_NETWORKS )); then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 1448 "\nERROR: The number of configured PowerHA SystemMirror Networks in the cluster has already reached its maximum limit(%1\$d).\n" "$MAX_NETWORKS" 1>&2
        rc=$RC_ERROR
    fi

    if [[ -n $typeUC && $typeUC != @(E|XD_D|XD_I)* ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" TYPE "$type" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "ether, XD_data, XD_ip" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -n $netmask && -n $prefix ]]; then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 36 "\nERROR: conflicting options were provided,\n\       \"%1\$s\" versus \"%2\$s\".\n\n" NETMASK PREFIX 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ $prefix != *([[:space:]]) ]] && \
         ( [[ $prefix != +([[:digit:]]) ]] || (( prefix < 1 || prefix > 128)) )
    then
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 113 "\nERROR: an invalid IPv6 prefix length was specified: %1\$s\n\n" "$prefix" 1>&2
        /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "1 .. 128" 1>&2
        rc=$RC_INCORRECT_INPUT
    fi

    if [[ -z $public ]]; then
        public="public"
    else
        case $public in
        @(t|pu)* ) public="public"  ;;
        @(f|pr)* ) public="private" ;;
               * ) /usr/bin/dspmsg -s $CLVT_SET $CLVT_MSGS 110 "\nERROR: invalid value specified for \"%1\$s\":  \"%2\$s\".\n" PUBLIC "$public" 1>&2
                   /usr/bin/dspmsg -s $CLVT_SET $CLVT_MSGS 3 "Valid values: %1\$s\n\n" "true, false" 1>&2
                   rc=$RC_INCORRECT_INPUT
               ;;
        esac
    fi

    typeset Eopt="" Lopt=""
    if [[ $unstable_threshold != *([[:space:]]) ]]; then
        CL=$LINENO verify_numeric_range "$unstable_threshold" 1 99 UNSTABLE_THRESHOLD
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT || Eopt="-e $unstable_threshold"
    fi
    if [[ $unstable_period != *([[:space:]]) ]]; then
        CL=$LINENO verify_numeric_range "$unstable_period" 1 120 UNSTABLE_PERIOD
        (( $? != RC_SUCCESS )) && rc=$RC_INCORRECT_INPUT || Lopt="-l $unstable_period"
    fi

    #===========================================================
    : Create the network if no input errors have been detected
    #===========================================================
    if (( $rc == RC_UNKNOWN )); then
        if [[ -z $type ]]; then
            /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 114 "\nWarning: \"%1\$s\" must be specified. Since it was not,\n         a default of \"%2\$s\" will be used.\n\n" TYPE ether 1>&2
            type=ether
        else
            case $typeUC in
                   E*) type="ether"   ;;
                XD_D*) type="XD_data" ;;
                XD_I*) type="XD_ip"   ;;
            esac
        fi

        if [[ -n $netmask ]]; then
            typeset nodots=${netmask//\./}
            if (( ${#netmask} - ${#nodots} != 3 )); then
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 115 "\nERROR: an invalid IPv4 netmask was specified: %1\$s\n\n" "$netmask" 1>&2
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "<###.###.###.###>; \"###\" must be in the range 0 .. 255." 1>&2
                rc=$RC_INCORRECT_INPUT
            else
                typeset value=$netmask
                for (( i=0; i<4; i++ )); do
                    typeset octet=${value%%.*}
                    value=${value#*.}
                    if [[ $octet == *([[:space:]]) || \
                          $octet != +([[:digit:]]) ]] || \
                       (( octet < 0 || octet > 255 ))
                    then
                         /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 115 "\nERROR: an invalid IPv4 netmask was specified: %1\$s\n\n" "$netmask" 1>&2
                         /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 3 "Valid values: %1\$s\n\n" "<###.###.###.###>; \"###\" must be in the range 0 .. 255." 1>&2
                         rc=$RC_INCORRECT_INPUT
                         break
                    fi
                done
            fi
        fi

        if (( $rc == RC_UNKNOWN )); then
            if [[ -n $netmask ]]; then
                args="-s $netmask"       # IPv4 network
            elif [[ -n $prefix ]]; then
                args="-s $prefix"        # IPv6 network
            else
                args="-s 255.255.255.0"  # Default value; IPv4 network
            fi

            print -- "$0()[$LINENO]($SECONDS): clmodnetwork -a -n \"$name\" -i \"$type\" $args -t \"$public\" $Eopt $Lopt" >>$CLMGR_TMPLOG  # Always log commands
            clmodnetwork -a -n "$name" -i "$type" $args -t "$public" \
                                $Eopt $Lopt
            rc=$?
            print " RC: $rc" >>$CLMGR_TMPLOG  # Always log command result
            if (( $rc != RC_SUCCESS )); then
                rc=$RC_ERROR
                /usr/bin/dspmsg -s $CLMGR_SET $CLMGR_MSGS 201 "\nERROR: failed to create \"%1\$s\".\n\n" "$name" 1>&2
            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_network_attributes "$name" properties
                fi
            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
        print -u2 ""
        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 network -h" "NETWORK:" "$CLMGR_PROGNAME" 1>&2
    fi

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

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