#!/bin/ksh93 # ALTRAN_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # Copyright (C) Altran ACT S.A.S. 2017,2018,2021. All rights reserved. # # ALTRAN_PROLOG_END_TAG # # @(#) 7d4c34b 43haes/usr/sbin/cluster/events/utils/cl_swap_IP_address.sh, 726, 2147A_aha726, Feb 05 2021 09:50 PM ############################################################################### # # Name: cl_swap_IP_address # # This script is used during adapter swap and IP address takeover. # The first form, the specified interface is set from the old address # to the new address # cl_swap_IP_address cascading/rotating acquire/release interface \ # new_address old_address netmask # i.e cl_swap_IP_address cascading acquire en0 \ # 1.1.1.2 1.1.1.1 255.255.255.128 # # The second form sets two interfaces in a single call. This is sometimes # necessary due to AIX routing quirks where an existing route gets # spuriously deleted. An example where this is required is the case of # swapping two interfaces. # cl_swap_IP_address swap_adapter swap \ # interface1 address1 interface2 address2 netmask # i.e cl_swap_IP_address swap_adapter swap \ # en0 1.1.1.1 en1 2.2.2.2 255.255.255.128 # # Returns: 0 - success # 1 - fatal error # 2 - bad number of arguments # 11 - recoverable error # ############################################################################### ############################################################################### # Name: flush_arp # # Flushes entire arp cache # # Returns: None. ############################################################################### function flush_arp { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x arp -an | grep "\?" | tr -d '()' | (while read host addr other ; do arp -d $addr done) return 0 } ############################################################################### # Name: add_rc_check # # Add an exit code check, message and error exit to a file. # # Arguments: # $1 - filename # $2 - function name (for message) # # Returns: N/A ############################################################################### function add_rc_check { typeset PS4_FUNC="add_rc_check" [[ "$VERBOSE_LOGGING" == "high" ]] && set -x RR=$1 FUNC=$2 cat >>$RR<<-EOF rc=\$? if [[ \$rc != 0 ]] then echo "ERROR: $FUNC failed with code \$rc" cl_route_change_RC=\$rc fi EOF } ############################################################################### # Name: check_alias_status # # Check that the desired address has been successfully aliased onto # the adapter. # # Arguments: # Interface to check # IP address in dotted-decimal format # Netmask in dotted-decimal format # # Returns: # 0 Interface has a proper entry # 1 Interface does not have a proper entry # ############################################################################### function check_alias_status { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x CH_INTERFACE=$1 CH_ADDRESS=$2 CH_ACQ_OR_RLSE=$3 # Infiniband doesn't display alias addresses when the ifconfig command is # executed, so we have to get it from netstat # if we are called with seven arguments, then IF is not set. In that case, # use the CH_INTERFACE argument instead. IF_IB=${IF:-$CH_INTERFACE} IS_IB=$(echo $IF_IB|awk '{print index($0, "ib")}') if [[ $IS_IB != 1 ]] then ADDR=$(clifconfig $CH_INTERFACE | fgrep -w $CH_ADDRESS | awk '{print $2}') else ADDR=$(netstat -in | fgrep -w $CH_INTERFACE | awk '{print $4}' | fgrep -w $CH_ADDRESS) fi if [ "$CH_ACQ_OR_RLSE" = "acquire" ] then # if acquiring, make sure the alias IS on the interface [[ "$ADDR" != "$CH_ADDRESS" ]] && { cl_log 7324 "$PROGNAME: Failed to ifconfig alias $CH_ADDRESS on interface $CH_INTERFACE" $PROGNAME $CH_ADDRESS $CH_INTERFACE return 1 } else # if releasing, make sure the alias IS NOT on the interface [[ "$ADDR" == "$CH_ADDRESS" ]] && { cl_log 7325 "$PROGNAME: Failed ifconfig delete alias $CH_ADDRESS from interface $CH_INTERFACE." $PROGNAME $CH_ADDRESS $CH_INTERFACE return 1 } fi return 0 } ############################################################################### # Name: alias_replace_routes # # For the list of interfaces given on command line, moves each route # to 127.1 (lo0) and writes a file (name in $1) containing a shell # script that will restore the original routing table # # Arguments: # $1 - filename # $2 - failing interface name # Also makes use of following variables, global or set in main routine # LOCALNODENAME, NET, NETMASK, ADDR1, INVOCATION_FLAG, PERSISTENT, # ACQ_OR_RLSE # # Returns: 1 on error, 0 otherwise ############################################################################### function alias_replace_routes { [[ "$VERBOSE_LOGGING" == "high" ]] && set -x RR=$1 shift interfaces="$*" RC=0 cp /dev/null $RR cat >$RR<<-EOF #!/bin/ksh # # Script created by $PROGNAME on $(date) # PATH=$PATH PS4='$PS4' export VERBOSE_LOGGING=\${VERBOSE_LOGGING:-"high"} [[ "\$VERBOSE_LOGGING" = "high" ]] && set -x : Starting \$0 at \$(date) # EOF #exclude all the IPv6 addresses(colon seperated) from netstat along with [Ll]ink. LOCADDRS=$(netstat -in | awk '$3 !~ "[Ll]ink" && $3 !~ ":" && $3 !~ "Network" {print $4}') netstat -rnC # according to the netstat command man page: # U = Up # c = Access to this route creates a cloned route # H = route to a host (use -host instead of -net) # W = the route is a cloned route # b = the route broadcast route for ifce in $interfaces ; do integer I=1 NXTSVC="" #exclude all the IPv6 addresses(colon seperated) from netstat along with [Ll]ink. IFADDRS=$(netstat -in | awk '$3 !~ "[Ll]ink" && $3 !~ ":" && ($1 == "'$ifce'" || $1 == "'$ifce\*'") {print $4}') SVCADDRS=$(cllsif -J "$OP_SEP" -Spi $LOCALNODENAME | \ grep "$OP_SEP$NET$OP_SEP" | grep -E "${OP_SEP}service${OP_SEP}|${OP_SEP}persistent${OP_SEP}"\ | cut -d"$OP_SEP" -f7 | sort -u) #since, we are going to hadle only IPv4 service IP addresses exclude #all the IPv6 service IP addresses from the SVCADDRS list SVCADDRS=$(echo "$SVCADDRS" | awk '$1 !~ ":" {print $1}') PERSISTENT_IP=$(cllsif -J "$OP_SEP" -Spi $LOCALNODENAME | \ grep "$OP_SEP$NET$OP_SEP" | grep -E \ "${OP_SEP}persistent${OP_SEP}" | cut -d"$OP_SEP" -f7) routeaddr="" for ifaddr in $IFADDRS do for svcaddr in $SVCADDRS do # Select only the addresses in the same subnet as that of the service address which we are releasing if [[ $(clgetnet $ifaddr $NETMASK) == $(clgetnet $svcaddr $NETMASK) && $(clgetnet $ifaddr $NETMASK) == $(clgetnet $ADDR1 $NETMASK) && "$ifaddr" == "$svcaddr" ]] then if [[ -z "$routeaddr" ]] then routeaddr=$ifaddr fi if [[ "$ifaddr" != "$ADDR1" && ( "$ADDR1" != "$PERSISTENT_IP" || ( ( ${INVOCATION_FLAG:-0} != 0 ) && ( $INVOCATION_FLAG == "USER_REQUESTED" ) && "$ADDR1" == "$PERSISTENT_IP" ) ) ]] then NXTSVC=$svcaddr break fi fi done if [[ -n $NXTSVC ]] then break fi done # If there is no service address in the same subnet, check if there are any other address # in the same subnet as that of the routes we are removing # as we needed to update when we are removing the address that has net routes. NXTADDR="" bootaddr="" if [[ -z $NXTSVC ]] then bootaddr=$(cllsif -J "$OP_SEP" -Spi $LOCALNODENAME | grep "$OP_SEP$NET$OP_SEP" | grep "${OP_SEP}boot${OP_SEP}" | awk -F"$OP_SEP" '$9 == "'$ifce'" { print $7; }') for ifaddr in $IFADDRS do if [[ "$ifaddr" == "$bootaddr" && $(clgetnet $ifaddr $NETMASK) == $(clgetnet $bootaddr $NETMASK) && $(clgetnet $ifaddr $NETMASK) == $(clgetnet $ADDR1 $NETMASK) && "$ifaddr" != "$ADDR1" ]] then NXTADDR=$ifaddr break fi done fi swaproute=0 NETSTAT_FLAGS="-nrf inet" if [[ "$ADDR1" == "$routeaddr" ]] then # swapping addr has net route swaproute=1 fi netstat $NETSTAT_FLAGS | fgrep -w $ifce | while read DEST GW FLAGS OTHER ; do LOOPBACK="127.0.0.$I" case $FLAGS in U|Uc) if [[ $(clgetnet $ADDR1 $NETMASK) == $(clgetnet $GW $NETMASK) ]] then if [[ "$ADDR1" == "$GW" || ("$PERSISTENT_IP" == "$GW" && -z $ACQ_OR_RLSE) ]] then if [[ ( $PERSISTENT != "" || "$ADDR1" == "$GW" ) || ( ( ${INVOCATION_FLAG:-0} == 0 ) || ( $INVOCATION_FLAG != "USER_REQUESTED" ) ) ]] then # all routes created by cloning are evil route delete -net $DEST $GW fi fi fi ;; U*W*) # all routes created by cloning are evil route delete -host $DEST $GW ;; U*H*b*) # Delete broadcast routes if failing address or persistent IP is gateway if [[ "$ADDR1" == "$GW" || ( "$PERSISTENT_IP" == "$GW" && -z $ACQ_OR_RLSE ) ]] then if [[ ( $PERSISTENT != "" || "$ADDR1" == "$GW" ) || ( ( ${INVOCATION_FLAG:-0} == 0) || ( $INVOCATION_FLAG != "USER_REQUESTED" ) ) ]] then route delete -host $DEST $GW fi fi ;; U*H*) # If $DEST is a locally configured address, do # nothing with this route since it may interfere # with netmon logic. integer found=0 for addr in $LOCADDRS do if [[ "$addr" == "$DEST" ]] then found=1 break fi done if (( $found == 0 )) then if [[ $(clgetnet $ADDR1 $NETMASK) == $(clgetnet $GW $NETMASK) ]] then if [[ ( ( ${INVOCATION_FLAG:-0} == 0 ) || ( $INVOCATION_FLAG != "USER_REQUESTED" ) ) || $swaproute == 1 ]] then # into RR we put the route command: if [[ -z $ACQ_OR_RLSE || "$routeaddr" == "$PERSISTENT_IP" ]] && [[ -n "$routeaddr" ]] then print "cl_route_change -if$routeaddr $DEST $LOOPBACK $GW inet" >>$RR add_rc_check $RR "cl_route_change" else print "cl_route_change $DEST $LOOPBACK $GW inet" >>$RR add_rc_check $RR "cl_route_change" fi # which will undo: cl_route_change $DEST $GW $LOOPBACK inet RC=$? : cl_route_change completed with $RC I=I+1 fi fi fi ;; U*) if [[ $(clgetnet $ADDR1 $NETMASK) == $(clgetnet $GW $NETMASK) ]] then if [[ ( ( ${INVOCATION_FLAG:-0} == 0 ) || ( $INVOCATION_FLAG != "USER_REQUESTED" ) ) || $swaproute == 1 ]] then # into RR we put the route command: if [[ -z $ACQ_OR_RLSE || "$routeaddr" == "$PERSISTENT_IP" ]] && [[ -n "$routeaddr" ]] then print "cl_route_change -if$routeaddr $DEST $LOOPBACK $GW inet" >>$RR add_rc_check $RR "cl_route_change" else print "cl_route_change $DEST $LOOPBACK $GW inet" >>$RR add_rc_check $RR "cl_route_change" fi # which will undo: cl_route_change $DEST $GW $LOOPBACK inet RC=$? : cl_route_change completed with $RC I=I+1 fi fi ;; esac done done echo "exit \$cl_route_change_RC" >> $RR chmod +x $RR return $RC } ############################################################################### # Name: disable_pmtu_gated # # Disable PMTU discovery and the gated daemon temporarily. # Global variables DISABLE_TCP_PMTU, DISABLE_UDP_PMTU and DISABLE_GATED # are set to retain current values. # # Arguments: 0 # # Returns: N/A ############################################################################### function disable_pmtu_gated { DISABLE_TCP_PMTU=0 DISABLE_UDP_PMTU=0 DISABLE_TCP_PMTU=$(no -o tcp_pmtu_discover | cut -f3,3 -d" ") DISABLE_UDP_PMTU=$(no -o udp_pmtu_discover | cut -f3,3 -d" ") no -o tcp_pmtu_discover=0 no -o udp_pmtu_discover=0 # Note that running gated is not presently supported by HACMP. # The user may experience side effects if gated is not implemented # properly. HACMP does at least attempt to stop gated: ps -eo "pid,comm" | grep -qw gated DISABLE_GATED=$? if (( $DISABLE_GATED == 0 )) then # This loop waits for gated to exit before continuing on. # The counter is set to 10 which means we will loop for # a maximum of 10 seconds before continuing on. This # counter can be increased however if it is increased # it might be wise to also increase the nim grace period # to prevent false fail_adapter events from occuring. integer GATED_COUNT=10; stopsrc -s gated 2> /dev/null while (( GATED_COUNT )) do ps -eo "pid,comm" | grep -qw gated if (( $? == 1 )) then break; fi (( GATED_COUNT-- )) sleep 1 done fi return 0 } ############################################################################### # Name: enable_pmtu_gated # # Reenable PMTU discovery and restart gated daemon. # Global variables DISABLE_TCP_PMTU, DISABLE_UDP_PMTU and DISABLE_GATED # hold values previously set in the disable_pmtu_gated subroutine. # # Arguments: 0 # # Returns: N/A ############################################################################### function enable_pmtu_gated { # if PMTU discovery was disabled, then reenable it. no -o tcp_pmtu_discover=$DISABLE_TCP_PMTU no -o udp_pmtu_discover=$DISABLE_UDP_PMTU # if gated was on when we entered this script, start it back [[ $DISABLE_GATED == 0 ]] && { startsrc -s gated; sleep 5; } return 0 } ############################################################################### # # Main entry point # ############################################################################### PROGNAME=${0##*/} export PATH="$(/usr/es/sbin/cluster/utilities/cl_get_path all)" # Including Availability metrics library file . /usr/es/lib/ksh93/availability/cl_amlib [[ "$VERBOSE_LOGGING" == "high" ]] && { set -x version='1.9.14.8' } OP_SEP="$(cl_get_path -S)" export LC_ALL=C RESTORE_ROUTES=/usr/es/sbin/cluster/.restore_routes cl_echo 33 "Starting execution of $0 with parameters $*" $0 "$*" typeset -i oslevel oslevel=$(/usr/bin/oslevel -r|/usr/bin/sed 's/-//g') # the number of arguments passed determines (in part) what kind of # swap we will be doing [[ $# == 6 || $# == 7 ]] && { if [[ $# == 7 ]] ; then # If PMTU discovery is enabled, we need to disable it temporarily. # If gated is running , disable it temporarily disable_pmtu_gated fi # save the current setting of ipignoreredirects then turn it on PRIOR_IPIGNORE_REDIRECTS_VALUE=$(no -a | grep ipignoreredirects | awk '{ print $3 }') /usr/sbin/no -o ipignoreredirects=1 } # if JOB_TYPE is set, and it doesn't equal to "GROUP", then # we are processing for process_resources PROC_RES=false if [[ ${JOB_TYPE:-0} != 0 && $JOB_TYPE != "GROUP" ]]; then PROC_RES=true fi set -u RC=0 case $# in # # This form changes a single interface, e.g. acquiring or releasing # 6) netstat -in netstat -rnC CASC_OR_ROT=$1 # rg relationship which owns the label ACQ_OR_RLSE=$2 # action IF=$3 # this is the interface (adapter) ADDR=$4 # address to be acquired or released OLD_ADDR=$5 # current address on the interface NETMASK=$6 # # For cascading release, need to get the boot adapter list if [[ "$CASC_OR_ROT" == "cascading" && "$ACQ_OR_RLSE" == "release" ]] then NET=$(cllsif -J "$OP_SEP" -Sw -n $OLD_ADDR | cut -f3 -d"$OP_SEP") ADDR=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | grep "${OP_SEP}$NET${OP_SEP}" | \ grep "${OP_SEP}boot${OP_SEP}" | cut -d"$OP_SEP" -f7 | tail -1) fi # get the network this new addr belongs to NET=$(cllsif -J "$OP_SEP" -Sw -n $ADDR | cut -f3 -d"$OP_SEP") # figure out how to set the alias first option ALIAS_FIRST=$(clodmget -q"identifier=$ADDR" -f max_aliases -n HACMPadapter) NUM_ADDRS=$(LC_ALL=C ifconfig $IF | grep -c -w "inet") if [[ "$ACQ_OR_RLSE" == "acquire" ]] then # Format for consumption by cl_am utility amlog_trace $AM_SERVICEIP_ALIAS_BEGIN "Aliasing Service IP|$ADDR" cl_echo 7310 "$PROGNAME: Configuring network interface $IF with aliased IP address $ADDR" $PROGNAME $IF $ADDR # alias add the specified address to the specified interface case $ALIAS_FIRST in 1027|771|1539|1283) #The user has chosen this address to be the first Address. clifconfig $IF alias $ADDR netmask $NETMASK firstalias ;; 0|1|2) #Find if other service addresses are present on this adapter. # if not then this will be the first address. if (( $NUM_ADDRS > 1 )) then clifconfig $IF alias $ADDR netmask $NETMASK else clifconfig $IF alias $ADDR netmask $NETMASK firstalias fi ;; 515) #If persistent is on this adapter it will stay as First #If not the service will be first. PERSIST_IF="" PERSISTON=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME | \ awk -F"$OP_SEP" -v NET="$NET" '{if ($2 == "persistent" \ && $3 == NET) print $1}' | sort) if [[ -n "$PERSISTON" ]] then PERSIST_IF=$(LC_ALL=C clgetif -a $PERSISTON 2>/dev/null) fi if [[ -n "$PERSIST_IF" && $IF == $PERSIST_IF ]] then clifconfig $IF alias $ADDR netmask $NETMASK else # There might be an address with 1539. if (( $NUM_ADDRS > 1 )) then clifconfig $IF alias $ADDR netmask $NETMASK else clifconfig $IF alias $ADDR netmask $NETMASK firstalias fi fi ;; *) clifconfig $IF alias $ADDR netmask $NETMASK ;; esac # tell the clstrmgr to start monitoring this alias hats_adapter_notify $IF -e $ADDR alias # make sure the alias is there check_alias_status $IF $ADDR $ACQ_OR_RLSE RC=$? # Format for consumption by cl_am utility if [[ $RC != 0 ]] then amlog_err $AM_SERVICEIP_ALIAS_FAILURE "Aliasing Service IP|$ADDR" else amlog_trace $AM_SERVICEIP_ALIAS_END "Aliasing Service IP|$ADDR" fi else cl_echo 7320 "$PROGNAME: Removing aliased IP address $OLD_ADDR from adapter $IF" $PROGNAME $OLD_ADDR $IF # Format for consumption by cl_am utility amlog_trace $AM_SERVICEIP_DEALIAS_BEGIN "Deliasing Service IP|$OLD_ADDR" PERSISTENT="" ADDR1=$OLD_ADDR disable_pmtu_gated alias_replace_routes $RESTORE_ROUTES $IF RC=$? : alias_replace_routes completed with $RC # delete the alias for the specified address clifconfig $IF delete $OLD_ADDR if [[ $swaproute == 1 ]] then if [[ -n $NXTSVC ]] then TEMP_ALIAS_FIRST=$(clodmget -q "identifier=$NXTSVC" -f max_aliases HACMPadapter) TEMP_NUM_ADDRS=$(LC_ALL=C ifconfig $IF | grep -v $NXTSVC | grep -c -w "inet") # alias add the specified address to the specified interface case $TEMP_ALIAS_FIRST in 1027|771|1539) #The user has chosen this address to be the first Address. clifconfig $IF alias $NXTSVC netmask $NETMASK firstalias ;; 0|1|2) #Find if other service addresses are present on this adapter. # if not then this will be the first address. if (( $TEMP_NUM_ADDRS > 1 )) then clifconfig $IF alias $NXTSVC netmask $NETMASK else clifconfig $IF alias $NXTSVC netmask $NETMASK firstalias fi ;; 515) #If persistent is on this adapter it will stay as First #If not the service will be first. PERSIST_IF="" PERSISTON=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME | \ awk -F"$OP_SEP" -v NET="$NET" '{if ($2 == "persistent" \ && $3 == NET) print $1}' | sort) if [[ -n "$PERSISTON" ]] then PERSIST_IF=$(LC_ALL=C clgetif -a $PERSISTON 2>/dev/null) fi if [[ -n "$PERSIST_IF" && $IF == $PERSIST_IF ]] then clifconfig $IF alias $NXTSVC netmask $NETMASK else # There might be an address with 1539. if (( $TEMP_NUM_ADDRS > 1 )) then clifconfig $IF alias $NXTSVC netmask $NETMASK else clifconfig $IF alias $NXTSVC netmask $NETMASK firstalias fi fi ;; *) clifconfig $IF alias $NXTSVC netmask $NETMASK ;; esac elif [[ -n $NXTADDR ]] then # In case of single adapter network, the bootIP and serviceIP are in same subnet, during ServiceIP # acquitstion bootIP routes are replaced with serviceIP routes. We are aliasing the bootIP # to restore the bootIP routes during the ServiceIP release. # But this alias may lead false network up events due to CAA and RSCT issues # To avoid this we are adding sleep 6seconds before aliasing the bootIP, so that CAA and RSCT will not # generate any false events. This is a temporary fix till RSCT gives a permanent fix and this fix is required # for AIX 71 TL3 and earlier verions of AIX 71 TL 3 releases if (( $oslevel <= 710003 )) then sleep 6 fi clifconfig $IF alias $NXTADDR netmask $NETMASK fi fi $RESTORE_ROUTES [[ $? == 0 && $RC != 0 ]] && RC=1 : Completed $RESTORE_ROUTES with return code $RC enable_pmtu_gated # Reset pmtu and restart gated # tell the clstrmgr not to monitor this alias any more hats_adapter_notify $IF -d $OLD_ADDR alias # verify the alias was removed check_alias_status $IF $OLD_ADDR $ACQ_OR_RLSE RC1=$? [[ $RC1 == 0 && $RC != 0 ]] && RC=1 # Format for consumption by cl_am utility if [[ $RC1 != 0 ]] then amlog_err $AM_SERVICEIP_DEALIAS_FAILURE "Dealiasing Service IP|$OLD_ADDR" else amlog_trace $AM_SERVICEIP_DEALIAS_END "Deliasing Service IP|$OLD_ADDR" fi fi [[ $RC != 0 ]] && { [[ -z $ADDR ]] && ADDR=$OLD_ADDR # tell the resource manager the results cl_RMupdate resource_error $ADDR $PROGNAME if [[ $PROC_RES == false ]]; then exit 1 else exit 11 fi } flush_arp netstat -in netstat -rnC ;; # # this form for changing two address e.g. swap_adapter # 7) UNUSED_1=$1 UNUSED_2=$2 IF1=$3 # interface currently holding the standby address ADDR1=$4 # the address to be recovered (service) IF2=$5 # interface currently holding the service ADDR2=$6 # the standby address NETMASK=$7 ACQ_OR_RLSE="" PERSISTENT=$(clodmget -q "function=persistent and nodename=$LOCALNODENAME and identifier=$ADDR1" -f ip_label -n HACMPadapter) if [[ -n $PERSISTENT ]]; then # The label passed in as the "service" label is actually # a persistent label, and it should be swapped to the # selected boot/standby. So just do that then exit. NET=$(cllsif -J "$OP_SEP" -Sw -n $ADDR2 | cut -f3 -d"$OP_SEP") cl_configure_persistent_address swap -n $NET -a $IF1 -f $IF2 RC=$? netstat -in netstat -rnC flush_arp enable_pmtu_gated #Reset pmtu and restart gated /usr/sbin/no -o ipignoreredirects=$PRIOR_IPIGNORE_REDIRECTS_VALUE exit $RC fi # # AIX route management # # This support in AIX currently only works for IPv4. This # change assumes AF_INET returned by cllsif is determined # by family_type = 1 in HACMPnetwork and further this means # the specified IP address is an IPV4 address. The assumption # is that AF_INET6 is used for IPV6 and AF_INET is used for IPV4 # NET=$(cllsif -J "$OP_SEP" -Sw -n $ADDR2 | cut -f3 -d"$OP_SEP") NET_FAMILY=$(cllsif -J "$OP_SEP" -Sw -n $ADDR1 | cut -f15 -d "$OP_SEP") # new transfer argument is only for IPV4 # If the IF1 and IF2 are same or the address does not exist on $IF2 transfer is not used as it fails if [[ "$NET_FAMILY" == "AF_INET" && $IF1 != $IF2 && -n $(ifconfig $IF2 | awk -v serv_addr=$ADDR1 '($1=="inet" && $2==serv_addr)') ]] then # get the setting for first alias option ALIAS_FIRST_TRANS=$(clodmget -q"identifier=$ADDR1" -f max_aliases HACMPadapter) NUM_ADDRS_ON_TOINF=$(LC_ALL=C ifconfig $IF1 | grep -c -w "inet") case $ALIAS_FIRST_TRANS in 1027|771|1539|1283) #The user has chosen this address to be the first Address. clifconfig $IF2 $ADDR1 transfer $IF1 firstalias ;; 0|1|2) #Find if other service addresses are present on this adapter. # if not then this will be the first address. if (( $NUM_ADDRS_ON_TOINF > 1 )) then clifconfig $IF2 $ADDR1 transfer $IF1 else clifconfig $IF2 $ADDR1 transfer $IF1 firstalias fi ;; 515) #If persistent is on this adapter it will stay as First #If not the service will be first. PERSIST_IF="" PERSISTON=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME | \ awk -F"$OP_SEP" -v NET="$NET" '{if ($2 == "persistent" \ && $3 == NET) print $1}' | sort) if [[ -n "$PERSISTON" ]] then PERSIST_IF=$(LC_ALL=C clgetif -a $PERSISTON 2>/dev/null) fi if [[ -n "$PERSIST_IF" && $IF1 == $PERSIST_IF ]] then clifconfig $IF2 $ADDR1 transfer $IF1 else # There might be an address with 1539. if (( $NUM_ADDRS_ON_TOINF > 1 )) then clifconfig $IF2 $ADDR1 transfer $IF1 else clifconfig $IF2 $ADDR1 transfer $IF1 firstalias fi fi ;; *) clifconfig $IF2 $ADDR1 transfer $IF1 ;; esac else # handle the swap without using the ifconfig transfer option alias_replace_routes $RESTORE_ROUTES $IF2 RC=$? if [[ (${INVOCATION_FLAG:-0} == 0) || ($INVOCATION_FLAG != "USER_REQUESTED") ]] then cl_configure_persistent_address swap -n $NET -a $IF1 -f $IF2 netstat -in netstat -rnC fi # Delete the alias service from the current interface clifconfig $IF2 delete $ADDR1 # add the alias service to the target interface ALIAS_FIRST_TRANS=$(clodmget -q"identifier=$ADDR1" -f max_aliases HACMPadapter) NUM_ADDRS_ON_TOINF=$(LC_ALL=C ifconfig $IF1 | grep -c -w "inet") case $ALIAS_FIRST_TRANS in 1027|771|1539|1283) #The user has chosen this address to be the first Address. clifconfig $IF1 alias $ADDR1 netmask $NETMASK firstalias ;; 0|1|2) #Find if other service addresses are present on this adapter. # if not then this will be the first address. if (( $NUM_ADDRS_ON_TOINF > 1 )) then clifconfig $IF1 alias $ADDR1 netmask $NETMASK else clifconfig $IF1 alias $ADDR1 netmask $NETMASK firstalias fi ;; 515) #If persistent is on this adapter it will stay as First #If not the service will be first. PERSIST_IF="" PERSISTON=$(cllsif -J "$OP_SEP" -Sp $LOCALNODENAME | \ awk -F"$OP_SEP" -v NET="$NET" '{if ($2 == "persistent" \ && $3 == NET) print $1}' | sort) if [[ -n "$PERSISTON" ]] then PERSIST_IF=$(LC_ALL=C clgetif -a $PERSISTON 2>/dev/null) fi if [[ -n "$PERSIST_IF" && $IF1 == $PERSIST_IF ]] then clifconfig $IF1 alias $ADDR1 netmask $NETMASK else # There might be an address with 1539. if (( $NUM_ADDRS_ON_TOINF > 1 )) then clifconfig $IF1 alias $ADDR1 netmask $NETMASK else clifconfig $IF1 alias $ADDR1 netmask $NETMASK firstalias fi fi ;; *) clifconfig $IF1 alias $ADDR1 netmask $NETMASK ;; esac # Add back pre-existing routes $RESTORE_ROUTES RC=$? : Completed $RESTORE_ROUTES with return code $RC if [[ ( ${INVOCATION_FLAG:-0} != 0 ) && ( $INVOCATION_FLAG == "USER_REQUESTED" ) ]] then if [[ -n $NXTSVC && $swaproute == 1 ]] then clifconfig $ifce alias $NXTSVC netmask $NETMASK fi fi # # If the subnets are equal and there is a default route # on this interface bounce the boot on failed interface. # This will move the default route to working adapter. # # find boots BOOT1=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | \ awk -F"$OP_SEP" -v if1=$IF1 \ '($2=="boot" && $9==if1) {printf("%s\n",$7)}') BOOT2=$(cllsif -J "$OP_SEP" -Si $LOCALNODENAME | \ awk -F"$OP_SEP" -v if2=$IF2 \ '($2=="boot" && $9==if2) {printf("%s\n",$7)}') # find route to delete BROUTE=$(netstat -rn|awk -v if2=$IF2 -v boot2=$BOOT2 \ '(NR > 4 && $6==if2 && $1!="default" && $2==boot2 && $3=="U") \ {printf("%s %s",$1,$2)}') if [[ $(clgetnet $BOOT1 $NETMASK) == $(clgetnet $BOOT2 $NETMASK) || ($(clgetnet $BOOT2 $NETMASK) == $(clgetnet $ADDR1 $NETMASK)) ]] then # The subnets are equal check for default. DEFAULTROUTE=$(netstat -rn|awk -v if2=$IF2 '(NR > 4 && $6==if2 && $1=="default")') if [[ -n $DEFAULTROUTE ]] then #exclude all the IPv6 addresses(colon seperated) from netstat along with [Ll]ink. LOCADDRS=$(netstat -in | awk '$3 !~ "[Ll]ink" && $3 !~ ":" && $3 !~ "Network" && ($1 == "'$IF2'" || $1 == "'$IF2\*'") {print $4}') SVCADDRS=$(cllsif -J "$OP_SEP" -Spi $LOCALNODENAME | \ grep "$OP_SEP$NET$OP_SEP" | grep -E \ "${OP_SEP}service${OP_SEP}" | cut -d"$OP_SEP" -f7 | sort -u) #since, we are going to hadle only IPv4 service IP addresses #exclude all the IPv6 service IP addresses from the SVCADDRS list SVCADDRS=$(echo "$SVCADDRS" | awk '$1 !~ ":" {print $1}') integer found=0 for locaddr in $LOCADDRS do for svcaddr in $SVCADDRS do if [[ "$locaddr" == "$svcaddr" || ("$locaddr" == "$PERSISTENT_IP" && $(clgetnet $locaddr $NETMASK) == $(clgetnet $BOOT2 $NETMASK)) ]] then found=1 break fi done if (( $found == 1 )) then break fi done set -A locaddrs $LOCADDRS LADDRLIST=$(echo ${locaddrs[@]} | tr ' ' '\n' | sort -u) if [[ $found == 0 && ( ( ${INVOCATION_FLAG:-0} == 0 ) || ( $INVOCATION_FLAG != "USER_REQUESTED" ) ) ]] then clifconfig $IF2 delete $BOOT2 clifconfig $IF2 alias $BOOT2 netmask $NETMASK if [[ -n $BROUTE ]] then route delete -net $BROUTE fi fi fi fi fi # non- transfer capable netstat -in netstat -rnC flush_arp enable_pmtu_gated # Tell the cluster manager to start monitoring this alias hats_adapter_notify $IF1 -e $ADDR1 alias check_alias_status $IF1 $ADDR1 "acquire" (( $? != 0 )) && { # tell the resource manager the results cl_RMupdate resource_error $ADDR1 $PROGNAME if [[ $PROC_RES == false ]]; then exit 1 else exit 11 fi } enable_pmtu_gated ;; *) # bad arg count echo "$PROGNAME An internal error occured.\nPlease report this problem to IBM support." exit 2 esac # restore ipignoreredirects to its original value no -o ipignoreredirects=$PRIOR_IPIGNORE_REDIRECTS_VALUE cl_echo 32 "Completed execution of $0 with parameters $*. Exit status = $RC" $0 "$*" $RC date exit $RC