summaryrefslogtreecommitdiffstats
path: root/ctdb/config/events/legacy/91.lvs.script
blob: 885506873a0b3c0cd3acec015e57a232a628a922 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/bin/sh
# script to manage the lvs ip multiplexer for a single public address cluster

[ -n "$CTDB_BASE" ] || \
	CTDB_BASE=$(d=$(dirname "$0") && cd -P "$d" && dirname "$PWD")

. "${CTDB_BASE}/functions"

load_script_options

[ -n "$CTDB_LVS_NODES" ] || exit 0
export CTDB_LVS_NODES

# type is commonly supported and more portable than which(1)
# shellcheck disable=SC2039
if ! type ipvsadm >/dev/null 2>&1 ; then
	echo "LVS configured but ipvsadm not found"
	exit 0
fi


lvs_follower_only ()
{
	_ip_address=$(ctdb_get_ip_address)
	awk -v my_ip="$_ip_address" \
	    '$1 == my_ip { if ($2 ~ "follower-only") { exit 0 } else { exit 1 } }' \
	    "$CTDB_LVS_NODES"
}

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_follower_only ; then
		[ -n "$CTDB_LVS_PUBLIC_IFACE" ] || \
			die "Invalid configuration: CTDB_LVS_PUBLIC_IFACE not set"
	fi
}

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

	# do not respond to ARPs that are for ip addresses with scope 'host'
	set_proc_maybe sys/net/ipv4/conf/all/arp_ignore 3
	# do not send out arp requests from loopback addresses
	set_proc_maybe sys/net/ipv4/conf/all/arp_announce 2
	;;

shutdown)
	lvs_check_config

	ipvsadm -D -t "$CTDB_LVS_PUBLIC_IP"
	ipvsadm -D -u "$CTDB_LVS_PUBLIC_IP"

	ip addr del "${CTDB_LVS_PUBLIC_IP}/32" dev lo >/dev/null 2>&1

	flush_route_cache
	;;

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"

	pnn=$(ctdb_get_pnn)
	lvsleader=$("${CTDB_HELPER_BINDIR}/ctdb_lvs" leader)
	if [ "$pnn" != "$lvsleader" ] ; then
	    # This node is not the LVS leader 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 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" -p 1999999 -s lc
	ipvsadm -A -u "$CTDB_LVS_PUBLIC_IP" -p 1999999 -s lc

	# 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

	# 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

	$CTDB gratarp \
	     "$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