[SCM] CTDB repository - branch 1.2.40 updated - ctdb-1.9.1-554-g9fd1d9c

Ronnie Sahlberg sahlberg at samba.org
Sat Mar 10 21:51:53 MST 2012


The branch, 1.2.40 has been updated
       via  9fd1d9cca3fcced1aa4af5d515f7e2617eae4a50 (commit)
       via  0b8280258f0d228b2e9659dccfd9633321323aaa (commit)
       via  f670f660a781b944aa776bd6270c4007b140cdd3 (commit)
       via  c02ee2bf6d83c8611ccb4e9b1036440f1231b724 (commit)
       via  adb90f1e80b2d34233b8175e77515c589f4026f5 (commit)
      from  545c343b19258fce01562b15f274eaf1a1deafc8 (commit)

http://gitweb.samba.org/?p=ctdb.git;a=shortlog;h=1.2.40


- Log -----------------------------------------------------------------
commit 9fd1d9cca3fcced1aa4af5d515f7e2617eae4a50
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Aug 23 16:32:34 2011 +1000

    Eventscripts - new function ctdb_check_args()
    
    Pass this "$@" to do common eventscript argument checking.
    
    For regular use putting this in 00.ctdb would be enough.  However, for
    developer testing it can be useful to call this in other eventscripts.
    For example, 10.interfaces and 13.per_ip_routing currently check these
    by hand.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

commit 0b8280258f0d228b2e9659dccfd9633321323aaa
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Mar 6 11:21:41 2012 +1100

    Eventscript functions - remove functions only used by 13.per_ip_routing
    
    The relevant functions are now in that script.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

commit f670f660a781b944aa776bd6270c4007b140cdd3
Author: Martin Schwenke <martin at meltin.net>
Date:   Thu Mar 1 15:23:53 2012 +1100

    Eventscripts - redesign and rewrite 13.per_ip_routing
    
    The current version is quite difficult to read.  This one is hopefully
    clearer.
    
    Major changes:
    
    * The configuration file has a more forgiving syntax.  Items can be
      separated by arbitrary whitespace.
    
    * Mappings between IP addresses and table IDs are no longer stored in
      files in a state directory.  Instead they are stored in
      /etc/iproute2/rt_tables as mappings between table IDs and labels, as
      allowed by the ip command.  The current structure of the labels is
      ctdb.<source-ip>.  This means that once the labels are setup the
      routing tables can be referenced by just knowing the source IP.  As
      with the old state directory, mappings in this file owned by CTDB
      are deleted when CTDB shuts down.
    
    * There are no release or re-add scripts.
    
      - Release scripts are not necessary as an optimisation because of
        the previous improvement (i.e. use of rt_tables).  No lookup is
        necessary to delete rules or flush tables.
    
      - Re-add scripts are no longer used.  Routes can still go missing
        when removal of a primary IP from an interfaces (or similar)
        causes removal of all other addresses (i.e. secondaries) and also
        all associated routes.  However, any missing routes are now
        re-added in the "ipreallocated" event.  This happens shortly after
        takeip/releaseip/updateip and means that the routes will only be
        re-added once.  The window for missing routes is slightly bigger
        but is not expected to be significant.
    
    * The magic "__auto_link_local__" configuration value no longer causes
      a dynamic configuration file to be maintained in a state directory.
      The link local configuration is now generated when needed from the
      public_addresses file.  This greatly simplifies the code.  This
      approach is slightly less efficient but should not be significant.
    
    The above changes mean that, apart from maintaining mappings in the
    rt_tables file, there are no state files kept anymore.
    
    Some utility functions only used by this script have been rewritten
    and moved into this script.  They will be removed from the functions
    file by a future commit.
    
    The route re-add code will also be removed from interface_modify.sh by
    a future commit.  It is currently harmless.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

commit c02ee2bf6d83c8611ccb4e9b1036440f1231b724
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Tue Mar 6 10:51:00 2012 +1100

    readonly, dont allow any kind of fast vacuum for ro delegated records

commit adb90f1e80b2d34233b8175e77515c589f4026f5
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Mar 2 14:48:15 2012 +1100

    Revert "READONLY: readonly fetch collapse. Make sure we only keep one single readonly fetch for a record in flight at a time."
    
    This reverts commit 9bde066f6eb46124168e5686fc41a323e67401e8.

-----------------------------------------------------------------------

Summary of changes:
 config/events.d/13.per_ip_routing |  663 ++++++++++++++-----------------------
 config/functions                  |   84 ++----
 include/ctdb_private.h            |    4 -
 server/ctdb_call.c                |    3 +-
 server/ctdb_daemon.c              |  208 ------------
 server/ctdb_ltdb_server.c         |   10 -
 6 files changed, 278 insertions(+), 694 deletions(-)


Changeset truncated at 500 lines:

diff --git a/config/events.d/13.per_ip_routing b/config/events.d/13.per_ip_routing
index c734bbc..d17342d 100755
--- a/config/events.d/13.per_ip_routing
+++ b/config/events.d/13.per_ip_routing
@@ -3,501 +3,350 @@
 . $CTDB_BASE/functions
 loadconfig
 
-[ -z "$CTDB_PER_IP_ROUTING_STATE" ] && {
-	CTDB_PER_IP_ROUTING_STATE="$CTDB_VARDIR/state/per_ip_routing"
-}
-
-AUTO_LINK_LOCAL="no"
-
-case "$CTDB_PER_IP_ROUTING_CONF" in
-	__auto_link_local__)
-		AUTO_LINK_LOCAL="yes"
-		CTDB_PER_IP_ROUTING_CONF="$CTDB_PER_IP_ROUTING_STATE/auto_link_local.conf"
-		;;
-	*)
-		[ -z "$CTDB_PER_IP_ROUTING_CONF" ] && {
-			#echo "No config file found. Nothing to do for 13.per_ip_routing"
-			exit 0;
-		}
-		;;
-esac
-
-_low=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
-_high=$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH
-
-test -z "$_low" && {
-	echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW not configured";
-	exit 1;
-}
-test -z "$_high" && {
-	echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_HIGH not configured";
-	exit 1;
-}
-test "$_low" -ge "$_high" && {
-	echo "$0: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$_low] needs to be below CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$_high]";
-	exit 1;
-}
+# For compatibility with master branch.
+[ -n "$CTDB_ETCDIR" ] || CTDB_ETCDIR="/etc"
 
-test -z "$CTDB_PER_IP_ROUTING_RULE_PREF" && {
-	echo "$0: CTDB_PER_IP_ROUTING_RULE_PREF not configured";
-	exit 1;
-}
+# Do nothing if unconfigured 
+[ -n "$CTDB_PER_IP_ROUTING_CONF" ] || exit 0
 
-locknesting=0
-lock_root="$CTDB_PER_IP_ROUTING_STATE"
-host=`hostname`
+table_id_prefix="ctdb."
 
-lock_debug()
+die ()
 {
-	echo -n ""
+    echo "$*"
+    exit 1
 }
 
-############################
-# grab a lock file. Not atomic, but close :)
-# tries to cope with NFS
-lock_file() {
-	if [ -z "$lock_root" ]; then
-		lock_root=`pwd`;
-	fi
-	lckf="$lock_root/$1"
-	machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
-	pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
+[ -n "$CTDB_PER_IP_ROUTING_RULE_PREF" ] || \
+    die "error: CTDB_PER_IP_ROUTING_RULE_PREF not configured"
 
-	if [ "$pid" = "$$" ]; then
-		locknesting=`expr $locknesting + 1`
-		lock_debug "lock nesting now $locknesting"
-		return 0
-	fi
+[ "$CTDB_PER_IP_ROUTING_TABLE_ID_LOW" -lt "$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH" ] 2>/dev/null || \
+    die "error: CTDB_PER_IP_ROUTING_TABLE_ID_LOW[$CTDB_PER_IP_ROUTING_TABLE_ID_LOW] and/or CTDB_PER_IP_ROUTING_TABLE_ID_HIGH[$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH] improperly configured"
 
-	if test -f "$lckf"; then
-		test $machine = $host || {
-			lock_debug "lock file $lckf is valid for other machine $machine"
-			stat -c%y "$lckf"
-			return 1
-		}
-		/bin/kill -0 $pid && {
-			lock_debug "lock file $lckf is valid for process $pid"
-			stat -c%y "$lckf"
-			return 1
-		}
-		lock_debug "stale lock file $lckf for $machine:$pid"
-		cat "$lckf"
-		/bin/rm -f "$lckf"
-	fi
-	echo "$host:$$" > "$lckf"
-	return 0
-}
+######################################################################
 
-############################
-# unlock a lock file
-unlock_file() {
-	if [ -z "$lock_root" ]; then
-		lock_root=`pwd`;
-	fi
-	if [ "$locknesting" != "0" ]; then
-		locknesting=`expr $locknesting - 1`
-		lock_debug "lock nesting now $locknesting"
-	else
-		lckf="$lock_root/$1"
-		/bin/rm -f "$lckf"
+ipv4_is_valid_addr()
+{
+    _ip="$1"
+
+    _count=0
+    # Get the shell to break up the address into 1 word per octet 
+    for _o in $(export IFS="." ; echo $_ip) ; do
+	# The 2>/dev/null stops output from failures where an "octet"
+	# is not numeric.  The test will still fail.
+	if ! [ 0 -le $_o -a $_o -le 255 ] 2>/dev/null ; then
+	    return 1
 	fi
+	_count=$(($_count + 1))
+    done
+
+    # A valid IPv4 address has 4 octets
+    [ $_count -eq 4 ]
 }
 
-generate_table_id () {
-	local _ip=$1
-	local _ipsdir="$CTDB_PER_IP_ROUTING_STATE/ips"
-	local _ipdir="$_ipsdir/$_ip"
+ensure_ipv4_is_valid_addr ()
+{
+    _event="$1"
+    _ip="$2"
 
-	mkdir -p $_ipdir
+    ipv4_is_valid_addr "$_ip" || {
+	echo "$0: $_event not an ipv4 address skipping IP:$_ip"
+	exit 0
+    }
+}
 
-	#echo "generate_table_id $_ip"
+ipv4_host_addr_to_net ()
+{
+    _host="$1"
+    _maskbits="$2"
+
+    # Convert the host address to an unsigned long by splitting out
+    # the octets and doing the math.
+    _host_ul=0
+    for _o in $(export IFS="." ; echo $_host) ; do
+	_host_ul=$(( ($_host_ul << 8) + $_o)) # work around Emacs color bug
+    done
+
+    # Calculate the mask and apply it.
+    _mask_ul=$(( 0xffffffff << (32 - $_maskbits) ))
+    _net_ul=$(( $_host_ul & $_mask_ul ))
+ 
+    # Now convert to a network address one byte at a time.
+    _net=""
+    for _o in $(seq 1 4) ; do
+	_net="$(($_net_ul & 255))${_net:+.}${_net}"
+	_net_ul=$(($_net_ul >> 8))
+    done
+
+    echo "${_net}/${_maskbits}"
+}
 
-	local _id=`cat $_ipdir/table_id 2>/dev/null| xargs`
-	test -n "$_id" && {
-		#echo "IP: $_ip => OLD TABLE: $_id"
-		table_id=$_id
-		return 0;
-	}
+######################################################################
 
-	local _low="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW"
-	local _high="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
-
-	local _newid=""
-	for _id in `seq $_low $_high | xargs`; do
-		local _table_lck="table_id_$_id.lock"
-		lock_file $_table_lck 2>/dev/null || {
-			continue;
-		}
-		local _taken=`grep "^$_id$" $_ipsdir/*/table_id 2>/dev/null| wc -l | xargs`
-		test x"$_taken" != x"0" && {
-			unlock_file $_table_lck
-			#echo "tableid: $_id taken"
-			continue
-		}
-		_newid=$_id;
-		echo "$_newid" > $_ipdir/table_id
-		unlock_file $_table_lck
-		break;
+# Setup a table id to use for the given IP.  We don't need to know it,
+# it just needs to exist in /etc/iproute2/rt_tables.  Fail if no free
+# table id could be found in the configured range.
+ensure_table_id_for_ip ()
+{
+    _ip=$1
+
+    _f="$CTDB_ETCDIR/iproute2/rt_tables"
+    # This file should always exist, but...
+    if [ ! -f "$_f" ] ; then
+	mkdir -p $(basename "$_f")
+	touch "$_f"
+    fi
+
+    # Maintain a table id for each IP address we've ever seen in
+    # rt_tables.  We use a "ctdb." prefix on the label.
+    _label="${table_id_prefix}${_ip}"
+
+    # This finds either the table id corresponding to the label or a
+    # new unused one (that is greater than all the used ones in the
+    # range).
+    (
+	flock 0
+
+	_new=$CTDB_PER_IP_ROUTING_TABLE_ID_LOW
+	while read _t _l ; do
+	    # Skip comments
+	    case "$_t" in
+		\#*) continue ;;
+	    esac
+	    # Found existing: done
+	    if [ "$_l" = "$_label" ] ; then
+		return 0
+	    fi
+	    # Potentially update the new table id to be used.  The
+	    # redirect stops error spam for a non-numeric value.
+	    if [ $_new -le $_t -a \
+		$_t -le $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH ] 2>/dev/null ; then
+		_new=$(($_t + 1))
+	    fi
 	done
 
-	test -z "$_newid" && {
-		echo "generate_table_id: out of table ids: $_low - $_high"
-		exit 1;
-	}
-
-	#echo "IP: $_ip => NEW TABLE: $_newid"
-	table_id=$_newid
-	return 0;
+	# If the new table id is legal then add it to the file and
+	# print it.
+	if [ $_new -le $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH ] ; then
+	    printf "%d\t%s\n" "$_new" "$_label" >>"$_f"
+	    return 0
+	else
+	    return 1
+	fi
+    ) <"$_f"
 }
 
-run_release_script_once()
+# Clean up all the table ids that we might own.
+clean_up_table_ids ()
 {
-	local _script=$1
-
-	#echo "run_release_script_once[$_script]"
-
-	test -x "$_script" && {
-		#echo "run it: start"
-		$_script || {
-			echo "release_script: $_script - failed $?"
-			return $?;
-		}
-		#echo "run it: end"
-	}
-
-	echo '#!/bin/sh' > $_script
-	echo '#' >> $_script
-	echo >> $_script
+    _f="$CTDB_ETCDIR/iproute2/rt_tables"
+    # Even if this didn't exist on the system, adding a route will
+    # have created it.  What if we startup and immediately shutdown?
+    if [ ! -f "$_f" ] ; then
+	mkdir -p $(basename "$_f")
+	touch "$_f"
+    fi
+
+    (
+	flock 0
+
+	# Delete any items from the file that have a table id in our
+	# range or a label matching our label.  Preserve comments.
+	_tmp="${_f}.$$.ctdb"
+	awk -v min="$CTDB_PER_IP_ROUTING_TABLE_ID_LOW" \
+	    -v max="$CTDB_PER_IP_ROUTING_TABLE_ID_HIGH" \
+	    -v pre="$table_id_prefix" \
+	    'index($0, "#") == 1 || \
+	     !(min <= $1 && $1 <= max) && \
+	     !(index($2, pre) == 1) \
+	     { print $0 }' "$_f" >"$_tmp"
+
+	mv "$_tmp" "$_f"
+	# The lock is gone - don't do anything else here
+    ) <"$_f"
+}
 
-	chmod +x $_script
+######################################################################
 
-	return 0;
+# This prints the config for an IP, which is either relevant entries
+# from the config file or, if set to the magic link local value, some
+# link local routing config for the IP.
+get_config_for_ip ()
+{
+    _ip="$1"
+
+    if [ "$CTDB_PER_IP_ROUTING_CONF" = "__auto_link_local__" ] ; then
+	# When parsing public_addresses also split on '/'.  This means
+	# that we get the maskbits as item #2 without further parsing.
+	while IFS="/$IFS" read _i _maskbits _x ; do
+	    if [ "$_ip" = "$_i" ] ; then
+		echo -n "$_ip "; ipv4_host_addr_to_net "$_ip" "$_maskbits"
+	    fi
+	done <"${CTDB_PUBLIC_ADDRESSES:-/dev/null}"
+    else
+	while read _i _rest ; do
+	    if [ "$_ip" = "$_i" ] ; then
+		printf "%s\t%s\n" "$_ip" "$_rest"
+	    fi
+	done <"$CTDB_PER_IP_ROUTING_CONF"
+    fi
 }
 
-generate_auto_link_local()
+ip_has_configuration ()
 {
-	local _ip=$1
-	local _maskbits=$2
-
-	#echo "generate_auto_link_local $_ip $_maskbits"
-
-	local _netip=`ipv4_host_addr_to_net_addr $_ip $_maskbits`
-
-	local _line="$_ip $_netip/$_maskbits"
-
-	local _lockfile="$CTDB_PER_IP_ROUTING_CONF.lock"
-	local _script="$CTDB_PER_IP_ROUTING_CONF.$$.sh"
-
-	echo "#!/bin/sh" > $_script
-	echo "#" >> $_script
-	echo "" >> $_script
-	echo "_config=\`cat $CTDB_PER_IP_ROUTING_CONF 2>/dev/null\`" >> $_script
-	echo "_exact=\`echo -n \"\$_config\" | grep \"^$_line\$\" | wc -l | xargs\`" >> $_script
-	echo "" >> $_script
-
-	echo "test x\"\$_exact\" = x\"1\" && {" >> $_script
-	echo "    exit 0;" >> $_script
-	echo "}" >> $_script
-	echo "" >> $_script
-
-	echo "_tmp=\"$CTDB_PER_IP_ROUTING_CONF.$$.tmp\"" >> $_script
-	echo "echo -n \"\$_config\" | grep -v \"^$_ip \" | cat > \$_tmp || {" >> $_script
-	echo "    echo \"echo -n \\\"\$_config\\\" | grep -v \\\"^$_ip \\\" > \$_tmp - failed\"" >> $_script
-	echo "    exit 1;" >> $_script
-	echo "}" >> $_script
-	echo "echo \"$_line\" >> \$_tmp || {" >> $_script
-	echo "    echo \"echo \\\"$_line\\\" >> \$_tmp - failed\"" >> $_script
-	echo "    exit 1;" >> $_script
-	echo "}" >> $_script
-	echo "" >> $_script
-
-	echo "mv \$_tmp $CTDB_PER_IP_ROUTING_CONF || {" >> $_script
-	echo "    echo \"mv \$_tmp $CTDB_PER_IP_ROUTING_CONF - failed\"" >> $_script
-	echo "    exit 1;" >> $_script
-	echo "}" >> $_script
-	echo "" >> $_script
-
-	echo "echo \"Added '$_line' to $CTDB_PER_IP_ROUTING_CONF\"">> $_script
-	echo "exit 0" >> $_script
-
-	chmod +x $_script
-
-	test -f $_lockfile || {
-		touch $_lockfile
-	}
+    _ip="$1"
 
-	flock --timeout 30 $_lockfile $_script
-	ret=$?
-	rm $_script
-	return $ret
+    [ -n "$(get_config_for_ip $_ip)" ]
 }
 
-generate_per_ip_routing()
+add_routing_for_ip ()
 {
-	local _ip=$1
-	local _maskbits=$2
-	local _iface=$3
-	local _readonly=$4
-	local _ipdir="$CTDB_PER_IP_ROUTING_STATE/ips/$_ip"
-
-	table_id=""
-	release_script="$_ipdir/per_ip_routing_release.sh"
-	setup_script="$_ipdir/per_ip_routing_setup.sh"
-
-	test x"$_readonly" = x"yes" && {
-		test -d $_ipdir || {
-			return 1;
-		}
-		return 0;
-	}
+    _iface="$1"
+    _ip="$2"
 
-	mkdir -p $_ipdir || {
-		echo "mkdir -p $_ipdir failed"
-		return 1;
-	}
-	echo "$_ip" > $_ipdir/ip
+    # Do nothing if no config for this IP.
+    ip_has_configuration "$_ip" || return 0
 
-	generate_table_id $_ip
+    ensure_table_id_for_ip "$_ip" || \
+	die "add_routing_for_ip: out of table ids in range $CTDB_PER_IP_ROUTING_TABLE_ID_LOW - $CTDB_PER_IP_ROUTING_TABLE_ID_HIGH"
 
-	test x"$AUTO_LINK_LOCAL" = x"yes" && {
-		generate_auto_link_local $_ip $_maskbits
-	}
+    _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
+    _table_id="${table_id_prefix}${_ip}"
 
-	run_release_script_once $release_script
+    del_routing_for_ip "$_ip"
 
-	echo '#!/bin/sh' > $setup_script
-	echo '#' >> $setup_script
-	echo >> $setup_script
-	chmod +x $setup_script
+    ip rule add from "$_ip" pref "$_pref" table "$_table_id" || \
+	die "add_routing_for_ip: failed to add rule for $_ip"
 
-	return 0;
+    # Add routes to table for any lines matching the IP.
+    get_config_for_ip "$_ip" |
+    while read _i _dest _gw ; do
+	_r="$_dest ${_gw:+via} $_gw dev $_iface table $_table_id"
+	ip route add $_r || \
+	    die "add_routing_for_ip: failed to add route: $_r"
+    done
 }
 
-setup_per_ip_routing()
+del_routing_for_ip ()
 {
-	local _ip=$1
-	local _iface=$2
-	local _table_id=$3
-	local _release_script=$4
-	local _setup_script=$5
-
-	local _config=`cat $CTDB_PER_IP_ROUTING_CONF`
-	local _lines=`echo -n "$_config" | grep -n "^$_ip " | cut -d ':' -f1 | xargs`
+    _ip="$1"
 
-	local _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
+    _pref="$CTDB_PER_IP_ROUTING_RULE_PREF"
+    _table_id="${table_id_prefix}${_ip}"
 
-	test -n "$_lines" && {
-		echo "ip rule del from $_ip pref $_pref table $_table_id" >> $_release_script
-		echo "ip route flush table $_table_id 2>/dev/null" >> $_release_script
-
-		cmd="ip rule del from $_ip pref $_pref 2>/dev/null"
-		echo "$cmd" >> $_setup_script
+    # Do this unconditionally since we own any matching table ids...
+    ip rule del from $_ip pref $_pref table $_table_id 2>/dev/null
+    ip route flush table $_table_id 2>/dev/null
+}
 
-		cmd="ip route flush table $_table_id 2>/dev/null"
-		echo "$cmd" >> $_setup_script
+######################################################################
 
-		cmd="ip rule add from $_ip pref $_pref table $_table_id"
-		echo "$cmd || {" >> $_setup_script
-		echo "    echo \"$cmd - failed \$ret\"" >> $_setup_script
-		echo "    exit \$ret" >> $_setup_script


-- 
CTDB repository


More information about the samba-cvs mailing list