add a missing part of the import of the previous ganesha patch
[sahlberg/ctdb.git] / config / functions
old mode 100644 (file)
new mode 100755 (executable)
index d68f607..4dc645b
@@ -4,28 +4,31 @@ PATH=/bin:/usr/bin:/usr/sbin:/sbin:$PATH
 
 #######################################
 # pull in a system config file, if any
-loadconfig() {
-    name="$1"
+_loadconfig() {
 
-    if [ "$name" != "ctdb" ] ; then
-       loadconfig "ctdb"
-    fi
-    if [ -z "$name" ] ; then
+    if [ -z "$1" ] ; then
        foo="${service_config:-${service_name}}"
        if [ -n "$foo" ] ; then
            loadconfig "$foo"
        fi
+    elif [ "$1" != "ctdb" ] ; then
+       loadconfig "ctdb"
     fi
 
-    if [ -f /etc/sysconfig/$name ]; then
-       . /etc/sysconfig/$name
-    elif [ -f /etc/default/$name ]; then
-       . /etc/default/$name
-    elif [ -f $CTDB_BASE/sysconfig/$name ]; then
-       . $CTDB_BASE/sysconfig/$name
+
+    if [ -f /etc/sysconfig/$1 ]; then
+       . /etc/sysconfig/$1
+    elif [ -f /etc/default/$1 ]; then
+       . /etc/default/$1
+    elif [ -f $CTDB_BASE/sysconfig/$1 ]; then
+       . $CTDB_BASE/sysconfig/$1
     fi
 }
 
+loadconfig () {
+    _loadconfig "$@"
+}
+
 ##############################################################
 # determine on what type of system (init style) we are running
 detect_init_style() {
@@ -48,7 +51,7 @@ service() {
   _op="$2"
 
   # do nothing, when no service was specified
-  test "x$_service_name" = "x" && return
+  [ -z "$_service_name" ] && return
 
   if [ -x /sbin/service ]; then
       /sbin/service "$_service_name" "$_op"
@@ -62,7 +65,19 @@ service() {
 ######################################################
 # simulate /sbin/service (niced) on platforms that don't have it
 nice_service() { 
-    nice service "$@"
+  _service_name="$1"
+  _op="$2"
+
+  # do nothing, when no service was specified
+  [ -z "$_service_name" ] && return
+
+  if [ -x /sbin/service ]; then
+      nice /sbin/service "$_service_name" "$_op"
+  elif [ -x /etc/init.d/$_service_name ]; then
+      nice /etc/init.d/$_service_name "$_op"
+  elif [ -x /etc/rc.d/init.d/$_service_name ]; then
+      nice /etc/rc.d/init.d/$_service_name "$_op"
+  fi
 }
 
 ######################################################
@@ -124,46 +139,23 @@ ctdb_wait_tcp_ports() {
 }
 
 
-
-######################################################
-# wait for a set of directories
-# usage: ctdb_wait_directories SERVICE_NAME <directories...>
-######################################################
-ctdb_wait_directories() {
-  service_name="$1"
-  shift
-  wait_dirs="$*"
-  [ -z "$wait_dirs" ] && return;
-  all_ok=0
-  echo "Waiting for local directories for $service_name"
-  while [ $all_ok -eq 0 ]; do
-         all_ok=1
-         for d in $wait_dirs; do
-             [ -d $d ] || all_ok=0
-         done
-         [ $all_ok -eq 1 ] || sleep 1
-         ctdb status > /dev/null 2>&1 || {
-               echo "ctdb daemon has died. Exiting directory wait for $service_name"
-               exit 1
-         }
-  done
-  echo "Local directories for $service_name are available"
-}
-
-
 ######################################################
 # check that a rpc server is registered with portmap
 # and responding to requests
 # usage: ctdb_check_rpc SERVICE_NAME PROGNUM VERSION
 ######################################################
 ctdb_check_rpc() {
-    service_name="$1"
+    progname="$1"
     prognum="$2"
     version="$3"
-    rpcinfo -u localhost $prognum $version > /dev/null || {
-           echo "ERROR: $service_name not responding to rpc requests"
-           exit 1
-    }
+
+    ctdb_check_rpc_out=$(rpcinfo -u localhost $prognum $version 2>&1)
+    if [ $? -ne 0 ] ; then
+       ctdb_check_rpc_out="ERROR: $progname failed RPC check:
+$ctdb_check_rpc_out"
+       echo "$ctdb_check_rpc_out"
+       return 1
+    fi
 }
 
 ######################################################
@@ -172,18 +164,15 @@ ctdb_check_rpc() {
 # usage: ctdb_check_directories_probe SERVICE_NAME <directories...>
 ######################################################
 ctdb_check_directories_probe() {
-  service_name="$1"
-  shift
-  for d ; do
-      case "$d" in
-         *%*)
-             continue
-             ;;
-         *)
-             [ -d "$d" ] || return 1
-      esac
-  done
-  return 0
+    while IFS="" read d ; do
+       case "$d" in
+           *%*)
+               continue
+               ;;
+           *)
+               [ -d "${d}/." ] || return 1
+       esac
+    done
 }
 
 ######################################################
@@ -191,59 +180,27 @@ ctdb_check_directories_probe() {
 # usage: ctdb_check_directories SERVICE_NAME <directories...>
 ######################################################
 ctdb_check_directories() {
-  # Note: ctdb_check_directories_probe sets both $service_name and $d.
-  ctdb_check_directories_probe "$@" || {
-      echo "ERROR: $service_name directory $d not available"
-      exit 1
-  }
+    n="${1:-${service_name}}"
+    ctdb_check_directories_probe || {
+       echo "ERROR: $n directory \"$d\" not available"
+       exit 1
+    }
 }
 
 ######################################################
 # check a set of tcp ports
-# usage: ctdb_check_tcp_ports SERVICE_NAME <ports...>
+# usage: ctdb_check_tcp_ports <ports...>
 ######################################################
 ctdb_check_tcp_ports() {
-  [ -z "$1" ] && return;
-
-  # check availability of netcat or netstat first
-  NETCAT=""
-  NETSTAT=""
-  if [ -x /usr/bin/netstat ]; then
-      NETSTAT=/usr/bin/netstat
-  elif [ -x /bin/netstat ]; then
-      NETSTAT=/bin/netstat
-  elif [ -x /usr/bin/netcat ]; then
-      NETCAT=/usr/bin/netcat
-  elif [ -x /bin/netcat ]; then
-      NETCAT=/bin/netcat
-  elif [ -x /usr/bin/nc ]; then
-      NETCAT=/usr/bin/nc
-  elif [ -x /bin/nc ]; then
-      NETCAT=/bin/nc
-  fi
 
-  for p ; do
-      all_ok=1
-
-      if [ "x${NETCAT}" != "x" ]; then
-          ${NETCAT} -z 127.0.0.1 $p > /dev/null || all_ok=0
-      elif [ "x${NETSTAT}" != "x" ]; then
-          if ! ${NETSTAT} -a -n | egrep "0.0.0.0:$p .*LISTEN" > /dev/null ; then
-              if ! ${NETSTAT} -a -n | egrep ":::$p .*LISTEN" > /dev/null ; then
-                  all_ok=0
-              fi
-          fi
-      else
-          echo "ERROR: neither netcat (or nc) nor netstat found!"
-          echo "ERROR: can't monitor ${service_name} tcp port ${p}"
-          all_ok=0
-      fi
-
-      [ $all_ok -eq 1 ] || {
-         echo "ERROR: $service_name tcp port $p is not responding"
-         return 1
-      }
-  done
+    for p ; do
+       if ! netstat -a -t -n | grep -q "0\.0\.0\.0:$p .*LISTEN" ; then
+            if ! netstat -a -t -n | grep -q ":::$p .*LISTEN" ; then
+               echo "ERROR: $service_name tcp port $p is not responding"
+               return 1
+            fi
+       fi
+    done
 }
 
 ######################################################
@@ -251,34 +208,13 @@ ctdb_check_tcp_ports() {
 # usage: ctdb_check_unix_socket SERVICE_NAME <socket_path>
 ######################################################
 ctdb_check_unix_socket() {
-  socket_path="$1"
-  [ -z "$socket_path" ] && return;
-
-  # check availability of netstat first
-  NETSTAT=""
-  if [ -x $(type -p netstat) ]; then
-        NETSTAT=$(type -p netstat)
-  elif [ -x /usr/bin/netstat ]; then
-      NETSTAT=/usr/bin/netstat
-  elif [ -x /bin/netstat ]; then
-      NETSTAT=/bin/netstat
-  fi
+    socket_path="$1"
+    [ -z "$socket_path" ] && return
 
-  all_ok=1
-  if [ "x$NETSTAT" != "x" ]; then
-    if $NETSTAT -l -a -n | grep -qE "^unix.*LISTEN.*${socket_path}$"; then
-      all_ok=1
-    else
-      all_ok=0
+    if ! netstat --unix -a -n | grep -q "^unix.*LISTEN.*${socket_path}$"; then
+        echo "ERROR: $service_name socket $socket_path not found"
+        return 1
     fi
-    else
-    [ -S ${socket_path} ] && all_ok=1 || all_ok=0
-  fi
-
-  [ $all_ok -eq 1 ] || {
-    echo "ERROR: $service_name socket $socket_path not found"
-    return 1
-  }
 }
 
 ######################################################
@@ -303,7 +239,7 @@ kill_tcp_connections() {
     _failed=0
 
     _killcount=0
-    connfile="$CTDB_BASE/state/connections.$_IP"
+    connfile="$CTDB_VARDIR/state/connections.$_IP"
     netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
     netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
 
@@ -353,7 +289,7 @@ kill_tcp_connections_local_only() {
     _failed=0
 
     _killcount=0
-    connfile="$CTDB_BASE/state/connections.$_IP"
+    connfile="$CTDB_VARDIR/state/connections.$_IP"
     netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
     netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
 
@@ -387,6 +323,36 @@ kill_tcp_connections_local_only() {
     echo "killed $_killcount TCP connections to released IP $_IP"
 }
 
+##################################################################
+# tickle any TCP connections with the given IP
+##################################################################
+tickle_tcp_connections() {
+    _IP="$1"
+    _failed=0
+
+    _killcount=0
+    connfile="$CTDB_VARDIR/state/connections.$_IP"
+    netstat -tn |egrep "^tcp.*[[:space:]]+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
+    netstat -tn |egrep "^tcp.*[[:space:]]+::ffff:$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' >> $connfile
+
+    while read dest src; do
+       srcip=`echo $src | sed -e "s/:[^:]*$//"`
+       srcport=`echo $src | sed -e "s/^.*://"`
+       destip=`echo $dest | sed -e "s/:[^:]*$//"`
+       destport=`echo $dest | sed -e "s/^.*://"`
+       echo "Tickle TCP connection $srcip:$srcport $destip:$destport"
+       ctdb tickle $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
+       echo "Tickle TCP connection $destip:$destport $srcip:$srcport"
+       ctdb tickle $destip:$destport $srcip:$srcport >/dev/null 2>&1 || _failed=1
+     done < $connfile
+    /bin/rm -f $connfile
+
+    [ $_failed = 0 ] || {
+       echo "Failed to send tickle control"
+       return;
+    }
+}
+
 ########################################################
 # start/stop the nfs service on different platforms
 ########################################################
@@ -408,6 +374,9 @@ startstop_nfs() {
                stop)
                        service nfsserver stop > /dev/null 2>&1
                        ;;
+               restart)
+                       service nfsserver restart
+                       ;;
                esac
                ;;
        rhel)
@@ -420,6 +389,10 @@ startstop_nfs() {
                        service nfs stop > /dev/null 2>&1
                        service nfslock stop > /dev/null 2>&1
                        ;;
+               restart)
+                       service nfslock restart
+                       service nfs restart
+                       ;;
                esac
                ;;
        *)
@@ -452,6 +425,10 @@ startstop_nfslock() {
                stop)
                        service nfsserver stop > /dev/null 2>&1
                        ;;
+               restart)
+                       service nfsserver stop
+                       service nfsserver start
+                       ;;
                esac
                ;;
        rhel)
@@ -462,6 +439,10 @@ startstop_nfslock() {
                stop)
                        service nfslock stop > /dev/null 2>&1
                        ;;
+               restart)
+                       service nfslock stop
+                       service nfslock start
+                       ;;
                esac
                ;;
        *)
@@ -471,28 +452,86 @@ startstop_nfslock() {
        esac
 }
 
-########################################################
-# remove an ip address from an interface
-########################################################
+# better use delete_ip_from_iface() together with add_ip_to_iface
+# remove_ip should be removed in future
 remove_ip() {
-       # the ip tool will delete all secondary IPs if this is the primary.
-       # To work around this _very_ annoying behaviour we have to keep a
-       # record of the secondaries and re-add them afterwards. yuck
-       secondaries=""
-       if ip addr list dev $2 primary | grep -q "inet $1 " ; then
-           secondaries=`ip addr list dev $2 secondary | grep " inet " | awk '{print $2}'`
-       fi
-       ip addr del $1 dev $2 >/dev/null 2>/dev/null || failed=1
-       [ -z "$secondaries" ] || {
-           for i in $secondaries; do
-               if ip addr list dev $2 | grep -q "inet $i" ; then
-                   echo "kept secondary $i on dev $2"
-               else 
-                   echo "re-adding secondary address $i to dev $2"
-                   ip addr add $i dev $2 || failed=1           
-               fi
-           done
+       local _ip_maskbits=$1
+       local _iface=$2
+       local _ip=`echo "$_ip_maskbits" | cut -d '/' -f1`
+       local _maskbits=`echo "$_ip_maskbits" | cut -d '/' -f2`
+
+       delete_ip_from_iface "$_iface" "$_ip" "$_maskbits"
+       return $?
+}
+
+add_ip_to_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+       local _state_dir="$CTDB_VARDIR/state/interface_modify"
+       local _lockfile="$_state_dir/$_iface.flock"
+       local _readd_base="$_state_dir/$_iface.readd.d"
+
+       mkdir -p $_state_dir || {
+               ret=$?
+               echo "Failed to mkdir -p $_state_dir - $ret"
+               return $ret
+       }
+
+       test -f $_lockfile || {
+               touch $_lockfile
+       }
+
+       flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh add "$_iface" "$_ip" "$_maskbits" "$_readd_base"
+       return $?
+}
+
+delete_ip_from_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+       local _state_dir="$CTDB_VARDIR/state/interface_modify"
+       local _lockfile="$_state_dir/$_iface.flock"
+       local _readd_base="$_state_dir/$_iface.readd.d"
+
+       mkdir -p $_state_dir || {
+               ret=$?
+               echo "Failed to mkdir -p $_state_dir - $ret"
+               return $ret
+       }
+
+       test -f $_lockfile || {
+               touch $_lockfile
        }
+
+       flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh delete "$_iface" "$_ip" "$_maskbits" "$_readd_base"
+       return $?
+}
+
+setup_iface_ip_readd_script()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+       local _readd_script=$4
+       local _state_dir="$CTDB_VARDIR/state/interface_modify"
+       local _lockfile="$_state_dir/$_iface.flock"
+       local _readd_base="$_state_dir/$_iface.readd.d"
+
+       mkdir -p $_state_dir || {
+               ret=$?
+               echo "Failed to mkdir -p $_state_dir - $ret"
+               return $ret
+       }
+
+       test -f $_lockfile || {
+               touch $_lockfile
+       }
+
+       flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh readd_script "$_iface" "$_ip" "$_maskbits" "$_readd_base" "$_readd_script"
+       return $?
 }
 
 ########################################################
@@ -509,7 +548,7 @@ _ctdb_counter_common () {
 ctdb_counter_init () {
     _ctdb_counter_common
 
-    echo -n > "$_counter_file"
+    >"$_counter_file"
 }
 ctdb_counter_incr () {
     _ctdb_counter_common
@@ -520,15 +559,31 @@ ctdb_counter_incr () {
 ctdb_check_counter_limit () {
     _ctdb_counter_common
 
+    _limit="${1:-${service_fail_limit}}"
+    _quiet="$2"
+
     # unary counting!
     _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
-    if [ $_size -ge $service_fail_limit ] ; then
-       echo "ERROR: more than $service_fail_limit consecutive failures, marking cluster unhealthy"
+    if [ $_size -ge $_limit ] ; then
+       echo "ERROR: more than $_limit consecutive failures for $service_name, marking cluster unhealthy"
        exit 1
-    else
-       echo "WARNING: less than $service_fail_limit consecutive failures, not unhealthy yet"
+    elif [ $_size -gt 0 -a -z "$_quiet" ] ; then
+       echo "WARNING: less than $_limit consecutive failures ($_size) for $service_name, not unhealthy yet"
     fi
 }
+ctdb_check_counter_equal () {
+    _ctdb_counter_common
+
+    _limit=$1
+
+    # unary counting!
+    _size=$(stat -c "%s" "$_counter_file" 2>/dev/null || echo 0)
+    if [ $_size -eq $_limit ] ; then
+       return 1
+    fi
+    return 0
+}
+
 ########################################################
 
 ctdb_spool_dir="/var/spool/ctdb"
@@ -536,13 +591,18 @@ ctdb_status_dir="$ctdb_spool_dir/status"
 ctdb_fail_dir="$ctdb_spool_dir/failcount"
 ctdb_active_dir="$ctdb_spool_dir/active"
 
+log_status_cat ()
+{
+    echo "node is \"$1\", \"${script_name}\" reports problem: $(cat $2)"
+}
+
 ctdb_checkstatus ()
 {
-    if [ -r "$ctdb_status_dir/$service_name/unhealthy" ] ; then
-       log_status_cat "unhealthy" "$ctdb_status_dir/$service_name/unhealthy"
+    if [ -r "$ctdb_status_dir/$script_name/unhealthy" ] ; then
+       log_status_cat "unhealthy" "$ctdb_status_dir/$script_name/unhealthy"
        return 1
-    elif [ -r "$ctdb_status_dir/$service_name/banned" ] ; then
-       log_status_cat "banned" "$ctdb_status_dir/$service_name/banned"
+    elif [ -r "$ctdb_status_dir/$script_name/banned" ] ; then
+       log_status_cat "banned" "$ctdb_status_dir/$script_name/banned"
        return 2
     else
        return 0
@@ -551,7 +611,7 @@ ctdb_checkstatus ()
 
 ctdb_setstatus ()
 {
-    d="$ctdb_status_dir/$service_name"
+    d="$ctdb_status_dir/$script_name"
     case "$1" in
        unhealthy|banned)
            mkdir -p "$d"
@@ -585,7 +645,7 @@ ctdb_service_unset_reconfigure ()
 ctdb_service_reconfigure ()
 {
     if [ -n "$service_reconfigure" ] ; then
-       $service_reconfigure
+       eval $service_reconfigure
     else
        service "$service_name" restart
     fi
@@ -602,48 +662,53 @@ ctdb_compat_managed_service ()
 
 is_ctdb_managed_service ()
 {
+    _service_name="${1:-${service_name}}"
+
     t=" $CTDB_MANAGED_SERVICES "
 
     ctdb_compat_managed_service "$CTDB_MANAGES_VSFTPD"   "vsftpd"
     ctdb_compat_managed_service "$CTDB_MANAGES_SAMBA"    "samba"
     ctdb_compat_managed_service "$CTDB_MANAGES_SCP"      "scp"
-    ctdb_compat_managed_service "$CTDB_MANAGES_WINDBIND" "windbind"
+    ctdb_compat_managed_service "$CTDB_MANAGES_WINBIND"  "winbind"
     ctdb_compat_managed_service "$CTDB_MANAGES_HTTPD"    "httpd"
     ctdb_compat_managed_service "$CTDB_MANAGES_ISCSI"    "iscsi"
     ctdb_compat_managed_service "$CTDB_MANAGES_CLAMD"    "clamd"
+    ctdb_compat_managed_service "$CTDB_MANAGES_NFS"      "nfs"
+    ctdb_compat_managed_service "$CTDB_MANAGES_NFS"      "nfs-ganesha-gpfs"
 
-    # Returns 0 if "<space>$service_name<space>" appears in $t
-    [ "${t#* ${service_name} }" != "${t}" ]
+    # Returns 0 if "<space>$_service_name<space>" appears in $t
+    [ "${t#* ${_service_name} }" != "${t}" ]
 }
 
 ctdb_start_stop_service ()
 {
-    _active="$ctdb_active_dir/$service_name"
+    _service_name="${1:-${service_name}}"
 
-    if is_ctdb_managed_service ; then
+    _active="$ctdb_active_dir/$_service_name"
+    if is_ctdb_managed_service "$_service_name"; then
        if ! [ -e "$_active" ] ; then
-           echo "Starting service $service_name"
+           echo "Starting service $_service_name"
            ctdb_service_start || exit $?
            mkdir -p "$ctdb_active_dir"
            touch "$_active"
            exit 0
        fi
-    elif ! is_ctdb_managed_service ; then
+    else
        if [ -e "$_active" ] ; then
-           echo "Stopping service $service_name"
+           echo "Stopping service $_service_name"
            ctdb_service_stop || exit $?
            rm -f "$_active"
+           exit 0
        fi
-       exit 0
     fi
 }
 
 ctdb_service_start ()
 {
     if [ -n "$service_start" ] ; then
-       $service_start
+       eval $service_start || return $?
     else
-       service "$service_name" start
+       service "$service_name" start || return $?
     fi
     ctdb_counter_init
 }
@@ -651,12 +716,152 @@ ctdb_service_start ()
 ctdb_service_stop ()
 {
     if [ -n "$service_stop" ] ; then
-       $service_stop
+       eval $service_stop
     else
        service "$service_name" stop
     fi
 }
 
+ctdb_standard_event_handler ()
+{
+    case "$1" in
+       status)
+           ctdb_checkstatus
+           exit
+           ;;
+       setstatus)
+            shift
+           ctdb_setstatus "$@"
+           exit
+           ;;
+    esac
+}
+
+ipv4_host_addr_to_net_addr()
+{
+       local HOST=$1
+       local MASKBITS=$2
+
+       local HOST0=$(echo $HOST | awk -F . '{print $4}')
+       local HOST1=$(echo $HOST | awk -F . '{print $3}')
+       local HOST2=$(echo $HOST | awk -F . '{print $2}')
+       local HOST3=$(echo $HOST | awk -F . '{print $1}')
+
+       local HOST_NUM=$(( $HOST0 + $HOST1 * 256 + $HOST2 * (256 ** 2) + $HOST3 * (256 ** 3) ))
+
+       local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
+
+       local NET_NUM=$(( $HOST_NUM & $MASK_NUM))
+
+       local NET0=$(( $NET_NUM & 255 ))
+       local NET1=$(( ($NET_NUM & (255 * 256)) / 256 ))
+       local NET2=$(( ($NET_NUM & (255 * 256**2)) / 256**2 ))
+       local NET3=$(( ($NET_NUM & (255 * 256**3)) / 256**3 ))
+
+       echo "$NET3.$NET2.$NET1.$NET0"
+}
+
+ipv4_maskbits_to_net_mask()
+{
+       local MASKBITS=$1
+
+       local MASK_NUM=$(( ( (2**32 - 1) * (2**(32 - $MASKBITS)) ) & (2**32 - 1) ))
+
+       local MASK0=$(( $MASK_NUM & 255 ))
+       local MASK1=$(( ($MASK_NUM & (255 * 256)) / 256 ))
+       local MASK2=$(( ($MASK_NUM & (255 * 256**2)) / 256**2 ))
+       local MASK3=$(( ($MASK_NUM & (255 * 256**3)) / 256**3 ))
+
+       echo "$MASK3.$MASK2.$MASK1.$MASK0"
+}
+
+ipv4_is_valid_addr()
+{
+       local ADDR=$1
+       local fail=0
+
+       local N=`echo $ADDR | sed -e 's/[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*//'`
+       test -n "$N" && fail=1
+
+       local ADDR0=$(echo $ADDR | awk -F . '{print $4}')
+       local ADDR1=$(echo $ADDR | awk -F . '{print $3}')
+       local ADDR2=$(echo $ADDR | awk -F . '{print $2}')
+       local ADDR3=$(echo $ADDR | awk -F . '{print $1}')
+
+       test "$ADDR0" -gt 255 && fail=1
+       test "$ADDR1" -gt 255 && fail=1
+       test "$ADDR2" -gt 255 && fail=1
+       test "$ADDR3" -gt 255 && fail=1
+
+       test x"$fail" != x"0" && {
+               #echo "IPv4: '$ADDR' is not a valid address"
+               return 1;
+       }
+
+       return 0;
+}
+
+# iptables doesn't like being re-entered, so flock-wrap it.
+iptables()
+{
+       flock -w 30 /var/ctdb/iptables-ctdb.flock /sbin/iptables "$@"
+}
+
+########################################################
+# tickle handling
+########################################################
+
+# Temporary directory for tickles.
+tickledir="$CTDB_VARDIR/state/tickles"
+mkdir -p "$tickledir"
+
+update_tickles ()
+{
+       _port="$1"
+
+       mkdir -p "$tickledir" # Just in case
+
+       # Who am I?
+       _pnn=$(ctdb pnn) ; _pnn=${_pnn#PNN:}
+
+       # What public IPs do I hold?
+       _ips=$(ctdb -Y ip | awk -F: -v pnn=$_pnn '$3 == pnn {print $2}')
+
+       # IPs as a regexp choice
+       _ipschoice="($(echo $_ips | sed -e 's/ /|/g' -e 's/\./\\\\./g'))"
+
+       # Record connections to our public IPs in a temporary file
+       _my_connections="${tickledir}/${_port}.connections"
+       rm -f "$_my_connections"
+       netstat -tn |
+       awk -v destpat="^${_ipschoice}:${_port}\$" \
+         '$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ destpat {print $5, $4}' |
+       sort >"$_my_connections"
+
+       # Record our current tickles in a temporary file
+       _my_tickles="${tickledir}/${_port}.tickles"
+       rm -f "$_my_tickles"
+       for _i in $_ips ; do
+               ctdb -Y gettickles $_i $_port | 
+               awk -F: 'NR > 1 { printf "%s:%s %s:%s\n", $2, $3, $4, $5 }'
+       done |
+       sort >"$_my_tickles"
+
+       # Add tickles for connections that we haven't already got tickles for
+       comm -23 "$_my_connections" "$_my_tickles" |
+       while read _src _dst ; do
+               ctdb addtickle $_src $_dst
+       done
+
+       # Remove tickles for connections that are no longer there
+       comm -13 "$_my_connections" "$_my_tickles" |
+       while read _src _dst ; do
+               ctdb deltickle $_src $_dst
+       done
+
+       rm -f "$_my_connections" "$_my_tickles" 
+}
+
 ########################################################
 # load a site local config file
 ########################################################
@@ -671,8 +876,6 @@ ctdb_service_stop ()
        done
 }
 
-# A reasonable default is the basename of the eventscript.
-service_name="${0##*/}" # basename
-
-ctdb_event="$1" ; shift
-cmd="$ctdb_event"
+script_name="${0##*/}"       # basename
+service_name="$script_name"  # default is just the script name
+service_fail_limit=1