1 # Hey Emacs, this is a -*- shell-script -*- !!!
3 # utility functions for ctdb event scripts
5 PATH=/bin:/usr/bin:/usr/sbin:/sbin:$PATH
7 [ -z "$CTDB_VARDIR" ] && {
8 export CTDB_VARDIR="/var/ctdb"
10 [ -z "$CTDB_ETCDIR" ] && {
11 export CTDB_ETCDIR="/etc"
14 #######################################
15 # pull in a system config file, if any
19 foo="${service_config:-${service_name}}"
20 if [ -n "$foo" ] ; then
23 elif [ "$1" != "ctdb" ] ; then
27 if [ -f $CTDB_ETCDIR/sysconfig/$1 ]; then
28 . $CTDB_ETCDIR/sysconfig/$1
29 elif [ -f $CTDB_ETCDIR/default/$1 ]; then
30 . $CTDB_ETCDIR/default/$1
31 elif [ -f $CTDB_BASE/sysconfig/$1 ]; then
32 . $CTDB_BASE/sysconfig/$1
40 ##############################################################
41 # make sure CTDB_CURRENT_DEBUGLEVEL is set to the desired debug level
44 # If it is already set then do nothing, since it might have been set
45 # via a file in rc.local.d/. If it is not set then set it by sourcing
46 # /var/ctdb/eventscript_debuglevel. If this file does not exist then
47 # create it using output from "ctdb getdebug". If the option 1st arg
48 # is "create" then don't source an existing file but create a new one
49 # instead - this is useful for creating the file just once in each
50 # event run in 00.ctdb. If there's a problem getting the debug level
51 # from ctdb then it is silently set to 0 - no use spamming logs if our
52 # debug code is broken...
53 ctdb_set_current_debuglevel ()
55 [ -z "$CTDB_CURRENT_DEBUGLEVEL" ] || return 0
57 _f="$CTDB_VARDIR/eventscript_debuglevel"
59 if [ "$1" = "create" -o ! -r "$_f" ] ; then
60 _t=$(ctdb getdebug -Y 2>/dev/null)
61 # get last field of output
65 echo "export CTDB_CURRENT_DEBUGLEVEL=\"${_t:-0}\"" >"$_f"
73 if [ $CTDB_CURRENT_DEBUGLEVEL -ge 4 ] ; then
74 # If there are arguments then echo them. Otherwise expect to
75 # use stdin, which allows us to pass lots of debug using a
85 ##############################################################
86 # determine on what type of system (init style) we are running
88 # only do detection if not already set:
89 test "x$CTDB_INIT_STYLE" != "x" && return
91 if [ -x /sbin/startproc ]; then
92 CTDB_INIT_STYLE="suse"
93 elif [ -x /sbin/start-stop-daemon ]; then
94 CTDB_INIT_STYLE="debian"
96 CTDB_INIT_STYLE="redhat"
100 ######################################################
101 # simulate /sbin/service on platforms that don't have it
102 # _service() makes it easier to hook the service() function for
109 # do nothing, when no service was specified
110 [ -z "$_service_name" ] && return
112 if [ -x /sbin/service ]; then
113 $_nice /sbin/service "$_service_name" "$_op"
114 elif [ -x $CTDB_ETCDIR/init.d/$_service_name ]; then
115 $_nice $CTDB_ETCDIR/init.d/$_service_name "$_op"
116 elif [ -x $CTDB_ETCDIR/rc.d/init.d/$_service_name ]; then
117 $_nice $CTDB_ETCDIR/rc.d/init.d/$_service_name "$_op"
127 ######################################################
128 # simulate /sbin/service (niced) on platforms that don't have it
135 ######################################################
136 # wrapper around /proc/ settings to allow them to be hooked
138 # 1st arg is relative path under /proc/, 2nd arg is value to set
141 echo "$2" >"/proc/$1"
144 ######################################################
145 # wrapper around getting file contents from /proc/ to allow
146 # this to be hooked for testing
147 # 1st arg is relative path under /proc/
153 ######################################################
154 # Check that an RPC service is healthy -
155 # this includes allowing a certain number of failures
156 # before marking the NFS service unhealthy.
158 # usage: nfs_check_rpc_service SERVICE_NAME [ triple ...]
160 # each triple is a set of 3 arguments: an operator, a
161 # fail count limit and an action string.
165 # nfs_check_rpc_service "lockd" \
166 # -ge 15 "verbose restart unhealthy" \
167 # -eq 10 "restart:bs"
169 # says that if lockd is down for 15 iterations then do
170 # a verbose restart of lockd and mark the node unhealthy.
171 # Before this, after 10 iterations of failure, the
172 # service is restarted silently in the background.
173 # Order is important: the number of failures need to be
174 # specified in reverse order because processing stops
175 # after the first condition that is true.
176 ######################################################
177 nfs_check_rpc_service ()
179 _prog_name="$1" ; shift
182 _rpc_prog="$_prog_name"
185 case "$_prog_name" in
189 _restart="echo 'Trying to restart NFS service'"
190 _restart="${_restart}; startstop_nfs restart"
193 _opts="${MOUNTD_PORT:+ -p }${MOUNTD_PORT}"
196 _opts="${RQUOTAD_PORT:+ -p }${RQUOTAD_PORT}"
201 _restart="echo 'Trying to restart lock manager service'"
202 _restart="${_restart}; startstop_nfslock restart"
206 _opts="${STATD_HOSTNAME:+ -n }${STATD_HOSTNAME}"
207 _opts="${_opts}${STATD_PORT:+ -p }${STATD_PORT}"
208 _opts="${_opts}${STATD_OUTGOING_PORT:+ -o }${STATD_OUTGOING_PORT}"
211 echo "Internal error: unknown RPC program \"$_prog_name\"."
215 _service_name="nfs_${_prog_name}"
217 if ctdb_check_rpc "$_rpc_prog" $_version >/dev/null ; then
218 ctdb_counter_init "$_service_name"
222 ctdb_counter_incr "$_service_name"
224 while [ -n "$3" ] ; do
225 ctdb_check_counter "quiet" "$1" "$2" "$_service_name" || {
226 for _action in $3 ; do
229 echo "$ctdb_check_rpc_out"
232 # No explicit command specified, construct rpc command.
233 if [ -z "$_restart" ] ; then
234 _p="rpc.${_prog_name}"
235 _restart="echo 'Trying to restart $_prog_name [${_p}${_opts}]'"
236 _restart="${_restart}; killall -q -9 $_p"
237 _restart="${_restart}; $_p $_opts"
240 # Process restart flags...
241 _flags="${_action#restart:}"
242 # There may not have been a colon...
243 [ "$_flags" != "$_action" ] || _flags=""
244 # q=quiet - everything to /dev/null
245 if [ "${_flags#*q}" != "$_flags" ] ; then
246 _restart="{ ${_restart} ; } >/dev/null 2>&1"
248 # s=stealthy - last command to /dev/null
249 if [ "${_flags#*s}" != "$_flags" ] ; then
250 _restart="${_restart} >/dev/null 2>&1"
252 # b=background - the whole thing, easy and reliable
253 if [ "${_flags#*b}" != "$_flags" ] ; then
254 _restart="{ ${_restart} ; } &"
264 echo "Internal error: unknown action \"$_action\"."
269 # Only process the first action group.
276 ######################################################
277 # check that a rpc server is registered with portmap
278 # and responding to requests
279 # usage: ctdb_check_rpc SERVICE_NAME VERSION
280 ######################################################
286 if ! ctdb_check_rpc_out=$(rpcinfo -u localhost $progname $version 2>&1) ; then
287 ctdb_check_rpc_out="ERROR: $progname failed RPC check:
289 echo "$ctdb_check_rpc_out"
294 ######################################################
295 # check a set of directories is available
296 # return 1 on a missing directory
297 # usage: ctdb_check_directories_probe SERVICE_NAME <directories...>
298 ######################################################
299 ctdb_check_directories_probe() {
300 while IFS="" read d ; do
306 [ -d "${d}/." ] || return 1
311 ######################################################
312 # check a set of directories is available
313 # usage: ctdb_check_directories SERVICE_NAME <directories...>
314 ######################################################
315 ctdb_check_directories() {
316 n="${1:-${service_name}}"
317 ctdb_check_directories_probe || {
318 echo "ERROR: $n directory \"$d\" not available"
323 ######################################################
324 # check a set of tcp ports
325 # usage: ctdb_check_tcp_ports <ports...>
326 ######################################################
328 # This flag file is created when a service is initially started. It
329 # is deleted the first time TCP port checks for that service succeed.
330 # Until then ctdb_check_tcp_ports() prints a more subtle "error"
331 # message if a port check fails.
332 _ctdb_check_tcp_common ()
334 _ctdb_service_started_file="$ctdb_fail_dir/$service_name.started"
337 ctdb_check_tcp_init ()
339 _ctdb_check_tcp_common
340 mkdir -p "${_ctdb_service_started_file%/*}" # dirname
341 touch "$_ctdb_service_started_file"
344 ctdb_check_tcp_ports()
346 _ctdb_check_tcp_common
348 _cmd='netstat -l -t -n'
350 for _p ; do # process each function argument (port)
351 for _a in '0\.0\.0\.0' '::' ; do
352 _pat="[[:space:]]${_a}:${_p}[[:space:]]+[^[:space:]]+[[:space:]]+LISTEN"
353 if echo "$_ns" | grep -E -q "$_pat" ; then
354 # We matched the port, so process next port
359 # We didn't match the port, so flag an error, print some debug
360 if [ ! -f "$_ctdb_service_started_file" ] ; then
361 echo "ERROR: $service_name tcp port $_p is not responding"
363 $_cmd shows this output:
367 echo "INFO: $service_name tcp port $_p is not responding"
373 rm -f "$_ctdb_service_started_file"
378 ######################################################
379 # check a unix socket
380 # usage: ctdb_check_unix_socket SERVICE_NAME <socket_path>
381 ######################################################
382 ctdb_check_unix_socket() {
384 [ -z "$socket_path" ] && return
386 if ! netstat --unix -a -n | grep -q "^unix.*LISTEN.*${socket_path}$"; then
387 echo "ERROR: $service_name socket $socket_path not found"
392 ######################################################
393 # check a command returns zero status
394 # usage: ctdb_check_command SERVICE_NAME <command>
395 ######################################################
396 ctdb_check_command() {
399 [ -z "$wait_cmd" ] && return;
400 $wait_cmd > /dev/null 2>&1 || {
401 echo "ERROR: $service_name - $wait_cmd returned error"
406 ################################################
407 # kill off any TCP connections with the given IP
408 ################################################
409 kill_tcp_connections() {
414 connfile="$CTDB_VARDIR/state/connections.$_IP"
415 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
416 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
418 while read dest src; do
419 srcip=`echo $src | sed -e "s/:[^:]*$//"`
420 srcport=`echo $src | sed -e "s/^.*://"`
421 destip=`echo $dest | sed -e "s/:[^:]*$//"`
422 destport=`echo $dest | sed -e "s/^.*://"`
423 echo "Killing TCP connection $srcip:$srcport $destip:$destport"
424 ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
426 # we only do one-way killtcp for CIFS
428 # for all others we do 2-way
430 ctdb killtcp $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
433 _killcount=`expr $_killcount + 1`
437 [ $_failed = 0 ] || {
438 echo "Failed to send killtcp control"
441 [ $_killcount -gt 0 ] || {
445 while netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" > /dev/null; do
447 _count=`expr $_count + 1`
448 [ $_count -gt 3 ] && {
449 echo "Timed out killing tcp connections for IP $_IP"
453 echo "killed $_killcount TCP connections to released IP $_IP"
456 ##################################################################
457 # kill off the local end for any TCP connections with the given IP
458 ##################################################################
459 kill_tcp_connections_local_only() {
464 connfile="$CTDB_VARDIR/state/connections.$_IP"
465 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
466 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
468 while read dest src; do
469 srcip=`echo $src | sed -e "s/:[^:]*$//"`
470 srcport=`echo $src | sed -e "s/^.*://"`
471 destip=`echo $dest | sed -e "s/:[^:]*$//"`
472 destport=`echo $dest | sed -e "s/^.*://"`
473 echo "Killing TCP connection $srcip:$srcport $destip:$destport"
474 ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
475 _killcount=`expr $_killcount + 1`
479 [ $_failed = 0 ] || {
480 echo "Failed to send killtcp control"
483 [ $_killcount -gt 0 ] || {
487 while netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" > /dev/null; do
489 _count=`expr $_count + 1`
490 [ $_count -gt 3 ] && {
491 echo "Timed out killing tcp connections for IP $_IP"
495 echo "killed $_killcount TCP connections to released IP $_IP"
498 ##################################################################
499 # tickle any TCP connections with the given IP
500 ##################################################################
501 tickle_tcp_connections() {
506 connfile="$CTDB_VARDIR/state/connections.$_IP"
507 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
508 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
510 while read dest src; do
511 srcip=`echo $src | sed -e "s/:[^:]*$//"`
512 srcport=`echo $src | sed -e "s/^.*://"`
513 destip=`echo $dest | sed -e "s/:[^:]*$//"`
514 destport=`echo $dest | sed -e "s/^.*://"`
515 echo "Tickle TCP connection $srcip:$srcport $destip:$destport"
516 ctdb tickle $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
517 echo "Tickle TCP connection $destip:$destport $srcip:$srcport"
518 ctdb tickle $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
522 [ $_failed = 0 ] || {
523 echo "Failed to send tickle control"
528 ########################################################
529 # start/stop the nfs service on different platforms
530 ########################################################
533 [ -x $CTDB_ETCDIR/init.d/nfsserver ] && {
536 [ -x $CTDB_ETCDIR/init.d/nfslock ] && {
544 service nfsserver start
547 service nfsserver stop > /dev/null 2>&1
550 set_proc "fs/nfsd/threads" 0
551 service nfsserver stop > /dev/null 2>&1
553 service nfsserver start
560 service nfslock start
568 set_proc "fs/nfsd/threads" 0
569 service nfs stop > /dev/null 2>&1
570 service nfslock stop > /dev/null 2>&1
572 service nfslock start
578 echo "Unknown platform. NFS is not supported with ctdb"
584 ########################################################
585 # start/stop the nfs lockmanager service on different platforms
586 ########################################################
587 startstop_nfslock() {
589 [ -x $CTDB_ETCDIR/init.d/nfsserver ] && {
592 [ -x $CTDB_ETCDIR/init.d/nfslock ] && {
598 # for sles there is no service for lockmanager
599 # so we instead just shutdown/restart nfs
602 service nfsserver start
605 service nfsserver stop > /dev/null 2>&1
608 service nfsserver stop
609 service nfsserver start
616 service nfslock start
619 service nfslock stop > /dev/null 2>&1
623 service nfslock start
628 echo "Unknown platform. NFS locking is not supported with ctdb"
639 local _state_dir="$CTDB_VARDIR/state/interface_modify"
640 local _lockfile="$_state_dir/$_iface.flock"
641 local _readd_base="$_state_dir/$_iface.readd.d"
643 mkdir -p $_state_dir || {
645 echo "Failed to mkdir -p $_state_dir - $ret"
649 test -f $_lockfile || {
653 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh add "$_iface" "$_ip" "$_maskbits" "$_readd_base"
657 delete_ip_from_iface()
662 local _state_dir="$CTDB_VARDIR/state/interface_modify"
663 local _lockfile="$_state_dir/$_iface.flock"
664 local _readd_base="$_state_dir/$_iface.readd.d"
666 mkdir -p $_state_dir || {
668 echo "Failed to mkdir -p $_state_dir - $ret"
672 test -f $_lockfile || {
676 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh delete "$_iface" "$_ip" "$_maskbits" "$_readd_base"
680 setup_iface_ip_readd_script()
685 local _readd_script=$4
686 local _state_dir="$CTDB_VARDIR/state/interface_modify"
687 local _lockfile="$_state_dir/$_iface.flock"
688 local _readd_base="$_state_dir/$_iface.readd.d"
690 mkdir -p $_state_dir || {
692 echo "Failed to mkdir -p $_state_dir - $ret"
696 test -f $_lockfile || {
700 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh readd_script "$_iface" "$_ip" "$_maskbits" "$_readd_base" "$_readd_script"
704 ########################################################
705 # some simple logic for counting events - per eventscript
706 # usage: ctdb_counter_init
708 # ctdb_check_counter_limit <limit>
709 # ctdb_check_counter_limit succeeds when count >= <limit>
710 ########################################################
711 _ctdb_counter_common () {
712 _service_name="${1:-${service_name}}"
713 _counter_file="$ctdb_fail_dir/$_service_name"
714 mkdir -p "${_counter_file%/*}" # dirname
716 ctdb_counter_init () {
717 _ctdb_counter_common "$1"
721 ctdb_counter_incr () {
722 _ctdb_counter_common "$1"
725 echo -n 1 >> "$_counter_file"
727 ctdb_check_counter_limit () {
730 _limit="${1:-${service_fail_limit}}"
734 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
735 if [ $_size -ge $_limit ] ; then
736 echo "ERROR: more than $_limit consecutive failures for $service_name, marking cluster unhealthy"
738 elif [ $_size -gt 0 -a -z "$_quiet" ] ; then
739 echo "WARNING: less than $_limit consecutive failures ($_size) for $service_name, not unhealthy yet"
742 ctdb_check_counter_equal () {
748 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
749 if [ $_size -eq $_limit ] ; then
754 ctdb_check_counter () {
755 _msg="${1:-error}" # "error" - anything else is silent on fail
756 _op="${2:--ge}" # an integer operator supported by test
757 _limit="${3:-${service_fail_limit}}"
759 _ctdb_counter_common "$1"
762 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
763 if [ $_size $_op $_limit ] ; then
764 if [ "$_msg" = "error" ] ; then
765 echo "ERROR: $_limit consecutive failures for $_service_name, marking node unhealthy"
773 ########################################################
775 ctdb_status_dir="$CTDB_VARDIR/status"
776 ctdb_fail_dir="$CTDB_VARDIR/failcount"
778 ctdb_setup_service_state_dir ()
780 service_state_dir="$CTDB_VARDIR/state/${1:-${service_name}}"
781 mkdir -p "$service_state_dir" || {
782 echo "Error creating state dir \"$service_state_dir\""
787 ########################################################
788 # Managed status history, for auto-start/stop
790 ctdb_managed_dir="$CTDB_VARDIR/managed_history"
792 _ctdb_managed_common ()
794 _service_name="${1:-${service_name}}"
795 _ctdb_managed_file="$ctdb_managed_dir/$_service_name"
798 ctdb_service_managed ()
800 _ctdb_managed_common "$@"
801 mkdir -p "$ctdb_managed_dir"
802 touch "$_ctdb_managed_file"
805 ctdb_service_unmanaged ()
807 _ctdb_managed_common "$@"
808 rm -f "$_ctdb_managed_file"
811 is_ctdb_previously_managed_service ()
813 _ctdb_managed_common "$@"
814 [ -f "$_ctdb_managed_file" ]
817 ########################################################
818 # Check and set status
822 echo "node is \"$1\", \"${script_name}\" reports problem: $(cat $2)"
827 if [ -r "$ctdb_status_dir/$script_name/unhealthy" ] ; then
828 log_status_cat "unhealthy" "$ctdb_status_dir/$script_name/unhealthy"
830 elif [ -r "$ctdb_status_dir/$script_name/banned" ] ; then
831 log_status_cat "banned" "$ctdb_status_dir/$script_name/banned"
840 d="$ctdb_status_dir/$script_name"
847 for i in "banned" "unhealthy" ; do
854 ##################################################################
855 # Reconfigure a service on demand
857 _ctdb_service_reconfigure_common ()
859 _d="$ctdb_status_dir/${1:-${service_name}}"
861 _ctdb_service_reconfigure_flag="$_d/reconfigure"
864 ctdb_service_needs_reconfigure ()
866 _ctdb_service_reconfigure_common "$@"
867 [ -e "$_ctdb_service_reconfigure_flag" ]
870 ctdb_service_set_reconfigure ()
872 _ctdb_service_reconfigure_common "$@"
873 >"$_ctdb_service_reconfigure_flag"
876 ctdb_service_unset_reconfigure ()
878 _ctdb_service_reconfigure_common "$@"
879 rm -f "$_ctdb_service_reconfigure_flag"
882 ctdb_service_reconfigure ()
884 echo "Reconfiguring service \"$service_name\"..."
885 ctdb_service_unset_reconfigure "$@"
886 service_reconfigure "$@" || return $?
887 ctdb_counter_init "$@"
890 # Default service_reconfigure() function.
891 service_reconfigure ()
893 service "${1:-$service_name}" restart
896 ctdb_service_check_reconfigure ()
898 # Only do this for certain events.
899 case "$event_name" in
900 monitor|ipreallocated) : ;;
904 if ctdb_service_needs_reconfigure "$@" ; then
905 ctdb_service_reconfigure "$@"
907 # Fall through to non-monitor events.
908 [ "$event_name" = "monitor" ] || return 0
910 # We don't want to proceed with the rest of the monitor event
911 # here, so we exit. However, if we exit 0 then, if the
912 # service was previously broken, we might return a false
913 # positive. So we simply retrieve the status of this script
914 # from the previous monitor loop and exit with that status.
915 ctdb scriptstatus | \
916 grep -q -E "^${script_name}[[:space:]]+Status:OK[[:space:]]"
921 ##################################################################
922 # Does CTDB manage this service? - and associated auto-start/stop
924 ctdb_compat_managed_service ()
926 if [ "$1" = "yes" -a "$2" = "$_service_name" ] ; then
927 CTDB_MANAGED_SERVICES="$CTDB_MANAGED_SERVICES $2"
931 is_ctdb_managed_service ()
933 _service_name="${1:-${service_name}}"
935 # $t is used just for readability and to allow better accurate
936 # matching via leading/trailing spaces
937 t=" $CTDB_MANAGED_SERVICES "
939 # Return 0 if "<space>$_service_name<space>" appears in $t
940 if [ "${t#* ${_service_name} }" != "${t}" ] ; then
944 # If above didn't match then update $CTDB_MANAGED_SERVICES for
945 # backward compatibility and try again.
946 ctdb_compat_managed_service "$CTDB_MANAGES_VSFTPD" "vsftpd"
947 ctdb_compat_managed_service "$CTDB_MANAGES_SAMBA" "samba"
948 ctdb_compat_managed_service "$CTDB_MANAGES_SCP" "scp"
949 ctdb_compat_managed_service "$CTDB_MANAGES_WINBIND" "winbind"
950 ctdb_compat_managed_service "$CTDB_MANAGES_HTTPD" "httpd"
951 ctdb_compat_managed_service "$CTDB_MANAGES_ISCSI" "iscsi"
952 ctdb_compat_managed_service "$CTDB_MANAGES_CLAMD" "clamd"
953 ctdb_compat_managed_service "$CTDB_MANAGES_NFS" "nfs"
954 ctdb_compat_managed_service "$CTDB_MANAGES_NFS" "nfs-ganesha-gpfs"
956 t=" $CTDB_MANAGED_SERVICES "
958 # Return 0 if "<space>$_service_name<space>" appears in $t
959 [ "${t#* ${_service_name} }" != "${t}" ]
962 ctdb_start_stop_service ()
964 _service_name="${1:-${service_name}}"
966 [ "$event_name" = "monitor" ] || return 0
968 if is_ctdb_managed_service "$_service_name" ; then
969 if ! is_ctdb_previously_managed_service "$_service_name" ; then
970 echo "Starting service \"$_service_name\" - now managed"
971 ctdb_service_start "$_service_name"
975 if is_ctdb_previously_managed_service "$_service_name" ; then
976 echo "Stopping service \"$_service_name\" - no longer managed"
977 ctdb_service_stop "$_service_name"
983 ctdb_service_start ()
985 # The service is marked managed if we've ever tried to start it.
986 ctdb_service_managed "$@"
988 # Here we only want $1. If no argument is passed then
989 # service_start needs to know.
990 service_start "$@" || return $?
992 ctdb_counter_init "$@"
998 ctdb_service_unmanaged "$@"
1002 # Default service_start() and service_stop() functions.
1004 # These may be overridden in an eventscript. When overriding, the
1005 # following convention must be followed. If these functions are
1006 # called with no arguments then they may use internal logic to
1007 # determine whether the service is managed and, therefore, whether
1008 # they should take any action. However, if the service name is
1009 # specified as an argument then an attempt must be made to start or
1010 # stop the service. This is because the auto-start/stop code calls
1011 # them with the service name as an argument.
1014 service "${1:-${service_name}}" start
1019 service "${1:-${service_name}}" stop
1022 ##################################################################
1024 ctdb_standard_event_handler ()
1039 ipv4_host_addr_to_net_addr()
1044 local HOST0=$(echo $HOST | awk -F . '{print $4}')
1045 local HOST1=$(echo $HOST | awk -F . '{print $3}')
1046 local HOST2=$(echo $HOST | awk -F . '{print $2}')
1047 local HOST3=$(echo $HOST | awk -F . '{print $1}')
1049 local HOST_NUM=$(( $HOST0 + $HOST1 * 256 + $HOST2 * (256 ** 2) + $HOST3 * (256 ** 3) ))
1051 local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
1053 local NET_NUM=$(( $HOST_NUM & $MASK_NUM))
1055 local NET0=$(( $NET_NUM & 255 ))
1056 local NET1=$(( ($NET_NUM & (255 * 256)) / 256 ))
1057 local NET2=$(( ($NET_NUM & (255 * 256**2)) / 256**2 ))
1058 local NET3=$(( ($NET_NUM & (255 * 256**3)) / 256**3 ))
1060 echo "$NET3.$NET2.$NET1.$NET0"
1063 ipv4_maskbits_to_net_mask()
1067 local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
1069 local MASK0=$(( $MASK_NUM & 255 ))
1070 local MASK1=$(( ($MASK_NUM & (255 * 256)) / 256 ))
1071 local MASK2=$(( ($MASK_NUM & (255 * 256**2)) / 256**2 ))
1072 local MASK3=$(( ($MASK_NUM & (255 * 256**3)) / 256**3 ))
1074 echo "$MASK3.$MASK2.$MASK1.$MASK0"
1077 ipv4_is_valid_addr()
1082 local N=`echo $ADDR | sed -e 's/[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*//'`
1083 test -n "$N" && fail=1
1085 local ADDR0=$(echo $ADDR | awk -F . '{print $4}')
1086 local ADDR1=$(echo $ADDR | awk -F . '{print $3}')
1087 local ADDR2=$(echo $ADDR | awk -F . '{print $2}')
1088 local ADDR3=$(echo $ADDR | awk -F . '{print $1}')
1090 test "$ADDR0" -gt 255 && fail=1
1091 test "$ADDR1" -gt 255 && fail=1
1092 test "$ADDR2" -gt 255 && fail=1
1093 test "$ADDR3" -gt 255 && fail=1
1095 test x"$fail" != x"0" && {
1096 #echo "IPv4: '$ADDR' is not a valid address"
1103 # iptables doesn't like being re-entered, so flock-wrap it.
1106 flock -w 30 $CTDB_VARDIR/iptables-ctdb.flock /sbin/iptables "$@"
1109 ########################################################
1111 ########################################################
1113 # Temporary directory for tickles.
1114 tickledir="$CTDB_VARDIR/state/tickles"
1115 mkdir -p "$tickledir"
1121 mkdir -p "$tickledir" # Just in case
1124 _pnn=$(ctdb pnn) ; _pnn=${_pnn#PNN:}
1126 # What public IPs do I hold?
1127 _ips=$(ctdb -Y ip | awk -F: -v pnn=$_pnn '$3 == pnn {print $2}')
1129 # IPs as a regexp choice
1130 _ipschoice="($(echo $_ips | sed -e 's/ /|/g' -e 's/\./\\\\./g'))"
1132 # Record connections to our public IPs in a temporary file
1133 _my_connections="${tickledir}/${_port}.connections"
1134 rm -f "$_my_connections"
1136 awk -v destpat="^${_ipschoice}:${_port}\$" \
1137 '$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ destpat {print $5, $4}' |
1138 sort >"$_my_connections"
1140 # Record our current tickles in a temporary file
1141 _my_tickles="${tickledir}/${_port}.tickles"
1142 rm -f "$_my_tickles"
1143 for _i in $_ips ; do
1144 ctdb -Y gettickles $_i $_port |
1145 awk -F: 'NR > 1 { printf "%s:%s %s:%s\n", $2, $3, $4, $5 }'
1147 sort >"$_my_tickles"
1149 # Add tickles for connections that we haven't already got tickles for
1150 comm -23 "$_my_connections" "$_my_tickles" |
1151 while read _src _dst ; do
1152 ctdb addtickle $_src $_dst
1155 # Remove tickles for connections that are no longer there
1156 comm -13 "$_my_connections" "$_my_tickles" |
1157 while read _src _dst ; do
1158 ctdb deltickle $_src $_dst
1161 rm -f "$_my_connections" "$_my_tickles"
1164 ########################################################
1165 # load a site local config file
1166 ########################################################
1168 [ -n "$CTDB_RC_LOCAL" -a -x "$CTDB_RC_LOCAL" ] && {
1172 [ -x $CTDB_BASE/rc.local ] && {
1173 . $CTDB_BASE/rc.local
1176 [ -d $CTDB_BASE/rc.local.d ] && {
1177 for i in $CTDB_BASE/rc.local.d/* ; do
1178 [ -x "$i" ] && . "$i"
1182 # We'll call this here to ensure $CTDB_CURRENT_DEBUGLEVEL is set.
1183 # This gives us a chance to override the debug level using a file in
1184 # $CTDB_BASE/rc.local.d/.
1185 ctdb_set_current_debuglevel
1187 script_name="${0##*/}" # basename
1188 service_name="$script_name" # default is just the script name
1189 service_fail_limit=1