📄 ipaddr.in
字号:
#!/bin/sh## This script manages IP alias IP addresses## It can add an IP alias, or remove one.## usage: $0 {start|stop|status|monitor|meta-data}## The "start" arg adds an IP alias.## Surprisingly, the "stop" arg removes one. :-)## OCF parameters are as below# OCF_RESKEY_ipaddr#export LC_ALL=Cprefix=@prefix@exec_prefix=@exec_prefix@HA_D=@sysconfdir@/ha.dCONF_D=@sysconfdir@/ha.d/conf. ${HA_D}/shellfuncsIFCONFIG=@IFCONFIG@IFCONFIG_A_OPT=@IFCONFIG_A_OPT@VARLIB=@localstatedir@/lib/@HB_PKG@VLDIR=$VARLIB/rsctmp/IPaddrSENDARPPIDDIR=$VARLIB/rsctmp/send_arpROUTE=@ROUTE@SENDARP=$HA_BIN/send_arpFINDIF=$HA_BIN/findifUSAGE="usage: $0 {start|stop|status|monitor|meta-data}";SYSTYPE="`uname -s`"case "$SYSTYPE" in SunOS) # `uname -r` = 5.9 -> SYSVERSION = 9 SYSVERSION="`uname -r | cut -d. -f 2`" ;; Darwin) # Treat Darwin the same as the other BSD variants (matched as *BSD) SYSTYPE="${SYSTYPE}BSD" ;; *) ;;esac## Find out which alias serves the given IP address# The argument is an IP address, and its output# is an aliased interface name (e.g., "eth0:0").#find_interface_solaris() { ipaddr="$1"; $IFCONFIG $IFCONFIG_A_OPT | nawk '{if ($0 ~ /.*: / && NR > 1) {print "\n"$0} else {print}}' | while read ifname linkstuff do : ifname = $ifname read inet addr junk : inet = $inet addr = $addr while read line && [ "X$line" != "X" ] do : Nothing done case $ifname in *:*) ;; *) continue;; esac # This doesn't look right for a box with multiple NICs. # It looks like it always selects the first interface on # a machine. Yet, we appear to use the results for this case too... ifname=`echo "$ifname" | sed s'%:$%%'` case $addr in addr:$ipaddr) echo $ifname; return 0;; $ipaddr) echo $ifname; return 0;; esac done return 1}## Find out which alias serves the given IP address# The argument is an IP address, and its output# is an aliased interface name (e.g., "eth0:0").#find_interface_generic() { ipaddr="$1"; $IFCONFIG $IFCONFIG_A_OPT | while read ifname linkstuff do : Read gave us ifname = $ifname read inet addr junk : Read gave us inet = $inet addr = $addr while read line && [ "X$line" != "X" ] do : Nothing done case $ifname in *:*) ;; *) continue;; esac case $SYSTYPE in *BSD) $IFCONFIG | grep "$ipaddr" -B4 | grep "UP," | cut -d ":" -f 1 return 0;; *) : "comparing $ipaddr to $addr (from ifconfig)" case $addr in addr:$ipaddr) echo $ifname; return 0;; $ipaddr) echo $ifname; return 0;; esac continue;; esac done return 1}## Find out which alias serves the given IP address# The argument is an IP address, and its output# is an aliased interface name (e.g., "eth0:0").#find_interface() { case $SYSTYPE in SunOS) IF=`find_interface_solaris $BASEIP` ;; *) IF=`find_interface_generic $BASEIP` ;; esac echo $IF return 0;}## This routine should handle any type of interface, but has only been# tested on ethernet-type NICs.#ifconfig2sendarp() { echo "$1" | sed "s%:%%g"}delete_route () { ipaddr="$1" case $SYSTYPE in SunOS) CMD="" ;; *BSD) CMD="$ROUTE -n delete -host $ipaddr" ;; *) CMD="$ROUTE -n del -host $ipaddr" ;; esac ha_log "info: $CMD" $CMD return $?}delete_interface () { ipaddr="$1" ifname="$2" case $SYSTYPE in SunOS) if [ "$SYSVERSION" -ge 8 ] ; then CMD="$IFCONFIG $ifname unplumb" else CMD="$IFCONFIG $ifname 0 down" fi ;; *BSD) CMD="$IFCONFIG $ifname inet $ipaddr -alias" ;; *) CMD="$IFCONFIG $ifname down" ;; esac ha_log "info: $CMD" $CMD return $?}add_interface () { ipaddr="$1" ifinfo="$2" iface="$3" # # On Linux the Alias is named ethx:y # This will remove the "extra" interface Data # leaving us with just ethx # case $SYSTYPE in *BSD) IFEXTRA="" ;; *) IFEXTRA=`echo "$ifinfo" | cut -f2-` ;; esac case $SYSTYPE in SunOS) if [ "$SYSVERSION" -ge 8 ] ; then $IFCONFIG $iface plumb rc=$? if [ $rc -ne 0 ] ; then echo "ERROR: '$IFCONFIG $iface plumb' failed." return $rc fi fi CMD="$IFCONFIG $iface inet $ipaddr $IFEXTRA up" ;; *BSD) CMD="$IFCONFIG $iface inet $ipaddr netmask 255.255.255.255 alias" ;; *) CMD="$IFCONFIG $iface $ipaddr $IFEXTRA" ;; esac ha_log "info: $CMD" $CMD rc=$? case $rc in 0) ;; *) echo "ERROR: $CMD failed." ;; esac return $rc}# On Linux systems the (hidden) loopback interface may# conflict with the requested IP address. If so, this# unoriginal code will remove the offending loopback address# and save it in VLDIR so it can be added back in later# when the IPaddr is released.#remove_conflicting_loopback() { ipaddr="$1" ifname="$2" ha_log "info: Removing conflicting loopback $ifname." if [ -d "$VLDIR/" ] || mkdir -p "$VLDIR/" then : Directory $VLDIR now exists else ha_log "ERROR: Could not create \"$VLDIR/\" conflicting" \ " loopback $ifname cannot be restored." fi if echo $ifname > "$VLDIR/$ipaddr" then : Saved loopback information in $VLDIR/$ipaddr else ha_log "ERROR: Could not save conflicting loopback $ifname." \ "it will not be restored." fi delete_interface "$ipaddr" "$ifname" # Forcibly remove the route (if it exists) to the loopback. delete_route "$ipaddr"}# On Linux systems the (hidden) loopback interface may# need to be restored if it has been taken down previously# by remove_conflicting_loopback()#restore_loopback() { ipaddr="$1" if [ -s "$VLDIR/$ipaddr" ]; then ifname=`cat "$VLDIR/$ipaddr"` ha_log "info: Restoring loopback IP Address " \ "$ipaddr on $ifname." add_interface "$ipaddr" "netmask 255.255.255.255" "$ifname" rm -f "$VLDIR/$ipaddr" fi}## Remove the IP alias for the requested IP address...#ip_stop() { BASEIP=`echo $1 | sed s'%/.*%%'` SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP" IF=`find_interface $BASEIP` if test -f "$SENDARPPIDFILE" then cat "$SENDARPPIDFILE" | xargs kill rm -f "$SENDARPPIDFILE" fi case $SYSTYPE in *BSD) if $IFCONFIG $IFCONFIG_A_OPT | \ grep "inet.*[: ]$BASEIP " >/dev/null 2>&1; then continue; else exit 0 fi;; Linux|SunOS) if [ -z "$IF" ]; then : Requested interface not in use exit 0 else case $IF in lo*) : Requested interface is on loopback exit 0 ;; esac fi;; *) if [ -z "$IF" ]; then : Requested interface not in use exit 0 fi;; esac if [ -x $HA_RCDIR/local_giveip ] then $HA_RCDIR/local_giveip $* fi delete_route "$BASEIP" delete_interface "$BASEIP" "$IF" rc=$? case $SYSTYPE in *BSD) ;; Linux|SunOS) restore_loopback "$BASEIP" # remove lock file... rm -f "$VLDIR/$IF";; *) # remove lock file... rm -f "$VLDIR/$IF";; esac case $rc in 0) ha_log "info: IP Address $BASEIP released" ;; *) ha_log "WARN: IP Address $BASEIP NOT released" ;; esac return $rc}## Find an unused interface/alias name for us to use for new IP alias# The argument is an IP address, and the output# is an aliased interface name (e.g., "eth0:0", "dc0", "le0:0").#find_free_interface() { if [ ! -d $VLDIR ] then mkdir -p $VLDIR fi BASEIP=`echo $1 | sed s'%/.*%%'` if NICINFO=`$FINDIF $1` then : OK else lrc=$? ha_log "ERROR: unable to find an interface for $BASEIP" return $lrc fi nicname=`echo "$NICINFO" | cut -f1` nicinfo=`echo "$NICINFO" | cut -f2-` if [ "X$nicname" = "X" ] then ha_log "ERROR: no interface found for $BASEIP" return 1; fi NICBASE="$VLDIR/$nicname" touch "$NICBASE" case $SYSTYPE in SunOS) IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \ grep "^$nicname:[0-9]" | sed 's%: .*%%'` ;; *) IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \ grep "^$nicname:[0-9]" | sed 's% .*%%'` ;; esac IFLIST=" `echo $IFLIST` " case $SYSTYPE in SunOS) j=1 ;; *) j=0 TRYADRCNT=`ls "${NICBASE}:"* | wc -l | tr -d ' ' 2>/dev/null` if [ -f "${NICBASE}:${TRYADRCNT}" ] then : OK else j="${TRYADRCNT}" fi ;; esac case $SYSTYPE in *BSD) echo $nicname; return 0;; *) while [ $j -lt 512 ] do case $IFLIST in *" "$nicname:$j" "*) ;; *) NICLINK="$NICBASE:$j" if ln "$NICBASE" "$NICLINK" 2>/dev/null then echo "$nicname:$j $nicinfo" return 0 fi;; esac j=`expr $j + 1` done;; esac return 1}## Add an IP alias for the requested IP address...## It could be that we already have taken it, in which case it should# do nothing.#ip_start() { # # Do we already service this IP address? # case `ip_status $1` in *unning*) exit 0; esac BASEIP=`echo $1 | sed s'%/.*%%'` SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP" case $SYSTYPE in Linux|SunOS) CURRENTIF=`find_interface "$BASEIP"` case $CURRENTIF in lo*) remove_conflicting_loopback "$BASEIP" "$CURRENTIF" ;; *) ;; esac ;; *) ;; esac if IFINFO=`find_free_interface $1`; then : OK got interface [$IFINFO] for $1 else exit 1 fi IF=`echo "$IFINFO" | cut -f1` if [ -x $HA_RCDIR/local_takeip ] then $HA_RCDIR/local_takeip $* fi add_interface "$BASEIP" "$IFINFO" "$IF" rc=$? case $rc in 0) ;; *) return $rc ;; esac TARGET_INTERFACE=`echo $IF | sed 's%:.*%%'` ha_log "info: Sending Gratuitous Arp for $BASEIP on $IF [$TARGET_INTERFACE]" [ -r ${CONF_D}/arp_config ] && . ${CONF_D}/arp_config [ -r "${CONF_D}/arp_config:${TARGET_INTERFACE}" ] && . "${CONF_D}/arp_config:${TARGET_INTERFACE}" # Set default values (can be overridden as described above) : ${ARP_INTERVAL_MS=500} # milliseconds between ARPs : ${ARP_REPEAT=10} # repeat count : ${ARP_BACKGROUND=yes} # no to run in foreground (no longer any reason to do this) : ${ARP_NETMASK=ffffffffffff} # netmask for ARP ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $TARGET_INTERFACE $BASEIP auto $BASEIP $ARP_NETMASK" ha_log "$SENDARP $ARGS" case $ARP_BACKGROUND in yes) ($SENDARP $ARGS || ha_log "ERROR: Could not send gratuitous arps")&;; *) $SENDARP $ARGS || ha_log "ERROR: Could not send gratuitous arps";; esac}ip_status() { BASEIP=`echo $1 | sed -e s'%/.*%%'` IF=`find_interface $BASEIP` case $SYSTYPE in *BSD) if $IFCONFIG $IFCONFIG_A_OPT | grep "inet.*[: ]$BASEIP " >/dev/null 2>&1 then echo "running" else echo "stopped"; return 3 fi;; Linux|SunOS) if [ -z "$IF" ] then echo "stopped"; return 3 else case $IF in lo*) echo "loopback" ;; *) echo "running" ;; esac fi;; *) if [ -z "$IF" ] then echo "stopped"; return 3 else echo "running" fi;; esac}## Determine if this IP address is really being served, or not.# Note that we don't distinguish if *we're* serving it locally...#ip_monitor() { BASEIP=`echo $1 | sed s'%/.*%%'` TIMEOUT=1 # seconds case $SYSTYPE in Linux) # -c count -t timetolive -q(uiet) -n(umeric) -W timeout PINGARGS="-c 1 -q -n -W $TIMEOUT $BASEIP" ;; SunOS) PINGARGS="$BASEIP $TIMEOUT" ;; *) PINGARGS="-c 1 @PING_TIMEOUT_OPT@ -q $BASEIP" ;; esac for j in 1 2 3 do if @PING@ $PINGARGS >/dev/null 2>&1 then echo "OK" return 0 fi done echo "down" return 1}meta_data() { echo "<?xml version=\"1.0\"?><!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\"><resource-agent name=\"IPaddr\" version=\"0.1\"> <version>1.0</version> <parameters> <parameter name=\"ipaddr\" unique=\"0\"> <longdesc lang=\"en\"> This script manages IP alias IP addresses,It can add an IP alias, or remove one. </longdesc> <shortdesc lang=\"en\">manages IP alias</shortdesc> <content type=\"string\" default=\"\" /> </parameter> </parameters> <actions> <action name=\"start\" timeout=\"15\" /> <action name=\"stop\" timeout=\"15\" /> <action name=\"status\" timeout=\"15\" interval=\"15\" start-delay=\"15\" /> <action name=\"monitor\" timeout=\"15\" interval=\"15\" start-delay=\"15\" /> <action name=\"meta-data\" timeout=\"5\" /> </actions> <special tag=\"heartbeat\"> <version>2.0</version> </special></resource-agent>"}usage() { echo $USAGE >&2}## Add or remove IP alias for the given IP address...#if [ $# -eq 1 ]then case $1 in info) cat <<-!INFO Abstract=IP address takeover Argument=IP address OR IP address/broadcast address OR IP address/broadcast address/netmaskbits Description: An IPaddr resource is an IP address which is to be taken over by \\ the owning node. An argument is required, and is of this form: nnn.nnn.nnn.nnn/bbb.bbb.bbb.bbb Where nnn.nnn.nnn.nnn is the IP address to be taken over, and\\ bbb.bbb.bbb.bbb is the broadcast address to be used with this address. Since IPaddr is the "default" resource type, it is not necessary\\ to prefix the IP address by "IPaddr::". This allows IPaddr::192.2.4.63 to be abbreviated as 192.2.4.63. !INFO exit 0;; esacfiif [ $# -eq 0 ]then usage exit 1fiif ( [ X$OCF_RA_VERSION_MAJOR != "X" ] && [ $OCF_RA_VERSION_MAJOR -ne 1 ] ) || ( [ X$OCF_RA_VERSION_MINOR != "X" ] && [ $OCF_RA_VERSION_MINOR -ne 0 ] )then echo incompatible API version exitficase $1 in start) ip_start $OCF_RESKEY_ipaddr;; stop) ip_stop $OCF_RESKEY_ipaddr;; status) ip_status $OCF_RESKEY_ipaddr;; monitor) ip_monitor $OCF_RESKEY_ipaddr;; meta-data) meta_data;; *) usage exit 1 ;;esac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -