Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3154104
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
index ae2edcecf..1dcff2271 100755
--- a/heartbeat/IPsrcaddr
+++ b/heartbeat/IPsrcaddr
@@ -1,488 +1,491 @@
#!/bin/sh
#
# Description: IPsrcaddr - Preferred source address modification
#
# Author: John Sutton <john@scl.co.uk>
# Support: linux-ha@lists.linux-ha.org
# License: GNU General Public License (GPL)
# Copyright: SCL Internet
#
# Based on the IPaddr script.
#
# This script manages the preferred source address associated with
# packets which originate on the localhost and are routed through the
# default route. By default, i.e. without the use of this script or
# similar, these packets will carry the IP of the primary i.e. the
# non-aliased interface. This can be a nuisance if you need to ensure
# that such packets carry the same IP irrespective of which host in
# a redundant cluster they actually originate from.
#
# It can add a preferred source address, or remove one.
#
# usage: IPsrcaddr {start|stop|status|monitor|validate-all|meta-data}
#
# The "start" arg adds a preferred source address.
#
# Surprisingly, the "stop" arg removes it. :-)
#
# NOTES:
#
# 1) There must be one and not more than 1 default route! Mainly because
# I can't see why you should have more than one. And if there is more
# than one, we would have to box clever to find out which one is to be
# modified, or we would have to pass its identity as an argument.
#
# 2) The script depends on Alexey Kuznetsov's ip utility from the
# iproute aka iproute2 package.
#
# 3) No checking is done to see if the passed in IP address can
# reasonably be associated with the interface on which the default
# route exists. So unless you want to deliberately spoof your source IP,
# check it! Normally, I would expect that your haresources looks
# something like:
#
# nodename ip1 ip2 ... ipN IPsrcaddr::ipX
#
# where ipX is one of the ip1 to ipN.
#
# OCF parameters are as below:
# OCF_RESKEY_ipaddress
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
#######################################################################
USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
CMDSHOW="$IP2UTIL route show to exact 0.0.0.0/0"
CMDCHANGE="$IP2UTIL route change to "
SYSTYPE="`uname -s`"
usage() {
echo $USAGE >&2
}
meta_data() {
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="IPsrcaddr">
<version>1.0</version>
<longdesc lang="en">
Resource script for IPsrcaddr. It manages the preferred source address
modification.
</longdesc>
<shortdesc lang="en">Manages the preferred source address for outgoing IP packets</shortdesc>
<parameters>
<parameter name="ipaddress" unique="0" required="1">
<longdesc lang="en">
The IP address.
</longdesc>
<shortdesc lang="en">IP address</shortdesc>
<content type="string" 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).
</longdesc>
<shortdesc lang="en">Netmask</shortdesc>
<content type="string" default=""/>
</parameter>
</parameters>
<actions>
<action name="start" timeout="20s" />
<action name="stop" timeout="20s" />
<action name="monitor" depth="0" timeout="20s" interval="10" />
<action name="validate-all" timeout="5" />
<action name="meta-data" timeout="5" />
</actions>
</resource-agent>
END
}
errorexit() {
ocf_log err "$*"
exit $OCF_ERR_GENERIC
}
#
# We can distinguish 3 cases: no preferred source address, a
# preferred source address exists which matches that specified, and one
# exists but doesn't match that specified. srca_read() returns 1,0,2
# respectively.
#
# The output of route show is something along the lines of:
#
# default via X.X.X.X dev eth1 src Y.Y.Y.Y
#
# where the src clause "src Y.Y.Y.Y" may or may not be present
WS="[`echo -en ' \t'`]"
OCTET="[0-9]\{1,3\}"
IPADDR="\($OCTET\.\)\{3\}$OCTET"
SRCCLAUSE="src$WS$WS*\($IPADDR\)"
MATCHROUTE="\(.*${WS}\)\($SRCCLAUSE\)\($WS.*\|$\)"
FINDIF=$HA_BIN/findif
# findif needs that to be set
export OCF_RESKEY_ip=$OCF_RESKEY_ipaddress
srca_read() {
# Capture the default route - doublequotes prevent word splitting...
DEFROUTE="`$CMDSHOW`" || errorexit "command '$CMDSHOW' failed"
# ... so we can make sure there is only 1 default route
[ 1 -eq `echo "$DEFROUTE" | wc -l` ] || \
errorexit "more than 1 default route exists"
# But there might still be no default route
[ -z "$DEFROUTE" ] && errorexit "no default route exists"
# Sed out the source ip address if it exists
SRCIP=`echo $DEFROUTE | sed -n "s/$MATCHROUTE/\3/p"`
# and what remains after stripping out the source ip address clause
ROUTE_WO_SRC=`echo $DEFROUTE | sed "s/$MATCHROUTE/\1\5/"`
[ -z "$SRCIP" ] && return 1
[ $SRCIP = $1 ] && return 0
return 2
}
#
# Add (or change if it already exists) the preferred source address
# The exit code should conform to LSB exit codes.
#
srca_start() {
srca_read $1
ip route replace $NETWORK dev $INTERFACE src $1 || \
errorexit "command 'ip route replace $NETWORK dev $INTERFACE src $1' failed"
$CMDCHANGE $ROUTE_WO_SRC src $1 || \
errorexit "command '$CMDCHANGE $ROUTE_WO_SRC src $1' failed"
return $?
}
#
# Remove (if it exists) the preferred source address.
# If one exists but it's not the same as the one specified, that's
# an error. Maybe that's the wrong behaviour because if this fails
# then when IPaddr releases the associated interface (if there is one)
# your default route will also get dropped ;-(
# The exit code should conform to LSB exit codes.
#
srca_stop() {
srca_read $1
rc=$?
if [ $rc = 1 ]; then
# We do not have a preferred source address for now
ocf_log info "No preferred source address defined, nothing to stop"
exit $OCF_SUCCESS
fi
[ $rc = 2 ] && errorexit "The address you specified to stop does not match the preferred source address"
ip route replace $NETWORK dev $INTERFACE || \
errorexit "command 'ip route replace $NETWORK dev $INTERFACE' failed"
$CMDCHANGE $ROUTE_WO_SRC || \
errorexit "command '$CMDCHANGE $ROUTE_WO_SRC' failed"
return $?
}
srca_status() {
srca_read $1
case $? in
0) echo "OK"
return $OCF_SUCCESS;;
1) echo "No preferred source address defined"
return $OCF_NOT_RUNNING;;
2) echo "Preferred source address has incorrect value"
return $OCF_ERR_GENERIC;;
esac
}
# A not reliable IP address checking function, which only picks up those _obvious_ violations...
#
# It accepts IPv4 address in dotted quad notation, for example "192.168.1.1"
#
# 100% confidence whenever it reports "negative",
# but may get false "positive" answer.
#
CheckIP() {
ip="$1"
case $ip in
*[!0-9.]*) #got invalid char
false;;
.*|*.) #begin or end by ".", which is invalid
false;;
*..*) #consecutive ".", which is invalid
false;;
*.*.*.*.*) #four decimal dots, which is too many
false;;
*.*.*.*) #exactly three decimal dots, candidate, evaluate each field
local IFS=.
set -- $ip
if
( [ $1 -le 254 ] && [ $2 -le 254 ] && [ $3 -le 254 ] && [ $4 -le 254 ] )
then
if [ $1 -eq 127 ]; then
ocf_log err "IP address [$ip] is a loopback address, thus can not be preferred source address"
- exit $OCF_ERR_ARGS
+ exit $OCF_ERR_CONFIGURED
fi
else
true
fi
# return $OCF_SUCCESS
;;
*) #less than three decimal dots
false;;
esac
return $? # This return is unnecessary, this comment too :)
}
#
# Find out which interface or alias serves the given IP address
# The argument is an IP address, and its output
# is an (aliased) interface name (e.g., "eth0" and "eth0:0").
#
find_interface_solaris() {
$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
# 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:$BASEIP) echo $ifname; return $OCF_SUCCESS;;
$BASEIP) echo $ifname; return $OCF_SUCCESS;;
esac
done
return $OCF_ERR_GENERIC
}
#
# Find out which interface or alias serves the given IP address
# The argument is an IP address, and its output
# is an (aliased) interface name (e.g., "eth0" and "eth0:0").
#
find_interface_generic() {
$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 "$SYSTYPE" in
*BSD)
$IFCONFIG | grep "$BASEIP" -B`$IFCONFIG | grep -c inet` | grep "UP," | cut -d ":" -f 1
return 0;;
*)
: "comparing $BASEIP to $addr (from ifconfig)"
case $addr in
addr:$BASEIP) echo $ifname; return $OCF_SUCCESS;;
$BASEIP) echo $ifname; return $OCF_SUCCESS;;
esac
continue;;
esac
done
return $OCF_ERR_GENERIC
}
#
# Find out which interface or alias serves the given IP address
# The argument is an IP address, and its output
# is an (aliased) interface name (e.g., "eth0" and "eth0:0").
#
find_interface() {
case "$SYSTYPE" in
SunOS)
IF=`find_interface_solaris $BASEIP`
;;
*)
IF=`find_interface_generic $BASEIP`
;;
esac
echo $IF
return $OCF_SUCCESS;
}
ip_status() {
BASEIP="$1"
case "$SYSTYPE" in
Darwin)
# Treat Darwin the same as the other BSD variants (matched as *BSD)
SYSTYPE="${SYSTYPE}BSD"
;;
*)
;;
esac
case "$SYSTYPE" in
*BSD)
$IFCONFIG $IFCONFIG_A_OPT | grep "inet.*[: ]$BASEIP " >/dev/null 2>&1
if [ $? = 0 ]; then
return $OCF_SUCCESS
else
return $OCF_NOT_RUNNING
fi;;
Linux|SunOS)
IF=`find_interface "$BASEIP"`
# echo $IF
if [ -z "$IF" ]; then
return $OCF_NOT_RUNNING
fi
case $IF in
lo*)
ocf_log err "IP address [$BASEIP] is served by loopback, thus can not be preferred source address"
- exit $OCF_ERR_ARGS
+ exit $OCF_ERR_CONFIGURED
;;
*)return $OCF_SUCCESS;;
esac
;;
*)
if [ -z "$IF" ]; then
return $OCF_NOT_RUNNING
else
return $OCF_SUCCESS
fi;;
esac
}
srca_validate_all() {
check_binary $AWK
check_binary $IPROUTE
check_binary $IFCONFIG
# The IP address should be in good shape
if CheckIP "$ipaddress"; then
:
else
ocf_log err "Invalid IP address [$ipaddress]"
- exit $OCF_ERR_ARGS
+ exit $OCF_ERR_CONFIGURED
fi
# We should serve this IP address of course
if ip_status "$ipaddress"; then
:
else
ocf_log err "We are not serving [$ipaddress], hence can not make it a preferred source address"
- exit $OCF_ERR_ARGS
+ exit $OCF_ERR_INSTALLED
fi
}
if
( [ $# -ne 1 ] )
then
usage
exit $OCF_ERR_ARGS
fi
# These operations do not require the OCF instance parameters to be set
case $1 in
meta-data) meta_data
exit $OCF_SUCCESS
;;
usage) usage
exit $OCF_SUCCESS
;;
*)
;;
esac
if
[ -z "$OCF_RESKEY_ipaddress" ]
then
# usage
ocf_log err "Please set OCF_RESKEY_ipaddress to the preferred source IP address!"
- exit $OCF_ERR_ARGS
+ exit $OCF_ERR_CONFIGURED
fi
ipaddress="$OCF_RESKEY_ipaddress"
-INTERFACE=`$FINDIF -C |grep -o "^[^[:space:]]*"`
+findif_out=`$FINDIF -C`
+rc=$?
+[ $rc -ne 0 ] && exit $rc
+INTERFACE=`echo $findif_out | awk '{print $1}'`
NETWORK=`ip route list dev $INTERFACE scope link|grep -o '^[^ ]*'`
case $1 in
start) srca_start $ipaddress
;;
stop) srca_stop $ipaddress
;;
status) srca_status $ipaddress
;;
monitor) srca_status $ipaddress
;;
validate-all) srca_validate_all
;;
*) usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
#
# Version 0.3 2002/11/04 17:00:00 John Sutton <john@scl.co.uk>
# Name changed from IPsrcroute to IPsrcaddr and now reports errors
# using ha_log rather than on stderr.
#
# Version 0.2 2002/11/02 17:00:00 John Sutton <john@scl.co.uk>
# Changed status output to "OK" to satisfy ResourceManager's
# we_own_resource() function.
#
# Version 0.1 2002/11/01 17:00:00 John Sutton <john@scl.co.uk>
# First effort but does the job?
#
diff --git a/tools/ocft/IPsrcaddr b/tools/ocft/IPsrcaddr
index 5077e7510..51434a454 100644
--- a/tools/ocft/IPsrcaddr
+++ b/tools/ocft/IPsrcaddr
@@ -1,61 +1,61 @@
# IPsrcaddr
CONFIG
#AgentRoot /usr/lib/ocf/resource.d/heartbeat
InstallPackage iproute2
HangTimeout 20
CASE-BLOCK required_args
Var OCF_RESKEY_ipaddress=127.0.0.3
CASE-BLOCK default_status
AgentRun stop
CASE-BLOCK prepare
Include required_args
Include default_status
CASE "check base env"
Include prepare
AgentRun start OCF_SUCCESS
CASE "check base env: unset 'OCF_RESKEY_ipaddress'"
Include prepare
Unvar OCF_RESKEY_ipaddress
- AgentRun start OCF_ERR_ARGS
+ AgentRun start OCF_ERR_CONFIGURED
-CASE "check base env: set worng 'OCF_RESKEY_ipaddress'"
+CASE "check base env: set invalid 'OCF_RESKEY_ipaddress'"
Include prepare
Var OCF_RESKEY_ipaddress=not_ip_address
- AgentRun start OCF_ERR_ARGS
+ AgentRun start OCF_ERR_CONFIGURED
CASE "normal start"
Include prepare
AgentRun start OCF_SUCCESS
CASE "normal stop"
Include prepare
AgentRun start
AgentRun stop OCF_SUCCESS
CASE "double start"
Include prepare
AgentRun start
AgentRun start OCF_SUCCESS
CASE "double stop"
Include prepare
AgentRun stop OCF_SUCCESS
CASE "monitor with running"
Include prepare
AgentRun start
AgentRun monitor OCF_SUCCESS
CASE "monitor with not running"
Include prepare
AgentRun monitor OCF_NOT_RUNNING
CASE "unimplemented command"
Include prepare
AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Feb 26, 8:42 AM (23 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1465220
Default Alt Text
(14 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment