summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2008-11-20 20:40:01 +1100
committerMartin Schwenke <martin@meltin.net>2008-11-20 20:40:01 +1100
commitd741559fa6ba8d2077ecaa7053c1eab7d96aeb31 (patch)
treeb830097881ad3c0e36065a3b9117233117c97564
parent71b16e1123e4d447a13c9260f5c4ece10fe77de2 (diff)
downloadsamba-d741559fa6ba8d2077ecaa7053c1eab7d96aeb31.tar.gz
Add some simple tests that can be run from within the tree.
Signed-off-by: Martin Schwenke <martin@meltin.net> (This used to be ctdb commit eacb2ef82ea4809d874158756db973dd1e3fc8fc)
-rw-r--r--ctdb/.gitignore2
-rw-r--r--ctdb/tests/nodes.txt1
-rw-r--r--ctdb/tests/scripts/ctdb_test_functions.bash333
-rwxr-xr-xctdb/tests/scripts/run_tests46
-rwxr-xr-xctdb/tests/scripts/test_wrap10
-rwxr-xr-xctdb/tests/simple/00_ctdb_init.sh8
-rwxr-xr-xctdb/tests/simple/00_ctdb_onnode.sh11
-rwxr-xr-xctdb/tests/simple/01_ctdb_version.sh.disabled24
-rwxr-xr-xctdb/tests/simple/02_ctdb_listvars.sh19
-rwxr-xr-xctdb/tests/simple/03_ctdb_getvar.sh27
-rwxr-xr-xctdb/tests/simple/04_ctdb_setvar.sh62
-rwxr-xr-xctdb/tests/simple/05_ctdb_listnodes.sh40
-rwxr-xr-xctdb/tests/simple/06_ctdb_getpid.sh67
-rwxr-xr-xctdb/tests/simple/07_ctdb_process_exists.sh45
-rwxr-xr-xctdb/tests/simple/08_ctdb_isnotrecmaster.sh32
-rwxr-xr-xctdb/tests/simple/11_ctdb_ip.sh38
-rwxr-xr-xctdb/tests/simple/31_ctdb_disable_simple.sh39
-rwxr-xr-xctdb/tests/simple/32_ctdb_enable_simple.sh90
-rwxr-xr-xctdb/tests/simple/41_ctdb_ban_simple.sh88
-rwxr-xr-xctdb/tests/simple/42_ctdb_unban_simple.sh91
-rwxr-xr-xctdb/tests/start_daemons.sh8
-rwxr-xr-xctdb/tools/onnode36
22 files changed, 1105 insertions, 12 deletions
diff --git a/ctdb/.gitignore b/ctdb/.gitignore
index 37b1a749d88..91124db066a 100644
--- a/ctdb/.gitignore
+++ b/ctdb/.gitignore
@@ -15,5 +15,7 @@ utils/smnotify/gen_smnotify.c
utils/smnotify/gen_xdr.c
utils/smnotify/smnotify.h
nodes.txt
+public_addresses.txt
rec.lock
test.db
+var
diff --git a/ctdb/tests/nodes.txt b/ctdb/tests/nodes.txt
index 99b07328b38..b910649a18c 100644
--- a/ctdb/tests/nodes.txt
+++ b/ctdb/tests/nodes.txt
@@ -1,4 +1,3 @@
127.0.0.1
127.0.0.2
127.0.0.3
-127.0.0.4
diff --git a/ctdb/tests/scripts/ctdb_test_functions.bash b/ctdb/tests/scripts/ctdb_test_functions.bash
new file mode 100644
index 00000000000..d1886b8ebde
--- /dev/null
+++ b/ctdb/tests/scripts/ctdb_test_functions.bash
@@ -0,0 +1,333 @@
+# Hey Emacs, this is a -*- shell-script -*- !!! :-)
+
+numnodes=3
+
+export CTDB_NODES_SOCKETS=""
+for i in $(seq 1 $numnodes) ; do
+ CTDB_NODES_SOCKETS="${CTDB_NODES_SOCKETS}${CTDB_NODES_SOCKETS:+ }${PWD}/sock.${i}"
+done
+
+
+######################################################################
+
+fail ()
+{
+ echo "$*"
+ exit 1
+}
+
+######################################################################
+
+#. /root/SOFS/autosofs/scripts/tester.bash
+
+test_begin ()
+{
+ local name="$1"
+
+ teststarttime=$(date '+%s')
+ testduration=0
+
+ echo "--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--"
+ echo "Running test $name ($(date '+%T'))"
+ echo "--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--"
+}
+
+test_end ()
+{
+ local name="$1" ; shift
+ local status="$1" ; shift
+ # "$@" is command-line
+
+ local interp="SKIPPED"
+ local statstr=" (reason $*)"
+ if [ -n "$status" ] ; then
+ if [ $status -eq 0 ] ; then
+ interp="PASSED"
+ statstr=""
+ echo "ALL OK: $*"
+ else
+ interp="FAILED"
+ statstr=" (status $status)"
+ testfailures=$(($testfailures+1))
+ fi
+ fi
+
+ testduration=$(($(date +%s)-$teststarttime))
+
+ echo "=========================================================================="
+ echo "TEST ${interp}: ${name}${statstr}, duration: $testduration sec."
+ echo "=========================================================================="
+
+}
+
+
+test_exit() {
+ exit $(($testfailures+0))
+}
+
+test_run ()
+{
+ local name="$1" ; shift
+
+ [ -n "$1" ] || set -- "$name"
+
+ test_begin "$name"
+
+ local status=0
+ "$@" || status=$?
+
+ test_end "$name" "$status" "$*"
+
+ return $status
+}
+
+########################################
+
+# Sets: $out
+try_command_on_node ()
+{
+ local nodespec="$1" ; shift
+ local cmd="$*"
+
+ out=$(onnode -q "$nodespec" "$cmd" 2>&1) || {
+
+ echo "Failed to execute \"$cmd\" on node(s) \"$nodespec\""
+ echo "$out"
+ exit 1
+ }
+}
+
+sanity_check_output ()
+{
+ local min_lines="$1"
+ local regexp="$2" # Should be anchored to match whole lines.
+ local output="$3"
+
+ local ret=0
+
+ local num_lines=$(echo "$output" | wc -l)
+ echo "There are $num_lines lines of output"
+ if [ $num_lines -lt $min_lines ] ; then
+ echo "BAD: that's less than the required number (${min_lines})"
+ ret=1
+ fi
+
+ local status=0
+ local unexpected # local doesn't pass through status of command on RHS.
+ unexpected=$(echo "$output" | egrep -v "$regexp") || status=$?
+
+ # Note that this is reversed.
+ if [ $status -eq 0 ] ; then
+ echo "BAD: unexpected lines in output:"
+ echo "$unexpected"
+ ret=1
+ else
+ echo "Output lines look OK"
+ fi
+
+ return $ret
+}
+
+#######################################
+
+# Wait until either timeout expires or command succeeds. The command
+# will be tried once per second.
+wait_until ()
+{
+ local timeout="$1" ; shift # "$@" is the command...
+
+ echo -n "|${timeout}|"
+ while [ $timeout -gt 0 ] ; do
+ if "$@" ; then
+ echo '|'
+ echo "OK"
+ return 0
+ fi
+ echo -n .
+ timeout=$(($timeout - 1))
+ sleep 1
+ done
+
+ echo "*TIMEOUT*"
+
+ return 1
+}
+
+sleep_for ()
+{
+ echo -n "|${1}|"
+ for i in $(seq 1 $1) ; do
+ echo -n '.'
+ sleep 1
+ done
+ echo '|'
+}
+
+_cluster_is_healthy ()
+{
+ local out x count line
+
+ out=$(ctdb -Y status 2>&1) || return 1
+
+ {
+ read x
+ count=0
+ while read line ; do
+ count=$(($count + 1))
+ [ "${line#:*:*:}" != "0:0:0:0:" ] && return 1
+ done
+ [ $count -gt 0 ] && return $?
+ } <<<"$out" # Yay bash!
+}
+
+cluster_is_healthy ()
+{
+ if _cluster_is_healthy ; then
+ echo "Cluster is HEALTHY"
+ exit 0
+ else
+ echo "Cluster is UNHEALTHY"
+ exit 1
+ fi
+}
+
+wait_until_healthy ()
+{
+ local timeout="${1:-120}"
+
+ echo "Waiting for cluster to become healthy..."
+
+ wait_until 120 _cluster_is_healthy
+}
+
+# Incomplete! Do not use!
+node_has_status ()
+{
+ local pnn="$1"
+ local status="$2"
+
+ local bits
+ case "$status" in
+ banned)
+ bits="?:1:?:?"
+ ;;
+ unbanned)
+ bits="?:0:?:?"
+ ;;
+ disabled)
+ bits="?:?:1:?"
+ ;;
+ enabled)
+ bits="?:?:0:?"
+ ;;
+ *)
+ echo "node_has_status: unknown status \"$status\""
+ return 1
+ esac
+
+ local out x line
+
+ out=$(ctdb -Y status 2>&1) || return 1
+
+ {
+ read x
+ while read line ; do
+ [ "${line#:${pnn}:*:${bits}:}" = "" ] && return 0
+ done
+ return 1
+ } <<<"$out" # Yay bash!
+}
+
+wait_until_node_has_status ()
+{
+ local pnn="$1"
+ local status="$2"
+ local timeout="${3:-30}"
+
+ echo "Waiting until node $pnn has status \"$status\"..."
+
+ wait_until $timeout node_has_status "$pnn" "$status"
+}
+
+# Useful for superficially testing IP failover.
+# IPs must be on nodes matching nodeglob.
+ips_are_on_nodeglob ()
+{
+ local nodeglob="$1" ; shift
+ local ips="$*"
+
+ local out
+
+ try_command_on_node 1 ctdb ip
+
+ while read ip pnn ; do
+ for check in $ips ; do
+ if [ "$check" = "$ip" ] ; then
+ case "$pnn" in
+ ($nodeglob) : ;;
+ (*) return 1 ;;
+ esac
+ ips="${ips/${ip}}" # Remove from list
+ fi
+ done
+ done <<<"$out" # bashism to avoid problem setting variable in pipeline.
+
+ ips="${ips// }" # Remove any spaces.
+ [ -z "$ips" ]
+}
+
+wait_until_ips_are_on_nodeglob ()
+{
+ echo "Waiting for IPs to fail over..."
+
+ wait_until 60 ips_are_on_nodeglob "$@"
+}
+
+
+start_daemons ()
+{
+ $CTDB_DIR/tests/start_daemons.sh $numnodes >$CTDB_DIR/var/daemons.log
+}
+
+_restart_ctdb ()
+{
+ if [ -e /etc/redhat-release ] ; then
+ service ctdb restart
+ else
+ /etc/init.d/ctdb restart
+ fi
+}
+
+restart_ctdb ()
+{
+ if [ -n "$CTDB_NODES_SOCKETS" ] ; then
+ onnode all ctdb shutdown
+ start_daemons
+ else
+ onnode -pq all $TEST_WRAP _restart_ctdb
+ fi || return 1
+
+ onnode -q 1 $TEST_WRAP wait_until_healthy || return 1
+
+ echo "Setting RerecoveryTimeout to 1"
+ onnode -pq all "ctdb setvar RerecoveryTimeout 1"
+
+ #echo "Sleeping to allow ctdb to settle..."
+ #sleep_for 10
+
+ echo "ctdb is ready"
+}
+
+ctdb_test_exit ()
+{
+ if ! onnode 0 $TEST_WRAP cluster_is_healthy ; then
+ echo "Restarting ctdb on all nodes to get back into known state..."
+ restart_ctdb
+ fi
+
+ test_exit
+}
+
+########################################
+
+export PATH=/usr/local/autocluster:$PATH
diff --git a/ctdb/tests/scripts/run_tests b/ctdb/tests/scripts/run_tests
new file mode 100755
index 00000000000..eab28f06ea9
--- /dev/null
+++ b/ctdb/tests/scripts/run_tests
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+export CTDB_DIR=$(cd $(dirname $(dirname $(dirname $0))) ; pwd)
+
+ctdb_bin_dir="${CTDB_DIR}/bin"
+ctdb_tools_dir="${CTDB_DIR}/tools"
+ctdb_test_scripts_dir=$(cd $(dirname $0) ; pwd)
+
+PATH="${ctdb_test_scripts_dir}:${ctdb_bin_dir}:${ctdb_tools_dir}:${PATH}"
+
+export TEST_WRAP="${ctdb_test_scripts_dir}/test_wrap"
+
+. ctdb_test_functions.bash
+
+usage() {
+ cat <<EOF
+Usage: run_tests [OPTIONS] [TESTS]
+
+EOF
+ exit 1
+}
+
+######################################################################
+
+temp=$(getopt -n "$prog" -o "xh" -l help -- "$@")
+
+[ $? != 0 ] && usage
+
+eval set -- "$temp"
+
+while true ; do
+ case "$1" in
+ -x) set -x; shift ;;
+ --) shift ; break ;;
+ -h|--help|*) usage ;; # * shouldn't happen, so this is reasonable.
+ esac
+done
+
+######################################################################
+
+for f; do
+ [ -x $f ] || fail "test $f is not executable"
+ test_run "$f"
+done
+
+test_exit
diff --git a/ctdb/tests/scripts/test_wrap b/ctdb/tests/scripts/test_wrap
new file mode 100755
index 00000000000..35ad41830f3
--- /dev/null
+++ b/ctdb/tests/scripts/test_wrap
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Execute the given command. The intention is that it is a function
+# from ctdb_test_functions.bash.
+
+PATH="$(dirname $0):${PATH}"
+
+. ctdb_test_functions.bash
+
+"$@"
diff --git a/ctdb/tests/simple/00_ctdb_init.sh b/ctdb/tests/simple/00_ctdb_init.sh
new file mode 100755
index 00000000000..13b4303fd20
--- /dev/null
+++ b/ctdb/tests/simple/00_ctdb_init.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+echo "Restartng ctdb on all nodes..."
+restart_ctdb
diff --git a/ctdb/tests/simple/00_ctdb_onnode.sh b/ctdb/tests/simple/00_ctdb_onnode.sh
new file mode 100755
index 00000000000..bd269d73cec
--- /dev/null
+++ b/ctdb/tests/simple/00_ctdb_onnode.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Do a recursive "onnode all" to make sure all the nodes can connect
+# to each other. On a cluster this ensures that SSH keys are known
+# between all hosts, which will stop output being corrupted with
+# messages about nodes being added to the list of known hosts.
+
+. ctdb_test_functions.bash
+
+echo "Checking connectivity between nodes..."
+onnode all onnode all true
diff --git a/ctdb/tests/simple/01_ctdb_version.sh.disabled b/ctdb/tests/simple/01_ctdb_version.sh.disabled
new file mode 100755
index 00000000000..36e0368ff63
--- /dev/null
+++ b/ctdb/tests/simple/01_ctdb_version.sh.disabled
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+. /root/SOFS/autosofs/scripts/functions
+
+set -e
+
+onnode 0 /root/SOFS/autosofs/scripts/cluster_is_healthy.sh
+
+rpm_ver_cmd="rpm -q ctdb"
+ctdb_ver_cmd="ctdb version"
+
+rpm_ver=$($rpm_ver_cmd)
+echo "$rpm_ver_cmd"
+echo " $rpm_ver"
+
+ctdb_ver=$(onnode 0 $ctdb_ver_cmd)
+echo "$ctdb_ver_cmd"
+echo " $ctdb_ver"
+
+set -x
+
+[ "${ctdb_ver#CTDB version: }" = "${rpm_ver#ctdb-}" ]
+
+test_exit
diff --git a/ctdb/tests/simple/02_ctdb_listvars.sh b/ctdb/tests/simple/02_ctdb_listvars.sh
new file mode 100755
index 00000000000..fd0af39c9c5
--- /dev/null
+++ b/ctdb/tests/simple/02_ctdb_listvars.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 0 "ctdb listvars"
+
+echo "Output from \"ctdb listvars\" on node 0:"
+echo "$out"
+
+sanity_check_output \
+ 5 \
+ '^[[:alpha:]]+[[:space:]]*=[[:space:]]*[[:digit:]]+$' \
+ "$out"
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/03_ctdb_getvar.sh b/ctdb/tests/simple/03_ctdb_getvar.sh
new file mode 100755
index 00000000000..f21b29b5b09
--- /dev/null
+++ b/ctdb/tests/simple/03_ctdb_getvar.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 0 "ctdb listvars"
+
+echo "Veryifying all variable values using \"ctdb getvar\"..."
+
+echo "$out" |
+while read var x val ; do
+ try_command_on_node 0 "ctdb getvar $var"
+
+ val2=$(echo $out | sed -e 's@.*[[:space:]]@@')
+
+ if [ "$val" != "$val2" ] ; then
+ echo "MISMATCH on $var: $val != $val2"
+ exit 1
+ fi
+done
+
+testfailures=$?
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/04_ctdb_setvar.sh b/ctdb/tests/simple/04_ctdb_setvar.sh
new file mode 100755
index 00000000000..d3b543d3797
--- /dev/null
+++ b/ctdb/tests/simple/04_ctdb_setvar.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# Doesn't strictly follow the procedure, since it doesn't pick a
+# variable from the output of "ctdb listvars".
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+var="RecoverTimeout"
+
+cmd="ctdb getvar $var"
+try_command_on_node 0 $cmd
+
+val=$(echo "$out" | sed -e 's@.*[[:space:]]@@')
+
+echo "$out"
+
+echo "Going to try incrementing it..."
+
+incr=$(($val + 1))
+
+cmd="ctdb setvar $var $incr"
+try_command_on_node 0 $cmd
+
+echo "That seemed to work, let's check the value..."
+
+cmd="ctdb getvar $var"
+try_command_on_node 0 $cmd
+
+newval=$(echo "$out" | sed -e 's@.*[[:space:]]@@')
+
+echo "$out"
+
+if [ "$incr" != "$newval" ] ; then
+ echo "Nope, that didn't work..."
+ exit 1
+fi
+
+echo "Look's good! Now verifying with \"ctdb listvars\""
+cmd="ctdb listvars"
+try_command_on_node 0 $cmd
+
+line=$(echo "$out" | grep "^$var")
+echo "$line"
+
+check=$(echo "$line" | sed -e 's@.*[[:space:]]@@')
+
+if [ "$incr" != "$check" ] ; then
+ echo "Nope, that didn't work..."
+ exit 1
+fi
+
+echo "Look's good! Putting the old value back..."
+cmd="ctdb setvar $var $val"
+try_command_on_node 0 $cmd
+
+echo "All done..."
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/05_ctdb_listnodes.sh b/ctdb/tests/simple/05_ctdb_listnodes.sh
new file mode 100755
index 00000000000..9337a40fc81
--- /dev/null
+++ b/ctdb/tests/simple/05_ctdb_listnodes.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 0 "ctdb listnodes"
+
+num_nodes=$(echo "$out" | wc -l)
+
+echo "Output for \"ctdb listnodes\" on node 0 (${num_nodes} nodes listed):"
+echo "$out"
+
+# Each line should look like an IP address.
+sanity_check_output \
+ 2 \
+ '^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+$' \
+ "$out"
+
+out_0="$out"
+
+echo "Checking other nodes..."
+
+n=1
+while [ $n -lt $num_nodes ] ; do
+ echo -n "Node ${n}: "
+ try_command_on_node $n "ctdb listnodes"
+ if [ "$out_0" = "$out" ] ; then
+ echo "OK"
+ else
+ echo "DIFFERs from node 0:"
+ echo "$out"
+ testfailures=1
+ fi
+ n=$(($n + 1))
+done
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/06_ctdb_getpid.sh b/ctdb/tests/simple/06_ctdb_getpid.sh
new file mode 100755
index 00000000000..4a3290c16bd
--- /dev/null
+++ b/ctdb/tests/simple/06_ctdb_getpid.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+# This is an attempt at being independent of the number of nodes
+# reported by "ctdb getpid -n all".
+try_command_on_node 0 "ctdb listnodes | wc -l"
+
+num_nodes="$out"
+
+echo "There are $num_nodes nodes..."
+
+# Call getpid a few different ways and make sure the answer is always the same.
+
+cmd="onnode -q all ctdb getpid"
+try_command_on_node 1 "$cmd"
+pids_onnode="$out"
+echo "Results from \"$cmd\":"
+echo "$pids_onnode"
+
+cmd="onnode -q 1 ctdb getpid -n all"
+try_command_on_node 1 "$cmd"
+pids_getpid_all="$out"
+echo "Results from \"$cmd\":"
+echo "$pids_getpid_all"
+
+cmd=""
+n=0
+while [ $n -lt $num_nodes ] ; do
+ cmd="${cmd}${cmd:+; }ctdb getpid -n $n"
+ n=$(($n + 1))
+done
+try_command_on_node 1 "$cmd"
+pids_getpid_n="$out"
+echo "Results from \"$cmd\":"
+echo "$pids_getpid_n"
+
+if [ "$pids_onnode" = "$pids_getpid_all" -a \
+ "$pids_getpid_all" = "$pids_getpid_n" ] ; then
+ echo "They're the same... cool!"
+else
+ echo "Error: they differ."
+ testfailures=1
+fi
+
+echo "Checking each PID for validity"
+
+n=0
+while [ $n -lt $num_nodes ] ; do
+ read line
+ pid=${line#Pid:}
+ try_command_on_node $n "ls -l /proc/${pid}/exe | sed -e 's@.*/@@'"
+ echo -n "Node ${n}, PID ${pid} looks to be running \"$out\" - "
+ if [ "$out" = "ctdbd" ] ; then
+ echo "GOOD!"
+ else
+ echo "BAD!"
+ testfailures=1
+ fi
+ n=$(($n + 1))
+done <<<"$pids_onnode"
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/07_ctdb_process_exists.sh b/ctdb/tests/simple/07_ctdb_process_exists.sh
new file mode 100755
index 00000000000..17f12314e2f
--- /dev/null
+++ b/ctdb/tests/simple/07_ctdb_process_exists.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+# Create a background process on node 2 that will last for 60 seconds.
+try_command_on_node 2 'sleep 60 >/dev/null 2>&1 & echo $!'
+pid="$out"
+
+echo "Checking for PID $pid on node 2"
+# set -e is good, but avoid it here
+status=0
+onnode 1 "ctdb process-exists 2:$pid" || status=$?
+echo "$out"
+
+if [ $status -eq 0 ] ; then
+ echo "OK"
+else
+ echo "BAD"
+ testfailures=1
+fi
+
+# Now just echo the PID of the shell from the onnode process on node
+# 2. This PID will disappear and PIDs shouldn't roll around fast
+# enough to trick the test... but there is a chance that will happen.
+try_command_on_node 2 'echo $$'
+pid="$out"
+
+echo "Checking for PID $pid on node 2"
+# set -e is good, but avoid it here
+status=0
+onnode 1 "ctdb process-exists 2:$pid" || status=$?
+echo "$out"
+
+if [ $status -ne 0 ] ; then
+ echo "OK"
+else
+ echo "BAD"
+ testfailures=1
+fi
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/08_ctdb_isnotrecmaster.sh b/ctdb/tests/simple/08_ctdb_isnotrecmaster.sh
new file mode 100755
index 00000000000..b0aac1ccaed
--- /dev/null
+++ b/ctdb/tests/simple/08_ctdb_isnotrecmaster.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+cmd='ctdb isnotrecmaster || true'
+try_command_on_node all "$cmd"
+echo "Output of \"$cmd\":"
+echo "$out"
+
+num_all_lines=$(echo "$out" | wc -l)
+num_rm_lines=$(echo "$out" | fgrep -c 'this node is the recmaster') || true
+num_not_rm_lines=$(echo "$out" | fgrep -c 'this node is not the recmaster') || true
+
+if [ $num_rm_lines -eq 1 ] ; then
+ echo "OK, there is only 1 recmaster"
+else
+ echo "BAD, there are ${num_rm_lines} nodes claiming to be the recmaster"
+ testfailures=1
+fi
+
+if [ $(($num_all_lines - $num_not_rm_lines)) -eq 1 ] ; then
+ echo "OK, all the other nodes claim not to be the recmaster"
+else
+ echo "BAD, there are only ${num_not_rm_lines} nodes claiming not to be the recmaster"
+ testfailures=1
+fi
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/11_ctdb_ip.sh b/ctdb/tests/simple/11_ctdb_ip.sh
new file mode 100755
index 00000000000..de1b4a86292
--- /dev/null
+++ b/ctdb/tests/simple/11_ctdb_ip.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+echo "Getting list of public IPs..."
+try_command_on_node 1 ctdb ip -n all
+ips=$(echo "$out" | sed -e '1d')
+colons=$(echo "$ips" | sed -e 's@^@:@' -e 's@$@:@' -e 's@ @:@')
+
+while read ip pnn ; do
+ try_command_on_node $pnn "ip addr show"
+ if [ "${out/inet ${ip}\/}" != "$out" ] ; then
+ echo "GOOD: node $pnn appears to have $ip assigned"
+ else
+ echo "BAD: node $pnn does not appear to have $ip assigned"
+ testfailures=1
+ fi
+done <<<"$ips" # bashism to avoid problem setting variable in pipeline.
+
+[ "$testfailures" != 1 ] && echo "Looks good!"
+
+cmd="ctdb -Y ip -n all | sed -e '1d'"
+echo "Checking that \"$cmd\" produces expected output..."
+
+try_command_on_node 1 "$cmd"
+if [ "$out" = "$colons" ] ; then
+ echo "Yep, looks good!"
+else
+ echo "Nope, it looks like this:"
+ echo "$out"
+ testfailures=1
+fi
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/31_ctdb_disable_simple.sh b/ctdb/tests/simple/31_ctdb_disable_simple.sh
new file mode 100755
index 00000000000..fdb7daed873
--- /dev/null
+++ b/ctdb/tests/simple/31_ctdb_disable_simple.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# From node 1, disable node 2. Make sure that according to "ctdb ip"
+# the public addresses are taken over and according to "ctdb status"
+# the node appears to be disabled. Don't actually check if the
+# address has been correctly taken over.
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 1 ctdb ip -n all
+
+ips=""
+while read ip pnn ; do
+ if [ "$pnn" = "2" ] ; then
+ ips="${ips}${ips:+ }${ip}"
+ fi
+done <<<"$out" # bashism to avoid problem setting variable in pipeline.
+
+echo "Node 2 has IPs: $ips"
+
+echo "Disabling node 2"
+
+try_command_on_node 1 ctdb disable -n 2
+
+# Avoid a potential race condition...
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 disabled
+
+if wait_until_ips_are_on_nodeglob '[!2]' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/32_ctdb_enable_simple.sh b/ctdb/tests/simple/32_ctdb_enable_simple.sh
new file mode 100755
index 00000000000..94b5beebb0b
--- /dev/null
+++ b/ctdb/tests/simple/32_ctdb_enable_simple.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+# From node 1, disable node 2. Make sure that according to "ctdb ip"
+# the public addresses are taken over and according to "ctdb status"
+# the node appears to be disabled. Don't actually check if the
+# address has been correctly taken over.
+
+. ctdb_test_functions.bash
+
+# Note that this doesn't work reliably over NFS!
+ctdb_trigger_recovered_file="/tmp/ctdb-trigger-recovered"
+
+setup_recovered_trigger ()
+{
+ onnode -q 0 touch "$ctdb_trigger_recovered_file"
+}
+
+recovered_triggered ()
+{
+ onnode -q 0 '! [ -e "$ctdb_trigger_recovered_file" ]'
+}
+
+wait_until_recovered_triggered ()
+{
+ wait_until 30 recovered_triggered
+}
+
+########################################
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 1 ctdb ip -n all
+
+ips=""
+while read ip pnn ; do
+ if [ "$pnn" = "2" ] ; then
+ ips="${ips}${ips:+ }${ip}"
+ fi
+done <<<"$out" # bashism to avoid problem setting variable in pipeline.
+
+echo "Node 2 has IPs: $ips"
+
+setup_recovered_trigger
+
+echo "Disabling node 2"
+try_command_on_node 1 ctdb disable -n 2
+
+# Avoid a potential race condition...
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 disabled
+
+if wait_until_ips_are_on_nodeglob '[!2]' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+#echo "Waiting until cluster has recovered..."
+#wait_until_recovered_triggered
+
+#echo "Sleeping to avoid potential race..."
+#sleep_for 3
+
+echo "Reenabling node 2"
+try_command_on_node 1 ctdb enable -n 2
+
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 enabled
+
+# BUG: this is only guaranteed if DeterministicIPs is 1 and
+# NoIPFailback is 0.
+if wait_until_ips_are_on_nodeglob '2' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+# Disabling this because for some reason it is completely unreliable.
+# Depend even more on the sleep below...
+echo "Waiting until cluster has recovered..."
+wait_until_recovered_triggered
+
+#echo "Sleeping to avoid potential race..."
+#sleep_for 10
+
+echo "All done!"
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/41_ctdb_ban_simple.sh b/ctdb/tests/simple/41_ctdb_ban_simple.sh
new file mode 100755
index 00000000000..e5d4bdbcee7
--- /dev/null
+++ b/ctdb/tests/simple/41_ctdb_ban_simple.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+CATEGORY="CTDB"
+
+test_info()
+{
+cat <<EOF
+Verify the operation of the 'ctdb ban' command.
+
+This is a superficial test of the 'ctdb ban' command. It trusts
+information from CTDB that indicates that the IP failover has
+happened correctly. Another test should check that the failover
+has actually happened at the networking level.
+
+Prerequisites:
+
+* An active CTDB cluster with at least 2 active nodes.
+
+Steps:
+
+1. Verify that the status on all of the ctdb nodes is 'OK'.
+2. Ban one of the nodes using the 'ctdb ban <timeout>' command.
+3. Before the ban timeout expires, verify that the status of the
+ node changes to 'banned'.
+4. Verify that the public IP addresses that were being served by
+ the node are failed over to one of the other nodes.
+5. When the ban expires ensure that the status of the node changes
+ back to 'OK' and that the public IP addresses move back to the
+ node.
+
+Expected results:
+
+* The status of the banned nodes changes as expected and IP addresses
+ failover as expected.
+
+EOF
+}
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 1 ctdb ip -n all
+
+ips=""
+while read ip pnn ; do
+ if [ "$pnn" = "2" ] ; then
+ ips="${ips}${ips:+ }${ip}"
+ fi
+done <<<"$out" # bashism to avoid problem setting variable in pipeline.
+
+echo "Node 2 has IPs: $ips"
+
+ban_time=15
+
+echo "Banning node 2 for $ban_time seconds"
+try_command_on_node 1 ctdb ban $ban_time -n 2
+
+# Avoid a potential race condition...
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 banned
+
+if wait_until_ips_are_on_nodeglob '[!2]' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+echo "Sleeping until ban expires..."
+sleep_for $ban_time
+
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 unbanned
+
+# BUG: this is only guaranteed if DeterministicIPs is 1 and
+# NoIPFailback is 0.
+if wait_until_ips_are_on_nodeglob '2' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+echo "Sleeping to avoid potential race..."
+sleep_for 3
+
+ctdb_test_exit
diff --git a/ctdb/tests/simple/42_ctdb_unban_simple.sh b/ctdb/tests/simple/42_ctdb_unban_simple.sh
new file mode 100755
index 00000000000..05b363a9162
--- /dev/null
+++ b/ctdb/tests/simple/42_ctdb_unban_simple.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+CATEGORY="CTDB"
+
+test_info()
+{
+cat <<EOF
+Verify the operation of the 'ctdb unban' command.
+
+This is a superficial test of the 'ctdb uban' command. It trusts
+information from CTDB that indicates that the IP failover and failback
+has happened correctly. Another test should check that the failover
+and failback has actually happened at the networking level.
+
+Prerequisites:
+
+* An active CTDB cluster with at least 2 active nodes.
+
+Steps:
+
+1. Verify that the status on all of the ctdb nodes is 'OK'.
+2. Ban one of the nodes using the 'ctdb ban <timeout>' command.
+3. Before the ban timeout expires, verify that the status of the
+ node changes to 'banned'.
+4. Verify that the public IP addresses that were being served by
+ the node are failed over to one of the other nodes.
+5. Before the ban timeout expires, use 'ctdb unban' to unban the
+ node.
+6. Verify that the status of the node changes back to 'OK' and that
+ the public IP addresses move back to the node.
+
+Expected results:
+
+* The 'ctdb unban' command successfully unbans a banned node.
+
+EOF
+}
+
+. ctdb_test_functions.bash
+
+set -e
+
+onnode 0 $TEST_WRAP cluster_is_healthy
+
+try_command_on_node 1 ctdb ip -n all
+
+ips=""
+while read ip pnn ; do
+ if [ "$pnn" = "2" ] ; then
+ ips="${ips}${ips:+ }${ip}"
+ fi
+done <<<"$out" # bashism to avoid problem setting variable in pipeline.
+
+echo "Node 2 has IPs: $ips"
+
+ban_time=60
+
+echo "Banning node 2 for $ban_time seconds"
+try_command_on_node 1 ctdb ban $ban_time -n 2
+
+# Avoid a potential race condition...
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 banned
+
+if wait_until_ips_are_on_nodeglob '[!2]' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+echo "Sleeping to avoid a potential race condition..."
+sleep_for 3
+
+echo "Unbanning node 2"
+try_command_on_node 1 ctdb unban -n 2
+
+onnode 0 $TEST_WRAP wait_until_node_has_status 2 unbanned
+
+# BUG: this is only guaranteed if DeterministicIPs is 1 and
+# NoIPFailback is 0.
+if wait_until_ips_are_on_nodeglob '2' $ips ; then
+ echo "All IPs moved."
+else
+ echo "Some IPs didn't move."
+ testfailures=1
+fi
+
+echo "Sleeping to avoid potential race..."
+sleep_for 3
+
+ctdb_test_exit
diff --git a/ctdb/tests/start_daemons.sh b/ctdb/tests/start_daemons.sh
index cf6b738f4a1..424d8920610 100755
--- a/ctdb/tests/start_daemons.sh
+++ b/ctdb/tests/start_daemons.sh
@@ -8,19 +8,25 @@ shift
NODES="./tests/nodes.txt"
rm -f $NODES
+PUBLIC_ADDRESSES=./tests/public_addresses.txt
+rm -f $PUBLIC_ADDRESSES
for i in `seq 1 $NUMNODES`; do
if [ "${CTDB_USE_IPV6}x" != "x" ]; then
echo ::$i >> $NODES
ip addr add ::$i/128 dev lo
else
echo 127.0.0.$i >> $NODES
+ #echo "127.0.1.$i/24 lo" >> $PUBLIC_ADDRESSES
+ #echo "127.0.1.$(($i + $NUMNODES))/24 lo" >> $PUBLIC_ADDRESSES
+ echo "192.0.2.$i/24 lo" >> $PUBLIC_ADDRESSES
+ echo "192.0.2.$(($i + $NUMNODES))/24 lo" >> $PUBLIC_ADDRESSES
fi
done
killall -q ctdbd
rm -rf test.db/persistent/*
-CTDB_OPTIONS="--reclock=rec.lock --nlist $NODES --event-script-dir=tests/events.d --logfile=- -d 0 --dbdir=test.db --dbdir-persistent=test.db/persistent $*"
+CTDB_OPTIONS="--reclock=rec.lock --nlist $NODES --public-addresses $PUBLIC_ADDRESSES --event-script-dir=tests/events.d --logfile=- -d 0 --dbdir=test.db --dbdir-persistent=test.db/persistent $*"
echo "Starting $NUMNODES ctdb daemons"
for i in `seq 1 $NUMNODES`; do
diff --git a/ctdb/tools/onnode b/ctdb/tools/onnode
index 6fb8fbe7bc7..5bb5ebbfb89 100755
--- a/ctdb/tools/onnode
+++ b/ctdb/tools/onnode
@@ -148,6 +148,7 @@ get_nodes_with_status ()
esac
if [ -z "$ctdb_status_output" ] ; then
+ # FIXME: need to do something if $CTDB_NODES_SOCKETS is set.
ctdb_status_output=$(ctdb -Y status 2>/dev/null)
if [ $? -ne 0 ] ; then
echo "${prog}: unable to get status of CTDB nodes" >&2
@@ -177,8 +178,14 @@ get_nodes_with_status ()
ctdb_recmaster=""
get_nodes ()
{
- [ -f "$CTDB_NODES_FILE" ] || CTDB_NODES_FILE=/etc/ctdb/nodes
- local all_nodes=$(egrep '^[[:alnum:]]' $CTDB_NODES_FILE)
+ local all_nodes
+
+ if [ -n "$CTDB_NODES_SOCKETS" ] ; then
+ all_nodes="$CTDB_NODES_SOCKETS"
+ else
+ [ -f "$CTDB_NODES_FILE" ] || CTDB_NODES_FILE=/etc/ctdb/nodes
+ all_nodes=$(egrep '^[[:alnum:]]' $CTDB_NODES_FILE)
+ fi
local nodes=""
local n
@@ -210,20 +217,29 @@ get_nodes ()
done
}
+fakessh ()
+{
+ CTDB_SOCKET="$1" sh -c "$2"
+}
+
######################################################################
parse_options "$@"
$current && command="cd $PWD && $command"
-SSH_OPTS=
-# Could "2>/dev/null || true" but want to see errors from typos in file.
-[ -r /etc/ctdb/onnode.conf ] && . /etc/ctdb/onnode.conf
-[ -n "$SSH" ] || SSH=ssh
-if [ "$SSH" = "ssh" ] ; then
- ssh_opts="-n"
-else
- : # rsh? All bets are off!
+ssh_opts=
+if [ -n "$CTDB_NODES_SOCKETS" ] ; then
+ SSH=fakessh
+else
+ # Could "2>/dev/null || true" but want to see errors from typos in file.
+ [ -r /etc/ctdb/onnode.conf ] && . /etc/ctdb/onnode.conf
+ [ -n "$SSH" ] || SSH=ssh
+ if [ "$SSH" = "ssh" ] ; then
+ ssh_opts="-n"
+ else
+ : # rsh? All bets are off!
+ fi
fi
######################################################################