6 Verify that adding/deleting IPs using 'ctdb reloadips' works
8 Checks that when IPs are added to and deleted from a single node then
9 those IPs are actually assigned and unassigned from the specified
14 * An active CTDB cluster with public IP addresses configured
18 * When IPs are added to a single node then they are assigned to an
21 * When IPs are deleted from a single node then they disappear from an
26 . "${TEST_SCRIPTS_DIR}/integration.bash"
32 ctdb_test_check_real_cluster
36 select_test_node_and_ips
40 # Search for an unused 10.B.1.0/24 network on which to add public IP
43 # The initial search is for a 10.B.0.0/16 network since some
44 # configurations may use a whole class B for the private network.
45 # Check that there are no public IP addresses (as reported by "ctdb ip
46 # all") or other IP addresses (as reported by "ip addr show") with
47 # the provided prefix. Note that this is an IPv4-specific test.
49 echo "Getting public IP information from CTDB..."
50 try_command_on_node any "$CTDB ip -X -v all"
51 ctdb_ip_info=$(awk -F'|' 'NR > 1 { print $2, $3, $5 }' "$outfile")
53 echo "Getting IP information from interfaces..."
54 try_command_on_node all "ip addr show"
55 ip_addr_info=$(awk '$1 == "inet" { ip = $2; sub(/\/.*/, "", ip); print ip }' \
59 for b in $(seq 0 255) ; do
62 # Does the prefix match any IP address returned by "ip addr info"?
64 if [ "${ip#${prefix}.}" != "$ip" ] ; then
68 done <<<"$ip_addr_info"
70 # Does the prefix match any public IP address "ctdb ip all"?
71 while read ip pnn iface ; do
72 if [ "${ip#${prefix}.}" != "$ip" ] ; then
76 done <<<"$ctdb_ip_info"
78 # Got through the IPs without matching prefix - done!
82 [ -n "$prefix" ] || die "Unable to find a usable IP address prefix"
84 # We really want a class C: 10.B.1.0/24
89 iface=$(echo "$ctdb_ip_info" | awk -v pnn=$test_node '$2 == pnn { print $3 ; exit }')
93 # This needs to be set only on the recmaster. All nodes should do the trick.
94 new_takeover_timeout=90
95 echo "Setting TakeoverTimeout=${new_takeover_timeout} to avoid potential bans"
96 try_command_on_node all "$CTDB setvar TakeoverTimeout ${new_takeover_timeout}"
100 try_command_on_node $test_node $CTDB_TEST_WRAPPER ctdb_base_show
101 addresses="${out}/public_addresses"
102 echo "Public addresses file on node $test_node is \"$addresses\""
103 backup="${addresses}.$$"
105 backup_public_addresses ()
107 try_command_on_node $test_node "cp -a $addresses $backup"
110 restore_public_addresses ()
112 try_command_on_node $test_node "mv $backup $addresses >/dev/null 2>&1 || true"
114 ctdb_test_exit_hook_add restore_public_addresses
116 # Now create that backup
117 backup_public_addresses
121 add_ips_to_original_config ()
130 echo "Adding new public IPs to original config on node ${test_node}..."
131 echo "IPs will be ${prefix}.${first}/24..${prefix}.${last}/24"
133 # Implement this by completely rebuilding the public_addresses
134 # file. This is easier than deleting entries on a remote node.
135 restore_public_addresses
136 backup_public_addresses
138 # Note that tee is a safe way of creating a file on a remote node.
139 # This avoids potential fragility with quoting or redirection.
140 for i in $(seq $first $last) ; do
141 echo "${prefix}.${i}/24 ${iface}"
143 try_command_on_node -i $test_node "tee -a $addresses"
154 # If just 0 specified then this is an empty range
155 local public_ips_file=$(mktemp)
156 if [ "$first" = 0 -a -z "$last" ] ; then
157 echo "Checking that there are no IPs in ${prefix}.0/24"
159 local prefix_regexp="inet *${prefix//./\.}"
161 echo "Checking IPs in range ${prefix}.${first}/24..${prefix}.${last}/24"
164 for i in $(seq $first $last) ; do
165 echo "${prefix}.${i}"
166 done | sort >"$public_ips_file"
169 try_command_on_node $test_node "ip addr show dev ${iface}"
170 local ip_addrs_file=$(mktemp)
172 sed -n -e "s@.*inet * \(${prefix//./\.}\.[0-9]*\)/.*@\1@p" | \
173 sort >"$ip_addrs_file"
175 local diffs=$(diff "$public_ips_file" "$ip_addrs_file") || true
176 rm -f "$ip_addrs_file" "$public_ips_file"
178 if [ -z "$diffs" ] ; then
179 echo "GOOD: IP addresses are as expected"
181 echo "BAD: IP addresses are incorrect:"
193 add_ips_to_original_config \
194 $test_node "$addresses" "$iface" "$prefix" 1 $new_ip_max
196 try_command_on_node $test_node "$CTDB reloadips"
198 check_ips $test_node "$iface" "$prefix" 1 $new_ip_max
200 try_command_on_node any $CTDB sync
204 # This should be the primary. Ensure that no other IPs are lost
205 echo "Using 'ctdb reloadips' to remove the 1st address just added..."
207 add_ips_to_original_config \
208 $test_node "$addresses" "$iface" "$prefix" 2 $new_ip_max
210 try_command_on_node $test_node "$CTDB reloadips"
212 check_ips $test_node "$iface" "$prefix" 2 $new_ip_max
214 try_command_on_node any $CTDB sync
218 # Get rid of about 1/2 the IPs
219 start=$(($new_ip_max / 2 + 1))
220 echo "Updating to include only about 1/2 of the new IPs..."
222 add_ips_to_original_config \
223 $test_node "$addresses" "$iface" "$prefix" $start $new_ip_max
225 try_command_on_node $test_node "$CTDB reloadips"
227 check_ips $test_node "$iface" "$prefix" $start $new_ip_max
229 try_command_on_node any $CTDB sync
234 echo "Restoring original IP configuration..."
235 restore_public_addresses
237 try_command_on_node $test_node "$CTDB reloadips"
239 check_ips $test_node "$iface" "$prefix" 0