diff options
Diffstat (limited to '')
-rwxr-xr-x | ctdb/tests/UNIT/eventscripts/stubs/ctdb | 481 | ||||
-rwxr-xr-x | ctdb/tests/UNIT/eventscripts/stubs/ctdb-config | 2 | ||||
-rwxr-xr-x | ctdb/tests/UNIT/eventscripts/stubs/ctdb_killtcp | 10 | ||||
-rwxr-xr-x | ctdb/tests/UNIT/eventscripts/stubs/ctdb_lvs | 53 | ||||
-rwxr-xr-x | ctdb/tests/UNIT/eventscripts/stubs/ctdb_natgw | 34 |
5 files changed, 580 insertions, 0 deletions
diff --git a/ctdb/tests/UNIT/eventscripts/stubs/ctdb b/ctdb/tests/UNIT/eventscripts/stubs/ctdb new file mode 100755 index 0000000..20135eb --- /dev/null +++ b/ctdb/tests/UNIT/eventscripts/stubs/ctdb @@ -0,0 +1,481 @@ +#!/bin/sh + +prog="ctdb" + +# Print a message and exit. +die() +{ + echo "$1" >&2 + exit "${2:-1}" +} + +not_implemented_exit_code=1 + +usage() +{ + cat >&2 <<EOF +Usage: $prog [-X] cmd + +A fake CTDB stub that prints items depending on the variables +FAKE_CTDB_PNN (default 0) depending on command-line options. +EOF + exit 1 +} + +not_implemented() +{ + echo "${prog}: command \"$1\" not implemented in stub" >&2 + exit $not_implemented_exit_code +} + +verbose=false +machine_readable=false +nodespec="" + +args="" + +# Options and command argument can appear in any order, so when +# getopts thinks it is done, process any non-option arguments and go +# around again. +while [ $# -gt 0 ]; do + while getopts "Xvhn:?" opt; do + case "$opt" in + X) machine_readable=true ;; + v) verbose=true ;; + n) nodespec="$OPTARG" ;; + \? | *) usage ;; + esac + done + shift $((OPTIND - 1)) + + # Anything left over must be a non-option arg + if [ $# -gt 0 ]; then + args="${args}${args:+ }${1}" + shift + fi +done + +[ -n "$args" ] || usage +# Want word splitting +# shellcheck disable=SC2086 +set -- $args + +setup_tickles() +{ + # Make sure tickles file exists. + tickles_file="${CTDB_TEST_TMP_DIR}/fake-ctdb/tickles" + mkdir -p "$(dirname "$tickles_file")" + touch "$tickles_file" +} + +ctdb_gettickles() +{ + _ip="$1" + _port="$2" + + setup_tickles + + echo "|source ip|port|destination ip|port|" + while read -r _src _dst; do + if [ -z "$_ip" ] || [ "$_ip" = "${_dst%:*}" ]; then + if [ -z "$_port" ] || [ "$_port" = "${_dst##*:}" ]; then + echo "|${_src%:*}|${_src##*:}|${_dst%:*}|${_dst##*:}|" + fi + fi + done <"$tickles_file" +} + +ctdb_addtickle() +{ + _src="$1" + _dst="$2" + + setup_tickles + + if [ -n "$_dst" ]; then + echo "${_src} ${_dst}" >>"$tickles_file" + else + cat >>"$tickles_file" + fi +} + +ctdb_deltickle() +{ + _src="$1" + _dst="$2" + + setup_tickles + + if [ -n "$_dst" ]; then + _t=$(grep -F -v "${_src} $${_dst}" "$tickles_file") + else + _t=$(cat "$tickles_file") + while read -r _src _dst; do + _t=$(echo "$_t" | grep -F -v "${_src} ${_dst}") + done + fi + echo "$_t" >"$tickles_file" +} + +parse_nodespec() +{ + if [ "$nodespec" = "all" ]; then + nodes="$(seq 0 $((FAKE_CTDB_NUMNODES - 1)))" + elif [ -n "$nodespec" ]; then + nodes="$(echo "$nodespec" | sed -e 's@,@ @g')" + else + nodes=$(ctdb_pnn) + fi +} + +# For testing backward compatibility... +for i in $CTDB_NOT_IMPLEMENTED; do + if [ "$i" = "$1" ]; then + not_implemented "$i" + fi +done + +ctdb_pnn() +{ + # Defaults to 0 + echo "${FAKE_CTDB_PNN:-0}" +} + +###################################################################### + +FAKE_CTDB_NODE_STATE="$FAKE_CTDB_STATE/node-state" +FAKE_CTDB_NODES_DISABLED="$FAKE_CTDB_NODE_STATE/0x4" + +###################################################################### + +# NOTE: all nodes share public addresses file + +FAKE_CTDB_IP_LAYOUT="$FAKE_CTDB_STATE/ip-layout" + +ip_reallocate() +{ + touch "$FAKE_CTDB_IP_LAYOUT" + + # ShellCheck doesn't understand this flock pattern + # shellcheck disable=SC2094 + ( + flock 0 + + _pa="${CTDB_BASE}/public_addresses" + + if [ ! -s "$FAKE_CTDB_IP_LAYOUT" ]; then + sed -n -e 's@^\([^#][^/]*\)/.*@\1 -1@p' \ + "$_pa" >"$FAKE_CTDB_IP_LAYOUT" + fi + + _t="${FAKE_CTDB_IP_LAYOUT}.new" + + _flags="" + for _i in $(seq 0 $((FAKE_CTDB_NUMNODES - 1))); do + if ls "$FAKE_CTDB_STATE/node-state/"*"/$_i" >/dev/null 2>&1; then + # Have non-zero flags + _this=0 + for _j in "$FAKE_CTDB_STATE/node-state/"*"/$_i"; do + _tf="${_j%/*}" # dirname + _f="${_tf##*/}" # basename + _this=$((_this | _f)) + done + else + _this="0" + fi + _flags="${_flags}${_flags:+,}${_this}" + done + CTDB_TEST_LOGLEVEL=NOTICE \ + "ctdb_takeover_tests" \ + "ipalloc" "$_flags" <"$FAKE_CTDB_IP_LAYOUT" | + sort >"$_t" + mv "$_t" "$FAKE_CTDB_IP_LAYOUT" + ) <"$FAKE_CTDB_IP_LAYOUT" +} + +ctdb_ip() +{ + # If nobody has done any IP-fu then generate a layout. + [ -f "$FAKE_CTDB_IP_LAYOUT" ] || ip_reallocate + + _mypnn=$(ctdb_pnn) + + if $machine_readable; then + if $verbose; then + echo "|Public IP|Node|ActiveInterface|AvailableInterfaces|ConfiguredInterfaces|" + else + echo "|Public IP|Node|" + fi + else + echo "Public IPs on node ${_mypnn}" + fi + + # Join public addresses file with $FAKE_CTDB_IP_LAYOUT, and + # process output line by line... + _pa="${CTDB_BASE}/public_addresses" + sed -e 's@/@ @' "$_pa" | sort | join - "$FAKE_CTDB_IP_LAYOUT" | + while read -r _ip _ _ifaces _pnn; do + if $verbose; then + # If more than 1 interface, assume all addresses are on the 1st. + _first_iface="${_ifaces%%,*}" + # Only show interface if address is on this node. + _my_iface="" + if [ "$_pnn" = "$_mypnn" ]; then + _my_iface="$_first_iface" + fi + if $machine_readable; then + echo "|${_ip}|${_pnn}|${_my_iface}|${_first_iface}|${_ifaces}|" + else + echo "${_ip} node[${_pnn}] active[${_my_iface}] available[${_first_iface}] configured[[${_ifaces}]" + fi + else + if $machine_readable; then + echo "|${_ip}|${_pnn}|" + else + echo "${_ip} ${_pnn}" + fi + fi + done +} + +ctdb_moveip() +{ + _ip="$1" + _target="$2" + + ip_reallocate # should be harmless and ensures we have good state + + # ShellCheck doesn't understand this flock pattern + # shellcheck disable=SC2094 + ( + flock 0 + + _t="${FAKE_CTDB_IP_LAYOUT}.new" + + while read -r _i _pnn; do + if [ "$_ip" = "$_i" ]; then + echo "$_i $_target" + else + echo "$_i $_pnn" + fi + done | sort >"$_t" + mv "$_t" "$FAKE_CTDB_IP_LAYOUT" + ) <"$FAKE_CTDB_IP_LAYOUT" +} + +###################################################################### + +ctdb_enable() +{ + parse_nodespec + + for _i in $nodes; do + rm -f "${FAKE_CTDB_NODES_DISABLED}/${_i}" + done + + ip_reallocate +} + +ctdb_disable() +{ + parse_nodespec + + for _i in $nodes; do + mkdir -p "$FAKE_CTDB_NODES_DISABLED" + touch "${FAKE_CTDB_NODES_DISABLED}/${_i}" + done + + ip_reallocate +} + +###################################################################### + +ctdb_shutdown() +{ + echo "CTDB says BYE!" +} + +###################################################################### + +# This is only used by the NAT and LVS gateway code at the moment, so +# use a hack. Assume that $CTDB_NATGW_NODES or $CTDB_LVS_NODES +# contains all nodes in the cluster (which is what current tests +# assume). Use the PNN to find the address from this file. The NAT +# gateway code only used the address, so just mark the node healthy. +ctdb_nodestatus() +{ + echo '|Node|IP|Disconnected|Banned|Disabled|Unhealthy|Stopped|Inactive|PartiallyOnline|ThisNode|' + _line=$((FAKE_CTDB_PNN + 1)) + _ip=$(sed -e "${_line}p" "${CTDB_NATGW_NODES:-${CTDB_LVS_NODES}}") + echo "|${FAKE_CTDB_PNN}|${_ip}|0|0|0|0|0|0|0|Y|" +} + +###################################################################### + +_t_setup() +{ + _t_dir="${CTDB_TEST_TMP_DIR}/fake-ctdb/fake-tdb/$1" + mkdir -p "$_t_dir" +} + +_t_put() +{ + echo "$2" >"${_t_dir}/$1" +} + +_t_get() +{ + cat "${_t_dir}/$1" +} + +_t_del() +{ + rm -f "${_t_dir}/$1" +} + +ctdb_pstore() +{ + _t_setup "$1" + _t_put "$2" "$3" +} + +ctdb_pdelete() +{ + _t_setup "$1" + _t_del "$2" +} + +ctdb_pfetch() +{ + _t_setup "$1" + _t_get "$2" >"$3" 2>/dev/null +} + +ctdb_ptrans() +{ + _t_setup "$1" + + while IFS="" read -r _line; do + _k=$(echo "$_line" | sed -n -e 's@^"\([^"]*\)" "[^"]*"$@\1@p') + _v=$(echo "$_line" | sed -e 's@^"[^"]*" "\([^"]*\)"$@\1@') + [ -n "$_k" ] || die "ctdb ptrans: bad line \"${_line}\"" + if [ -n "$_v" ]; then + _t_put "$_k" "$_v" + else + _t_del "$_k" + fi + done +} + +ctdb_catdb() +{ + _t_setup "$1" + + # This will break on keys with spaces but we don't have any of + # those yet. + _count=0 + for _i in "${_t_dir}/"*; do + [ -r "$_i" ] || continue + _k="${_i##*/}" # basename + _v=$(_t_get "$_k") + _kn=$(printf '%s' "$_k" | wc -c) + _vn=$(printf '%s' "$_v" | wc -c) + cat <<EOF +key(${_kn}) = "${_k}" +dmaster: 0 +rsn: 1 +data(${_vn}) = "${_v}" + +EOF + _count=$((_count + 1)) + done + + echo "Dumped ${_count} records" +} + +###################################################################### + +FAKE_CTDB_IFACES_DOWN="${FAKE_CTDB_STATE}/ifaces-down" +rm -f "${FAKE_CTDB_IFACES_DOWN}"/* + +ctdb_ifaces() +{ + _f="${CTDB_BASE}/public_addresses" + + if [ ! -f "$_f" ]; then + die "Public addresses file \"${_f}\" not found" + fi + + # Assume -Y. + echo "|Name|LinkStatus|References|" + while read -r _ip _iface; do + case "$_ip" in + \#*) : ;; + *) + _status=1 + # For now assume _iface contains only 1. + if [ -f "{FAKE_CTDB_IFACES_DOWN}/${_iface}" ]; then + _status=0 + fi + # Nobody looks at references + echo "|${_iface}|${_status}|0|" + ;; + esac + done <"$_f" | + sort -u +} + +ctdb_setifacelink() +{ + _iface="$1" + _state="$2" + + mkdir -p "$FAKE_CTDB_IFACES_DOWN" + + # Existence of file means CTDB thinks interface is down. + _f="${FAKE_CTDB_IFACES_DOWN}/${_iface}" + + case "$_state" in + up) rm -f "$_f" ;; + down) touch "$_f" ;; + *) die "ctdb setifacelink: unsupported interface status ${_state}" ;; + esac +} + +###################################################################### + +ctdb_checktcpport() +{ + _port="$1" + + for _i in $FAKE_TCP_LISTEN; do + if [ "$_port" = "$_i" ]; then + exit 98 + fi + done + + exit 0 +} + +ctdb_gratarp() +{ + # Do nothing for now + : +} + +###################################################################### + +cmd="$1" +shift + +func="ctdb_${cmd}" + +# This could inadvertently run an external function instead of a local +# function. However, this can only happen if testing a script +# containing a new ctdb command that is not implemented, so this is +# unlikely to do harm. +if type "$func" >/dev/null 2>&1; then + "$func" "$@" +else + not_implemented "$cmd" +fi diff --git a/ctdb/tests/UNIT/eventscripts/stubs/ctdb-config b/ctdb/tests/UNIT/eventscripts/stubs/ctdb-config new file mode 100755 index 0000000..818e3db --- /dev/null +++ b/ctdb/tests/UNIT/eventscripts/stubs/ctdb-config @@ -0,0 +1,2 @@ +#!/bin/sh +exec $VALGRIND "${CTDB_SCRIPTS_HELPER_BINDIR}/ctdb-config" "$@" diff --git a/ctdb/tests/UNIT/eventscripts/stubs/ctdb_killtcp b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_killtcp new file mode 100755 index 0000000..2a4bac4 --- /dev/null +++ b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_killtcp @@ -0,0 +1,10 @@ +#!/bin/sh + +# Only supports reading from stdin + +# shellcheck disable=SC2034 +iface="$1" # ignored + +while read -r src dst; do + sed -i -e "/^${dst} ${src}\$/d" "$FAKE_NETSTAT_TCP_ESTABLISHED_FILE" +done diff --git a/ctdb/tests/UNIT/eventscripts/stubs/ctdb_lvs b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_lvs new file mode 100755 index 0000000..31f56e8 --- /dev/null +++ b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_lvs @@ -0,0 +1,53 @@ +#!/bin/sh + +prog="ctdb_lvs" + +# Print a message and exit. +die() +{ + echo "$1" >&2 + exit "${2:-1}" +} + +not_implemented_exit_code=1 + +usage() +{ + cat >&2 <<EOF +Usage: $prog { leader | list } +EOF + exit 1 +} + +not_implemented() +{ + echo "${prog}: command \"$1\" not implemented in stub" >&2 + exit $not_implemented_exit_code +} + +ctdb_lvs_leader() +{ + if [ -n "$FAKE_CTDB_LVS_LEADER" ]; then + echo "$FAKE_CTDB_LVS_LEADER" + return 0 + else + return 255 + fi +} + +ctdb_lvs_list() +{ + _pnn=0 + while read -r _ip _; do + echo "${_pnn} ${_ip}" + _pnn=$((_pnn + 1)) + done <"$CTDB_LVS_NODES" +} + +###################################################################### + +case "$1" in +leader) ctdb_lvs_leader "$@" ;; +list) ctdb_lvs_list "$@" ;; +*) not_implemented "$1" ;; +esac diff --git a/ctdb/tests/UNIT/eventscripts/stubs/ctdb_natgw b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_natgw new file mode 100755 index 0000000..22a2191 --- /dev/null +++ b/ctdb/tests/UNIT/eventscripts/stubs/ctdb_natgw @@ -0,0 +1,34 @@ +#!/bin/sh + +prog="ctdb_natgw" + +not_implemented_exit_code=1 + +not_implemented() +{ + echo "${prog}: command \"$1\" not implemented in stub" >&2 + exit $not_implemented_exit_code +} + +ctdb_natgw_leader() +{ + [ -r "$CTDB_NATGW_NODES" ] || + die "error: missing CTDB_NATGW_NODES=${CTDB_NATGW_NODES}" + + # Determine the leader node + _leader="-1 0.0.0.0" + _pnn=0 + while read -r _ip; do + if [ "$FAKE_CTDB_NATGW_LEADER" = "$_ip" ]; then + _leader="${_pnn} ${_ip}" + break + fi + _pnn=$((_pnn + 1)) + done <"$CTDB_NATGW_NODES" + echo "$_leader" +} + +case "$1" in +leader) ctdb_natgw_leader "$@" ;; +*) not_implemented "$1" ;; +esac |