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"
71 ##############################################################
72 # determine on what type of system (init style) we are running
74 # only do detection if not already set:
75 test "x$CTDB_INIT_STYLE" != "x" && return
77 if [ -x /sbin/startproc ]; then
78 CTDB_INIT_STYLE="suse"
79 elif [ -x /sbin/start-stop-daemon ]; then
80 CTDB_INIT_STYLE="debian"
82 CTDB_INIT_STYLE="redhat"
86 ######################################################
87 # simulate /sbin/service on platforms that don't have it
88 # _service() makes it easier to hook the service() function for
95 # do nothing, when no service was specified
96 [ -z "$_service_name" ] && return
98 if [ -x /sbin/service ]; then
99 $_nice /sbin/service "$_service_name" "$_op"
100 elif [ -x $CTDB_ETCDIR/init.d/$_service_name ]; then
101 $_nice $CTDB_ETCDIR/init.d/$_service_name "$_op"
102 elif [ -x $CTDB_ETCDIR/rc.d/init.d/$_service_name ]; then
103 $_nice $CTDB_ETCDIR/rc.d/init.d/$_service_name "$_op"
113 ######################################################
114 # simulate /sbin/service (niced) on platforms that don't have it
121 ######################################################
122 # wrapper around /proc/ settings to allow them to be hooked
124 # 1st arg is relative path under /proc/, 2nd arg is value to set
127 echo "$2" >"/proc/$1"
130 ######################################################
131 # wrapper around getting file contents from /proc/ to allow
132 # this to be hooked for testing
133 # 1st arg is relative path under /proc/
139 ######################################################
140 # Check that an RPC service is healthy -
141 # this includes allowing a certain number of failures
142 # before marking the NFS service unhealthy.
144 # usage: nfs_check_rpc_service SERVICE_NAME [ triple ...]
146 # each triple is a set of 3 arguments: an operator, a
147 # fail count limit and an action string.
151 # nfs_check_rpc_service "lockd" \
152 # -ge 15 "verbose restart unhealthy" \
153 # -eq 10 "restart:bs"
155 # says that if lockd is down for 15 iterations then do
156 # a verbose restart of lockd and mark the node unhealthy.
157 # Before this, after 10 iterations of failure, the
158 # service is restarted silently in the background.
159 # Order is important: the number of failures need to be
160 # specified in reverse order because processing stops
161 # after the first condition that is true.
162 ######################################################
163 nfs_check_rpc_service ()
165 _prog_name="$1" ; shift
168 _rpc_prog="$_prog_name"
171 case "$_prog_name" in
175 _restart="echo 'Trying to restart NFS service'"
176 _restart="${_restart}; startstop_nfs restart"
179 _opts="${MOUNTD_PORT:+ -p }${MOUNTD_PORT}"
182 _opts="${RQUOTAD_PORT:+ -p }${RQUOTAD_PORT}"
187 _restart="echo 'Trying to restart lock manager service'"
188 _restart="${_restart}; startstop_nfslock restart"
192 _opts="${STATD_HOSTNAME:+ -n }${STATD_HOSTNAME}"
193 _opts="${_opts}${STATD_PORT:+ -p }${STATD_PORT}"
194 _opts="${_opts}${STATD_OUTGOING_PORT:+ -o }${STATD_OUTGOING_PORT}"
197 echo "Internal error: unknown RPC program \"$_prog_name\"."
201 _service_name="nfs_${_prog_name}"
203 if ctdb_check_rpc "$_rpc_prog" $_version >/dev/null ; then
204 ctdb_counter_init "$_service_name"
208 ctdb_counter_incr "$_service_name"
210 while [ -n "$3" ] ; do
211 ctdb_check_counter "quiet" "$1" "$2" "$_service_name" || {
212 for _action in $3 ; do
215 echo "$ctdb_check_rpc_out"
218 # No explicit command specified, construct rpc command.
219 if [ -z "$_restart" ] ; then
220 _p="rpc.${_prog_name}"
221 _restart="echo 'Trying to restart $_prog_name [${_p}${_opts}]'"
222 _restart="${_restart}; killall -q -9 $_p"
223 _restart="${_restart}; $_p $_opts"
226 # Process restart flags...
227 _flags="${_action#restart:}"
228 # There may not have been a colon...
229 [ "$_flags" != "$_action" ] || _flags=""
230 # q=quiet - everything to /dev/null
231 if [ "${_flags#*q}" != "$_flags" ] ; then
232 _restart="{ ${_restart} ; } >/dev/null 2>&1"
234 # s=stealthy - last command to /dev/null
235 if [ "${_flags#*s}" != "$_flags" ] ; then
236 _restart="${_restart} >/dev/null 2>&1"
238 # b=background - the whole thing, easy and reliable
239 if [ "${_flags#*b}" != "$_flags" ] ; then
240 _restart="{ ${_restart} ; } &"
250 echo "Internal error: unknown action \"$_action\"."
255 # Only process the first action group.
262 ######################################################
263 # check that a rpc server is registered with portmap
264 # and responding to requests
265 # usage: ctdb_check_rpc SERVICE_NAME VERSION
266 ######################################################
272 if ! ctdb_check_rpc_out=$(rpcinfo -u localhost $progname $version 2>&1) ; then
273 ctdb_check_rpc_out="ERROR: $progname failed RPC check:
275 echo "$ctdb_check_rpc_out"
280 ######################################################
281 # check a set of directories is available
282 # return 1 on a missing directory
283 # usage: ctdb_check_directories_probe SERVICE_NAME <directories...>
284 ######################################################
285 ctdb_check_directories_probe() {
286 while IFS="" read d ; do
292 [ -d "${d}/." ] || return 1
297 ######################################################
298 # check a set of directories is available
299 # usage: ctdb_check_directories SERVICE_NAME <directories...>
300 ######################################################
301 ctdb_check_directories() {
302 n="${1:-${service_name}}"
303 ctdb_check_directories_probe || {
304 echo "ERROR: $n directory \"$d\" not available"
309 ######################################################
310 # check a set of tcp ports
311 # usage: ctdb_check_tcp_ports <ports...>
312 ######################################################
313 ctdb_check_tcp_ports() {
316 if ! netstat -a -t -n | grep -q "0\.0\.0\.0:$p .*LISTEN" ; then
317 if ! netstat -a -t -n | grep -q ":::$p .*LISTEN" ; then
318 echo "ERROR: $service_name tcp port $p is not responding"
325 ######################################################
326 # check a unix socket
327 # usage: ctdb_check_unix_socket SERVICE_NAME <socket_path>
328 ######################################################
329 ctdb_check_unix_socket() {
331 [ -z "$socket_path" ] && return
333 if ! netstat --unix -a -n | grep -q "^unix.*LISTEN.*${socket_path}$"; then
334 echo "ERROR: $service_name socket $socket_path not found"
339 ######################################################
340 # check a command returns zero status
341 # usage: ctdb_check_command SERVICE_NAME <command>
342 ######################################################
343 ctdb_check_command() {
346 [ -z "$wait_cmd" ] && return;
347 $wait_cmd > /dev/null 2>&1 || {
348 echo "ERROR: $service_name - $wait_cmd returned error"
353 ################################################
354 # kill off any TCP connections with the given IP
355 ################################################
356 kill_tcp_connections() {
361 connfile="$CTDB_VARDIR/state/connections.$_IP"
362 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
363 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
365 while read dest src; do
366 srcip=`echo $src | sed -e "s/:[^:]*$//"`
367 srcport=`echo $src | sed -e "s/^.*://"`
368 destip=`echo $dest | sed -e "s/:[^:]*$//"`
369 destport=`echo $dest | sed -e "s/^.*://"`
370 echo "Killing TCP connection $srcip:$srcport $destip:$destport"
371 ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
373 # we only do one-way killtcp for CIFS
375 # for all others we do 2-way
377 ctdb killtcp $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
380 _killcount=`expr $_killcount + 1`
384 [ $_failed = 0 ] || {
385 echo "Failed to send killtcp control"
388 [ $_killcount -gt 0 ] || {
392 while netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" > /dev/null; do
394 _count=`expr $_count + 1`
395 [ $_count -gt 3 ] && {
396 echo "Timed out killing tcp connections for IP $_IP"
400 echo "killed $_killcount TCP connections to released IP $_IP"
403 ##################################################################
404 # kill off the local end for any TCP connections with the given IP
405 ##################################################################
406 kill_tcp_connections_local_only() {
411 connfile="$CTDB_VARDIR/state/connections.$_IP"
412 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
413 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
415 while read dest src; do
416 srcip=`echo $src | sed -e "s/:[^:]*$//"`
417 srcport=`echo $src | sed -e "s/^.*://"`
418 destip=`echo $dest | sed -e "s/:[^:]*$//"`
419 destport=`echo $dest | sed -e "s/^.*://"`
420 echo "Killing TCP connection $srcip:$srcport $destip:$destport"
421 ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
422 _killcount=`expr $_killcount + 1`
426 [ $_failed = 0 ] || {
427 echo "Failed to send killtcp control"
430 [ $_killcount -gt 0 ] || {
434 while netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" > /dev/null; do
436 _count=`expr $_count + 1`
437 [ $_count -gt 3 ] && {
438 echo "Timed out killing tcp connections for IP $_IP"
442 echo "killed $_killcount TCP connections to released IP $_IP"
445 ##################################################################
446 # tickle any TCP connections with the given IP
447 ##################################################################
448 tickle_tcp_connections() {
453 connfile="$CTDB_VARDIR/state/connections.$_IP"
454 netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
455 netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
457 while read dest src; do
458 srcip=`echo $src | sed -e "s/:[^:]*$//"`
459 srcport=`echo $src | sed -e "s/^.*://"`
460 destip=`echo $dest | sed -e "s/:[^:]*$//"`
461 destport=`echo $dest | sed -e "s/^.*://"`
462 echo "Tickle TCP connection $srcip:$srcport $destip:$destport"
463 ctdb tickle $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
464 echo "Tickle TCP connection $destip:$destport $srcip:$srcport"
465 ctdb tickle $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
469 [ $_failed = 0 ] || {
470 echo "Failed to send tickle control"
475 ########################################################
476 # start/stop the nfs service on different platforms
477 ########################################################
480 [ -x $CTDB_ETCDIR/init.d/nfsserver ] && {
483 [ -x $CTDB_ETCDIR/init.d/nfslock ] && {
491 service nfsserver start
494 service nfsserver stop > /dev/null 2>&1
497 set_proc "fs/nfsd/threads" 0
498 service nfsserver stop > /dev/null 2>&1
500 service nfsserver start
507 service nfslock start
515 set_proc "fs/nfsd/threads" 0
516 service nfs stop > /dev/null 2>&1
517 service nfslock stop > /dev/null 2>&1
519 service nfslock start
525 echo "Unknown platform. NFS is not supported with ctdb"
531 ########################################################
532 # start/stop the nfs lockmanager service on different platforms
533 ########################################################
534 startstop_nfslock() {
536 [ -x $CTDB_ETCDIR/init.d/nfsserver ] && {
539 [ -x $CTDB_ETCDIR/init.d/nfslock ] && {
545 # for sles there is no service for lockmanager
546 # so we instead just shutdown/restart nfs
549 service nfsserver start
552 service nfsserver stop > /dev/null 2>&1
555 service nfsserver stop
556 service nfsserver start
563 service nfslock start
566 service nfslock stop > /dev/null 2>&1
570 service nfslock start
575 echo "Unknown platform. NFS locking is not supported with ctdb"
586 local _state_dir="$CTDB_VARDIR/state/interface_modify"
587 local _lockfile="$_state_dir/$_iface.flock"
588 local _readd_base="$_state_dir/$_iface.readd.d"
590 mkdir -p $_state_dir || {
592 echo "Failed to mkdir -p $_state_dir - $ret"
596 test -f $_lockfile || {
600 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh add "$_iface" "$_ip" "$_maskbits" "$_readd_base"
604 delete_ip_from_iface()
609 local _state_dir="$CTDB_VARDIR/state/interface_modify"
610 local _lockfile="$_state_dir/$_iface.flock"
611 local _readd_base="$_state_dir/$_iface.readd.d"
613 mkdir -p $_state_dir || {
615 echo "Failed to mkdir -p $_state_dir - $ret"
619 test -f $_lockfile || {
623 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh delete "$_iface" "$_ip" "$_maskbits" "$_readd_base"
627 setup_iface_ip_readd_script()
632 local _readd_script=$4
633 local _state_dir="$CTDB_VARDIR/state/interface_modify"
634 local _lockfile="$_state_dir/$_iface.flock"
635 local _readd_base="$_state_dir/$_iface.readd.d"
637 mkdir -p $_state_dir || {
639 echo "Failed to mkdir -p $_state_dir - $ret"
643 test -f $_lockfile || {
647 flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh readd_script "$_iface" "$_ip" "$_maskbits" "$_readd_base" "$_readd_script"
651 ########################################################
652 # some simple logic for counting events - per eventscript
653 # usage: ctdb_counter_init
655 # ctdb_check_counter_limit <limit>
656 # ctdb_check_counter_limit succeeds when count >= <limit>
657 ########################################################
658 _ctdb_counter_common () {
659 _service_name="${1:-${service_name}}"
660 _counter_file="$ctdb_fail_dir/$_service_name"
661 mkdir -p "${_counter_file%/*}" # dirname
663 ctdb_counter_init () {
664 _ctdb_counter_common "$1"
668 ctdb_counter_incr () {
669 _ctdb_counter_common "$1"
672 echo -n 1 >> "$_counter_file"
674 ctdb_check_counter_limit () {
677 _limit="${1:-${service_fail_limit}}"
681 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
682 if [ $_size -ge $_limit ] ; then
683 echo "ERROR: more than $_limit consecutive failures for $service_name, marking cluster unhealthy"
685 elif [ $_size -gt 0 -a -z "$_quiet" ] ; then
686 echo "WARNING: less than $_limit consecutive failures ($_size) for $service_name, not unhealthy yet"
689 ctdb_check_counter_equal () {
695 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
696 if [ $_size -eq $_limit ] ; then
701 ctdb_check_counter () {
702 _msg="${1:-error}" # "error" - anything else is silent on fail
703 _op="${2:--ge}" # an integer operator supported by test
704 _limit="${3:-${service_fail_limit}}"
706 _ctdb_counter_common "$1"
709 _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
710 if [ $_size $_op $_limit ] ; then
711 if [ "$_msg" = "error" ] ; then
712 echo "ERROR: $_limit consecutive failures for $_service_name, marking node unhealthy"
720 ########################################################
722 ctdb_status_dir="$CTDB_VARDIR/status"
723 ctdb_fail_dir="$CTDB_VARDIR/failcount"
725 ctdb_setup_service_state_dir ()
727 service_state_dir="$CTDB_VARDIR/state/${1:-${service_name}}"
728 mkdir -p "$service_state_dir" || {
729 echo "Error creating state dir \"$service_state_dir\""
734 ########################################################
735 # Managed status history, for auto-start/stop
737 ctdb_managed_dir="$CTDB_VARDIR/managed_history"
739 _ctdb_managed_common ()
741 _service_name="${1:-${service_name}}"
742 _ctdb_managed_file="$ctdb_managed_dir/$_service_name"
745 ctdb_service_managed ()
747 _ctdb_managed_common "$@"
748 mkdir -p "$ctdb_managed_dir"
749 touch "$_ctdb_managed_file"
752 ctdb_service_unmanaged ()
754 _ctdb_managed_common "$@"
755 rm -f "$_ctdb_managed_file"
758 is_ctdb_previously_managed_service ()
760 _ctdb_managed_common "$@"
761 [ -f "$_ctdb_managed_file" ]
764 ########################################################
765 # Check and set status
769 echo "node is \"$1\", \"${script_name}\" reports problem: $(cat $2)"
774 if [ -r "$ctdb_status_dir/$script_name/unhealthy" ] ; then
775 log_status_cat "unhealthy" "$ctdb_status_dir/$script_name/unhealthy"
777 elif [ -r "$ctdb_status_dir/$script_name/banned" ] ; then
778 log_status_cat "banned" "$ctdb_status_dir/$script_name/banned"
787 d="$ctdb_status_dir/$script_name"
794 for i in "banned" "unhealthy" ; do
801 ##################################################################
802 # Reconfigure a service on demand
804 _ctdb_service_reconfigure_common ()
806 _d="$ctdb_status_dir/${1:-${service_name}}"
808 _ctdb_service_reconfigure_flag="$_d/reconfigure"
811 ctdb_service_needs_reconfigure ()
813 _ctdb_service_reconfigure_common "$@"
814 [ -e "$_ctdb_service_reconfigure_flag" ]
817 ctdb_service_set_reconfigure ()
819 _ctdb_service_reconfigure_common "$@"
820 >"$_ctdb_service_reconfigure_flag"
823 ctdb_service_unset_reconfigure ()
825 _ctdb_service_reconfigure_common "$@"
826 rm -f "$_ctdb_service_reconfigure_flag"
829 ctdb_service_reconfigure ()
831 echo "Reconfiguring service \"$service_name\"..."
832 ctdb_service_unset_reconfigure "$@"
833 service_reconfigure "$@" || return $?
834 ctdb_counter_init "$@"
837 # Default service_reconfigure() function.
838 service_reconfigure ()
840 service "${1:-$service_name}" restart
843 ctdb_service_check_reconfigure ()
845 # Only do this for certain events.
846 case "$event_name" in
847 monitor|ipreallocated) : ;;
851 if ctdb_service_needs_reconfigure "$@" ; then
852 ctdb_service_reconfigure "$@"
854 # Fall through to non-monitor events.
855 [ "$event_name" = "monitor" ] || return 0
857 # We don't want to proceed with the rest of the monitor event
858 # here, so we exit. However, if we exit 0 then, if the
859 # service was previously broken, we might return a false
860 # positive. So we simply retrieve the status of this script
861 # from the previous monitor loop and exit with that status.
862 ctdb scriptstatus | \
863 grep -q -E "^${script_name}[[:space:]]+Status:OK[[:space:]]"
868 ##################################################################
869 # Does CTDB manage this service? - and associated auto-start/stop
871 ctdb_compat_managed_service ()
873 if [ "$1" = "yes" -a "$2" = "$_service_name" ] ; then
874 CTDB_MANAGED_SERVICES="$CTDB_MANAGED_SERVICES $2"
878 is_ctdb_managed_service ()
880 _service_name="${1:-${service_name}}"
882 # $t is used just for readability and to allow better accurate
883 # matching via leading/trailing spaces
884 t=" $CTDB_MANAGED_SERVICES "
886 # Return 0 if "<space>$_service_name<space>" appears in $t
887 if [ "${t#* ${_service_name} }" != "${t}" ] ; then
891 # If above didn't match then update $CTDB_MANAGED_SERVICES for
892 # backward compatibility and try again.
893 ctdb_compat_managed_service "$CTDB_MANAGES_VSFTPD" "vsftpd"
894 ctdb_compat_managed_service "$CTDB_MANAGES_SAMBA" "samba"
895 ctdb_compat_managed_service "$CTDB_MANAGES_SCP" "scp"
896 ctdb_compat_managed_service "$CTDB_MANAGES_WINBIND" "winbind"
897 ctdb_compat_managed_service "$CTDB_MANAGES_HTTPD" "httpd"
898 ctdb_compat_managed_service "$CTDB_MANAGES_ISCSI" "iscsi"
899 ctdb_compat_managed_service "$CTDB_MANAGES_CLAMD" "clamd"
900 ctdb_compat_managed_service "$CTDB_MANAGES_NFS" "nfs"
901 ctdb_compat_managed_service "$CTDB_MANAGES_NFS" "nfs-ganesha-gpfs"
903 t=" $CTDB_MANAGED_SERVICES "
905 # Return 0 if "<space>$_service_name<space>" appears in $t
906 [ "${t#* ${_service_name} }" != "${t}" ]
909 ctdb_start_stop_service ()
911 _service_name="${1:-${service_name}}"
913 [ "$event_name" = "monitor" ] || return 0
915 if is_ctdb_managed_service "$_service_name" ; then
916 if ! is_ctdb_previously_managed_service "$_service_name" ; then
917 echo "Starting service \"$_service_name\" - now managed"
918 ctdb_service_start "$_service_name"
922 if is_ctdb_previously_managed_service "$_service_name" ; then
923 echo "Stopping service \"$_service_name\" - no longer managed"
924 ctdb_service_stop "$_service_name"
930 ctdb_service_start ()
932 # The service is marked managed if we've ever tried to start it.
933 ctdb_service_managed "$@"
935 # Here we only want $1. If no argument is passed then
936 # service_start needs to know.
937 service_start "$@" || return $?
939 ctdb_counter_init "$@"
944 ctdb_service_unmanaged "$@"
948 # Default service_start() and service_stop() functions.
950 # These may be overridden in an eventscript. When overriding, the
951 # following convention must be followed. If these functions are
952 # called with no arguments then they may use internal logic to
953 # determine whether the service is managed and, therefore, whether
954 # they should take any action. However, if the service name is
955 # specified as an argument then an attempt must be made to start or
956 # stop the service. This is because the auto-start/stop code calls
957 # them with the service name as an argument.
960 service "${1:-${service_name}}" start
965 service "${1:-${service_name}}" stop
968 ##################################################################
970 ctdb_standard_event_handler ()
985 ipv4_host_addr_to_net_addr()
990 local HOST0=$(echo $HOST | awk -F . '{print $4}')
991 local HOST1=$(echo $HOST | awk -F . '{print $3}')
992 local HOST2=$(echo $HOST | awk -F . '{print $2}')
993 local HOST3=$(echo $HOST | awk -F . '{print $1}')
995 local HOST_NUM=$(( $HOST0 + $HOST1 * 256 + $HOST2 * (256 ** 2) + $HOST3 * (256 ** 3) ))
997 local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
999 local NET_NUM=$(( $HOST_NUM & $MASK_NUM))
1001 local NET0=$(( $NET_NUM & 255 ))
1002 local NET1=$(( ($NET_NUM & (255 * 256)) / 256 ))
1003 local NET2=$(( ($NET_NUM & (255 * 256**2)) / 256**2 ))
1004 local NET3=$(( ($NET_NUM & (255 * 256**3)) / 256**3 ))
1006 echo "$NET3.$NET2.$NET1.$NET0"
1009 ipv4_maskbits_to_net_mask()
1013 local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
1015 local MASK0=$(( $MASK_NUM & 255 ))
1016 local MASK1=$(( ($MASK_NUM & (255 * 256)) / 256 ))
1017 local MASK2=$(( ($MASK_NUM & (255 * 256**2)) / 256**2 ))
1018 local MASK3=$(( ($MASK_NUM & (255 * 256**3)) / 256**3 ))
1020 echo "$MASK3.$MASK2.$MASK1.$MASK0"
1023 ipv4_is_valid_addr()
1028 local N=`echo $ADDR | sed -e 's/[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*//'`
1029 test -n "$N" && fail=1
1031 local ADDR0=$(echo $ADDR | awk -F . '{print $4}')
1032 local ADDR1=$(echo $ADDR | awk -F . '{print $3}')
1033 local ADDR2=$(echo $ADDR | awk -F . '{print $2}')
1034 local ADDR3=$(echo $ADDR | awk -F . '{print $1}')
1036 test "$ADDR0" -gt 255 && fail=1
1037 test "$ADDR1" -gt 255 && fail=1
1038 test "$ADDR2" -gt 255 && fail=1
1039 test "$ADDR3" -gt 255 && fail=1
1041 test x"$fail" != x"0" && {
1042 #echo "IPv4: '$ADDR' is not a valid address"
1049 # iptables doesn't like being re-entered, so flock-wrap it.
1052 flock -w 30 $CTDB_VARDIR/iptables-ctdb.flock /sbin/iptables "$@"
1055 ########################################################
1057 ########################################################
1059 # Temporary directory for tickles.
1060 tickledir="$CTDB_VARDIR/state/tickles"
1061 mkdir -p "$tickledir"
1067 mkdir -p "$tickledir" # Just in case
1070 _pnn=$(ctdb pnn) ; _pnn=${_pnn#PNN:}
1072 # What public IPs do I hold?
1073 _ips=$(ctdb -Y ip | awk -F: -v pnn=$_pnn '$3 == pnn {print $2}')
1075 # IPs as a regexp choice
1076 _ipschoice="($(echo $_ips | sed -e 's/ /|/g' -e 's/\./\\\\./g'))"
1078 # Record connections to our public IPs in a temporary file
1079 _my_connections="${tickledir}/${_port}.connections"
1080 rm -f "$_my_connections"
1082 awk -v destpat="^${_ipschoice}:${_port}\$" \
1083 '$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ destpat {print $5, $4}' |
1084 sort >"$_my_connections"
1086 # Record our current tickles in a temporary file
1087 _my_tickles="${tickledir}/${_port}.tickles"
1088 rm -f "$_my_tickles"
1089 for _i in $_ips ; do
1090 ctdb -Y gettickles $_i $_port |
1091 awk -F: 'NR > 1 { printf "%s:%s %s:%s\n", $2, $3, $4, $5 }'
1093 sort >"$_my_tickles"
1095 # Add tickles for connections that we haven't already got tickles for
1096 comm -23 "$_my_connections" "$_my_tickles" |
1097 while read _src _dst ; do
1098 ctdb addtickle $_src $_dst
1101 # Remove tickles for connections that are no longer there
1102 comm -13 "$_my_connections" "$_my_tickles" |
1103 while read _src _dst ; do
1104 ctdb deltickle $_src $_dst
1107 rm -f "$_my_connections" "$_my_tickles"
1110 ########################################################
1111 # load a site local config file
1112 ########################################################
1114 [ -n "$CTDB_RC_LOCAL" -a -x "$CTDB_RC_LOCAL" ] && {
1118 [ -x $CTDB_BASE/rc.local ] && {
1119 . $CTDB_BASE/rc.local
1122 [ -d $CTDB_BASE/rc.local.d ] && {
1123 for i in $CTDB_BASE/rc.local.d/* ; do
1124 [ -x "$i" ] && . "$i"
1128 script_name="${0##*/}" # basename
1129 service_name="$script_name" # default is just the script name
1130 service_fail_limit=1