ensure we use killtcp on non-NFS/non-CIFS ports for faster failover of
[sahlberg/ctdb.git] / config / functions
1 # utility functions for ctdb event scripts
2
3 #######################################
4 # pull in a system config file, if any
5 loadconfig() {
6     name="$1"
7     if [ -f /etc/sysconfig/$name ]; then
8         . /etc/sysconfig/$name
9     elif [ -f /etc/default/$name ]; then
10         . /etc/default/$name
11     elif [ -f $CTDB_BASE/sysconfig/$name ]; then
12         . $CTDB_BASE/sysconfig/$name
13     fi
14 }
15
16
17 ######################################################
18 # simulate /sbin/service on platforms that don't have it
19 service() { 
20   service_name="$1"
21   op="$2"
22   if [ -x /sbin/service ]; then
23       /sbin/service "$service_name" "$op"
24   elif [ -x /etc/init.d/$service_name ]; then
25       /etc/init.d/$service_name "$op"
26   elif [ -x /etc/rc.d/init.d/$service_name ]; then
27       /etc/rc.d/init.d/$service_name "$op"
28   fi
29 }
30
31 ######################################################
32 # simulate /sbin/service (niced) on platforms that don't have it
33 nice_service() { 
34   service_name="$1"
35   op="$2"
36   if [ -x /sbin/service ]; then
37       nice /sbin/service "$service_name" "$op"
38   elif [ -x /etc/init.d/$service_name ]; then
39       nice /etc/init.d/$service_name "$op"
40   elif [ -x /etc/rc.d/init.d/$service_name ]; then
41       nice /etc/rc.d/init.d/$service_name "$op"
42   fi
43 }
44
45 ######################################################
46 # wait for a command to return a zero exit status
47 # usage: ctdb_wait_command SERVICE_NAME <command>
48 ######################################################
49 ctdb_wait_command() {
50   service_name="$1"
51   wait_cmd="$2"
52   [ -z "$wait_cmd" ] && return;
53   all_ok=0
54   echo "Waiting for service $service_name to start"
55   while [ $all_ok -eq 0 ]; do
56           $wait_cmd > /dev/null 2>&1 && all_ok=1
57           ctdb status > /dev/null 2>&1 || {
58                 echo "ctdb daemon has died. Exiting wait for $service_name"
59                 exit 1
60           }
61           [ $all_ok -eq 1 ] || sleep 1
62   done
63   echo "Local service $service_name is up"
64 }
65
66
67 ######################################################
68 # wait for a set of tcp ports
69 # usage: ctdb_wait_tcp_ports SERVICE_NAME <ports...>
70 ######################################################
71 ctdb_wait_tcp_ports() {
72   service_name="$1"
73   shift
74   wait_ports="$*"
75   [ -z "$wait_ports" ] && return;
76   all_ok=0
77   echo "Waiting for tcp service $service_name to start"
78   while [ $all_ok -eq 0 ]; do
79           all_ok=1
80           for p in $wait_ports; do
81               if [ -x /usr/bin/netcat ]; then
82                   /usr/bin/netcat -z 127.0.0.1 $p > /dev/null || all_ok=0
83               elif [ -x /usr/bin/nc ]; then
84                   /usr/bin/nc -z 127.0.0.1 $p > /dev/null || all_ok=0
85               elif [ -x /usr/bin/netstat ]; then
86                   (netstat -a -n | egrep "0.0.0.0:$p[[:space:]]*LISTEN" > /dev/null) || all_ok=0
87               elif [ -x /bin/netstat ]; then
88                   (netstat -a -n | egrep "0.0.0.0:$p[[:space:]]*LISTEN" > /dev/null) || all_ok=0
89               else 
90                   echo "No tool to check tcp ports availabe. can not check in ctdb_wait_tcp_ports"
91                   return
92               fi
93           done
94           [ $all_ok -eq 1 ] || sleep 1
95           ctdb status > /dev/null 2>&1 || {
96                 echo "ctdb daemon has died. Exiting tcp wait $service_name"
97                 exit 1
98           }
99   done
100   echo "Local tcp services for $service_name are up"
101 }
102
103
104
105 ######################################################
106 # wait for a set of directories
107 # usage: ctdb_wait_directories SERVICE_NAME <directories...>
108 ######################################################
109 ctdb_wait_directories() {
110   service_name="$1"
111   shift
112   wait_dirs="$*"
113   [ -z "$wait_dirs" ] && return;
114   all_ok=0
115   echo "Waiting for local directories for $service_name"
116   while [ $all_ok -eq 0 ]; do
117           all_ok=1
118           for d in $wait_dirs; do
119               [ -d $d ] || all_ok=0
120           done
121           [ $all_ok -eq 1 ] || sleep 1
122           ctdb status > /dev/null 2>&1 || {
123                 echo "ctdb daemon has died. Exiting directory wait for $service_name"
124                 exit 1
125           }
126   done
127   echo "Local directories for $service_name are available"
128 }
129
130
131 ######################################################
132 # check that a rpc server is registered with portmap
133 # and responding to requests
134 # usage: ctdb_check_rpc SERVICE_NAME PROGNUM VERSION
135 ######################################################
136 ctdb_check_rpc() {
137     service_name="$1"
138     prognum="$2"
139     version="$3"
140     rpcinfo -u localhost $prognum $version > /dev/null || {
141             echo "ERROR: $service_name not responding to rpc requests"
142             exit 1
143     }
144 }
145
146 ######################################################
147 # check a set of directories is available
148 # return 0 on a missing directory
149 # usage: ctdb_check_directories_probe SERVICE_NAME <directories...>
150 ######################################################
151 ctdb_check_directories_probe() {
152   service_name="$1"
153   shift
154   wait_dirs="$*"
155   [ -z "$wait_dirs" ] && return;
156   for d in $wait_dirs; do
157       [ -d $d ] || return 1
158   done
159   return 0
160 }
161
162 ######################################################
163 # check a set of directories is available
164 # usage: ctdb_check_directories SERVICE_NAME <directories...>
165 ######################################################
166 ctdb_check_directories() {
167   service_name="$1"
168   shift
169   wait_dirs="$*"
170   ctdb_check_directories_probe "$service_name" $wait_dirs || {
171       echo "ERROR: $service_name directory $d not available"
172       exit 1
173   }
174 }
175
176 ######################################################
177 # check a set of tcp ports
178 # usage: ctdb_check_tcp_ports SERVICE_NAME <ports...>
179 ######################################################
180 ctdb_check_tcp_ports() {
181   service_name="$1"
182   shift
183   wait_ports="$*"
184   [ -z "$wait_ports" ] && return;
185   for p in $wait_ports; do
186       all_ok=1
187       if [ -x /usr/bin/netcat ]; then
188           /usr/bin/netcat -z 127.0.0.1 $p > /dev/null || all_ok=0
189       elif [ -x /usr/bin/nc ]; then
190           /usr/bin/nc -z 127.0.0.1 $p > /dev/null || all_ok=0
191       elif [ -x /usr/bin/netstat ]; then
192           (netstat -a -n | egrep "0.0.0.0:$p .*LISTEN" > /dev/null ) || all_ok=0
193       elif [ -x /bin/netstat ]; then
194           (netstat -a -n | egrep "0.0.0.0:$p .*LISTEN" > /dev/null ) || all_ok=0
195       fi
196       [ $all_ok -eq 1 ] || {
197           echo "ERROR: $service_name tcp port $p is not responding"
198           exit 1
199       }
200   done
201 }
202
203 ######################################################
204 # check a command returns zero status
205 # usage: ctdb_check_command SERVICE_NAME <command>
206 ######################################################
207 ctdb_check_command() {
208   service_name="$1"
209   wait_cmd="$2"
210   [ -z "$wait_cmd" ] && return;
211   $wait_cmd > /dev/null 2>&1 || {
212       echo "ERROR: $service_name - $wait_cmd returned error"
213       exit 1
214   }
215 }
216
217 ################################################
218 # kill off any TCP connections with the given IP
219 ################################################
220 kill_tcp_connections() {
221     _IP="$1"    
222     _failed=0
223
224     _killcount=0
225     connfile="$CTDB_BASE/state/connections.$_IP"
226     netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
227     while read dest src; do
228         srcip=`echo $src | cut -d: -f1`
229         srcport=`echo $src | cut -d: -f2`
230         destip=`echo $dest | cut -d: -f1`
231         destport=`echo $dest | cut -d: -f2`
232         echo "Killing TCP connection $srcip:$srcport $destip:$destport"
233         ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
234         case $destport in
235           # we only do one-way killtcp for NFS and CIFS
236           139|445|2049) : ;;
237           # for all others we do 2-way
238           *) 
239                 ctdb killtcp $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
240                 ;;
241         esac
242         _killcount=`expr $_killcount + 1`
243     done < $connfile
244     /bin/rm -f $connfile
245     [ $_failed = 0 ] || {
246         echo "Failed to send killtcp control"
247         return;
248     }
249     [ $_killcount -gt 0 ] || {
250         return;
251     }
252     _count=0
253     while netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" > /dev/null; do
254         sleep 1
255         _count=`expr $_count + 1`
256         [ $_count -gt 3 ] && {
257             echo "Timed out killing tcp connections for IP $_IP"
258             return;
259         }
260     done
261     echo "killed $_killcount TCP connections to released IP $_IP"
262 }
263
264 ########################################################
265 # start/stop the nfs service on different platforms
266 ########################################################
267 startstop_nfs() {
268         PLATFORM="unknown"
269         [ -x /etc/init.d/nfsserver ] && {
270                 PLATFORM="sles"
271         }
272         [ -x /etc/init.d/nfslock ] && {
273                 PLATFORM="rhel"
274         }
275
276         case $PLATFORM in
277         sles)
278                 case $1 in
279                 start)
280                         service nfsserver start
281                         ;;
282                 stop)
283                         service nfsserver stop > /dev/null 2>&1
284                         ;;
285                 esac
286                 ;;
287         rhel)
288                 case $1 in
289                 start)
290                         service nfslock start
291                         service nfs start
292                         ;;
293                 stop)
294                         service nfs stop > /dev/null 2>&1
295                         service nfslock stop > /dev/null 2>&1
296                         ;;
297                 esac
298                 ;;
299         *)
300                 echo "Unknown platform. NFS is not supported with ctdb"
301                 exit 1
302                 ;;
303         esac
304 }
305
306 ########################################################
307 # start/stop the nfs lockmanager service on different platforms
308 ########################################################
309 startstop_nfslock() {
310         PLATFORM="unknown"
311         [ -x /etc/init.d/nfsserver ] && {
312                 PLATFORM="sles"
313         }
314         [ -x /etc/init.d/nfslock ] && {
315                 PLATFORM="rhel"
316         }
317
318         case $PLATFORM in
319         sles)
320                 # for sles there is no service for lockmanager
321                 # so we instead just shutdown/restart nfs
322                 case $1 in
323                 start)
324                         service nfsserver start
325                         ;;
326                 stop)
327                         service nfsserver stop > /dev/null 2>&1
328                         ;;
329                 esac
330                 ;;
331         rhel)
332                 case $1 in
333                 start)
334                         service nfslock start
335                         ;;
336                 stop)
337                         service nfslock stop > /dev/null 2>&1
338                         ;;
339                 esac
340                 ;;
341         *)
342                 echo "Unknown platform. NFS locking is not supported with ctdb"
343                 exit 1
344                 ;;
345         esac
346 }
347
348 ########################################################
349 # load a site local config file
350 ########################################################
351
352 [ -x $CTDB_BASE/rc.local ] && {
353         . $CTDB_BASE/rc.local
354 }