mirror of https://github.com/sipwise/heartbeat.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
841 lines
20 KiB
841 lines
20 KiB
#!/bin/sh
|
|
#
|
|
# License: GNU General Public License (GPL)
|
|
# Support: linux-ha@lists.linux-ha.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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
|
|
|
|
HA_HBCONF_DIR=${HA_DIR}
|
|
SENDARP=$HA_BIN/send_arp
|
|
FINDIF=$HA_BIN/findif
|
|
VLDIR=$HA_RSCTMP/IPaddr
|
|
SENDARPPIDDIR=$HA_RSCTMP/send_arp
|
|
SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
|
|
USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
|
|
|
|
#######################################################################
|
|
|
|
# Prevent ifconfig localization issues
|
|
unset LC_ALL; export LC_ALL
|
|
unset LANGUAGE; export LANGUAGE
|
|
LC_ALL=C; export LC_ALL
|
|
LC_MESSAGES=C; export LC_MESSAGES
|
|
|
|
. $HA_HBCONF_DIR/shellfuncs
|
|
|
|
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>
|
|
<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</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="" />
|
|
</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.
|
|
|
|
</longdesc>
|
|
<shortdesc lang="en">Network interface</shortdesc>
|
|
<content type="string" default="eth0"/>
|
|
</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=""/>
|
|
</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=""/>
|
|
</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=""/>
|
|
</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="false"/>
|
|
</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=""/>
|
|
</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=""/>
|
|
</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="500"/>
|
|
</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="10"/>
|
|
</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="yes"/>
|
|
</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="ffffffffffff"/>
|
|
</parameter>
|
|
|
|
</parameters>
|
|
|
|
<actions>
|
|
<action name="start" timeout="90" />
|
|
<action name="stop" timeout="100" />
|
|
<action name="monitor" depth="10" timeout="20s" interval="5s" start-delay="1s" />
|
|
<action name="validate-all" timeout="30s" />
|
|
<action name="meta-data" timeout="5s" />
|
|
</actions>
|
|
</resource-agent>
|
|
END
|
|
exit $OCF_SUCCESS
|
|
}
|
|
|
|
# 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
|
|
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`
|
|
then
|
|
netmask_text=`echo "$NICINFO" | cut -f2 -d " "`
|
|
broadcast=`echo "$NICINFO" | cut -f3 -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 | grep "inet.*[: ]$OCF_RESKEY_ip "
|
|
$IFCONFIG | grep "$ipaddr" -B20 | grep "UP," | tail -n 1 | cut -d ":" -f 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
|
|
|
|
: "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/$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() {
|
|
echo "In 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/$NIC"
|
|
|
|
if [ $rc != 0 ]; then
|
|
ocf_log warn "IP Address $OCF_RESKEY_ip NOT released"
|
|
fi
|
|
return $rc
|
|
}
|
|
|
|
|
|
#
|
|
# 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
|
|
|
|
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"
|
|
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=""
|
|
fi
|
|
|
|
if [ x$SENDARP != x ]; 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
|
|
if $PING $PINGARGS >/dev/null 2>&1 ; then
|
|
return $OCF_SUCCESS
|
|
fi
|
|
done
|
|
|
|
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() {
|
|
: ${OCF_RESKEY_ARP_BACKGROUND=yes}
|
|
: ${OCF_RESKEY_ARP_NETMASK=ffffffffffff}
|
|
: ${OCF_RESKEY_ARP_INTERVAL_MS=500}
|
|
: ${OCF_RESKEY_ARP_REPEAT=10}
|
|
|
|
|
|
check_binary $AWK
|
|
check_binary $IFCONFIG
|
|
check_binary $ROUTE
|
|
check_binary $PING
|
|
|
|
if
|
|
[ -d "$VLDIR/" ] || mkdir -p "$VLDIR/"
|
|
then
|
|
: Directory $VLDIR now exists
|
|
else
|
|
ocf_log err "Could not create \"$VLDIR/\"."
|
|
return $OCF_ERR_GENERIC
|
|
fi
|
|
|
|
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
|
|
|
|
: ${OCF_RESKEY_lvs_support=0}
|
|
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
|
|
|
|
: ${OCF_RESKEY_lvs_support=0}
|
|
# 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 $?
|