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