When starting and stopping ctdb through the init-script, make sure we first clear...
[ctdb.git] / config / ctdb.init
1 #!/bin/sh
2 #
3 ##############################
4 # ctdb:                        Starts the clustered tdb daemon
5 #
6 # chkconfig:           - 90 01
7 #
8 # description:                 Starts and stops the clustered tdb daemon
9 # pidfile:             /var/run/ctdbd/ctdbd.pid
10 #
11
12 ### BEGIN INIT INFO
13 # Provides:            ctdb
14 # Required-Start:      $network
15 # Required-Stop:       $network
16 # Default-Stop:
17 # Default-Start:       3 5
18 # Short-Description:   start and stop ctdb service
19 # Description:         initscript for the ctdb service
20 ### END INIT INFO
21
22 # Source function library.
23 if [ -f /etc/init.d/functions ] ; then
24     . /etc/init.d/functions
25 elif [ -f /etc/rc.d/init.d/functions ] ; then
26     . /etc/rc.d/init.d/functions
27 fi
28
29 [ -f /etc/rc.status ] && {
30     . /etc/rc.status
31     rc_reset
32     LC_ALL=en_US.UTF-8
33 }
34
35 # Avoid using root's TMPDIR
36 unset TMPDIR
37
38 [ -z "$CTDB_BASE" ] && {
39     export CTDB_BASE="/etc/ctdb"
40 }
41
42 . $CTDB_BASE/functions
43 loadconfig network
44 loadconfig ctdb
45
46 # check networking is up (for redhat)
47 [ "$NETWORKING" = "no" ] && exit 0
48
49 detect_init_style
50 export CTDB_INIT_STYLE
51
52 ctdbd=${CTDBD:-/usr/sbin/ctdbd}
53
54 if [ "$CTDB_VALGRIND" = "yes" ]; then
55     init_style="valgrind"
56 else
57     init_style="$CTDB_INIT_STYLE"
58 fi
59
60 build_ctdb_options () {
61
62     maybe_set () {
63         # If the 2nd arg is null then return - don't set anything.
64         # Else if the 3rd arg is set and it doesn't match the 2nd arg
65         # then return
66         [ -z "$2" -o \( -n "$3" -a "$3" != "$2" \) ] && return
67
68         val="'$2'"
69         case "$1" in
70             --*) sep="=" ;;
71             -*)  sep=" " ;;
72         esac
73         # For these options we're only passing a value-less flag.
74         [ -n "$3" ] && {
75             val=""
76             sep=""
77         }
78
79         CTDB_OPTIONS="${CTDB_OPTIONS}${CTDB_OPTIONS:+ }${1}${sep}${val}"
80     }
81
82     [ -z "$CTDB_RECOVERY_LOCK" ] && {
83         echo "No recovery lock specified. Starting CTDB without split brain prevention"
84     }
85     maybe_set "--reclock"                "$CTDB_RECOVERY_LOCK"
86
87     # build up CTDB_OPTIONS variable from optional parameters
88     maybe_set "--logfile"                "$CTDB_LOGFILE"
89     maybe_set "--nlist"                  "$CTDB_NODES"
90     maybe_set "--socket"                 "$CTDB_SOCKET"
91     maybe_set "--public-addresses"       "$CTDB_PUBLIC_ADDRESSES"
92     maybe_set "--public-interface"       "$CTDB_PUBLIC_INTERFACE"
93     maybe_set "--dbdir"                  "$CTDB_DBDIR"
94     maybe_set "--dbdir-persistent"       "$CTDB_DBDIR_PERSISTENT"
95     maybe_set "--event-script-dir"       "$CTDB_EVENT_SCRIPT_DIR"
96     maybe_set "--transport"              "$CTDB_TRANSPORT"
97     maybe_set "-d"                       "$CTDB_DEBUGLEVEL"
98     maybe_set "--notification-script"    "$CTDB_NOTIFY_SCRIPT"
99     maybe_set "--start-as-disabled"      "$CTDB_START_AS_DISABLED"    "yes"
100     maybe_set "--start-as-stopped "      "$CTDB_START_AS_STOPPED"     "yes"
101     maybe_set "--no-recmaster"           "$CTDB_CAPABILITY_RECMASTER" "no"
102     maybe_set "--no-lmaster"             "$CTDB_CAPABILITY_LMASTER"   "no"
103     maybe_set "--lvs --single-public-ip" "$CTDB_LVS_PUBLIC_IP"
104     maybe_set "--script-log-level"       "$CTDB_SCRIPT_LOG_LEVEL"
105     maybe_set "--log-ringbuf-size"       "$CTDB_LOG_RINGBUF_SIZE"
106     maybe_set "--syslog"                 "$CTDB_SYSLOG"               "yes"
107     maybe_set "--max-persistent-check-errors" "$CTDB_MAX_PERSISTENT_CHECK_ERRORS"
108 }
109
110 check_tdb () {
111         local PDBASE=$1
112
113         test x"$TDBTOOL_HAS_CHECK" = x"1" && {
114                 #
115                 # Note tdbtool always exits with 0
116                 #
117                 local OK=`tdbtool $PDBASE check | grep "Database integrity is OK" | wc -l`
118                 test x"$OK" = x"1" || {
119                         return 1;
120                 }
121
122                 return 0;
123         }
124
125         tdbdump $PDBASE >/dev/null 2>/dev/null || {
126                 return $?;
127         }
128
129         return 0;
130 }
131
132 check_persistent_databases () {
133     PERSISTENT_DB_DIR="${CTDB_DBDIR:-/var/ctdb}/persistent"
134     mkdir -p $PERSISTENT_DB_DIR 2>/dev/null
135     local ERRCOUNT=$CTDB_MAX_PERSISTENT_CHECK_ERRORS
136
137     test -z "$ERRCOUNT" && {
138         ERRCOUNT="0"
139     }
140     test x"$ERRCOUNT" != x"0" && {
141         return 0;
142     }
143
144     if test -x /usr/bin/tdbtool ; then
145         HAVE_TDBTOOL=1
146     else
147         HAVE_TDBTOOL=0
148     fi
149
150     if test x"$HAVE_TDBTOOL" = x"1" ; then
151         TDBTOOL_HAS_CHECK=`echo "help" | /usr/bin/tdbtool | grep check | wc -l`
152     else
153         TDBTOOL_HAS_CHECK=0
154     fi
155
156     if test -x /usr/bin/tdbdump ; then
157         HAVE_TDBDUMP=1
158     else
159         HAVE_TDBDUMP=0
160     fi
161
162     if test x"$HAVE_TDBDUMP" = x"0" -a x"$TDBTOOL_HAS_CHECK" = x"0" ; then
163         echo "WARNING: Cannot check persistent databases since"
164         echo "neither 'tdbdump' nor 'tdbtool check' is available."
165         echo "Consider installing tdbtool or at least tdbdump!"
166         return 0
167     fi
168
169     if test x"$HAVE_TDBDUMP" = x"1" -a x"$TDBTOOL_HAS_CHECK" = x"0" ; then
170         if test x"$HAVE_TDBTOOL" = x"0"; then
171             echo "WARNING: 'tdbtool' is not available. Using 'tdbdump' to"
172             echo "check the persistent databases."
173             echo "Consider installing a recent 'tdbtool' for better checks!"
174         else
175             echo "WARNING: The installed 'tdbtool' does not offer the 'check'"
176             echo "subcommand. Using 'tdbdump' for persistent database checks."
177             echo "Consider updating 'tdbtool' for better checks!"
178         fi
179     fi
180
181     for PDBASE in `ls $PERSISTENT_DB_DIR/*.tdb.[0-9] 2>/dev/null`; do
182         check_tdb $PDBASE || {
183             echo "Persistent database $PDBASE is corrupted! CTDB will not start."
184             return 1
185         }
186     done
187 }
188
189 set_ctdb_variables () {
190     # set any tunables from the config file
191     set | grep ^CTDB_SET_ | cut -d_ -f3- | 
192     while read v; do
193         varname=`echo $v | cut -d= -f1`
194         value=`echo $v | cut -d= -f2`
195         ctdb setvar $varname $value || RETVAL=1
196     done || exit 1
197 }
198
199 set_retval() {
200     return $1
201 }
202
203 wait_until_ready () {
204     _timeout="${1:-10}" # default is 10 seconds
205
206     _count=0
207     while ! ctdb ping >/dev/null 2>&1 ; do
208         if [ $_count -ge $_timeout ] ; then
209             return 1
210         fi
211         sleep 1
212         _count=$(($_count + 1))
213     done
214 }
215
216 ctdbd=${CTDBD:-/usr/sbin/ctdbd}
217
218 drop_all_public_ips() {
219     [ -z "$CTDB_PUBLIC_ADDRESSES" ] && {
220         return
221     }
222
223     cat $CTDB_PUBLIC_ADDRESSES | while read IP IFACE REST; do
224         ip addr del $IP dev $IFACE >/dev/null 2>/dev/null
225     done
226 }
227
228 start() {
229     echo -n $"Starting ctdbd service: "
230
231     ctdb ping >/dev/null 2>&1 && {
232         echo $"CTDB is already running"
233         return 0
234     }
235
236     build_ctdb_options
237
238     # make sure we drop any ips that might still be held if previous
239     # instance of ctdb got killed with -9 or similar
240     drop_all_public_ips
241
242     check_persistent_databases || return $?
243
244     if [ "$CTDB_SUPPRESS_COREFILE" = "yes" ]; then
245         ulimit -c 0
246     else
247         ulimit -c unlimited
248     fi
249
250     case $init_style in
251         valgrind)
252             eval valgrind -q --log-file=/var/log/ctdb_valgrind \
253                 $ctdbd --valgrinding "$CTDB_OPTIONS"
254             RETVAL=$?
255             echo
256             ;;
257         suse)
258             eval startproc $ctdbd "$CTDB_OPTIONS"
259             RETVAL=$?
260             ;;
261         redhat)
262             eval $ctdbd "$CTDB_OPTIONS"
263             RETVAL=$?
264             [ $RETVAL -eq 0 ] && touch /var/lock/subsys/ctdb || RETVAL=1
265             ;;
266         debian)
267             eval start-stop-daemon --start --quiet --background \
268                 --exec $ctdbd -- "$CTDB_OPTIONS"
269             RETVAL=$?
270             ;;
271     esac
272
273     if [ $RETVAL -eq 0 ] ; then
274         if wait_until_ready ; then
275             set_ctdb_variables
276         else
277             RETVAL=1
278             pkill -9 -f $ctdbd >/dev/null 2>&1
279         fi
280     fi
281
282     case $init_style in
283         suse)
284             set_retval $RETVAL
285             rc_status -v
286             ;;
287         redhat)
288             [ $RETVAL -eq 0 ] && success || failure
289             echo
290             ;;
291     esac
292
293     return $RETVAL
294 }
295
296 stop() {
297     echo -n $"Shutting down ctdbd service: "
298     pkill -0 -f $ctdbd || {
299         echo -n "  Warning: ctdbd not running ! "
300         case $init_style in
301             suse)
302                 rc_status -v
303                 ;;
304             redhat)
305                 echo ""
306                 ;;
307         esac
308         return 0
309     }
310     ctdb shutdown >/dev/null 2>&1
311     RETVAL=$?
312     count=0
313     while pkill -0 -f $ctdbd ; do
314         sleep 1
315         count=$(($count + 1))
316         [ $count -gt 10 ] && {
317             echo -n $"killing ctdbd "
318             pkill -9 -f $ctdbd
319             pkill -9 -f $CTDB_BASE/events.d/
320         }
321     done
322     # make sure all ips are dropped, pfkill -9 might leave them hanging around
323     drop_all_public_ips
324
325     case $init_style in
326         suse)
327             # re-set the return code to the recorded RETVAL in order
328             # to print the correct status message
329             set_retval $RETVAL
330             rc_status -v
331             ;;
332         redhat)
333             [ $RETVAL -eq 0 ] && success || failure
334             [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/ctdb
335             echo ""
336             ;;
337     esac
338
339     return $RETVAL
340 }
341
342 restart() {
343     stop
344     start
345 }
346
347 status() {
348     echo -n $"Checking for ctdbd service: "
349     ctdb ping >/dev/null 2>&1 || {
350         RETVAL=$?
351         echo -n "  ctdbd not running. "
352         case $init_style in
353             suse)
354                 set_retval $RETVAL
355                 rc_status -v
356                 ;;
357             redhat)
358                 if [ -f /var/lock/subsys/ctdb ]; then
359                         echo $"ctdb dead but subsys locked"
360                         RETVAL=2
361                 else
362                         echo $"ctdb is stopped"
363                         RETVAL=3
364                 fi
365                 ;;
366         esac
367         return $RETVAL
368     }
369     echo ""
370     ctdb status
371 }
372
373
374 case "$1" in
375     start)
376         start
377         ;;
378     stop)
379         stop
380         ;;
381     restart|reload|force-reload)
382         restart
383         ;;
384     status)
385         status
386         ;;
387     condrestart|try-restart)
388         ctdb status > /dev/null && restart || :
389         ;;
390     cron)
391         # used from cron to auto-restart ctdb
392         ctdb status > /dev/null || restart
393         ;;
394     *)
395         echo $"Usage: $0 {start|stop|restart|reload|force-reload|status|cron|condrestart|try-restart}"
396         exit 1
397 esac
398
399 exit $?