summaryrefslogtreecommitdiffstats
path: root/heartbeat/IPaddr
diff options
context:
space:
mode:
Diffstat (limited to 'heartbeat/IPaddr')
-rwxr-xr-xheartbeat/IPaddr912
1 files changed, 912 insertions, 0 deletions
diff --git a/heartbeat/IPaddr b/heartbeat/IPaddr
new file mode 100755
index 0000000..9b0ea81
--- /dev/null
+++ b/heartbeat/IPaddr
@@ -0,0 +1,912 @@
+#!/bin/sh
+#
+# License: GNU General Public License (GPL)
+# Support: users@clusterlabs.org
+#
+# This script manages IP alias IP addresses
+#
+# It can add an IP alias, or remove one.
+#
+# usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+# The "start" arg adds an IP alias.
+#
+# Surprisingly, the "stop" arg removes one. :-)
+#
+# OCF parameters are as below
+# OCF_RESKEY_ip
+# OCF_RESKEY_broadcast
+# OCF_RESKEY_nic
+# OCF_RESKEY_cidr_netmask
+# OCF_RESKEY_lvs_support ( e.g. true, on, 1 )
+# OCF_RESKEY_ARP_INTERVAL_MS
+# OCF_RESKEY_ARP_REPEAT
+# OCF_RESKEY_ARP_BACKGROUND (e.g. yes )
+# OCF_RESKEY_ARP_NETMASK
+# OCF_RESKEY_local_start_script
+# OCF_RESKEY_local_stop_script
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Parameter defaults
+
+OCF_RESKEY_ip_default=""
+OCF_RESKEY_nic_default="eth0"
+OCF_RESKEY_cidr_netmask_default=""
+OCF_RESKEY_broadcast_default=""
+OCF_RESKEY_iflabel_default=""
+OCF_RESKEY_lvs_support_default="false"
+OCF_RESKEY_local_stop_script_default=""
+OCF_RESKEY_local_start_script_default=""
+OCF_RESKEY_ARP_INTERVAL_MS_default="500"
+OCF_RESKEY_ARP_REPEAT_default="10"
+OCF_RESKEY_ARP_BACKGROUND_default="yes"
+OCF_RESKEY_ARP_NETMASK_default="ffffffffffff"
+
+: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
+: ${OCF_RESKEY_nic=${OCF_RESKEY_nic_default}}
+: ${OCF_RESKEY_cidr_netmask=${OCF_RESKEY_cidr_netmask_default}}
+: ${OCF_RESKEY_broadcast=${OCF_RESKEY_broadcast_default}}
+: ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}}
+: ${OCF_RESKEY_lvs_support=${OCF_RESKEY_lvs_support_default}}
+: ${OCF_RESKEY_local_stop_script=${OCF_RESKEY_local_stop_script_default}}
+: ${OCF_RESKEY_local_start_script=${OCF_RESKEY_local_start_script_default}}
+: ${OCF_RESKEY_ARP_INTERVAL_MS=${OCF_RESKEY_ARP_INTERVAL_MS_default}}
+: ${OCF_RESKEY_ARP_REPEAT=${OCF_RESKEY_ARP_REPEAT_default}}
+: ${OCF_RESKEY_ARP_BACKGROUND=${OCF_RESKEY_ARP_BACKGROUND_default}}
+: ${OCF_RESKEY_ARP_NETMASK=${OCF_RESKEY_ARP_NETMASK_default}}
+
+SENDARP=$HA_BIN/send_arp
+FINDIF=$HA_BIN/findif
+VLDIR=$HA_RSCTMP
+SENDARPPIDDIR=$HA_RSCTMP
+SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+USAGE="usage: $0 {start|stop|status|monitor|validate-all|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
+
+
+
+meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="IPaddr" version="1.0">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages IP alias IP addresses
+It can add an IP alias, or remove one.
+</longdesc>
+<shortdesc lang="en">Manages virtual IPv4 addresses (portable version)</shortdesc>
+
+<parameters>
+<parameter name="ip" unique="1" required="1">
+<longdesc lang="en">
+The IPv4 address to be configured in dotted quad notation, for example
+"192.168.1.1".
+</longdesc>
+<shortdesc lang="en">IPv4 address</shortdesc>
+<content type="string" default="${OCF_RESKEY_ip_default}" />
+</parameter>
+<parameter name="nic" unique="0">
+<longdesc lang="en">
+The base network interface on which the IP address will be brought
+online.
+
+If left empty, the script will try and determine this from the
+routing table.
+
+Do NOT specify an alias interface in the form eth0:1 or anything here;
+rather, specify the base interface only.
+
+Prerequisite:
+
+There must be at least one static IP address, which is not managed by
+the cluster, assigned to the network interface.
+
+If you can not assign any static IP address on the interface,
+modify this kernel parameter:
+sysctl -w net.ipv4.conf.all.promote_secondaries=1
+(or per device)
+
+</longdesc>
+<shortdesc lang="en">Network interface</shortdesc>
+<content type="string" default="${OCF_RESKEY_nic_default}"/>
+</parameter>
+
+<parameter name="cidr_netmask">
+<longdesc lang="en">
+The netmask for the interface in CIDR format. (ie, 24), or in
+dotted quad notation 255.255.255.0).
+
+If unspecified, the script will also try to determine this from the
+routing table.
+</longdesc>
+<shortdesc lang="en">Netmask</shortdesc>
+<content type="string" default="${OCF_RESKEY_cidr_netmask_default}"/>
+</parameter>
+
+<parameter name="broadcast">
+<longdesc lang="en">
+Broadcast address associated with the IP. If left empty, the script will
+determine this from the netmask.
+</longdesc>
+<shortdesc lang="en">Broadcast address</shortdesc>
+<content type="string" default="${OCF_RESKEY_broadcast_default}"/>
+</parameter>
+
+<parameter name="iflabel">
+<longdesc lang="en">
+You can specify an additional label for your IP address here.
+</longdesc>
+<shortdesc lang="en">Interface label</shortdesc>
+<content type="string" default="${OCF_RESKEY_iflabel_default}"/>
+</parameter>
+
+<parameter name="lvs_support">
+<longdesc lang="en">
+Enable support for LVS Direct Routing configurations. In case a IP
+address is stopped, only move it to the loopback device to allow the
+local node to continue to service requests, but no longer advertise it
+on the network.
+</longdesc>
+<shortdesc lang="en">Enable support for LVS DR</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_lvs_support_default}"/>
+</parameter>
+
+<parameter name="local_stop_script">
+<longdesc lang="en">
+Script called when the IP is released
+</longdesc>
+<shortdesc lang="en">Script called when the IP is released</shortdesc>
+<content type="string" default="${OCF_RESKEY_local_stop_script_default}"/>
+</parameter>
+
+<parameter name="local_start_script">
+<longdesc lang="en">
+Script called when the IP is added
+</longdesc>
+<shortdesc lang="en">Script called when the IP is added</shortdesc>
+<content type="string" default="${OCF_RESKEY_local_start_script_default}"/>
+</parameter>
+
+<parameter name="ARP_INTERVAL_MS">
+<longdesc lang="en">
+milliseconds between ARPs
+</longdesc>
+<shortdesc lang="en">milliseconds between gratuitous ARPs</shortdesc>
+<content type="integer" default="${OCF_RESKEY_ARP_INTERVAL_MS_default}"/>
+</parameter>
+
+<parameter name="ARP_REPEAT">
+<longdesc lang="en">
+How many gratuitous ARPs to send out when bringing up a new address
+</longdesc>
+<shortdesc lang="en">repeat count</shortdesc>
+<content type="integer" default="${OCF_RESKEY_ARP_REPEAT_default}"/>
+</parameter>
+
+<parameter name="ARP_BACKGROUND">
+<longdesc lang="en">
+run in background (no longer any reason to do this)
+</longdesc>
+<shortdesc lang="en">run in background</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_ARP_BACKGROUND_default}"/>
+</parameter>
+
+<parameter name="ARP_NETMASK">
+<longdesc lang="en">
+netmask for ARP - in nonstandard hexadecimal format.
+</longdesc>
+<shortdesc lang="en">netmask for ARP</shortdesc>
+<content type="string" default="${OCF_RESKEY_ARP_NETMASK_default}"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="monitor" depth="0" timeout="20s" interval="5s" />
+<action name="validate-all" timeout="20s" />
+<action name="meta-data" timeout="5s" />
+</actions>
+</resource-agent>
+END
+ exit $OCF_SUCCESS
+}
+
+# The 'ping' command takes highly OS-dependent arguments, so this
+# function creates a suitable argument list for the host OS's 'ping'.
+# We use a subset of its functionality:
+# 1. single packet
+# 2. reasonable timeout (say 1 second)
+#
+# arguments:
+# $1: IP address to ping
+# result string:
+# arguments for ping command
+#
+# If more flexibility is needed, they could be specified in the environment
+# to this function, to adjust the resulting 'ping' arguments.
+# David Lee <t.d.lee@durham.ac.uk> May 2007
+pingargs() {
+ _baseip=$1
+ _timeout=1 # seconds
+ _pktcount=1
+ _systype="`uname -s`"
+ case $_systype in
+ Linux)
+ # Default is perpetual ping: need "-c $_pktcount".
+ # -c count -t timetolive -q(uiet) -n(umeric) -W timeout
+ _pingargs="-c $_pktcount -q -n $_baseip"
+ ;;
+ SunOS)
+ # Default is immediate (or timeout) return.
+ _pingargs="$_baseip $_timeout"
+ ;;
+ *)
+ _pingargs="-c $_pktcount $_baseip"
+ ;;
+ esac
+
+ echo "$_pingargs"
+}
+
+# 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.
+#
+lvs_remove_conflicting_loopback() {
+ ipaddr="$1"
+ ifname="$2"
+
+ ocf_log info "Removing conflicting loopback $ifname."
+ if
+ echo $ifname > "$VLDIR/$ipaddr"
+ then
+ : Saved loopback information in $VLDIR/$ipaddr
+ else
+ ocf_log err "Could not save conflicting loopback $ifname." \
+ "it will not be restored."
+ fi
+
+ if [ ! -z "${OCF_RESKEY_local_stop_script}" ]; then
+ if [ -x "${OCF_RESKEY_local_stop_script}" ]; then
+ ${OCF_RESKEY_local_stop_script} $*
+ fi
+ fi
+
+ delete_interface "$ifname" "$ipaddr"
+
+ # 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 lvs_remove_conflicting_loopback()
+#
+lvs_restore_loopback() {
+ ipaddr="$1"
+
+ if [ ! -s "$VLDIR/$ipaddr" ]; then
+ return
+ fi
+
+ ifname=`cat "$VLDIR/$ipaddr"`
+ ocf_log info "Restoring loopback IP Address $ipaddr on $ifname."
+
+ CMD="OCF_RESKEY_cidr_netmask=32 OCF_RESKEY_ip=$1 OCF_RESKEY_nic=$ifname $FINDIF"
+ if
+ NICINFO=`eval $CMD`
+ NICINFO=`echo $NICINFO | tr " " " " | tr -s " "`
+ then
+ netmask_text=`echo "$NICINFO" | cut -f3 -d " "`
+ broadcast=`echo "$NICINFO" | cut -f5 -d " "`
+ else
+ echo "ERROR: $CMD failed (rc=$rc)"
+ exit $OCF_ERR_GENERIC
+ fi
+
+ add_interface "$ipaddr" "$ifname" "$ifname" $netmask_text $broadcast
+ rm -f "$VLDIR/$ipaddr"
+}
+
+#
+# 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 | $AWK '{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 $OCF_SUCCESS;;
+ $ipaddr) echo $ifname; return $OCF_SUCCESS;;
+ esac
+ done
+ return $OCF_ERR_GENERIC
+}
+
+find_interface_bsd() {
+ $IFCONFIG $IFCONFIG_A_OPT | awk -v ip_addr="$ipaddr" '
+ /UP,/ && $0 ~ /^[a-z]+[0-9]:/ {
+ if_name=$1; sub(":$","",if_name);
+ }
+ $1 == "inet" && $2 == ip_addr {
+ print if_name
+ exit(0)
+ }'
+
+}
+
+#
+# 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
+ *:*) ifname=`echo $ifname | sed 's/:$//'`;;
+ *) continue;;
+ esac
+
+ : "comparing $ipaddr to $addr (from ifconfig)"
+ case $addr in
+ addr:$ipaddr) echo $ifname; return $OCF_SUCCESS;;
+ $ipaddr) echo $ifname; return $OCF_SUCCESS;;
+ esac
+ done
+ return $OCF_ERR_GENERIC
+}
+
+#
+# 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() {
+ ipaddr="$1"
+ case "$SYSTYPE" in
+ SunOS)
+ NIC=`find_interface_solaris $ipaddr`;;
+ *BSD)
+ NIC=`find_interface_bsd $ipaddr`;;
+ *)
+ NIC=`find_interface_generic $ipaddr`;;
+ esac
+
+ echo $NIC
+ return $OCF_SUCCESS;
+}
+
+#
+# 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() {
+ NIC="$1"
+
+ if [ "X$NIC" = "X" ]; then
+ ocf_log err "No free interface found for $OCF_RESKEY_ip"
+ return $OCF_ERR_GENERIC;
+ fi
+
+ NICBASE="$VLDIR/IPaddr-$NIC"
+ touch "$NICBASE"
+
+ case "$SYSTYPE" in
+ *BSD)
+ echo $NIC;
+ return $OCF_SUCCESS;;
+ SunOS)
+ j=1
+ IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \
+ grep "^$NIC:[0-9]" | sed 's%: .*%%'`;;
+ *)
+ j=0
+ IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \
+ grep "^$NIC:[0-9]" | sed 's% .*%%'`
+ TRYADRCNT=`ls "${NICBASE}:"* 2>/dev/null | wc -w | tr -d ' '`
+ if [ -f "${NICBASE}:${TRYADRCNT}" ]; then
+ : OK
+ else
+ j="${TRYADRCNT}"
+ fi
+ ;;
+ esac
+
+ IFLIST=" `echo $IFLIST` "
+ while
+ [ $j -lt 512 ]
+ do
+ case $IFLIST in
+ *" "$NIC:$j" "*)
+ ;;
+ *)
+ NICLINK="$NICBASE:$j"
+ if
+ ln "$NICBASE" "$NICLINK" 2>/dev/null
+ then
+ echo "$NIC:$j"
+ return $OCF_SUCCESS
+ fi
+ ;;
+ esac
+ j=`expr $j + 1`
+ done
+ return $OCF_ERR_GENERIC
+}
+
+delete_route () {
+ ipaddr="$1"
+
+ case "$SYSTYPE" in
+ SunOS) return 0;;
+ *BSD) CMD="$ROUTE -n delete -host $ipaddr";;
+ *) CMD="$ROUTE -n del -host $ipaddr";;
+ esac
+
+ $CMD
+
+ return $?
+}
+
+delete_interface () {
+ ifname="$1"
+ ipaddr="$2"
+
+ case "$SYSTYPE" in
+ SunOS)
+ if [ "$SYSVERSION" -ge 8 ] ; then
+ CMD="$IFCONFIG $ifname unplumb"
+ else
+ CMD="$IFCONFIG $ifname 0 down"
+ fi;;
+ Darwin*)
+ CMD="$IFCONFIG $ifname $ipaddr delete";;
+ *BSD)
+ CMD="$IFCONFIG $ifname inet $ipaddr delete";;
+ *)
+ CMD="$IFCONFIG $ifname down";;
+ esac
+
+ ocf_log info "$CMD"
+ $CMD
+
+ return $?
+}
+
+
+add_interface () {
+ ipaddr="$1"
+ iface_base="$2"
+ iface="$3"
+ netmask="$4"
+ broadcast="$5"
+
+ if [ $# != 5 ]; then
+ ocf_log err "Insufficient arguments to add_interface: $*"
+ exit $OCF_ERR_ARGS
+ fi
+
+ 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
+ # At Solaris 10, this single-command version sometimes broke.
+ # Almost certainly an S10 bug.
+ # CMD="$IFCONFIG $iface inet $ipaddr $text up"
+ # So hack the following workaround:
+ CMD="$IFCONFIG $iface inet $ipaddr"
+ CMD="$CMD && $IFCONFIG $iface netmask $netmask"
+ CMD="$CMD && $IFCONFIG $iface up"
+ ;;
+
+ *BSD)
+ # netmask is always set to 255.255.255.255 for an alias
+ CMD="$IFCONFIG $iface inet $ipaddr netmask 255.255.255.255 alias";;
+ *)
+ CMD="$IFCONFIG $iface $ipaddr netmask $netmask broadcast $broadcast";;
+ esac
+
+ # Use "eval $CMD" (not "$CMD"): it might be a chain of two or more commands.
+ ocf_log info "eval $CMD"
+ eval $CMD
+ rc=$?
+ if [ $rc != 0 ]; then
+ echo "ERROR: eval $CMD failed (rc=$rc)"
+ fi
+
+ return $rc
+}
+
+#
+# Remove the IP alias for the requested IP address...
+#
+ip_stop() {
+ SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+ NIC=`find_interface $OCF_RESKEY_ip`
+
+ if [ -f "$SENDARPPIDFILE" ]; then
+ cat "$SENDARPPIDFILE" | xargs kill
+ rm -f "$SENDARPPIDFILE"
+ fi
+
+ if [ -z "$NIC" ]; then
+ : Requested interface not in use
+ return $OCF_SUCCESS
+ fi
+
+ if [ ${OCF_RESKEY_lvs_support} = 1 ]; then
+ case $NIC in
+ lo*)
+ : Requested interface is on loopback
+ return $OCF_SUCCESS;;
+ esac
+ fi
+
+ delete_route "$OCF_RESKEY_ip"
+ delete_interface "$NIC" "$OCF_RESKEY_ip"
+ rc=$?
+
+ if [ ${OCF_RESKEY_lvs_support} = 1 ]; then
+ lvs_restore_loopback "$OCF_RESKEY_ip"
+ fi
+
+ # remove lock file...
+ rm -f "$VLDIR/IPaddr-$NIC"
+
+ if [ $rc != 0 ]; then
+ ocf_log warn "IP Address $OCF_RESKEY_ip NOT released: rc=$rc"
+ return $OCF_ERR_GENERIC
+ fi
+ return $OCF_SUCCESS
+}
+
+
+#
+# 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?
+ #
+ ip_status_internal
+ if [ $? = $OCF_SUCCESS ]; then
+ # Nothing to do, the IP is already active
+ return $OCF_SUCCESS;
+ fi
+
+ NIC_unique=`find_free_interface $OCF_RESKEY_nic`
+ if [ -n "$NIC_unique" ]; then
+ : OK got interface [$NIC_unique] for $OCF_RESKEY_ip
+ else
+ return $OCF_ERR_GENERIC
+ fi
+
+ # This logic is mostly to support LVS (If I understand it correctly)
+ if [ ${OCF_RESKEY_lvs_support} = 1 ]; then
+ NIC_current=`find_interface $OCF_RESKEY_ip`
+ case $NIC_unique in
+ lo*)
+ if [ x"$NIC_unique" = x"$NIC_current" ]; then
+ # Its already "running" and not moving, nothing to do.
+ ocf_log err "Could not find a non-loopback device to move $OCF_RESKEY_ip to"
+ return $OCF_ERR_GENERIC
+ fi;;
+ *) lvs_remove_conflicting_loopback "$OCF_RESKEY_ip" "$NIC_current";;
+ esac
+ fi
+
+ if [ ! -z "${OCF_RESKEY_local_start_script}" ]; then
+ if [ -x "${OCF_RESKEY_local_start_script}" ]; then
+ ${OCF_RESKEY_local_start_script} $*
+ fi
+ fi
+
+ add_interface "$OCF_RESKEY_ip" "$OCF_RESKEY_nic" "$NIC_unique" \
+ "$OCF_RESKEY_cidr_netmask" "$OCF_RESKEY_broadcast"
+ rc=$?
+ if [ $rc != 0 ]; then
+ ocf_log err "Could not add $OCF_RESKEY_ip to $OCF_RESKEY_nic: rc=$rc"
+ return $rc
+ fi
+
+ # The address is active, now notify others about it using sendarp
+
+ if [ "$SYSTYPE" = "DarwinBSD" -a "$NIC_unique" = "lo0" ]; then
+ # Darwin can't send ARPs on loopback devices
+ SENDARP="x$SENDARP" # Prevent the binary from being found
+ fi
+
+ if [ -x $SENDARP ]; then
+ TARGET_INTERFACE=`echo $NIC_unique | sed 's%:.*%%'`
+ SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+
+ ARGS="-i $OCF_RESKEY_ARP_INTERVAL_MS -r $OCF_RESKEY_ARP_REPEAT"
+ ARGS="$ARGS -p $SENDARPPIDFILE $TARGET_INTERFACE $OCF_RESKEY_ip"
+ ARGS="$ARGS auto $OCF_RESKEY_ip $OCF_RESKEY_ARP_NETMASK"
+
+ ocf_log debug "Sending Gratuitous Arp for $OCF_RESKEY_ip on $NIC_unique [$TARGET_INTERFACE]"
+ case $OCF_RESKEY_ARP_BACKGROUND in
+ yes) ($SENDARP $ARGS || ocf_log err "Could not send gratuitous arps. rc=$?" & ) >&2 ;;
+ *) $SENDARP $ARGS || ocf_log err "Could not send gratuitous arps. rc=$?";;
+ esac
+ fi
+
+ ip_status_internal
+ return $?
+}
+
+ip_status_internal() {
+ NIC=`find_interface "$OCF_RESKEY_ip"`
+
+ if [ "x$NIC" = x ]; then
+ return $OCF_NOT_RUNNING
+
+ elif [ "${OCF_RESKEY_lvs_support}" = "1" ]; then
+ case $NIC in
+ lo*) return $OCF_NOT_RUNNING;;
+ *) return $OCF_SUCCESS;;
+ esac
+ else
+ if [ x$OCF_RESKEY_nic != x ]; then
+ simple_OCF_NIC=`echo $OCF_RESKEY_nic | awk -F: '{print $1}'`
+ simple_NIC=`echo $NIC | awk -F: '{print $1}'`
+ if [ $simple_OCF_NIC != $simple_NIC ]; then
+ ocf_log err "$OCF_RESKEY_ip is running an interface ($simple_NIC) instead of the configured one ($simple_OCF_NIC)"
+ return $OCF_ERR_GENERIC
+ fi
+ fi
+ return $OCF_SUCCESS
+ fi
+}
+
+ip_status() {
+ ip_status_internal
+ rc=$?
+ if [ $rc = $OCF_SUCCESS ]; then
+ echo "running"
+ elif [ $rc = $OCF_NOT_RUNNING ]; then
+ echo "stopped"
+ else
+ echo "unknown"
+ fi
+ return $rc;
+}
+
+#
+# Determine if this IP address is really being served, or not.
+# Note that we must distinguish if *we're* serving it locally...
+#
+ip_monitor() {
+ ip_status_internal
+ rc=$?
+
+ if [ $OCF_CHECK_LEVEL = 0 -o $rc != 0 ]; then
+ return $rc
+ fi
+
+ ocf_log info "Checking IP stack"
+
+ PINGARGS="`pingargs $OCF_RESKEY_ip`"
+ for j in 1 2 3 4 5 6 7 8 9 10; do
+ MSG=`$PING $PINGARGS 2>&1`
+ if [ $? = 0 ]; then
+ return $OCF_SUCCESS
+ fi
+ done
+
+ ocf_log err "$MSG"
+ return $OCF_ERR_GENERIC
+}
+
+is_positive_integer() {
+ ocf_is_decimal $1 && [ $1 -ge 1 ]
+ if [ $? = 0 ]; then
+ return 1
+ fi
+ return 0
+}
+
+ip_validate_all() {
+ check_binary $AWK
+ check_binary $IFCONFIG
+ check_binary $ROUTE
+ check_binary $PING
+
+ if is_positive_integer $OCF_RESKEY_ARP_INTERVAL_MS
+ then
+ ocf_log err "Invalid parameter value: ARP_INTERVAL_MS [$OCF_RESKEY_ARP_INTERVAL_MS]"
+ return $OCF_ERR_ARGS
+ fi
+
+ if is_positive_integer $OCF_RESKEY_ARP_REPEAT
+ then
+ ocf_log err "Invalid parameter value: ARP_REPEAT [$OCF_RESKEY_ARP_REPEAT]"
+ return $OCF_ERR_ARGS
+ fi
+
+ if [ "$SYSTYPE" = "Linux" -o "$SYSTYPE" = "SunOS" ]; then
+ :
+ else
+ if [ "${OCF_RESKEY_lvs_support}" = "1" ]; then
+ ocf_log err "$SYSTYPE does not support LVS"
+ return $OCF_ERR_GENERIC
+ fi
+ fi
+
+ case $OCF_RESKEY_ip in
+ "") ocf_log err "Required parameter OCF_RESKEY_ip is missing"
+ return $OCF_ERR_CONFIGURED;;
+ [0-9]*.[0-9]*.[0-9]*.*[0-9]) : OK;;
+ *) ocf_log err "Parameter OCF_RESKEY_ip [$OCF_RESKEY_ip] not an IP address"
+ return $OCF_ERR_CONFIGURED;;
+ esac
+
+ # Unconditionally do this?
+ case $OCF_RESKEY_nic in
+ *:*)
+ OCF_RESKEY_nic=`echo $OCF_RESKEY_nic | sed 's/:.*//'`
+ ;;
+ esac
+
+ NICINFO=`$FINDIF`
+ rc=$?
+
+ if [ $rc != 0 ]; then
+ ocf_log err "$FINDIF failed [rc=$rc]."
+ return $OCF_ERR_GENERIC
+ fi
+
+ tmp=`echo "$NICINFO" | cut -f1`
+ if
+ [ "x$OCF_RESKEY_nic" = "x" ]
+ then
+ ocf_log info "Using calculated nic for ${OCF_RESKEY_ip}: $tmp"
+ OCF_RESKEY_nic=$tmp
+ elif
+ [ x$tmp != x${OCF_RESKEY_nic} ]
+ then
+ ocf_log err "Invalid parameter value: nic [$OCF_RESKEY_nic] Calculated nic: [$tmp]"
+ return $OCF_ERR_ARGS
+ fi
+
+ tmp=`echo "$NICINFO" | cut -f2 | cut -d ' ' -f2`
+ if
+ [ "x$OCF_RESKEY_cidr_netmask" != "x$tmp" ]
+ then
+ ocf_log info "Using calculated netmask for ${OCF_RESKEY_ip}: $tmp"
+ fi
+
+ # Always use the calculated version becuase it might have been specified
+ # using CIDR notation which not every system accepts
+ OCF_RESKEY_netmask=$tmp
+ OCF_RESKEY_cidr_netmask=$tmp; export OCF_RESKEY_cidr_netmask
+
+ tmp=`echo "$NICINFO" | cut -f3 | cut -d ' ' -f2`
+ if
+ [ "x$OCF_RESKEY_broadcast" = "x" ]
+ then
+ ocf_log debug "Using calculated broadcast for ${OCF_RESKEY_ip}: $tmp"
+ OCF_RESKEY_broadcast=$tmp
+
+ elif [ x$tmp != x${OCF_RESKEY_broadcast} ]; then
+ ocf_log err "Invalid parameter value: broadcast [$OCF_RESKEY_broadcast] Calculated broadcast: [$tmp]"
+ return $OCF_ERR_ARGS
+ fi
+
+ return $OCF_SUCCESS
+}
+
+usage() {
+ echo $USAGE >&2
+ return $1
+}
+
+if [ $# -ne 1 ]; then
+ usage $OCF_ERR_ARGS
+fi
+
+# Normalize the value of lvs_support
+if [ "${OCF_RESKEY_lvs_support}" = "true" \
+ -o "${OCF_RESKEY_lvs_support}" = "on" \
+ -o "${OCF_RESKEY_lvs_support}" = "yes" \
+ -o "${OCF_RESKEY_lvs_support}" = "1" ]; then
+ OCF_RESKEY_lvs_support=1
+else
+ OCF_RESKEY_lvs_support=0
+fi
+
+# Note: We had a version out there for a while which used
+# netmask instead of cidr_netmask. So, don't remove this aliasing code!
+if
+ [ ! -z "$OCF_RESKEY_netmask" -a -z "$OCF_RESKEY_cidr_netmask" ]
+then
+ OCF_RESKEY_cidr_netmask=$OCF_RESKEY_netmask
+ export OCF_RESKEY_cidr_netmask
+fi
+
+case $1 in
+ meta-data) meta_data;;
+ start) ip_validate_all && ip_start;;
+ stop) ip_stop;;
+ status) ip_status;;
+ monitor) ip_monitor;;
+ validate-all) ip_validate_all;;
+ usage) usage $OCF_SUCCESS;;
+ *) usage $OCF_ERR_UNIMPLEMENTED;;
+esac
+
+exit $?