config: add interface_modify.sh and call it under flock to make modification on inter...
authorStefan Metzmacher <metze@samba.org>
Wed, 20 Jan 2010 10:10:48 +0000 (11:10 +0100)
committerStefan Metzmacher <metze@samba.org>
Wed, 20 Jan 2010 10:10:48 +0000 (11:10 +0100)
When two releaseip events run in parallel it's possible that the 2nd script
readds a secondary ip that was removed by the 1st script.

metze

Makefile.in
config/events.d/10.interface
config/functions
config/interface_modify.sh [new file with mode: 0755]
packaging/RPM/ctdb.spec.in

index 41b255d71cc173d4d51d81c2ef5ea92996e7d035..eeef41d4abbed4bf161b3b7d936ea8fd720cdadb 100755 (executable)
@@ -211,6 +211,7 @@ install: all
        ${INSTALLCMD} -m 644 include/ctdb_private.h $(DESTDIR)$(includedir) # for samba3
        ${INSTALLCMD} -m 644 config/functions $(DESTDIR)$(etcdir)/ctdb
        ${INSTALLCMD} -m 755 config/statd-callout $(DESTDIR)$(etcdir)/ctdb
+       ${INSTALLCMD} -m 755 config/interface_modify.sh $(DESTDIR)$(etcdir)/ctdb
        ${INSTALLCMD} -m 644 config/events.d/README $(DESTDIR)$(docdir)/ctdb/README.eventscripts
        ${INSTALLCMD} -m 644 doc/recovery-process.txt $(DESTDIR)$(docdir)/ctdb/recovery-process.txt
        ${INSTALLCMD} -m 755 config/events.d/00.ctdb $(DESTDIR)$(etcdir)/ctdb/events.d
index afecd9c1b79ed2d17315e905d2da4860c78bfccf..71274c56783b6f09a1b18d37a65fe9733753c560 100755 (executable)
@@ -17,58 +17,6 @@ loadconfig
        exit 0
 }
 
-add_ip_to_iface()
-{
-       local _iface=$1
-       local _ip=$2
-       local _maskbits=$3
-
-       # we make sure the interface is up first
-       /sbin/ip link set $_iface up || {
-               echo "Failed to bringup interface $_iface"
-               return 1;
-       }
-       /sbin/ip addr add $_ip/$_maskbits brd + dev $_iface || {
-               echo "Failed to add $_ip/$_maskbits on dev $_iface"
-               return 1;
-       }
-
-       return 0;
-}
-
-delete_ip_from_iface()
-{
-       local _iface=$1
-       local _ip=$2
-       local _maskbits=$3
-
-       # 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
-       local _secondaries=""
-       if /sbin/ip addr list dev $_iface primary | grep -q "inet $_ip/$_maskbits " ; then
-           _secondaries=`/sbin/ip addr list dev $_iface secondary | grep " inet " | awk '{print $2}'`
-       fi
-       local _failed=0
-       /sbin/ip addr del $_ip/$_maskbits dev $_iface || _failed=1
-       [ -z "$_secondaries" ] || {
-           local _i=""
-           for _i in $_secondaries; do
-               if /sbin/ip addr list dev $_iface | grep -q "inet $_i" ; then
-                   echo "kept secondary $_i on dev $_iface"
-               else
-                   echo "re-adding secondary address $_i to dev $_iface"
-                   /sbin/ip addr add $_i dev $_iface || _failed=1
-               fi
-           done
-       }
-       [ $_failed = 0 ] || {
-               echo "Failed to del $_ip on dev $_iface"
-               return 1;
-       }
-       return 0;
-}
-
 case "$1" in 
      #############################
      # called when ctdbd starts up
index 8ac348f357b350aa0f98c306285ccdcdc0d7a042..115794ec101ce8ba44b5dfc953f9f937857bfd6a 100644 (file)
@@ -421,9 +421,7 @@ startstop_nfslock() {
        esac
 }
 
-########################################################
-# remove an ip address from an interface
-########################################################
+# better use delete_ip_from_iface() together with add_ip_to_iface
 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
@@ -445,6 +443,36 @@ remove_ip() {
        }
 }
 
+add_ip_to_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+       local _lockfile="$CTDB_BASE/state/interface_modify.$_iface.flock"
+
+       test -f $_lockfile || {
+               touch $_lockfile
+       }
+
+       flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh add "$_iface" "$_ip" "$_maskbits"
+       return $?
+}
+
+delete_ip_from_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+       local _lockfile="$CTDB_BASE/state/interface_modify.$_iface.flock"
+
+       test -f $_lockfile || {
+               touch $_lockfile
+       }
+
+       flock --timeout 30 $_lockfile $CTDB_BASE/interface_modify.sh delete "$_iface" "$_ip" "$_maskbits"
+       return $?
+}
+
 ########################################################
 # some simple logic for counting events - per eventscript
 # usage: ctdb_counter_init
diff --git a/config/interface_modify.sh b/config/interface_modify.sh
new file mode 100755 (executable)
index 0000000..3ac7fe8
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+
+OP=$1
+IFACE=$2
+IP=$3
+MASKBITS=$4
+
+add_ip_to_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+
+       # we make sure the interface is up first
+       /sbin/ip link set $_iface up || {
+               echo "Failed to bringup interface $_iface"
+               return 1;
+       }
+       /sbin/ip addr add $_ip/$_maskbits brd + dev $_iface || {
+               echo "Failed to add $_ip/$_maskbits on dev $_iface"
+               return 1;
+       }
+
+       return 0;
+}
+
+delete_ip_from_iface()
+{
+       local _iface=$1
+       local _ip=$2
+       local _maskbits=$3
+
+       # 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
+       local _secondaries=""
+       if /sbin/ip addr list dev $_iface primary | grep -q "inet $_ip/$_maskbits " ; then
+           _secondaries=`/sbin/ip addr list dev $_iface secondary | grep " inet " | awk '{print $2}'`
+       fi
+       local _failed=0
+       /sbin/ip addr del $_ip/$_maskbits dev $_iface || _failed=1
+       [ -z "$_secondaries" ] || {
+           local _i=""
+           for _i in $_secondaries; do
+               if /sbin/ip addr list dev $_iface | grep -q "inet $_i" ; then
+                   echo "kept secondary $_i on dev $_iface"
+               else
+                   echo "re-adding secondary address $_i to dev $_iface"
+                   /sbin/ip addr add $_i dev $_iface || _failed=1
+               fi
+           done
+       }
+       [ $_failed = 0 ] || {
+               echo "Failed to del $_ip on dev $_iface"
+               return 1;
+       }
+       return 0;
+}
+
+case "$OP" in
+       add)
+               add_ip_to_iface $IFACE $IP $MASKBITS
+               exit $?
+               ;;
+       delete)
+               delete_ip_from_iface $IFACE $IP $MASKBITS
+               exit $?
+               ;;
+esac
+
+echo "$0: unknown operation[$OP]"
+exit 1
index 9101f80c0728e8c78804a8cd1af3fae99775ca3b..3263aa1e68ae083caf23be03a1301e5dbb5ca382 100644 (file)
@@ -107,6 +107,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_sysconfdir}/ctdb/events.d/70.iscsi
 %{_sysconfdir}/ctdb/events.d/91.lvs
 %{_sysconfdir}/ctdb/statd-callout
+%{_sysconfdir}/ctdb/interface_modify.sh
 %{_sbindir}/ctdbd
 %{_bindir}/ctdb
 %{_bindir}/smnotify