# Hey Emacs, this is a -*- shell-script -*- !!! :-) # # Augment PATH with relevant stubs/ directories. # stubs_dir="${CTDB_TEST_SUITE_DIR}/stubs" [ -d "${stubs_dir}" ] || die "Failed to locate stubs/ subdirectory" # Make the path absolute for tests that change directory case "$stubs_dir" in /*) : ;; *) stubs_dir="${PWD}/${stubs_dir}" ;; esac # Use stubs as helpers export CTDB_HELPER_BINDIR="$stubs_dir" PATH="${stubs_dir}:${PATH}" export CTDB="ctdb" # Force this to be absolute - event scripts can change directory CTDB_TEST_TMP_DIR=$(cd "$CTDB_TEST_TMP_DIR" && echo "$PWD") export CTDB_LOGGING="file:" if [ -d "${CTDB_TEST_SUITE_DIR}/etc" ]; then cp -a "${CTDB_TEST_SUITE_DIR}/etc" "$CTDB_TEST_TMP_DIR" export CTDB_SYS_ETCDIR="${CTDB_TEST_TMP_DIR}/etc" else die "Unable to setup \$CTDB_SYS_ETCDIR" fi setup_ctdb_base "$CTDB_TEST_TMP_DIR" "etc-ctdb" \ debug_locks.sh \ functions \ nfs-checks.d \ nfs-linux-kernel-callout \ statd-callout export FAKE_CTDB_STATE="${CTDB_TEST_TMP_DIR}/fake-ctdb" mkdir -p "$FAKE_CTDB_STATE" export FAKE_NETWORK_STATE="${CTDB_TEST_TMP_DIR}/fake-network-state" mkdir -p "$FAKE_NETWORK_STATE" ###################################################################### if "$CTDB_TEST_VERBOSE"; then debug() { if [ -n "$1" ]; then echo "$@" >&2 else cat >&2 fi } else debug() { : } fi ###################################################################### # General setup fakery # Default is to use script name with ".options" appended. With # arguments, this can specify an alternate script name (and # component). setup_script_options() { if [ $# -eq 2 ]; then _script="$2" elif [ $# -eq 0 ]; then _script="" else die "usage: setup_script_options [ component script ]" fi if [ -n "$_script" ]; then _options="${CTDB_BASE}/events/legacy/${_script}.options" else _options="${script_dir}/${script%.script}.options" fi cat >>"$_options" # Source the options so that tests can use the variables . "$_options" } setup_dbdir() { export CTDB_DBDIR_BASE="${CTDB_TEST_TMP_DIR}/db" CTDB_DBDIR="${CTDB_DBDIR_BASE}/volatile" CTDB_DBDIR_PERSISTENT="${CTDB_DBDIR_BASE}/persistent" CTDB_DBDIR_STATE="${CTDB_DBDIR_BASE}/state" cat >>"${CTDB_BASE}/ctdb.conf" <> 8)) done echo "${_net}/${_maskbits}" } ###################################################################### # CTDB fakery # shellcheck disable=SC2120 # Argument can be used in testcases setup_numnodes() { export FAKE_CTDB_NUMNODES="${1:-3}" echo "Setting up CTDB with ${FAKE_CTDB_NUMNODES} fake nodes" } # For now this creates the same public addresses each time. However, # it could be made more flexible. setup_public_addresses() { _f="${CTDB_BASE}/public_addresses" echo "Setting up public addresses in ${_f}" cat >"$_f" < 1 {print $2}' | xargs } ctdb_get_1_interface() { _t=$(ctdb_get_interfaces) echo "${_t%% *}" } # Print public addresses on this node as: interface IP maskbits # Each line is suitable for passing to takeip/releaseip ctdb_get_my_public_addresses() { ctdb ip -v -X | { read -r _ # skip header line while IFS="|" read -r _ _ip _ _iface _; do [ -n "$_iface" ] || continue while IFS="/$IFS" read -r _i _maskbits _; do if [ "$_ip" = "$_i" ]; then echo "$_iface $_ip $_maskbits" break fi done <"${CTDB_BASE}/public_addresses" done } } # Prints the 1st public address as: interface IP maskbits # This is suitable for passing to takeip/releaseip ctdb_get_1_public_address() { ctdb_get_my_public_addresses | { head -n 1 cat >/dev/null } } # Check the routes against those that are expected. $1 is the number # of assigned IPs to use (, all), defaulting to 1. If $2 is # "default" then expect default routes to have been added. check_routes() { _num_ips="${1:-1}" _should_add_default="$2" _policy_rules="" _policy_routes="" ctdb_get_my_public_addresses | if [ "$_num_ips" = "all" ]; then cat else { head -n "$_num_ips" cat >/dev/null } fi | { while read -r _dev _ip _bits; do _net=$(ipv4_host_addr_to_net "$_ip" "$_bits") _gw="${_net%.*}.254" # a dumb, calculated default _policy_rules="${_policy_rules} ${CTDB_PER_IP_ROUTING_RULE_PREF}: from $_ip lookup ctdb.$_ip " _policy_routes="${_policy_routes} # ip route show table ctdb.$_ip $_net dev $_dev scope link " if [ "$_should_add_default" = "default" ]; then _policy_routes="${_policy_routes} default via $_gw dev $_dev " fi done ok <] fake_stack_trace_for_pid_${_pid}/stack+0x0/0xff EOF } ###################################################################### # Result and test functions ############################################################ setup() { die "setup() is not defined" } # Set some globals and print the summary. define_test() { desc="$1" _f=$(basename "$0" ".sh") # Remaining format should be NN.script.event.NUM or # NN.script.NUM or script.NUM: _num="${_f##*.}" _f="${_f%.*}" case "$_f" in [0-9][0-9].*) case "$_f" in [0-9][0-9].*.*) script="${_f%.*}.script" event="${_f##*.}" ;; [0-9][0-9].*) script="${_f}.script" unset event ;; esac # "Enable" the script _subdir="events/legacy" script_dir="${CTDB_BASE}/${_subdir}" # Symlink target needs to be absolute case "$CTDB_SCRIPTS_DATA_DIR" in /*) _data_dir="${CTDB_SCRIPTS_DATA_DIR}/${_subdir}" ;; *) _data_dir="${PWD}/${CTDB_SCRIPTS_DATA_DIR}/${_subdir}" ;; esac mkdir -p "$script_dir" ln -s "${_data_dir}/${script}" "$script_dir" ;; *) script="${_f%.*}" script="$_f" unset event script_dir="${CTDB_BASE}" ;; esac _s="${script_dir}/${script}" [ -r "$_s" ] || die "Internal error - unable to find script \"${_s}\"" case "$script" in *.script) script_short="${script%.script}" ;; *.sh) script_short="${script%.sh}" ;; *) script_short="$script" ;; esac printf "%-17s %-10s %-4s - %s\n\n" \ "$script_short" "$event" "$_num" "$desc" _f="${CTDB_TEST_SUITE_DIR}/scripts/${script_short}.sh" if [ -r "$_f" ]; then . "$_f" fi ctdb_set_pnn 0 } # Run an eventscript once. The test passes if the return code and # output match those required. # Any args are passed to the eventscript. simple_test() { [ -n "$event" ] || die 'simple_test: event not set' args="$*" # shellcheck disable=SC2317 # used in unit_test(), etc. test_header() { echo "Running script \"$script $event${args:+ }$args\"" } # shellcheck disable=SC2317 # used in unit_test(), etc. extra_header() { cat <