#!/bin/sh
# script to manage the lvs ip multiplexer for a single public address cluster
-. $CTDB_BASE/functions
+[ -n "$CTDB_BASE" ] || \
+ CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
+
+. "${CTDB_BASE}/functions"
loadconfig ctdb
-[ -z "$CTDB_LVS_PUBLIC_IP" ] && exit 0
-[ -z "$CTDB_PUBLIC_INTERFACE" ] && exit 0
+[ -n "$CTDB_LVS_NODES" ] || exit 0
+export CTDB_LVS_NODES
+
+if ! type ipvsadm >/dev/null 2>&1 ; then
+ echo "LVS configured but ipvsadm not found"
+ exit 0
+fi
+
+
+lvs_slave_only ()
+{
+ ctdb_get_ip_address
+
+ awk -v my_ip="$ip_address" \
+ '$1 == my_ip { if ($2 ~ "slave-only") { exit 0 } else { exit 1 } }' \
+ "$CTDB_LVS_NODES"
+}
-[ -x /sbin/ipvsadm ] || {
- echo "LVS configured but /sbin/ipvsadm is not installed."
- exit 0
+lvs_check_config ()
+{
+ [ -r "$CTDB_LVS_NODES" ] || \
+ die "error: CTDB_LVS_NODES=${CTDB_LVS_NODES} unreadable"
+ [ -n "$CTDB_LVS_PUBLIC_IP" ] || \
+ die "Invalid configuration: CTDB_LVS_PUBLIC_IP not set"
+ if ! lvs_slave_only ; then
+ [ -n "$CTDB_LVS_PUBLIC_IFACE" ] || \
+ die "Invalid configuration: CTDB_LVS_PUBLIC_IFACE not set"
+ fi
+
+ if [ "$CTDB_PARTIALLY_ONLINE_INTERFACES" = "yes" ] ; then
+ die "Invalid configuration: CTDB_PARTIALLY_ONLINE_INTERFACES=yes incompatible with LVS"
+ fi
}
-case $cmd in
- startup)
- ipvsadm -D -t $CTDB_LVS_PUBLIC_IP:0
- ipvsadm -D -u $CTDB_LVS_PUBLIC_IP:0
+case "$1" in
+setup)
+ lvs_check_config
+ ;;
+startup)
+ lvs_check_config
+
+ ipvsadm -D -t "$CTDB_LVS_PUBLIC_IP" >/dev/null 2>&1
+ ipvsadm -D -u "$CTDB_LVS_PUBLIC_IP" >/dev/null 2>&1
- ip addr add $CTDB_LVS_PUBLIC_IP/32 dev lo scope host >/dev/null 2>/dev/null
+ ip addr add "${CTDB_LVS_PUBLIC_IP}/32" dev lo scope host
# do not respond to ARPs that are for ip addresses with scope 'host'
- echo 3 > /proc/sys/net/ipv4/conf/all/arp_ignore
+ set_proc_maybe sys/net/ipv4/conf/all/arp_ignore 3
# do not send out arp requests from loopback addresses
- echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
+ set_proc_maybe sys/net/ipv4/conf/all/arp_announce 2
;;
- shutdown)
- ipvsadm -D -t $CTDB_LVS_PUBLIC_IP:0
- ipvsadm -D -u $CTDB_LVS_PUBLIC_IP:0
+shutdown)
+ lvs_check_config
+
+ ipvsadm -D -t "$CTDB_LVS_PUBLIC_IP"
+ ipvsadm -D -u "$CTDB_LVS_PUBLIC_IP"
- # remove the ip
- ip addr del $CTDB_LVS_PUBLIC_IP/32 dev lo >/dev/null 2>/dev/null
+ ip addr del "${CTDB_LVS_PUBLIC_IP}/32" dev lo >/dev/null 2>&1
- # flush our route cache
- echo 1 > /proc/sys/net/ipv4/route/flush
+ flush_route_cache
;;
- recovered|stopped)
- # kill off any tcp connections
- ipvsadm -D -t $CTDB_LVS_PUBLIC_IP:0
- ipvsadm -D -u $CTDB_LVS_PUBLIC_IP:0
- kill_tcp_connections_local_only $CTDB_LVS_PUBLIC_IP
-
- PNN=`ctdb pnn | sed -e "s/.*PNN://"`
- LVSMASTER=`ctdb lvsmaster | sed -e "s/.*Node //" -e "s/ .*//"`
-
- [ "$PNN" != "$LVSMASTER" ] && {
- # we are not the lvs master so we have to
- # change the ip address to have scope host so we wont respond
- # to arps
- ip addr del $CTDB_LVS_PUBLIC_IP/32 dev lo >/dev/null 2>/dev/null
- ip addr add $CTDB_LVS_PUBLIC_IP/32 dev lo scope host >/dev/null 2>/dev/null
+ipreallocated)
+ lvs_check_config
+
+ # Kill connections
+ ipvsadm -D -t "$CTDB_LVS_PUBLIC_IP" >/dev/null 2>&1
+ ipvsadm -D -u "$CTDB_LVS_PUBLIC_IP" >/dev/null 2>&1
+ kill_tcp_connections_local_only \
+ "$CTDB_LVS_PUBLIC_IFACE" "$CTDB_LVS_PUBLIC_IP"
+
+ ctdb_get_pnn
+ lvsmaster=$("${CTDB_HELPER_BINDIR}/ctdb_lvs" master)
+ if [ "$pnn" != "$lvsmaster" ] ; then
+ # This node is not the LVS master so change the IP address
+ # to have scope "host" so this node won't respond to ARPs
+ ip addr del "${CTDB_LVS_PUBLIC_IP}/32" dev lo >/dev/null 2>&1
+ ip addr add "${CTDB_LVS_PUBLIC_IP}/32" dev lo scope host
exit 0
- }
+ fi
- # change the scope so we start responding to arps
- ip addr del $CTDB_LVS_PUBLIC_IP/32 dev lo >/dev/null 2>/dev/null
- ip addr add $CTDB_LVS_PUBLIC_IP/32 dev lo >/dev/null 2>/dev/null
+ # Change the scope so this node starts responding to ARPs
+ ip addr del "${CTDB_LVS_PUBLIC_IP}/32" dev lo >/dev/null 2>&1
+ ip addr add "${CTDB_LVS_PUBLIC_IP}/32" dev lo >/dev/null 2>&1
- ipvsadm -A -t $CTDB_LVS_PUBLIC_IP:0 -p 9999 -s lc
- ipvsadm -A -u $CTDB_LVS_PUBLIC_IP:0 -p 9999 -s lc
+ ipvsadm -A -t "$CTDB_LVS_PUBLIC_IP" -p 1999999 -s lc
+ ipvsadm -A -u "$CTDB_LVS_PUBLIC_IP" -p 1999999 -s lc
- # add all nodes (except ourselves) to the lvs config
- ctdb lvs | egrep -v "^$PNN:" | sed -e "s/.*://" | while read IP; do
- ipvsadm -a -t $CTDB_LVS_PUBLIC_IP:0 -r $IP -g
- ipvsadm -a -u $CTDB_LVS_PUBLIC_IP:0 -r $IP -g
+ # Add all nodes (except this node) as LVS servers
+ "${CTDB_HELPER_BINDIR}/ctdb_lvs" list |
+ awk -v pnn="$pnn" '$1 != pnn { print $2 }' |
+ while read ip ; do
+ ipvsadm -a -t "$CTDB_LVS_PUBLIC_IP" -r "$ip" -g
+ ipvsadm -a -u "$CTDB_LVS_PUBLIC_IP" -r "$ip" -g
done
- # and add the localhost too
- ipvsadm -a -t $CTDB_LVS_PUBLIC_IP:0 -r 127.0.0.1
- ipvsadm -a -u $CTDB_LVS_PUBLIC_IP:0 -r 127.0.0.1
- # send out a gratious arp so our peers will update their arp tables
- ctdb gratiousarp $CTDB_LVS_PUBLIC_IP $CTDB_PUBLIC_INTERFACE >/dev/null 2>/dev/null
+ # Add localhost too...
+ ipvsadm -a -t "$CTDB_LVS_PUBLIC_IP" -r 127.0.0.1
+ ipvsadm -a -u "$CTDB_LVS_PUBLIC_IP" -r 127.0.0.1
- # flush our route cache
- echo 1 > /proc/sys/net/ipv4/route/flush
+ $CTDB gratiousarp \
+ "$CTDB_LVS_PUBLIC_IP" "$CTDB_LVS_PUBLIC_IFACE" >/dev/null 2>&1
+
+ flush_route_cache
;;
+monitor)
+ lvs_check_config
+
+ if [ -n "$CTDB_LVS_PUBLIC_IFACE" ] ; then
+ interface_monitor "$CTDB_LVS_PUBLIC_IFACE" || exit 1
+ fi
+ ;;
esac
exit 0