test,qa/workunits: add tests for public_bind_addr

Add a set of new tests for the case when public_addr and public_bind_addr
are different for a mon. In order to test this properly I had to employ
port forwarding with socat. This helps simulate what would happen in a
environment like Kubernetes. socat is now a build dependency.

Also, moved jq_success to ceph-helpers.sh and refactored run_mon to enable
creating the mons without creating the rbd pool immediately.

Signed-off-by: Bassam Tabbara <bassam.tabbara@quantum.com>
This commit is contained in:
Bassam Tabbara 2017-07-07 01:13:35 -07:00
parent bf49385679
commit a8da9fd077
7 changed files with 205 additions and 44 deletions

View File

@ -131,6 +131,7 @@ BuildRequires: python-pecan
BuildRequires: python-requests
BuildRequires: python-virtualenv
BuildRequires: python-werkzeug
BuildRequires: socat
BuildRequires: snappy-devel
BuildRequires: udev
BuildRequires: util-linux

1
debian/control vendored
View File

@ -58,6 +58,7 @@ Build-Depends: bc,
python-werkzeug,
python3-all-dev,
python3-setuptools,
socat,
uuid-runtime,
valgrind,
virtualenv | python-virtualenv,

View File

@ -43,6 +43,7 @@ if [ x`uname`x = xFreeBSDx ]; then
ftp/curl \
misc/e2fsprogs-libuuid \
misc/getopt \
net/socat \
textproc/expat2 \
textproc/gsed \
textproc/libxml2 \

View File

@ -363,7 +363,7 @@ function test_kill_daemons() {
# @param ... can be any option valid for ceph-mon
# @return 0 on success, 1 on error
#
function run_mon() {
function run_mon_no_pool() {
local dir=$1
shift
local id=$1
@ -398,13 +398,23 @@ function run_mon() {
--mon-allow-pool-delete \
"$@" || return 1
ceph osd pool create rbd 8
cat > $dir/ceph.conf <<EOF
[global]
fsid = $(get_config mon $id fsid)
mon host = $(get_config mon $id mon_host)
EOF
}
function run_mon() {
local dir=$1
shift
local id=$1
shift
run_mon_no_pool $dir $id "$@" || return 1
ceph osd pool create rbd 8
if test -z "$(get_config mon $id mon_initial_members)" ; then
ceph osd pool delete rbd rbd --yes-i-really-really-mean-it || return 1
ceph osd pool create rbd $PG_NUM || return 1
@ -1766,6 +1776,46 @@ if test "$1" = TESTS ; then
run_tests "$@"
fi
# NOTE:
# jq only support --exit-status|-e from version 1.4 forwards, which makes
# returning on error waaaay prettier and straightforward.
# However, the current automated upstream build is running with v1.3,
# which has no idea what -e is. Hence the convoluted error checking we
# need. Sad.
# The next time someone changes this code, please check if v1.4 is now
# a thing, and, if so, please change these to use -e. Thanks.
# jq '.all.supported | select([.[] == "foo"] | any)'
function jq_success() {
input="$1"
filter="$2"
expects="\"$3\""
in_escaped=$(printf %s "$input" | sed "s/'/'\\\\''/g")
filter_escaped=$(printf %s "$filter" | sed "s/'/'\\\\''/g")
ret=$(echo "$in_escaped" | jq "$filter_escaped")
if [[ "$ret" == "true" ]]; then
return 0
elif [[ -n "$expects" ]]; then
if [[ "$ret" == "$expects" ]]; then
return 0
fi
fi
return 1
input=$1
filter=$2
expects="$3"
ret="$(echo $input | jq \"$filter\")"
if [[ "$ret" == "true" ]]; then
return 0
elif [[ -n "$expects" && "$ret" == "$expects" ]]; then
return 0
fi
return 1
}
# Local Variables:
# compile-command: "cd ../../src ; make -j4 && ../qa/workunits/ceph-helpers.sh TESTS # test_get_config"
# End:

View File

@ -23,6 +23,7 @@ set_target_properties(ceph_test_mon_msg PROPERTIES COMPILE_FLAGS
#scripts
add_ceph_test(misc.sh ${CMAKE_CURRENT_SOURCE_DIR}/misc.sh)
add_ceph_test(mkfs.sh ${CMAKE_CURRENT_SOURCE_DIR}/mkfs.sh)
add_ceph_test(mon-bind.sh ${CMAKE_CURRENT_SOURCE_DIR}/mon-bind.sh)
add_ceph_test(mon-created-time.sh ${CMAKE_CURRENT_SOURCE_DIR}/mon-created-time.sh)
add_ceph_test(mon-handle-forward.sh ${CMAKE_CURRENT_SOURCE_DIR}/mon-handle-forward.sh)
add_ceph_test(mon-ping.sh ${CMAKE_CURRENT_SOURCE_DIR}/mon-ping.sh)

View File

@ -151,36 +151,6 @@ function TEST_no_segfault_for_bad_keyring() {
teardown $dir || return 1
}
function jq_success() {
input="$1"
filter="$2"
expects="\"$3\""
in_escaped=$(printf %s "$input" | sed "s/'/'\\\\''/g")
filter_escaped=$(printf %s "$filter" | sed "s/'/'\\\\''/g")
ret=$(echo "$in_escaped" | jq "$filter_escaped")
if [[ "$ret" == "true" ]]; then
return 0
elif [[ -n "$expects" ]]; then
if [[ "$ret" == "$expects" ]]; then
return 0
fi
fi
return 1
input=$1
filter=$2
expects="$3"
ret="$(echo $input | jq \"$filter\")"
if [[ "$ret" == "true" ]]; then
return 0
elif [[ -n "$expects" && "$ret" == "$expects" ]]; then
return 0
fi
return 1
}
function TEST_mon_features() {
local dir=$1
setup $dir || return 1
@ -200,17 +170,6 @@ function TEST_mon_features() {
run_mon $dir b --public-addr $MONB || return 1
timeout 120 ceph -s > /dev/null || return 1
# NOTE:
# jq only support --exit-status|-e from version 1.4 forwards, which makes
# returning on error waaaay prettier and straightforward.
# However, the current automated upstream build is running with v1.3,
# which has no idea what -e is. Hence the convoluted error checking we
# need. Sad.
# The next time someone changes this code, please check if v1.4 is now
# a thing, and, if so, please change these to use -e. Thanks.
# jq '.all.supported | select([.[] == "foo"] | any)'
# expect monmap to contain 3 monitors (a, b, and c)
jqinput="$(ceph mon_status --format=json 2>/dev/null)"
jq_success "$jqinput" '.monmap.mons | length == 3' || return 1

148
src/test/mon/mon-bind.sh Executable file
View File

@ -0,0 +1,148 @@
#!/bin/bash
#
# Copyright (C) 2017 Quantum Corp.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library Public License for more details.
#
source $(dirname $0)/../detect-build-env-vars.sh
source $CEPH_ROOT/qa/workunits/ceph-helpers.sh
SOCAT_PIDS=()
function port_forward() {
local source_port=$1
local target_port=$2
socat TCP-LISTEN:${source_port},fork,reuseaddr TCP:localhost:${target_port} &
SOCAT_PIDS+=( $! )
}
function cleanup() {
for p in "${SOCAT_PIDS[@]}"; do
kill $p
done
SOCAT_PIDS=()
}
trap cleanup SIGTERM SIGKILL SIGQUIT SIGINT
function run() {
local dir=$1
shift
export MON_IP=127.0.0.1
export MONA_PUBLIC=7132 # git grep '\<7132\>' ; there must be only one
export MONB_PUBLIC=7133 # git grep '\<7133\>' ; there must be only one
export MONC_PUBLIC=7134 # git grep '\<7134\>' ; there must be only one
export MONA_BIND=7135 # git grep '\<7135\>' ; there must be only one
export MONB_BIND=7136 # git grep '\<7136\>' ; there must be only one
export MONC_BIND=7137 # git grep '\<7137\>' ; there must be only one
export CEPH_ARGS
CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
for func in $funcs ; do
setup $dir || return 1
$func $dir && cleanup || { cleanup; return 1; }
teardown $dir
done
}
function TEST_mon_client_connect_fails() {
local dir=$1
# start the mon with a public-bind-addr that is different
# from the public-addr.
CEPH_ARGS+="--mon-initial-members=a "
CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC} "
run_mon_no_pool $dir a --mon-host=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
# now attempt to ping it that should fail.
timeout 3 ceph ping mon.a || return 0
return 1
}
function TEST_mon_client_connect() {
local dir=$1
# start the mon with a public-bind-addr that is different
# from the public-addr.
CEPH_ARGS+="--mon-initial-members=a "
CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC} "
run_mon_no_pool $dir a --mon-host=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
# now forward the public port to the bind port.
port_forward ${MONA_PUBLIC} ${MONA_BIND}
# attempt to connect. we expect that to work
ceph ping mon.a || return 1
}
function TEST_mon_quorum() {
local dir=$1
# start the mon with a public-bind-addr that is different
# from the public-addr.
CEPH_ARGS+="--mon-initial-members=a,b,c "
CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC},${MON_IP}:${MONB_PUBLIC},${MON_IP}:${MONC_PUBLIC} "
run_mon_no_pool $dir a --public-addr=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
run_mon_no_pool $dir b --public-addr=${MON_IP}:${MONB_PUBLIC} --public-bind-addr=${MON_IP}:${MONB_BIND} || return 1
run_mon_no_pool $dir c --public-addr=${MON_IP}:${MONC_PUBLIC} --public-bind-addr=${MON_IP}:${MONC_BIND} || return 1
# now forward the public port to the bind port.
port_forward ${MONA_PUBLIC} ${MONA_BIND}
port_forward ${MONB_PUBLIC} ${MONB_BIND}
port_forward ${MONC_PUBLIC} ${MONC_BIND}
# expect monmap to contain 3 monitors (a, b, and c)
jqinput="$(ceph mon_status --format=json 2>/dev/null)"
jq_success "$jqinput" '.monmap.mons | length == 3' || return 1
# quorum should form
wait_for_quorum 300 3 || return 1
# expect quorum to have all three monitors
jqfilter='.quorum | length == 3'
jq_success "$jqinput" "$jqfilter" || return 1
}
function TEST_put_get() {
local dir=$1
# start the mon with a public-bind-addr that is different
# from the public-addr.
CEPH_ARGS+="--mon-initial-members=a,b,c "
CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC},${MON_IP}:${MONB_PUBLIC},${MON_IP}:${MONC_PUBLIC} "
run_mon_no_pool $dir a --public-addr=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
run_mon_no_pool $dir b --public-addr=${MON_IP}:${MONB_PUBLIC} --public-bind-addr=${MON_IP}:${MONB_BIND} || return 1
run_mon_no_pool $dir c --public-addr=${MON_IP}:${MONC_PUBLIC} --public-bind-addr=${MON_IP}:${MONC_BIND} || return 1
# now forward the public port to the bind port.
port_forward ${MONA_PUBLIC} ${MONA_BIND}
port_forward ${MONB_PUBLIC} ${MONB_BIND}
port_forward ${MONC_PUBLIC} ${MONC_BIND}
# quorum should form
wait_for_quorum 300 3 || return 1
run_mgr $dir x || return 1
run_osd $dir 0 || return 1
run_osd $dir 1 || return 1
run_osd $dir 2 || return 1
ceph osd pool create hello 8 || return 1
echo "hello world" > $dir/hello
rados --pool hello put foo $dir/hello || return 1
rados --pool hello get foo $dir/hello2 || return 1
diff $dir/hello $dir/hello2 || return 1
}
main mon-bind "$@"