Remove logging of spam/errors from the 10.interfrace
[ctdb.git] / config / events.d / 10.interface
1 #!/bin/sh
2
3 #################################
4 # interface event script for ctdb
5 # this adds/removes IPs from your 
6 # public interface
7
8 . $CTDB_BASE/functions
9 loadconfig
10
11 [ -z "$CTDB_PUBLIC_ADDRESSES" ] && {
12         CTDB_PUBLIC_ADDRESSES=$CTDB_BASE/public_addresses
13 }
14
15 [ ! -f "$CTDB_PUBLIC_ADDRESSES" ] && {
16         exit 0
17 }
18
19 monitor_interfaces()
20 {
21         local INTERFACES=`cat $CTDB_PUBLIC_ADDRESSES |
22                 sed -e "s/^[^\t ]*[\t ]*//" -e "s/,/ /g" -e "s/[\t ]*$//"`
23
24         [ "$CTDB_PUBLIC_INTERFACE" ] && INTERFACES="$CTDB_PUBLIC_INTERFACE $INTERFACES"
25         [ "$CTDB_NATGW_PUBLIC_IFACE" ] && INTERFACES="$CTDB_NATGW_PUBLIC_IFACE $INTERFACES"
26
27         local IFACES=`ctdb ifaces -Y | grep -v '^:Name:LinkStatus:References:'`
28
29         local I
30         local IFACE
31
32         for I in $IFACES; do
33                 IFACE=`echo -n "$I" | cut -d ':' -f2`
34                 INTERFACES="$IFACE $INTERFACES"
35         done
36
37         INTERFACES=`for IFACE in $INTERFACES ; do echo $IFACE ; done | sort | uniq`
38
39         local fail=0
40         local ok=0
41         for IFACE in $INTERFACES ; do
42
43             ip addr show $IFACE 2>/dev/null >/dev/null || {
44                 echo Interface $IFACE does not exist but it is used by public addresses.
45                 exit 1
46             }
47
48             # These interfaces are sometimes bond devices
49             # When we use VLANs for bond interfaces, there will only
50             # be an entry in /proc for the underlying real interface
51             local REALIFACE=`echo $IFACE |sed -e 's/\..*$//'`
52             [ -f /proc/net/bonding/$REALIFACE ] && {
53                 grep -q 'Currently Active Slave: None' /proc/net/bonding/$REALIFACE && {
54                         echo "ERROR: No active slaves for bond device $REALIFACE"
55                         fail=1
56                         ctdb setifacelink $IFACE down >/dev/null 2>/dev/null
57                         continue;
58                 }
59                 grep -q '^MII Status: up' /proc/net/bonding/$REALIFACE || {
60                         echo "ERROR: public network interface $REALIFACE is down"
61                         fail=1
62                         ctdb setifacelink $IFACE down >/dev/null 2>/dev/null
63                         continue;
64                 }
65                 grep -q '^Bonding Mode: IEEE 802.3ad Dynamic link aggregation' /proc/net/bonding/$REALIFACE && {
66                         grep 'MII Status:' /proc/net/bonding/$REALIFACE | tail -n +2 | grep -q '^MII Status: up' || {
67                                 echo No active slaves for 802.ad bond device $REALIFACE
68                                 ctdb setifacelink $IFACE down >/dev/null 2>/dev/null
69                                 fail=1
70                                 continue
71                         }
72                 }
73                 ok=1 # we only set ok for interfaces known to ctdbd
74                 ctdb setifacelink $IFACE up >/dev/null 2>/dev/null
75                 continue;
76             }
77
78             case $IFACE in
79             lo*)
80                 # loopback is always working
81                 ok=1 # we only set ok for interfaces known to ctdbd
82                 ctdb setifacelink $IFACE up >/dev/null 2>/dev/null
83                 ;;
84             ib*)
85                 # we dont know how to test ib links
86                 ok=1 # we only set ok for interfaces known to ctdbd
87                 ctdb setifacelink $IFACE up >/dev/null 2>/dev/null
88                 ;;
89             *)
90                 [ -z "$IFACE" ] || {
91                     [ "$(basename $(readlink /sys/class/net/$IFACE/device/driver) 2>/dev/null)" = virtio_net ] ||
92                     ethtool $IFACE | grep -q 'Link detected: yes' || {
93                         # On some systems, this is not successful when a
94                         # cable is plugged but the interface has not been
95                         # brought up previously. Bring the interface up and
96                         # try again...
97                         /sbin/ip link set $IFACE up
98                         ethtool $IFACE | grep -q 'Link detected: yes' || {
99                             echo "ERROR: No link on the public network interface $IFACE"
100                             fail=1
101                             ctdb setifacelink $IFACE down >/dev/null 2>/dev/null
102                             continue
103                         }
104                     }
105                     ok=1 # we only set ok for interfaces known to ctdbd
106                     ctdb setifacelink $IFACE up >/dev/null 2>/dev/null
107                 }
108                 ;;
109             esac
110
111         done
112
113         test x"$fail" = x"0" && {
114                 return 0;
115         }
116
117         test x"$ok" = x"1" && {
118                 return 2;
119         }
120
121         return 1;
122 }
123
124 case "$1" in 
125      #############################
126      # called when ctdbd starts up
127      init)
128         # make sure that we only respond to ARP messages from the NIC where
129         # a particular ip address is associated.
130         [ -f /proc/sys/net/ipv4/conf/all/arp_filter ] && {
131             echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
132         }
133         ;;
134
135      #############################
136      # called after ctdbd has done its initial recovery
137      # and we start the services to become healthy
138      startup)
139         # Assume all links are good initially
140         INTERFACES=`for IFACE in $INTERFACES ; do echo $IFACE ; done | sort | uniq`
141
142         for IFACE in $INTERFACES ; do
143                 ctdb setifacelink $IFACE down >/dev/null 2>/dev/null
144         done
145         
146         monitor_interfaces
147
148         ;;
149
150
151      ################################################
152      # called when ctdbd wants to claim an IP address
153      takeip)
154         if [ $# != 4 ]; then
155            echo "must supply interface, IP and maskbits"
156            exit 1
157         fi
158         iface=$2
159         ip=$3
160         maskbits=$4
161
162         add_ip_to_iface $iface $ip $maskbits || {
163                 exit 1;
164         }
165
166         # cope with the script being killed while we have the interface blocked
167         iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
168
169         # flush our route cache
170         echo 1 > /proc/sys/net/ipv4/route/flush
171         ;;
172
173
174      ##################################################
175      # called when ctdbd wants to release an IP address
176      releaseip)
177         if [ $# != 4 ]; then
178            echo "must supply interface, IP and maskbits"
179            exit 1
180         fi
181
182         # releasing an IP is a bit more complex than it seems. Once the IP
183         # is released, any open tcp connections to that IP on this host will end
184         # up being stuck. Some of them (such as NFS connections) will be unkillable
185         # so we need to use the killtcp ctdb function to kill them off. We also
186         # need to make sure that no new connections get established while we are 
187         # doing this! So what we do is this:
188         # 1) firewall this IP, so no new external packets arrive for it
189         # 2) use netstat -tn to find existing connections, and kill them 
190         # 3) remove the IP from the interface
191         # 4) remove the firewall rule
192         iface=$2
193         ip=$3
194         maskbits=$4
195
196         failed=0
197         # we do an extra delete to cope with the script being killed
198         iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
199         iptables -I INPUT -i $iface -d $ip -j DROP
200         kill_tcp_connections $ip
201
202         delete_ip_from_iface $iface $ip $maskbits || {
203                 iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
204                 exit 1;
205         }
206
207         iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
208
209         # flush our route cache
210         echo 1 > /proc/sys/net/ipv4/route/flush
211         ;;
212
213      ##################################################
214      # called when ctdbd wants to update an IP address
215      updateip)
216         if [ $# != 5 ]; then
217            echo "must supply old interface, new interface, IP and maskbits"
218            exit 1
219         fi
220
221         # moving an IP is a bit more complex than it seems.
222         # First we drop all traffic on the old interface.
223         # Then we try to add the ip to the new interface and before
224         # we finally remove it from the old interface.
225         #
226         # 1) firewall this IP, so no new external packets arrive for it
227         # 2) add the IP to the new interface
228         # 3) remove the IP from the old interface
229         # 4) remove the firewall rule
230         # 5) use ctdb gratiousarp to propagate the new mac address
231         # 6) use netstat -tn to find existing connections, and tickle them
232         oiface=$2
233         niface=$3
234         ip=$4
235         maskbits=$5
236
237         failed=0
238         # we do an extra delete to cope with the script being killed
239         iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
240         iptables -I INPUT -i $oiface -d $ip -j DROP
241
242         delete_ip_from_iface $oiface $ip $maskbits 2>/dev/null
243         delete_ip_from_iface $niface $ip $maskbits 2>/dev/null
244
245         add_ip_to_iface $niface $ip $maskbits || {
246                 iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
247                 exit 1;
248         }
249
250         # cope with the script being killed while we have the interface blocked
251         iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null
252
253         # flush our route cache
254         echo 1 > /proc/sys/net/ipv4/route/flush
255
256         # propagate the new mac address
257         ctdb gratiousarp $ip $niface
258
259         # tickle all existing connections, so that dropped packets
260         # are retransmited and the tcp streams work
261
262         tickle_tcp_connections $ip
263
264         ;;
265
266
267      ###########################################
268      # called when ctdbd has finished a recovery
269      recovered)
270         ;;
271
272      ####################################
273      # called when ctdbd is shutting down
274      shutdown)
275         ;;
276
277      monitor)
278         monitor_interfaces
279         ret=$?
280
281         test x"$ret" = x"2" && {
282                 test x"$CTDB_PARTIALLY_ONLINE_INTERFACES" != x"yes" && {
283                         exit 1;
284                 }
285                 # as long as we have one interface available don't become
286                 # unhealthy
287                 ret=0
288         }
289
290         test x"$ret" != x"0" && {
291                 exit 1;
292         }
293         ;;
294     *)
295         ctdb_standard_event_handler "$@"
296         ;;
297 esac
298
299 exit 0
300