#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r720 src/43haes/usr/sbin/cluster/events/acquire_takeover_addr.sh 1.71.1.6 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1990,2015 
# 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 
# @(#)66  1.71.1.6  src/43haes/usr/sbin/cluster/events/acquire_takeover_addr.sh, hacmp.events, 61haes_r720, 1543B_hacmp720 10/21/15 07:44:18

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

#########################################################################
#
#   COMPONENT_NAME: EVENTS
#
#   FUNCTIONS: name_to_addr
#
#########################################################################

#########################################################################
#
# Name:           acquire_takeover_addr
#
# Description:    This script is called when a remote node leaves
#                 the cluster. The script first checks to see if a
#                 configured standby address exists and is
#                 considered 'up' by clstrmgr, then does a
#                 standby_address -> takeover_address swap.
#
#                 For an SP-switch, the script aliases the takeover
#                 address on the same adapter as the local service
#                 address.
#
# Called by:      node_down_remote, node_up_local
#
# Calls to:       cl_swap_IP_address, cl_swap_IPv6_address
#
# Arguments:      takeover_address...
#
# Environment:
#                 GROUPNAME
#
# Returns:        0   success
#                 1   failure
#                 2   bad argument
#
#########################################################################

###############################################################################
#
# Name: get_inet_family
#
# The routines returns the internet family of the given IP label.
#
# Arguments: IP address
#
# Returns: unspec: unknown family
#          inet:   AF_INET family (IPv4 IP address)
#          inet6:  AF_INET6 family (IPv6 IP address)
#
###############################################################################
get_inet_family() {
    typeset PS4_FUNC="get_inet_family"
    [[ $VERBOSE_LOGGING == "high" ]] && set -x
    ip_label=$1
    inet_family=$(cllsif -J "$OP_SEP" -Sn $ip_label | awk -F"$OP_SEP" '{print $15}')
    if [[ $inet_family == "AF_INET" ]]
    then
        echo "inet"
        return
    elif [[ $inet_family == "AF_INET6" ]]
    then
        echo "inet6"
        return
    else
        dspmsg scripts.cat 9503 "\n$PROGNAME: ERROR: Invalid address \
family for IP address \"$ip_label\".\n" $PROGNAME $ip_label
        exit 1
    fi
}

#########################################################################
#
# Name: best_boot_addr
#
# This routine finds the best boot interface for hosting an aliased service
# address. This routine exercises the resource distribution preference for
# service labels. The available options are:
#       anit-collocation - the default - all UP interfaces are sorted
#               according to the number of addresses currently on the interface.
#               The interface with the least number is selected.
#       collocation - put all service on the same interface
#       collocation with persistent - put all service on the same interface
#               as the one holding the persistent
#       anti-collocation with persistent - avoid putting service on the
#               same interface as the persistent
#
# Arguments: network name
#            List of candidate boot addresses on that network
#
# Returns: network address of the selected boot interface
#
#########################################################################
best_boot_addr() {
    typeset PS4_FUNC="best_boot_addr"
    [[ $VERBOSE_LOGGING == "high" ]] && set -x
    NETWORK=$1
    shift
    candidate_boots=$*

    # if there is only one boot then thats the candidate - regardless of
    # state or distribution preference
    integer num_candidates=$(echo $candidate_boots | tr " " "\n" | wc -l)
    if (( $num_candidates == 1 )); then
        echo $candidate_boots
        return
    fi

    best_candidate=NONE
    best_aliases=0
    ip_family=""

    # find the (optional) service label distribution preference for this network
    MA=$(odmget -q"network = $NETWORK AND function = shared" HACMPadapter |\
         grep "max_aliases" | awk '{print $3}' | sort -nu | tail -1)
    # decode the setting
    case $MA in
        1|771 )     # simple collocation
        # if there is already a service on any of the candidates, then
        # that is the candidate for this service

        # find all services on this network
        services=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME |\
                       awk -F"$OP_SEP" -v NET="$NETWORK" \
                       '{if ($2 == "service" && $3 == NET) print $1}' | sort)
        service_if=""
        for service in $services
        do
            # is it on this node ?
            service_if=$(LC_ALL=C clgetif -a $service 2>/dev/null | awk '{print $1}')
            [[ -n "$service_if" ]] && break  #found it
        done
        # if there is a service, scan list of candidates
        if [[ -n "$service_if" ]]
        then
            for candidate in $candidate_boots
            do
                boot_if=$(LC_ALL=C clgetif -a $candidate 2>/dev/null | awk '{print $1}')
                if [[ -n $boot_if && $boot_if == $service_if ]]
                then
                    best_candidate=$candidate
                    break
                fi
            done
        fi

        # if the loop above did not identify a candidate, then the
        # candidate is the first UP boot
        if [[ $best_candidate == "NONE" ]]; then
            for candidate in $candidate_boots
            do
                LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate | \
                cut -f7,11 -d"$OP_SEP" | tr "$OP_SEP" " " | \
                read candidate_dot_addr junk
                # check to see if candidate is configured on an interface
                candidate_if=$(LC_ALL=C clgetif -a $candidate_dot_addr 2>/dev/null | awk '{print $1}')
                if [[ -n "$candidate_if" ]]
                then
                    #
                    : Finding IP address family
                    #
                    ip_family=$(get_inet_family $candidate_dot_addr)

                    # find the state of this candidate
                    if [[ "$ip_family" == "inet" ]]; then
                        addr=\$i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    elif [[ "$ip_family" == "inet6" ]]; then
                        addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    fi
                    candidate_state=$(eval print $addr)

                    if [[ $candidate_state == "UP" ]]; then
                        best_candidate=$candidate
                        break  # all done
                    fi
                fi
            done
        fi
        ;;
        259|1283 )   # collocation with persistent
        # if there is a persistent label on any of the candidates, then
        # that is the candidate for this service
        persistent=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME |\
        awk -F"$OP_SEP" -v NET="$NETWORK" \
        '{if ($2 == "persistent" && $3 == NET) print $1}' \
        | sort)
        persistent_if=""
        if [[ -n "$persistent" ]]
        then
            # is it on this node ?
            persistent_if=$(LC_ALL=C clgetif -a $persistent 2>/dev/null | awk '{print $1}')
        fi
        # if there is a persistent, scan list of candidates
        if [[ -n "$persistent_if" ]]
        then
            for candidate in $candidate_boots
            do
                boot_if=$(LC_ALL=C clgetif -a $candidate 2>/dev/null | awk '{print $1}')
                if [[ -n $boot_if && $boot_if == $persistent_if ]]
                then
                    best_candidate=$candidate
                    break
                fi
            done
        fi
        # if the loop above did not identify a candidate, then go through
        # the same calculation as we use for simple anti-collocation
        if [[ $best_candidate == "NONE" ]]; then
            for candidate in $candidate_boots
            do
                LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate | \
                cut -f7,11 -d"$OP_SEP" | tr "$OP_SEP" " " | read \
                candidate_dot_addr junk
                # check to see if candidate is configured on an interface
                candidate_if=$(LC_ALL=C clgetif -a $candidate_dot_addr 2>/dev/null | awk '{print $1}')
                if [[ -n "$candidate_if" ]]
                then

                    #
                    : Finding IP address family
                    #
                    ip_family=""
                    ip_family=$(get_inet_family $candidate_dot_addr)

                    # find the state of this candidate
                    if [[ "$ip_family" == "inet" ]]; then
                        addr=\$i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    elif [[ "$ip_family" == "inet6" ]]; then
                        addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    fi
                    candidate_state=$(eval print $addr)

                    if [[ $candidate_state == "UP" ]]; then
                        # this interface is UP - now lets check how many
                        # addresses it is already hosting
                        candidate_aliases=$(LC_ALL=C ifconfig $candidate_if | egrep -c -w "inet|inet6")

                        if [[ $best_candidate == "NONE" ]] || \
                           (( $candidate_aliases < $best_aliases ))
                        then
                            best_candidate=$candidate
                            best_aliases=$candidate_aliases
                        fi
                    fi
                fi
            done
        fi
        ;;
        515|1539 )   # anti-collocation with persistent
        # if there is a persistent label on any of the candidates, then
        # that candidate should be marked DOWN to avoid its selection
        persistent=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME | \
        awk -F"$OP_SEP" -v NET="$NETWORK" \
        '{if ($2 == "persistent" && $3 == NET) print $1}' \
        | sort)
        save_if="NONE"
        persistent_if=""
        if [[ -n "$persistent" ]]
        then
            # is it on this node ?
            persistent_if=$(LC_ALL=C clgetif -a $persistent 2>/dev/null | awk '{print $1}')
        fi
        # if there is a persistent, scan list of candidates
        if [[ -n "$persistent_if" ]]
        then
            for candidate in $candidate_boots
            do
                boot_if=$(LC_ALL=C clgetif -a $candidate 2>/dev/null | awk '{print $1}')
                if [[ -n $boot_if && $boot_if == $persistent_if ]]
                then
                    LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate | \
                    cut -f7,11 -d"$OP_SEP" | tr "$OP_SEP" " " | \
                    read candidate_dot_addr junk

                    # if the interface is up, save it away just in case
                    # its our only up interface

                    #
                    : Finding IP address family
                    #
                    ip_family=""
                    ip_family=$(get_inet_family $candidate_dot_addr)

                    if [[ "$ip_family" == "inet" ]]; then
                        addr=\$i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    elif [[ "$ip_family" == "inet6" ]]; then
                        addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    fi
                    candidate_state=$(eval print $addr)

                    [[ $candidate_state == "UP" ]] && save_if=$candidate_dot_addr

                    # set state to down
                    if [[ "$ip_family" == "inet" ]]; then
                        addr=i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    elif [[ "$ip_family" == "inet6" ]]; then
                        addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                    fi

                    export $addr="DOWN"
                    break
                fi
            done
        fi

        # now that any interface holding the persistent is marked as DOWN,
        # go through the same calculation as we use for simple
        # anti-collocation
        for candidate in $candidate_boots
        do
            LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate | \
            cut -f7,11 -d"$OP_SEP" | tr "$OP_SEP" " " | \
            read candidate_dot_addr junk
            # check to see if candidate is configured on an interface
            candidate_if=$(LC_ALL=C clgetif -a $candidate_dot_addr 2>/dev/null | awk '{print $1}')
            if [[ -n "$candidate_if" ]]
            then

                # Finding IP address family
                ip_family=""
                ip_family=$(get_inet_family $candidate_dot_addr)

                # find the state of this candidate
                if [[ "$ip_family" == "inet" ]]; then
                    addr=\$i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                elif [[ "$ip_family" == "inet6" ]]; then
                    addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                fi
                candidate_state=$(eval print $addr)

                if [[ $candidate_state == "UP" ]]; then

                    # this interface is UP - now lets check how many
                    # addresses
                    # it is already hosting
                    candidate_aliases=$(LC_ALL=C ifconfig $candidate_if | egrep -c -w "inet|inet6")

                    if [[ $best_candidate == "NONE" ]] || \
                       (( $candidate_aliases < $best_aliases ))
                    then
                        best_candidate=$candidate
                        best_aliases=$candidate_aliases
                    fi
                fi
            fi
        done
        # if the loop above did not find a candidate then we cannot
        # exercise the preference - try setting the candidate to the
        # same interface as has the persistent
        [[ $best_candidate == "NONE" ]] && best_candidate=$save_if

        ;;
        * )     # default to rdp_anti_collocation
        # test all the candidates in the list
        for candidate in $candidate_boots
        do
            LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate   |\
                cut -f7,11 -d"$OP_SEP" | tr "$OP_SEP" " " |\
                read candidate_dot_addr junk
            # check to see if candidate is configured on an interface
            candidate_if=$(LC_ALL=C clgetif -a $candidate_dot_addr 2>/dev/null | awk '{print $1}')
            if [[ -n "$candidate_if" ]]
            then

                #
                : Finding IP address family
                #
                ip_family=""
                ip_family=$(get_inet_family $candidate_dot_addr)

                # find the state of this candidate
                if [[ "$ip_family" == "inet" ]]; then
                    addr=\$i${candidate_dot_addr//\./x}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                elif [[ "$ip_family" == "inet6" ]]; then
                    addr=\$i${candidate_dot_addr//:/y}_${LOCALNODENAME//-/$HA_DASH_CHAR}
                fi
                candidate_state=$(eval print $addr)

                if [[ $candidate_state == "UP" ]]; then

                    # this interface is UP - now lets check how many
                    # addresses it
                    # is already hosting
                    candidate_aliases=$(LC_ALL=C ifconfig $candidate_if | egrep -c -w "inet|inet6")
                    if [[ $best_candidate == "NONE" ]] || \
                       (( $candidate_aliases < $best_aliases ))
                    then
                        best_candidate=$candidate
                        best_aliases=$candidate_aliases
                    fi
                fi
            fi
        done
        ;;
    esac

    # once here, the best candidate should have been selected
    if [[ "$best_candidate" != "NONE" ]]; then
        echo $best_candidate
        return
    fi

    # Should never get here
    dspmsg scripts.cat 342 "Unable to determine local boot/service interface.\n"
    exit 1
} # End of "best_boot_addr()"


###############################################################################
#
# Name: addback_route
#
#       When two or more standbys are on the same subnet, only one of the
#	standbys is in the routing table as the route. If this standby is
#	used to takeover the remote address, the route also gets destroyed
#	in routing table. This routine is used to restore the route for
#	the remaining standbys on the subnet.
#
# Arguments: standby_IP_address
#
# Returns: None
#
###############################################################################
addback_route() {

    typeset PS4_FUNC="addback_route"
    [[ $VERBOSE_LOGGING == "high" ]] && set -x

    ip_family=""
    NETWORK=$(cllsif -J "$OP_SEP" -Sn $1 | cut -d"$OP_SEP" -f3 | uniq)

    standby_list=$(cllsif -SJ "$OP_SEP" | cut -d"$OP_SEP" -f2,7 | \
    grep standby"$OP_SEP" | cut -d"$OP_SEP" -f2)

    for standby in $standby_list
    do
        #
        # Make sure the standby is not the same one
        #
        if [[ $standby == $1 ]]
        then
            continue
        fi

        #
        # Make sure two standbys are on the same network
        #
        network=$(cllsif -J "$OP_SEP" -Sn $standby | cut -d"$OP_SEP" -f3 | uniq)
        if [ "$network" != "$NETWORK" ]
        then
            continue
        fi

        #
        # Make sure the standby is defined on local node
        #
        LC_ALL=C clgetif -n $standby >/dev/null 2>&1
        if [ $? != 0 ]
        then
            continue
        fi

        INTERFACE=$(LC_ALL=C clgetif -a $standby 2>/dev/null | awk '{print $1}')

        #
        # Make sure the standby is up on local node
        #
        ip_family=$(get_inet_family $standby)
        if [[ "$ip_family" == "inet" ]]; then
            NETMASK=$(LC_ALL=C clgetif -n $standby)
            addr=i"${standby//\./x}"_"${LOCALNODENAME//-/$HA_DASH_CHAR}"
        fi
        if [[ "$ip_family" == "inet6" ]]; then
            PREFIX_LEN=$(LC_ALL=C clgetif -p $standby)
            addr=i"${standby//:/y}"_"${LOCALNODENAME//-/$HA_DASH_CHAR}"
        fi

        VAR=\$"$addr"
        set +u
        VAL="$(eval echo $VAR)"
        set -u

        if [ "$VAL" != "UP" ]
        then
            continue
        fi

        #
        # Do ifconfig to add the route in. Will be a no-op if already in
        #
        if [[ "$ip_family" == "inet" ]]; then
            ifconfig $INTERFACE $standby netmask $NETMASK up
        fi
        if [[ "$ip_family" == "inet6" ]]; then
            ifconfig $INTERFACE inet6 $standby prefixlen $PREFIX_LEN up
        fi

    done
}

#
# This routine maps a label_address to the internet_dot_address.
# Thus, given a label_address, we do not require the name server
# to get its corresponding dot address.
#
name_to_addr() {
    typeset PS4_FUNC="name_to_addr"
    [[ $VERBOSE_LOGGING == "high" ]] && set -x
    echo $(cllsif -J "$OP_SEP" -Sn $1 | cut -d"$OP_SEP" -f7 | uniq)
    exit $?
}

###############################################################################
# Name: get_subnet
#
#    Returns network portion of address, given an
#    IP address and a netmask.
#    This has been extended to support IPv6 addresses,this work fine even
#    if the 2nd argment is either netmask or prefix lenght.
# Arguments: Two network addresses, in dotted decimal form.
#            i.e. get_subnet 1.1.1.1 255.255.255.0
#            IPv6 address in colon separated format and its prefix length
#            i.e. get_subnet 2001::1 64
# Returns: network address
###############################################################################
get_subnet() {
    typeset PS4_FUNC="get_subnet"

    echo $(clgetnet $1 $2)
    exit $?
}

#########################################################################
#
# This routine sorts the list of standbys according to their netmask
# and that of the takeover address.
#
#########################################################################
sort_standbys() {
    typeset PS4_FUNC="sort_standbys"
    [[ $VERBOSE_LOGGING == "high" ]] && set -x
    takeover=$1
    shift
    candidates=$*

    integer num_candidates=$(echo $candidates | tr " " "\n" | wc -l)
    if (( $num_candidates == 1 )); then
        echo $candidates
        return
    fi

    #since, service address can be either an IPv4/IPv6 address,
    #its always better to get the prefix length instead of netmask.
    service_netmask=$(LC_ALL=C cllsif -J "$OP_SEP" -Sn $takeover | cut -f14 -d"$OP_SEP")

    service_subnet=$(get_subnet $takeover $service_netmask)

    CANDIDATES_ON_SAME_SUBNET=""
    CANDIDATES_ON_OTHER_SUBNET=""
    # test all the candidates in the list
    for candidate in $candidates
    do
        # find the subnet for this candidate
        # Slight modification w.r.t subnet mask/prefix lenght, since get_subnet
        # is able to handle both prefix length and netmask, so always better to
        # get prefix lenght instead of netmask.
        LC_ALL=C cllsif -J "$OP_SEP" -Sn $candidate | \
        cut -f7,14 -d"$OP_SEP" | tr "$OP_SEP" " " | \
        read candidate_dot_addr candidate_netmask
        candidate_subnet=$(get_subnet $candidate_dot_addr $candidate_netmask)

        if [[ $candidate_subnet == $service_subnet ]]; then
            CANDIDATES_ON_SAME_SUBNET="$CANDIDATES_ON_SAME_SUBNET $candidate"
        else    # different subnet
            CANDIDATES_ON_OTHER_SUBNET="$CANDIDATES_ON_OTHER_SUBNET $candidate"
        fi
    done

    echo $CANDIDATES_ON_OTHER_SUBNET $CANDIDATES_ON_SAME_SUBNET
    return
}


#============================================================================
#
# Name:        get_list_head
#
# Description: 
#
# Inputs:      
#
# Outputs:     
#
# Returns:     
#
#============================================================================
get_list_head() {
    typeset PS4_FUNC="get_list_head"
    echo $* | cut -f 1 -d : | sed 's/,/ /g' |read LIST
    print $LIST
} # End of "get_list_head()"


#============================================================================
#
# Name:        get_list_tail
#
# Description: 
#
# Inputs:      
#
# Outputs:     
#
# Returns:     
#
#============================================================================
get_list_tail() {
    typeset PS4_FUNC="get_list_tail"
    case $* in
        *:* )
            echo $* | cut -f 2- -d : |read LIST
            print $LIST
            return
        ;;
        * )
            echo ""
        ;;
    esac
} # End of "get_list_tail()"


#########################################################################
#
#  MAIN Main main
#
#########################################################################

PROGNAME=${0##*/}
export PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)"
if [[ $VERBOSE_LOGGING == "high" ]]; then
    set -x
    version='1.71.1.6'
fi
OP_SEP="$(cl_get_path -S)"

# these variable control the telinit wait loop
TELINIT=false
TELINIT_FILE="/usr/es/sbin/cluster/.telinit"
# try this number of times
typeset -i telinit_wait_count=36
# waiting this much between tries
DELAY=5
# by default produces a wait of 3 minutes for telinit to complete

STATUS=0

PROC_RES=false

# if JOB_TYPE is set, and it doesn't equal to "GROUP", then
# we are processing for process_resources
if [[ ${JOB_TYPE:-0} != 0 && $JOB_TYPE != "GROUP" ]]; then
    PROC_RES=true
    _IP_LABELS=$IP_LABELS
else
    # check arguments for serial case only. Otherwise everything comes
    # from the environment.
    if [ $# -eq 0 ]
    then
        cl_echo  1029 "Usage: $PROGNAME takeover_address...\n"  $PROGNAME
        exit 2
    fi

    export RESOURCE_GROUPS=$GROUPNAME

fi

# Change NSORDER
saveNSORDER=${NSORDER:-UNDEFINED}
NSORDER=local; export NSORDER

#set -u

BOOT_ADDR=""
SERVICE_ADDR=""

# go through all resource groups
# for serial groups, this will be once only
for GROUPNAME in $RESOURCE_GROUPS; do

    export GROUPNAME

    if [[ $PROC_RES == true ]]; then
        get_list_head $IP_LABELS | read SERVICELABELS
        get_list_tail $IP_LABELS | read IP_LABELS

    else
        SERVICELABELS=$*
    fi

    # update the resource manager with this operation
    ALLSRVADDRS="All_service_addrs"
    ALLNOERRSRV="All_nonerror_service_addrs"

    cl_RMupdate resource_acquiring $ALLSRVADDRS $PROGNAME

    for addr in $SERVICELABELS
    do

        #
        # Determine if address is already configured.  If not, try to
        # acquire it.
        #
        LC_ALL=C clgetif -a $addr 2>/dev/null
        if (( $? != 0 ))
        then
            #
            # Get dot address of takeover_address, network and
            # configured standby addresses for later use.
            #
            STATUS=1
            addr_textual_addr=$(name_to_addr $addr)
            # NETWORK=$(cllsif -J "$OP_SEP" -Sn $addr_textual_addr | \
            # cut -d"$OP_SEP" -f3 | uniq)
            cllsif -J "$OP_SEP" -Sn $addr_textual_addr | \
            cut -d"$OP_SEP" -f3,4 | tr "$OP_SEP" " " | read NETWORK NET_TYPE

            if [[ -z "$NETWORK" ]]
            then
                MSG=$(dspmsg scripts.cat 342 "Unable to determine local boot/service interface.\n")
                STATUS=1

                cl_RMupdate resource_error $addr $PROGNAME

                if [[ $PROC_RES == true ]]; then
                    STATUS=11
                    continue
                else
                    STATUS=1
                fi

            fi

            # build a list of valid target adapters for this service label
            ALIAS=$(cllsnw -J "$OP_SEP" -Sw -n $NETWORK | cut -f3 -d"$OP_SEP")
            if [[ $ALIAS == "true" ]]
            then
                STDBYS=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | \
                grep "$OP_SEP"boot"$OP_SEP" | cut -d "$OP_SEP" -f1,3 | \
                grep -w $NETWORK | cut -d "$OP_SEP" -f1 | sort)
                if [ "$ALIAS" != "true" ]
                then
                    SERVICE=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | \
                    grep "$OP_SEP"service"$OP_SEP" | cut -d"$OP_SEP" -f1,3 | \
                    grep -w $NETWORK | cut -d "$OP_SEP" -f1 )
                    STDBYS="$STDBYS $SERVICE"
                else
                    # for alias network, we give preference to the subnet that
                    # is not already occupied by a service
                    STDBYS=$(sort_standbys $addr_textual_addr $STDBYS)
                fi
            else
                STDBYS=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | \
                grep "$OP_SEP"standby"$OP_SEP" | cut -d "$OP_SEP" -f1,3 \
                | grep -w $NETWORK | cut -d "$OP_SEP" -f1 )
            fi

            # sort standby adapters
            standby=$(best_boot_addr $NETWORK $STDBYS)
            if (( $? != 0 ))
            then
                dspmsg scripts.cat 342 "Unable to determine local boot/service interface.\n"

                cl_RMupdate resource_error $addr $PROGNAME

                if [[ $PROC_RES == true ]]; then
                    STATUS=11
                else
                    STATUS=1
                fi
                continue
            fi

            standby_dot_addr=$(name_to_addr $standby)

            INTERFACE=$(LC_ALL=C clgetif -a $standby_dot_addr 2>/dev/null | awk '{print $1}')

            # if in process_resources, this variable is already set
            if [[ $PROC_RES == false ]]; then
                # get resources to work on
                set -a
                eval $(clsetenvres $GROUPNAME $PROGNAME)
                set +a
            fi

            if [[ -n "$INTERFACE" ]]
            then
                INET_FAMILY=$(get_inet_family $addr_textual_addr)
                if [[ $INET_FAMILY == "inet6" ]]
                then
                        cl_swap_IPv6_address cascading acquire $INTERFACE \
                        $addr_textual_addr $standby_dot_addr
                else
                        # use the netmask of the service being acquired
                        NETMASK=$(clodmget -q"identifier=$addr_textual_addr" -f netmask -n HACMPadapter)
                        cl_swap_IP_address cascading acquire $INTERFACE \
                        $addr_textual_addr $standby_dot_addr $NETMASK
                fi
                RC=$?
                if (( $RC != 0 )); then
                    if [[ $PROC_RES == false ]]; then
                        STATUS=1
                    else
                        if [[ $RC != 11 ]]; then
                            cl_RMupdate resource_error $addr $PROGNAME
                        fi
                        STATUS=11
                    fi
                else
                    if [[ $PROC_RES == true ]]; then
                        if [[ $STATUS != 11 ]]; then
                            STATUS=0
                        fi
                    else
                        STATUS=0
                    fi
                fi

                addback_route $standby_dot_addr
            else   # if not a valid INTERFACE mark STATUS as 1
                STATUS=1
            fi     # end of valid INTERFACE 

            if (( $STATUS != 0 ))
            then
                MSG=$(dspmsg scripts.cat 340 "IP Address Takeover of $addr_textual_addr failed.\n" $addr_textual_addr)
                echo $MSG >/dev/console

                if [[ $saveNSORDER != UNDEFINED ]]; then
                    export NSORDER=$saveNSORDER
                else
                    export NSORDER=""
                fi

                exit $STATUS
            else

                TELINIT=true
            fi #end of STATUS check

        fi	# not already on the node
    done # for addr in SERVICELABELS

    # update the resource manager with the results
    ALLNOERRSRV="All_nonerror_service_addrs"
    cl_RMupdate resource_up $ALLNOERRSRV $PROGNAME

done # for GROUPNAME in RESOURCE_GROUPS

if [[ $saveNSORDER != UNDEFINED ]]; then
    export NSORDER=$saveNSORDER
else
    export NSORDER=""
fi

# telinit is called (here) only for serially processed RGs
if [[ $PROC_RES == false ]]; then
    if [ $TELINIT == "true" ]
    then
        cl_telinit
    fi
fi

exit $STATUS
