2014-02-12 09:49:11 +11:00
#!/bin/bash
2019-09-11 16:07:49 +10:00
# Verify that adding/deleting IPs using 'ctdb reloadips' works
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# Checks that when IPs are added to and deleted from a single node then
# those IPs are actually assigned and unassigned from the specified
# interface.
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# Prerequisites:
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# * An active CTDB cluster with public IP addresses configured
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# Expected results:
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# * When IPs are added to a single node then they are assigned to an
# interface.
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
# * When IPs are deleted from a single node then they disappear from an
# interface.
2014-02-12 09:49:11 +11:00
2019-09-11 16:07:49 +10:00
. " ${ TEST_SCRIPTS_DIR } /cluster.bash "
2014-02-12 09:49:11 +11:00
set -e
2018-10-08 15:04:24 +11:00
ctdb_test_init
2014-02-12 09:49:11 +11:00
select_test_node_and_ips
####################
# Search for an unused 10.B.1.0/24 network on which to add public IP
# addresses.
# The initial search is for a 10.B.0.0/16 network since some
# configurations may use a whole class B for the private network.
# Check that there are no public IP addresses (as reported by "ctdb ip
2015-10-20 12:28:16 +11:00
# all") or other IP addresses (as reported by "ip addr show") with
2014-02-12 09:49:11 +11:00
# the provided prefix. Note that this is an IPv4-specific test.
echo "Getting public IP information from CTDB..."
2019-12-10 11:33:02 +11:00
ctdb_onnode " $test_node " "ip -X -v all"
2019-04-11 20:55:20 +10:00
ctdb_ip_info = $( awk -F'|' 'NR > 1 { print $2, $3, $5 }' " $outfile " )
2014-02-12 09:49:11 +11:00
echo "Getting IP information from interfaces..."
try_command_on_node all "ip addr show"
2019-04-11 20:55:20 +10:00
ip_addr_info = $( awk '$1 == "inet" { ip = $2; sub(/\/.*/, "", ip); print ip }' \
" $outfile " )
2014-02-12 09:49:11 +11:00
prefix = ""
for b in $( seq 0 255) ; do
prefix = " 10. ${ b } "
# Does the prefix match any IP address returned by "ip addr info"?
while read ip ; do
if [ " ${ ip # ${ prefix } . } " != " $ip " ] ; then
prefix = ""
continue 2
fi
done <<< " $ip_addr_info "
2015-10-20 12:28:16 +11:00
# Does the prefix match any public IP address "ctdb ip all"?
2014-02-12 09:49:11 +11:00
while read ip pnn iface ; do
if [ " ${ ip # ${ prefix } . } " != " $ip " ] ; then
prefix = ""
continue 2
fi
done <<< " $ctdb_ip_info "
# Got through the IPs without matching prefix - done!
break
done
[ -n " $prefix " ] || die "Unable to find a usable IP address prefix"
# We really want a class C: 10.B.1.0/24
prefix = " ${ prefix } .1 "
####################
iface = $( echo " $ctdb_ip_info " | awk -v pnn = $test_node '$2 == pnn { print $3 ; exit }' )
####################
2016-04-11 14:01:42 +10:00
# This needs to be set only on the recmaster. All nodes should do the trick.
2014-02-12 09:49:11 +11:00
new_takeover_timeout = 90
echo " Setting TakeoverTimeout= ${ new_takeover_timeout } to avoid potential bans "
2016-04-11 14:01:42 +10:00
try_command_on_node all " $CTDB setvar TakeoverTimeout ${ new_takeover_timeout } "
2014-02-12 09:49:11 +11:00
####################
2018-03-08 15:11:51 +11:00
try_command_on_node $test_node $CTDB_TEST_WRAPPER ctdb_base_show
addresses = " ${ out } /public_addresses "
2014-02-12 09:49:11 +11:00
echo " Public addresses file on node $test_node is \" $addresses \" "
backup = " ${ addresses } . $$ "
backup_public_addresses ( )
{
try_command_on_node $test_node " cp -a $addresses $backup "
}
restore_public_addresses ( )
{
try_command_on_node $test_node " mv $backup $addresses >/dev/null 2>&1 || true "
}
ctdb_test_exit_hook_add restore_public_addresses
# Now create that backup
backup_public_addresses
####################
add_ips_to_original_config ( )
{
local test_node = " $1 "
local addresses = " $2 "
local iface = " $3 "
local prefix = " $4 "
local first = " $5 "
local last = " $6 "
echo " Adding new public IPs to original config on node ${ test_node } ... "
echo " IPs will be ${ prefix } . ${ first } /24.. ${ prefix } . ${ last } /24 "
# Implement this by completely rebuilding the public_addresses
# file. This is easier than deleting entries on a remote node.
restore_public_addresses
backup_public_addresses
# Note that tee is a safe way of creating a file on a remote node.
# This avoids potential fragility with quoting or redirection.
for i in $( seq $first $last ) ; do
echo " ${ prefix } . ${ i } /24 ${ iface } "
done |
try_command_on_node -i $test_node " tee -a $addresses "
}
check_ips ( )
{
local test_node = " $1 "
local iface = " $2 "
local prefix = " $3 "
local first = " $4 "
local last = " $5 "
# If just 0 specified then this is an empty range
local public_ips_file = $( mktemp)
if [ " $first " = 0 -a -z " $last " ] ; then
echo " Checking that there are no IPs in ${ prefix } .0/24 "
else
local prefix_regexp = " inet * ${ prefix //./ \. } "
echo " Checking IPs in range ${ prefix } . ${ first } /24.. ${ prefix } . ${ last } /24 "
local i
for i in $( seq $first $last ) ; do
echo " ${ prefix } . ${ i } "
done | sort >" $public_ips_file "
fi
try_command_on_node $test_node " ip addr show dev ${ iface } "
local ip_addrs_file = $( mktemp)
2019-04-11 20:55:20 +10:00
cat " $outfile " | \
2014-02-12 09:49:11 +11:00
sed -n -e " s@.*inet * \( ${ prefix //./ \. } \.[0-9]*\)/.*@\1@p " | \
sort >" $ip_addrs_file "
local diffs = $( diff " $public_ips_file " " $ip_addrs_file " ) || true
rm -f " $ip_addrs_file " " $public_ips_file "
if [ -z " $diffs " ] ; then
echo "GOOD: IP addresses are as expected"
else
echo "BAD: IP addresses are incorrect:"
echo " $diffs "
exit 1
fi
}
2019-05-07 15:29:19 +10:00
# ctdb reloadips will fail if it can't disable takover runs. The most
# likely reason for this is that there is already a takeover run in
# progress. We can't predict when this will happen, so retry if this
# occurs.
do_ctdb_reloadips ( )
{
local retry_max = 10
local retry_count = 0
while : ; do
if try_command_on_node " $test_node " " $CTDB reloadips " ; then
return 0
fi
if [ " $out " != "Failed to disable takeover runs" ] ; then
return 1
fi
if [ $retry_count -ge $retry_max ] ; then
return 1
fi
retry_count = $(( retry_count + 1 ))
echo "Retrying..."
sleep_for 1
done
}
2014-02-12 09:49:11 +11:00
####################
new_ip_max = 100
####################
add_ips_to_original_config \
$test_node " $addresses " " $iface " " $prefix " 1 $new_ip_max
2019-05-07 15:29:19 +10:00
do_ctdb_reloadips
2014-02-12 09:49:11 +11:00
check_ips $test_node " $iface " " $prefix " 1 $new_ip_max
2019-12-10 11:33:02 +11:00
ctdb_onnode " $test_node " sync
2017-02-15 19:33:02 +11:00
2014-02-12 09:49:11 +11:00
####################
# This should be the primary. Ensure that no other IPs are lost
echo "Using 'ctdb reloadips' to remove the 1st address just added..."
add_ips_to_original_config \
$test_node " $addresses " " $iface " " $prefix " 2 $new_ip_max
2019-05-07 15:29:19 +10:00
do_ctdb_reloadips
2014-02-12 09:49:11 +11:00
check_ips $test_node " $iface " " $prefix " 2 $new_ip_max
2019-12-10 11:33:02 +11:00
ctdb_onnode " $test_node " sync
2017-02-15 19:33:02 +11:00
2014-02-12 09:49:11 +11:00
####################
# Get rid of about 1/2 the IPs
start = $(( $new_ip_max / 2 + 1 ))
echo "Updating to include only about 1/2 of the new IPs..."
add_ips_to_original_config \
$test_node " $addresses " " $iface " " $prefix " $start $new_ip_max
2019-05-07 15:29:19 +10:00
do_ctdb_reloadips
2014-02-12 09:49:11 +11:00
check_ips $test_node " $iface " " $prefix " $start $new_ip_max
2019-12-10 11:33:02 +11:00
ctdb_onnode " $test_node " sync
2017-02-15 19:33:02 +11:00
2014-02-12 09:49:11 +11:00
####################
# Delete the rest
echo "Restoring original IP configuration..."
restore_public_addresses
2019-05-07 15:29:19 +10:00
do_ctdb_reloadips
2014-02-12 09:49:11 +11:00
check_ips $test_node " $iface " " $prefix " 0