param: remove two unused #defines
[Samba.git] / ctdb / config / events.d / 10.interface
blob51d1b974dcf29032d81c35c766d78305ddaefab4
1 #!/bin/sh
3 #################################
4 # interface event script for ctdb
5 # this adds/removes IPs from your
6 # public interface
8 [ -n "$CTDB_BASE" ] || \
9 export CTDB_BASE=$(cd -P $(dirname "$0") ; dirname "$PWD")
11 . $CTDB_BASE/functions
12 loadconfig
14 [ -z "$CTDB_PUBLIC_ADDRESSES" ] && {
15 CTDB_PUBLIC_ADDRESSES=$CTDB_BASE/public_addresses
18 [ ! -f "$CTDB_PUBLIC_ADDRESSES" ] && {
19 if [ "$1" = "init" ]; then
20 echo "No public addresses file found. Nothing to do for 10.interfaces"
22 exit 0
25 mark_up ()
27 up_interfaces_found=true
28 ctdb setifacelink $1 up >/dev/null 2>&1
31 mark_down ()
33 fail=true
34 ctdb setifacelink $1 down >/dev/null 2>&1
37 # This sets $all_interfaces as a side-effect.
38 get_all_interfaces ()
40 # Get all the interfaces listed in the public_addresses file
41 all_interfaces=$(sed -e "s/^[^\t ]*[\t ]*//" -e "s/,/ /g" -e "s/[\t ]*$//" $CTDB_PUBLIC_ADDRESSES)
43 # Add some special interfaces if they're defined
44 [ "$CTDB_PUBLIC_INTERFACE" ] && all_interfaces="$CTDB_PUBLIC_INTERFACE $all_interfaces"
45 [ "$CTDB_NATGW_PUBLIC_IFACE" ] && all_interfaces="$CTDB_NATGW_PUBLIC_IFACE $all_interfaces"
47 # Get the interfaces for which CTDB has public IPs configured.
48 # That is, for all but the 1st line, get the 1st field.
49 ctdb_ifaces=$(ctdb -X ifaces | sed -e '1d' -e 's@^|@@' -e 's@|.*@@')
51 # Add $ctdb_interfaces and uniquify
52 all_interfaces=$(echo $all_interfaces $ctdb_ifaces | tr ' ' '\n' | sort -u)
55 monitor_interfaces()
57 get_all_interfaces
59 fail=false
60 up_interfaces_found=false
62 # Note that this loop must not exit early. It must process
63 # all interfaces so that the correct state for each interface
64 # is set in CTDB using mark_up/mark_down. If there is a
65 # problem with an interface then set fail=true and continue.
66 for iface in $all_interfaces ; do
68 ip link show $iface 2>/dev/null >/dev/null || {
69 echo "ERROR: Interface $iface does not exist but it is used by public addresses."
70 mark_down $iface
71 continue
74 # These interfaces are sometimes bond devices
75 # When we use VLANs for bond interfaces, there will only
76 # be an entry in /proc for the underlying real interface
77 realiface=`echo $iface |sed -e 's/\..*$//'`
78 bi=$(get_proc "net/bonding/$realiface" 2>/dev/null) && {
79 echo "$bi" | grep -q 'Currently Active Slave: None' && {
80 echo "ERROR: No active slaves for bond device $realiface"
81 mark_down $iface
82 continue
84 echo "$bi" | grep -q '^MII Status: up' || {
85 echo "ERROR: public network interface $realiface is down"
86 mark_down $iface
87 continue
89 echo "$bi" | grep -q '^Bonding Mode: IEEE 802.3ad Dynamic link aggregation' && {
90 # This works around a bug in the driver where the
91 # overall bond status can be up but none of the actual
92 # physical interfaces have a link.
93 echo "$bi" | grep 'MII Status:' | tail -n +2 | grep -q '^MII Status: up' || {
94 echo "ERROR: No active slaves for 802.ad bond device $realiface"
95 mark_down $iface
96 continue
99 mark_up $iface
100 continue
103 case $iface in
104 lo*)
105 # loopback is always working
106 mark_up $iface
108 ib*)
109 # we dont know how to test ib links
110 mark_up $iface
113 ethtool $iface | grep -q 'Link detected: yes' || {
114 # On some systems, this is not successful when a
115 # cable is plugged but the interface has not been
116 # brought up previously. Bring the interface up
117 # and try again...
118 ip link set $iface up
119 ethtool $iface | grep -q 'Link detected: yes' || {
120 echo "ERROR: No link on the public network interface $iface"
121 mark_down $iface
122 continue
125 mark_up $iface
127 esac
129 done
131 $fail || return 0
133 $up_interfaces_found && \
134 [ "$CTDB_PARTIALLY_ONLINE_INTERFACES" = "yes" ] && \
135 return 0
137 return 1
140 # Sets: iface, ip, maskbits, family
141 get_iface_ip_maskbits_family ()
143 _iface_in="$1"
144 ip="$2"
145 _maskbits_in="$3"
147 set -- $(ip_maskbits_iface "$ip")
148 if [ -n "$1" ] ; then
149 maskbits="$1"
150 iface="$2"
151 family="$3"
153 if [ "$iface" != "$_iface_in" ] ; then
154 printf \
155 'WARNING: Public IP %s hosted on interface %s but VNN says %s\n' \
156 "$ip" "$iface" "$_iface_in"
158 if [ "$maskbits" != "$_maskbits_in" ] ; then
159 printf \
160 'WARNING: Public IP %s has %s bit netmask but VNN says %s\n' \
161 "$ip" "$maskbits" "$_maskbits_in"
163 else
164 die "ERROR: Unable to determine interface for IP ${ip}"
168 ctdb_check_args "$@"
170 case "$1" in
171 #############################
172 # called when ctdbd starts up
173 init)
174 # make sure that we only respond to ARP messages from the NIC where
175 # a particular ip address is associated.
176 get_proc sys/net/ipv4/conf/all/arp_filter >/dev/null 2>&1 && {
177 set_proc sys/net/ipv4/conf/all/arp_filter 1
180 _promote="sys/net/ipv4/conf/all/promote_secondaries"
181 get_proc "$_promote" >/dev/null 2>&1 || \
182 die "Public IPs only supported if promote_secondaries is available"
185 #############################
186 # called after ctdbd has done its initial recovery
187 # and we start the services to become healthy
188 startup)
189 monitor_interfaces
193 ################################################
194 # called when ctdbd wants to claim an IP address
195 takeip)
196 iface=$2
197 ip=$3
198 maskbits=$4
200 add_ip_to_iface $iface $ip $maskbits || {
201 exit 1;
204 # cope with the script being killed while we have the interface blocked
205 case "$ip" in
206 *:*) family="inet6" ;;
207 *) family="inet" ;;
208 esac
209 iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
211 flush_route_cache
215 ##################################################
216 # called when ctdbd wants to release an IP address
217 releaseip)
218 # releasing an IP is a bit more complex than it seems. Once the IP
219 # is released, any open tcp connections to that IP on this host will end
220 # up being stuck. Some of them (such as NFS connections) will be unkillable
221 # so we need to use the killtcp ctdb function to kill them off. We also
222 # need to make sure that no new connections get established while we are
223 # doing this! So what we do is this:
224 # 1) firewall this IP, so no new external packets arrive for it
225 # 2) use netstat -tn to find existing connections, and kill them
226 # 3) remove the IP from the interface
227 # 4) remove the firewall rule
228 shift
229 get_iface_ip_maskbits_family "$@"
231 # we do an extra delete to cope with the script being killed
232 iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
233 iptables_wrapper $family -I INPUT -i $iface -d $ip -j DROP
234 kill_tcp_connections $ip
236 delete_ip_from_iface $iface $ip $maskbits || {
237 iptables_wrapper $family \
238 -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
239 exit 1
242 iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
244 flush_route_cache
247 ##################################################
248 # called when ctdbd wants to update an IP address
249 updateip)
250 # moving an IP is a bit more complex than it seems.
251 # First we drop all traffic on the old interface.
252 # Then we try to add the ip to the new interface and before
253 # we finally remove it from the old interface.
255 # 1) firewall this IP, so no new external packets arrive for it
256 # 2) remove the IP from the old interface (and new interface, to be sure)
257 # 3) add the IP to the new interface
258 # 4) remove the firewall rule
259 # 5) use ctdb gratiousarp to propagate the new mac address
260 # 6) use netstat -tn to find existing connections, and tickle them
261 _oiface=$2
262 niface=$3
263 _ip=$4
264 _maskbits=$5
266 get_iface_ip_maskbits_family "$_oiface" "$ip" "$maskbits"
267 oiface="$iface"
269 # we do an extra delete to cope with the script being killed
270 iptables_wrapper $family -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
271 iptables_wrapper $family -I INPUT -i $oiface -d $ip -j DROP
273 delete_ip_from_iface $oiface $ip $maskbits 2>/dev/null
274 delete_ip_from_iface $niface $ip $maskbits 2>/dev/null
276 add_ip_to_iface $niface $ip $maskbits || {
277 iptables_wrapper $family \
278 -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
279 exit 1
282 # cope with the script being killed while we have the interface blocked
283 iptables_wrapper $family -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
285 flush_route_cache
287 # propagate the new mac address
288 ctdb gratiousarp $ip $niface
290 # tickle all existing connections, so that dropped packets
291 # are retransmited and the tcp streams work
293 tickle_tcp_connections $ip
297 monitor)
298 monitor_interfaces || exit 1
301 ctdb_standard_event_handler "$@"
303 esac
305 exit 0