mirror of
https://github.com/gluster/glusterfs.git
synced 2026-02-06 00:49:30 +01:00
Results of some regression tests may vary on diffirent env,
due to the unready status of shd process or unexpected
output language of key commands in test case.
So, it should be made sure that shd process has got ready before
a `gluster v heal` cmd is triggered in testcase. And if the output
of command is the judge standard of sub-testcase, we also shuold
assure it is shown in specified language as expected.
> Fixes: #4432
> Signed-off-by: chenjinhao <chen.jinhao@zte.com.cn>
> Co-authored-by: chenjinhao <chen.jinhao@zte.com.cn>
backport-of: 3dc314933b
Signed-off-by: Pranith Kumar Karampuri <pranith.karampuri@phonepe.com>
Change-Id: I6614cff5aa375deab04065270d0b2270fb0a4e71
Co-authored-by: Chen Jinhao <1195585098@qq.com>
1239 lines
29 KiB
Plaintext
1239 lines
29 KiB
Plaintext
# clang-format off
|
|
export LANG=en_US.UTF-8
|
|
checkpoint_time="$(date +%s%N)"
|
|
|
|
M0=${M0:=/mnt/glusterfs/0}; # 0th mount point for FUSE
|
|
M1=${M1:=/mnt/glusterfs/1}; # 1st mount point for FUSE
|
|
M2=${M2:=/mnt/glusterfs/2}; # 2nd mount point for FUSE
|
|
M3=${M3:=/mnt/glusterfs/3}; # 3rd mount point for FUSE
|
|
N0=${N0:=/mnt/nfs/0}; # 0th mount point for NFS
|
|
N1=${N1:=/mnt/nfs/1}; # 1st mount point for NFS
|
|
V0=${V0:=patchy}; # volume name to use in tests
|
|
V1=${V1:=patchy1}; # volume name to use in tests
|
|
GMV0=${GMV0:=primary}; # primary volume name to use in geo-rep tests
|
|
GSV0=${GSV0:=secondary}; # secondary volume name to use in geo-rep tests
|
|
GSV1=${GSV1:=secondary1} # secondary volume name to use in geo-rep tests
|
|
B0=${B0:=/d/backends}; # top level of brick directories
|
|
DEVDIR=${DEVDIR:=/d/dev} # directory for loop device management
|
|
WORKDIRS="$B0 $M0 $M1 $M2 $M3 $N0 $N1 $DEVDIR"
|
|
|
|
ROOT_GFID="00000000-0000-0000-0000-000000000001"
|
|
DOT_SHARD_GFID="be318638-e8a0-4c6d-977d-7a937aa84806"
|
|
|
|
META_VOL=${META_VOL:=gluster_shared_storage}; # shared gluster storage volume used by snapshot scheduler, nfs ganesha and geo-rep.
|
|
META_MNT=${META_MNT:=/var/run/gluster/shared_storage}; # Mount point of shared gluster volume.
|
|
|
|
CC=cc
|
|
OSTYPE=$(uname -s)
|
|
GFREG_ID="$(hostname -s)"
|
|
|
|
env_dir=$(dirname $0)
|
|
while true; do
|
|
ENV_RC=${env_dir}/env.rc
|
|
if [ -f ${ENV_RC} ]; then
|
|
break
|
|
fi
|
|
new_dir=$(dirname $env_dir)
|
|
if [ x"$new_dir" = x"$old_dir" ]; then
|
|
ENV_RC="/not/found"
|
|
break
|
|
fi
|
|
old_dir=$env_dir
|
|
env_dir=$new_dir
|
|
done
|
|
|
|
if [ ! -f $ENV_RC ]; then
|
|
echo "Aborting." | tee /dev/stderr
|
|
echo | tee /dev/stderr
|
|
echo "env.rc not found" | tee /dev/stderr
|
|
echo | tee /dev/stderr
|
|
echo "Please correct the problem and try again." | tee /dev/stderr
|
|
echo | tee /dev/stderr
|
|
exit 1
|
|
fi
|
|
. $ENV_RC
|
|
|
|
H0=${H0:=`ip -o -4 addr | grep -v "\<lo\>" | awk '{print $4}' | cut -d/ -f1 | head -n 1`}; # hostname
|
|
MOUNT_TYPE_FUSE="fuse.glusterfs"
|
|
GREP_MOUNT_OPT_RO="grep (ro"
|
|
GREP_MOUNT_OPT_RW="grep (rw"
|
|
UMOUNT_F="umount -f"
|
|
|
|
PATH=$PATH:${PWD}/tests/utils
|
|
|
|
case $OSTYPE in
|
|
Linux)
|
|
H0=${H0:=`hostname --fqdn`}; # hostname
|
|
;;
|
|
NetBSD)
|
|
MOUNT_TYPE_FUSE="puffs|perfuse|fuse.glusterfs"
|
|
GREP_MOUNT_OPT_RO="grep (read-only"
|
|
GREP_MOUNT_OPT_RW="grep -v (read-only"
|
|
UMOUNT_F="umount -f -R"
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
|
|
DEBUG=${DEBUG:=0} # turn on debugging?
|
|
|
|
MIGRATION_START_TIMEOUT=5
|
|
PROCESS_DOWN_TIMEOUT=5
|
|
PROCESS_UP_TIMEOUT=45
|
|
NFS_EXPORT_TIMEOUT=20
|
|
CHILD_UP_TIMEOUT=20
|
|
PROBE_TIMEOUT=60
|
|
PEER_SYNC_TIMEOUT=20
|
|
REBALANCE_TIMEOUT=600
|
|
REOPEN_TIMEOUT=20
|
|
HEAL_TIMEOUT=80
|
|
IO_HEAL_TIMEOUT=120
|
|
MARKER_UPDATE_TIMEOUT=20
|
|
JANITOR_TIMEOUT=60
|
|
UMOUNT_TIMEOUT=5
|
|
CONFIG_UPDATE_TIMEOUT=5
|
|
AUTH_REFRESH_INTERVAL=10
|
|
GRAPH_SWITCH_TIMEOUT=10
|
|
UNLINK_TIMEOUT=5
|
|
MDC_TIMEOUT=5
|
|
IO_WAIT_TIMEOUT=5
|
|
DISK_FAIL_TIMEOUT=80
|
|
|
|
LOGDIR=$(gluster --print-logdir)
|
|
|
|
statedumpdir=`gluster --print-statedumpdir`; # Default directory for statedump
|
|
|
|
CLI="gluster --mode=script --wignore";
|
|
CLI_NO_FORCE="gluster --mode=script";
|
|
|
|
# CLI_IGNORE_PARTITION makes sure that the warning related to bricks being on
|
|
# root partition is ignored while running the command in a "no force" mode
|
|
CLI_IGNORE_PARTITION="gluster --mode=script --wignore-partition"
|
|
|
|
function wait_delay() {
|
|
local delay="$1"
|
|
local interval="$2"
|
|
shift 2
|
|
local deadline="$(($(date +%s%N) + ${delay}000000000))"
|
|
|
|
$*
|
|
while [[ $? -ne 0 ]]; do
|
|
if [[ $(date +%s%N) -ge ${deadline} ]]; then
|
|
return 1
|
|
fi
|
|
sleep ${interval}
|
|
$*
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
_GFS () {
|
|
glusterfs "$@"
|
|
local mount_ret=$?
|
|
if [ $mount_ret != 0 ]; then
|
|
return $mount_ret
|
|
fi
|
|
local mount_point=${!#}
|
|
local i=0
|
|
while true; do
|
|
touch $mount_point/xy_zzy 2> /dev/null && break
|
|
i=$((i+1))
|
|
[ $i -lt 100 ] || break
|
|
sleep 0.1
|
|
done
|
|
rm -f $mount_point/xy_zzy
|
|
return $mount_ret
|
|
}
|
|
GFS="_GFS --attribute-timeout=0 --entry-timeout=0";
|
|
|
|
mkdir -p $WORKDIRS
|
|
|
|
case $OSTYPE in
|
|
FreeBSD | Darwin)
|
|
wc () {
|
|
if test "x$1" = "x-l"; then
|
|
awk '{ lines++ } END {print lines}'
|
|
fi
|
|
if test "x$1" = "x-w"; then
|
|
awk '{ words += NF } END {print words}' }
|
|
fi
|
|
if test "x$1" = "x-c"; then
|
|
awk '{ chars += length($0) + 1 } END {print chars}'
|
|
fi
|
|
if test "x$1" = "x-m"; then
|
|
awk '{ chars += length($0) + 1 } END {print chars}'
|
|
fi
|
|
}
|
|
;;
|
|
NetBSD)
|
|
wc() {
|
|
/usr/bin/wc $@ | sed 's/^ *\([0-9]*\).*$/\1/g'
|
|
}
|
|
;;
|
|
esac
|
|
|
|
testcnt=`egrep '^[[:space:]]*(EXPECT|EXPECT_NOT|TEST|TEST_WITHIN|EXPECT_WITHIN|EXPECT_KEYWORD)[[:space:]]' $0 | wc -l`
|
|
expect_tests=`egrep '^[[:space:]]*TESTS_EXPECTED_IN_LOOP[[:space:]]*' $0`
|
|
|
|
x_ifs=$IFS
|
|
IFS=$'\n'
|
|
for line in $expect_tests; do
|
|
expect_tests=`echo $line | cut -f 2 -d =`
|
|
testcnt=`expr $testcnt + $expect_tests`
|
|
done
|
|
IFS=$x_ifs
|
|
|
|
echo "1..`echo $testcnt`"
|
|
|
|
t=1
|
|
|
|
function dbg()
|
|
{
|
|
[ "x$DEBUG" = "x0" ] || echo "$*" >&2;
|
|
}
|
|
|
|
function G_LOG()
|
|
{
|
|
local g_log_logdir;
|
|
g_log_logdir=`$CLI --print-logdir`
|
|
test -d $g_log_logdir
|
|
if [ $? != 0 ]; then
|
|
return
|
|
fi
|
|
local g_log_string;
|
|
g_log_string="++++++++++ G_LOG:$0: TEST: $@ ++++++++++"
|
|
g_log_string="`date -u +["%F %T.%6N"]`:$g_log_string"
|
|
local g_log_filename
|
|
for g_log_filename in `find $g_log_logdir/ -type f -name \*.log`;
|
|
do
|
|
echo "$g_log_string" >> "$g_log_filename"
|
|
done
|
|
}
|
|
|
|
function test_header()
|
|
{
|
|
dbg "=========================";
|
|
dbg "TEST $t (line $TESTLINE): $*";
|
|
saved_cmd="$*"
|
|
start_time="$(date +%s%N)"
|
|
}
|
|
|
|
|
|
function test_footer()
|
|
{
|
|
RET=$?
|
|
local lineno=$1
|
|
local err=$2
|
|
local end_time
|
|
local elapsed1
|
|
local elapsed2
|
|
|
|
end_time="$(date +%s%N)"
|
|
elapsed1="$(((start_time - checkpoint_time) / 1000000))"
|
|
elapsed2="$(((end_time - start_time) / 1000000))"
|
|
checkpoint_time="$end_time"
|
|
if [ $RET -eq 0 ]; then
|
|
printf "ok %3d [%7d/%7d] <%4d> '%s'\n" "$t" "$elapsed1" "$elapsed2" "$lineno" "$saved_cmd";
|
|
else
|
|
printf "not ok %3d [%7d/%7d] <%4d> '%s' -> '%s'\n" "$t" "$elapsed1" "$elapsed2" "$lineno" "$saved_cmd" "$err"
|
|
if [ "$EXIT_EARLY" = "1" ]; then
|
|
cleanup
|
|
exit $RET
|
|
fi
|
|
fi
|
|
|
|
dbg "RESULT $t: $RET";
|
|
|
|
t=`expr $t + 1`;
|
|
}
|
|
|
|
function test_expect_footer()
|
|
{
|
|
local lineno=$1
|
|
local e=$2
|
|
local a=$3
|
|
local err=""
|
|
|
|
if ! [[ "$a" =~ $e ]]; then
|
|
err="Got \"$a\" instead of \"$e\""
|
|
fi
|
|
[[ "$a" =~ $e ]];
|
|
|
|
test_footer "$lineno" "$err";
|
|
}
|
|
|
|
function _EXPECT()
|
|
{
|
|
TESTLINE=$1;
|
|
shift;
|
|
local a=""
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@";
|
|
|
|
e="$1";
|
|
shift;
|
|
a=$("$@" | tail -1)
|
|
|
|
if [ "x$e" = "x" ] ; then
|
|
test_expect_footer "$TESTLINE" "x$e" "x$a";
|
|
else
|
|
test_expect_footer "$TESTLINE" "$e" "$a";
|
|
fi
|
|
}
|
|
|
|
function test_expect_not_footer()
|
|
{
|
|
local lineno=$1
|
|
local e=$2
|
|
local a=$3
|
|
local err=""
|
|
|
|
if [[ "$a" =~ $e ]]; then
|
|
err="Got \"$a\" when not expecting it"
|
|
fi
|
|
|
|
! [[ "$a" =~ $e ]];
|
|
test_footer "$lineno" "$err";
|
|
}
|
|
|
|
function _EXPECT_NOT()
|
|
{
|
|
TESTLINE=$1;
|
|
shift;
|
|
local a=""
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@";
|
|
|
|
e="$1";
|
|
shift;
|
|
a=$("$@" | tail -1)
|
|
|
|
if [ "x$e" = "x" ] ; then
|
|
test_expect_not_footer "$TESTLINE" "x$e" "x$a";
|
|
else
|
|
test_expect_not_footer "$TESTLINE" "$e" "$a";
|
|
fi
|
|
}
|
|
|
|
function _EXPECT_KEYWORD()
|
|
{
|
|
TESTLINE=$1;
|
|
shift;
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@";
|
|
|
|
e="$1";
|
|
shift;
|
|
"$@" | tail -1 | grep -q "$e"
|
|
|
|
test_footer "$TESTLINE";
|
|
}
|
|
|
|
function _TEST()
|
|
{
|
|
TESTLINE=$1;
|
|
shift;
|
|
local redirect=""
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@";
|
|
|
|
if [ "$1" = "!" ]; then
|
|
redirect="2>&1"
|
|
fi
|
|
|
|
eval "$@" >/dev/null $redirect
|
|
|
|
test_footer "$TESTLINE";
|
|
}
|
|
|
|
|
|
function _TEST_WITHIN()
|
|
{
|
|
local res output
|
|
|
|
TESTLINE=$1
|
|
shift;
|
|
|
|
local timeout=$1
|
|
shift;
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@"
|
|
|
|
local endtime="$(( ${timeout}000000000 + $(date +%s%N) ))"
|
|
|
|
# We *want* this to be globally visible.
|
|
EW_RETRIES=0
|
|
|
|
output=""
|
|
res="1"
|
|
while [[ "$(date +%s%N)" < "$endtime" ]]; do
|
|
output="$("${@}" 2>/dev/null)"
|
|
res="${?}"
|
|
if [[ "${res}" == "0" ]]; then
|
|
break
|
|
fi
|
|
sleep 0.25;
|
|
EW_RETRIES=$((EW_RETRIES+1))
|
|
done
|
|
|
|
! [[ "${res}" != "0" ]]
|
|
|
|
test_footer "$TESTLINE"
|
|
|
|
TEST_OUTPUT="${output}"
|
|
}
|
|
|
|
#This function should be used carefully.
|
|
#The expected regex, given to this function, should be
|
|
#used within ^ and $ to match exactly with the output of
|
|
#command.
|
|
function _EXPECT_WITHIN()
|
|
{
|
|
TESTLINE=$1
|
|
shift;
|
|
|
|
local timeout=$1
|
|
shift;
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@"
|
|
|
|
e=$1;
|
|
a="";
|
|
shift;
|
|
|
|
local endtime="$(( ${timeout}000000000 + $(date +%s%N) ))"
|
|
|
|
# We *want* this to be globally visible.
|
|
EW_RETRIES=0
|
|
|
|
while [[ "$(date +%s%N)" < "$endtime" ]]; do
|
|
a=$("$@" | tail -1 ; exit ${PIPESTATUS[0]})
|
|
## Check command success
|
|
if [ $? -ne 0 ]; then
|
|
break;
|
|
fi
|
|
## Check match success
|
|
if [[ "$a" =~ $e ]]; then
|
|
break;
|
|
fi
|
|
sleep 0.25;
|
|
EW_RETRIES=$((EW_RETRIES+1))
|
|
done
|
|
|
|
if [ "x$e" = "x" ] ; then
|
|
test_expect_footer "$TESTLINE" "x$e" "x$a";
|
|
else
|
|
test_expect_footer "$TESTLINE" "$e" "$a";
|
|
fi
|
|
}
|
|
|
|
|
|
function SKIP_TESTS()
|
|
{
|
|
dbg "Skipping tests $t-$testcnt";
|
|
while [ $t -le $testcnt ]; do
|
|
true ; test_footer;
|
|
done
|
|
}
|
|
|
|
|
|
function _TEST_IN_LOOP()
|
|
{
|
|
testcnt=`expr $testcnt + 1`;
|
|
_TEST $@
|
|
}
|
|
|
|
function _EXPECT_WITHIN_TEST_IN_LOOP()
|
|
{
|
|
testcnt=`expr $testcnt + 1`;
|
|
_EXPECT_WITHIN $@
|
|
}
|
|
|
|
which killall > /dev/null || {
|
|
killall() {
|
|
pkill $@
|
|
}
|
|
}
|
|
|
|
which pidof > /dev/null || {
|
|
pidof() {
|
|
$PYTHON pidof.py $@
|
|
}
|
|
}
|
|
|
|
stat -c %s /dev/null > /dev/null 2>&1 || {
|
|
stat() {
|
|
local format=""
|
|
local f=""
|
|
|
|
if [ "x$1" = "x-c" ] ; then
|
|
oformat=$2
|
|
shift
|
|
shift
|
|
files=$@
|
|
else
|
|
files=$@
|
|
fi
|
|
|
|
for f in $files ; do
|
|
format=$oformat
|
|
|
|
# %t/%T should return 0 for non devices.
|
|
case "${format}" in
|
|
*%t*|*%T*)
|
|
`which stat` -f '%HT' $f | grep -q 'Device$' || \
|
|
format=`echo "${format}" | sed 's/%t/0/g; s/%T/0/g;'`
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
|
|
if [ "x${format}" = "x" ] ; then
|
|
`which stat` $f
|
|
else
|
|
cmd=""
|
|
case $format in
|
|
*%u*) cmd="${cmd} s/%u/`$( which stat ) -f %u $f`/g;" ;&
|
|
*%g*) cmd="${cmd} s/%g/`$( which stat ) -f %g $f`/g;" ;&
|
|
*%a*) cmd="${cmd} s/%a/`$( which stat ) -f %p $f |
|
|
sed 's/^..//; s/^0//'`/g;" ;&
|
|
*%A*) cmd="${cmd} s/%A/`ls -ld $f|awk '{print $1}'`/g;" ;&
|
|
*%s*) cmd="${cmd} s/%s/`$( which stat ) -f %z $f`/g;" ;&
|
|
*%h*) cmd="${cmd} s/%h/`$( which stat ) -f %l $f`/g;" ;&
|
|
*%F*) cmd="${cmd} s/%F/`$( which stat ) -f %HT $f | sed '
|
|
s/Directory/directory/;
|
|
s/Fifo File/fifo/;
|
|
s/Symbolic Link/symbolic link/;
|
|
s/Regular File/regular file/;
|
|
s/Block Device/block special file/;
|
|
s/Character Device/character special file/;
|
|
' | sed \"$(
|
|
test -s $f || echo 's/regular file/regular empty file/g'
|
|
)\"`/g;" ;&
|
|
*%n*) cmd="${cmd} s|%n|`$( which stat ) -f %N $f`|g;" ;&
|
|
*%Y*) cmd="${cmd} s/%Y/`$( which stat ) -f %m $f`/g;" ;&
|
|
*%X*) cmd="${cmd} s/%X/`$( which stat ) -f %a $f`/g;" ;&
|
|
*%Z*) cmd="${cmd} s/%Z/`$( which stat ) -f %c $f`/g;" ;&
|
|
*%.Z*) cmd="${cmd} s/%.Z/`$( which stat ) -f %.9Fc $f`/g;" ;&
|
|
*%b*) cmd="${cmd} s/%b/`$( which stat ) -f %b $f`/g;" ;&
|
|
*%B*) cmd="${cmd} s/%B/512/g;" ;&
|
|
*%t*) cmd="${cmd} s/%t/`$( which stat ) -f %XHr $f`/g;" ;&
|
|
*%T*) cmd="${cmd} s/%T/`$( which stat ) -f %XLr $f`/g;" ;&
|
|
esac
|
|
|
|
`which stat` -f "`echo $format|sed \"$cmd\"`" $f
|
|
fi
|
|
done
|
|
}
|
|
}
|
|
|
|
function signal_pids() {
|
|
local sig="$1"
|
|
shift
|
|
local pids=($*)
|
|
|
|
if [[ ${#pids[@]} -gt 0 ]]; then
|
|
kill -${sig} ${pids[@]} 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
function check_pids() {
|
|
local pids=($*)
|
|
local tmp=()
|
|
local pid
|
|
|
|
for pid in "${pids[@]}"; do
|
|
kill -0 "${pid}" 2>/dev/null && tmp+=(${pid})
|
|
done
|
|
|
|
echo "${tmp[@]}"
|
|
}
|
|
|
|
function pids_alive() {
|
|
local pids=($*)
|
|
|
|
if [[ "$(check_pids ${pids[@]})" != "" ]]; then
|
|
return 1;
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function terminate_pids() {
|
|
local pids=($*)
|
|
|
|
signal_pids TERM ${pids[@]}
|
|
wait_delay ${PROCESS_DOWN_TIMEOUT} 0.1 pids_alive ${pids[@]}
|
|
if [[ $? -ne 0 ]]; then
|
|
pids=($(check_pids ${pids[@]}))
|
|
signal_pids KILL ${pids[@]}
|
|
wait_delay 1 0.1 pids_alive ${pids[@]}
|
|
if [[ $? -ne 0 ]]; then
|
|
return 2
|
|
fi
|
|
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function process_pids() {
|
|
local proc
|
|
local pids=()
|
|
|
|
for proc in $*; do
|
|
pids+=($(pgrep ${proc}))
|
|
done
|
|
|
|
echo "${pids[@]}"
|
|
}
|
|
|
|
## Lock files should get automatically removed once "usradd" or "groupadd"
|
|
## command finishes. But sometimes we encounter situations (bugs) where
|
|
## some of these files may not get properly unlocked after the execution of
|
|
## the command. In that case, when we execute useradd next time, it may show
|
|
## the error “cannot lock /etc/password” or “unable to lock group file”.
|
|
## So, to avoid any such errors, check for any lock files under /etc.
|
|
## and remove those.
|
|
|
|
function remove_lock_files()
|
|
{
|
|
if [ ! -f /etc/passwd.lock ];
|
|
then
|
|
rm -rf /etc/passwd.lock;
|
|
fi
|
|
|
|
if [ ! -f /etc/group.lock ];
|
|
then
|
|
rm -rf /etc/group.lock;
|
|
fi
|
|
|
|
if [ ! -f /etc/shadow.lock ];
|
|
then
|
|
rm -rf /etc/shadow.lock;
|
|
fi
|
|
|
|
if [ ! -f /etc/gshadow.lock ];
|
|
then
|
|
rm -rf /etc/gshadow.lock;
|
|
fi
|
|
}
|
|
|
|
|
|
function cleanup()
|
|
{
|
|
local end_time
|
|
|
|
# Prepare flags for umount
|
|
case `uname -s` in
|
|
Linux)
|
|
flag="-l"
|
|
;;
|
|
NetBSD)
|
|
flag="-f -R"
|
|
;;
|
|
FreeBSD|Darwin)
|
|
flag="-f"
|
|
;;
|
|
*)
|
|
flag=""
|
|
;;
|
|
esac
|
|
|
|
# Clean up lock files.
|
|
remove_lock_files
|
|
|
|
# Clean up all client mounts
|
|
for m in `mount | grep fuse.glusterfs | awk '{print $3}'`; do
|
|
umount $flag $m
|
|
done
|
|
|
|
# Unmount all well known mount points
|
|
umount $flag $M0 2>/dev/null || umount -f $M0 2>/dev/null || true;
|
|
umount $flag $M1 2>/dev/null || umount -f $M1 2>/dev/null || true;
|
|
umount $flag $M2 2>/dev/null || umount -f $M2 2>/dev/null || true;
|
|
umount $flag $N0 2>/dev/null || umount -f $N0 2>/dev/null || true;
|
|
umount $flag $N1 2>/dev/null || umount -f $N1 2>/dev/null || true;
|
|
|
|
|
|
# unmount all stale mounts from /tmp, This is a temporary work around
|
|
# till the stale mount in /tmp is found.
|
|
umount $flag /tmp/mnt* 2>/dev/null
|
|
|
|
|
|
# Send SIGTERM to all gluster processes and rpc.statd that are still running
|
|
terminate_pids $(process_pids glusterfs glusterfsd glusterd rpc.statd)
|
|
|
|
test x"$OSTYPE" = x"NetBSD" && pkill -9 perfused || true
|
|
|
|
# unregister nfs and related services from portmapper/rpcbind
|
|
## nfs
|
|
rpcinfo -d 100003 3 2>/dev/null || true;
|
|
## mountd
|
|
rpcinfo -d 100005 1 2>/dev/null || true;
|
|
rpcinfo -d 100005 3 2>/dev/null || true;
|
|
## nlockmgr
|
|
rpcinfo -d 100021 1 2>/dev/null || true;
|
|
rpcinfo -d 100021 4 2>/dev/null || true;
|
|
## nfs_acl
|
|
rpcinfo -d 100227 3 2>/dev/null || true;
|
|
|
|
# unmount brick filesystems after killing daemons
|
|
MOUNTPOINTS=`findmnt -nRlT "${B0}" -o TARGET,SOURCE | grep "$B0/" | awk '{print $2}'`
|
|
for m in $MOUNTPOINTS;
|
|
do
|
|
umount $flag $m
|
|
done
|
|
|
|
# Cleanup lvm
|
|
type cleanup_lvm &>/dev/null && cleanup_lvm || true;
|
|
|
|
# Destroy loop devices
|
|
# TODO: This should be a function DESTROY_LOOP
|
|
case `uname -s` in
|
|
Linux)
|
|
for l in $(ls ${DEVDIR}/loop* 2>/dev/null); do
|
|
losetup -d "${l}"
|
|
rm -f "${l}"
|
|
done
|
|
;;
|
|
NetBSD)
|
|
# cleanup loopback device with unmounted backing store
|
|
for vnd in /dev/vnd* ; do
|
|
vnconfig -l ${vnd} 2>&1 | \
|
|
grep -q 'Bad file descriptor' && vnconfig -u ${vnd}
|
|
done
|
|
|
|
vnd=`vnconfig -l | \
|
|
awk '!/not in use/{printf("%s%s:%d ", $1, $2, $5);}'`
|
|
for l in ${vnd} ; do
|
|
dev=${l%%:*}
|
|
tmp=${l#*:}
|
|
fs=${tmp%%:*}
|
|
inode=${tmp#*:}
|
|
file=`find -x ${fs} -inum ${inode} -print -exit`
|
|
echo ${file} | grep "$B0/" && \
|
|
LOOPDEVICES="${LOOPDEVICES} $dev"
|
|
done
|
|
for l in $LOOPDEVICES;
|
|
do
|
|
vnconfig -u $l
|
|
done
|
|
;;
|
|
*)
|
|
echo "`uname -s` loopback device supportmissing"
|
|
;;
|
|
esac
|
|
|
|
# remove contents of "GLUSTERD_WORKDIR" except hooks and groups
|
|
# directories.
|
|
if [ -n $GLUSTERD_WORKDIR ]
|
|
then
|
|
find $GLUSTERD_WORKDIR/* -maxdepth 0 -name 'hooks' -prune \
|
|
-o -name 'groups' -prune -o -exec rm -rf '{}' ';'
|
|
else
|
|
echo "GLUSTERD_WORKDIR is not set"
|
|
fi
|
|
|
|
# Complete cleanup time
|
|
rm -rf "$B0/*" "/etc/glusterd/*";
|
|
rm -rf $WORKDIRS
|
|
find $GLUSTERD_PIDFILEDIR -name "*.pid" | xargs rm -rf
|
|
leftover=""
|
|
for d in $WORKDIRS ; do
|
|
if test -d $d ; then
|
|
leftover="$leftover $d"
|
|
fi
|
|
done
|
|
if [ "x$leftover" != "x" ] ; then
|
|
echo "Aborting."
|
|
echo
|
|
echo "$d could not be deleted, here are the left over items"
|
|
for d in $leftover; do
|
|
find $d -exec ls -ld {} \;
|
|
done
|
|
echo
|
|
echo "Please correct the problem and try again."
|
|
echo
|
|
return 1;
|
|
fi >&2
|
|
|
|
# Physically release unused space
|
|
fstrim /d
|
|
|
|
mkdir -p $WORKDIRS
|
|
# This is usually the last thing a test script calls, so our return
|
|
# value becomes their exit value. While it's not great for the mkdir
|
|
# above to fail, promoting that into a failure of the whole test (and
|
|
# thus of an entire regression-test run) seems a bit excessive. Make
|
|
# sure we return good status anyway.
|
|
|
|
return 0
|
|
}
|
|
|
|
function force_terminate () {
|
|
local ret=$?;
|
|
>&2 echo -e "\nreceived external"\
|
|
"signal --`kill -l $ret`--, calling 'cleanup' ...\n";
|
|
cleanup;
|
|
exit $ret;
|
|
}
|
|
|
|
trap force_terminate INT TERM HUP
|
|
|
|
function cleanup_tester ()
|
|
{
|
|
local exe=$1
|
|
rm -f $exe
|
|
}
|
|
|
|
function build_tester ()
|
|
{
|
|
local cfile=$1
|
|
local fname=$(basename "$cfile")
|
|
local ext="${fname##*.}"
|
|
local execname="${fname%.*}"
|
|
shift
|
|
local cflags=$*
|
|
if [ `echo $cflags | grep -c "lgfapi" ` -gt 0 ]
|
|
then
|
|
cflags="$cflags $(pkg-config glusterfs-api --cflags-only-I --libs-only-L)"
|
|
fi
|
|
$CC -g -o $(dirname $cfile)/$execname $cfile $cflags
|
|
}
|
|
|
|
function process_leak_count ()
|
|
{
|
|
local pid=$1;
|
|
return $(ls -lh /proc/$pid/fd | grep "(deleted)"| wc -l)
|
|
}
|
|
|
|
which truncate > /dev/null || {
|
|
truncate() {
|
|
local nocreate=0
|
|
local ioblocks=0
|
|
local fileref=""
|
|
local newsize=""
|
|
|
|
args=`getopt xor:s: $*`
|
|
if [ $? -ne 0 ]; then
|
|
echo 'Usage: truncate [-co](-r file | -s size) file ...'
|
|
exit 2
|
|
fi
|
|
set -- $args
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-c)
|
|
nocreate=1;
|
|
;;
|
|
-o)
|
|
ioblocks=1;
|
|
echo "Unimplemented -o option"
|
|
exit 2
|
|
;;
|
|
-r)
|
|
fileref=$2;
|
|
shift;
|
|
;;
|
|
-s)
|
|
newsize=$2;
|
|
shift;
|
|
;;
|
|
--)
|
|
shift;
|
|
break;
|
|
;;
|
|
*)
|
|
echo 'Usage: truncate [-co](-r file | -s size) file ...'
|
|
exit 2;
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ "x$newsize" = "x" -a "x$fileref" = "x" ] ; then
|
|
echo 'Usage: truncate [-co](-r file | -s size) file ...'
|
|
exit 2;
|
|
fi
|
|
|
|
if [ "x$newsize" != "x" -a "x$fileref" != "x" ] ; then
|
|
echo 'Usage: truncate [-co](-r file | -s size) file ...'
|
|
exit 2;
|
|
fi
|
|
|
|
if [ "x$newsize" != "x" ] ; then
|
|
echo $newsize | grep -q '^[-_<>%/]' && {
|
|
echo "Unimplemented prefix in ${newsize}"
|
|
exit 2;
|
|
}
|
|
|
|
echo $newsize | egrep -q '[TPEZY]B?$' && {
|
|
echo "Unit not implemented for ${newsize}"
|
|
exit 2;
|
|
}
|
|
|
|
case $newsize in
|
|
*KB)
|
|
newsize=$(( ${newsize/KB/} * 1000 ))
|
|
;;
|
|
*K)
|
|
newsize=$(( ${newsize/K/} * 1024 ))
|
|
;;
|
|
*MB)
|
|
newsize=$(( ${newsize/MB/} * 1000 * 1000 ))
|
|
;;
|
|
*M)
|
|
newsize=$(( ${newsize/M/} * 1024 * 1024 ))
|
|
;;
|
|
*GB)
|
|
newsize=$(( ${newsize/GB/} * 1000 * 1000 * 1000 ))
|
|
;;
|
|
*G)
|
|
newsize=$(( ${newsize/G/} * 1024 * 1024 * 1024 ))
|
|
;;
|
|
esac
|
|
|
|
fi
|
|
|
|
if [ "x$fileref" != "x" ] ; then
|
|
if [ ! -f $fileref ] ; then
|
|
echo "File does not exists: ${fileref}"
|
|
exit 2;
|
|
fi
|
|
newsize=`ls -l ${fileref}|awk '{print $5}'`
|
|
fi
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo 'Usage: truncate [-co](-r file | -s size) file ...'
|
|
exit 2;
|
|
fi
|
|
|
|
for f in $* ; do
|
|
if [ "x$nocreate" = "x1" -a ! -f $f ] ; then
|
|
continue;
|
|
fi
|
|
|
|
dd bs=1 seek=$newsize if=/dev/null of=$f msgfmt=quiet
|
|
done
|
|
}
|
|
}
|
|
|
|
which md5sum > /dev/null || {
|
|
md5sum() {
|
|
for f in $* ; do
|
|
md5 $f | awk -F'[() ]' '{printf("%s %s\n", $6, $3)}'
|
|
done
|
|
}
|
|
}
|
|
|
|
which setfattr > /dev/null || {
|
|
setfattr() {
|
|
$PYTHON setfattr.py $@
|
|
}
|
|
}
|
|
|
|
which getfattr > /dev/null || {
|
|
getfattr() {
|
|
$PYTHON getfattr.py $@
|
|
}
|
|
}
|
|
|
|
which sha1sum > /dev/null || {
|
|
sha1sum() {
|
|
case $OSTYPE in
|
|
Darwin)
|
|
for f in $* ; do
|
|
openssl sha1 $f | awk -F'[() ]' '{printf("%s %s\n", $4, $2)}'
|
|
done
|
|
;;
|
|
NetBSD | FreeBSD)
|
|
for f in $* ; do
|
|
sha1 $f | awk -F'[() ]' '{printf("%s %s\n", $6, $3)}'
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
}
|
|
|
|
userdel --help 2>/dev/null | grep -q -- '--force' || {
|
|
userdel() {
|
|
if [ "x$1" = "x--force" ]; then
|
|
user=$2
|
|
else
|
|
user=$1
|
|
fi
|
|
eval "$( which userdel ) $user"
|
|
}
|
|
}
|
|
|
|
useradd --help 2>/dev/null | grep -q -- '--no-create-home' || {
|
|
useradd() {
|
|
# Just remove -M (do not create home) which is the default
|
|
# other options are identical
|
|
args=`echo $*|sed 's/-M//'`
|
|
eval "$( which useradd ) $args"
|
|
}
|
|
}
|
|
|
|
userdel --help 2>/dev/null | grep -q -- '--force' || {
|
|
userdel() {
|
|
if [ "x$1" = "x--force" ]; then
|
|
user=$2
|
|
else
|
|
user=$1
|
|
fi
|
|
eval "$( which userdel ) $user"
|
|
}
|
|
}
|
|
|
|
useradd --help 2>/dev/null | grep -q -- '--no-create-home' || {
|
|
useradd() {
|
|
# Just remove -M (do not create home) which is the default
|
|
# other options are identical
|
|
args=`echo $*|sed 's/-M//'`
|
|
eval "$( which useradd ) $args"
|
|
}
|
|
}
|
|
|
|
DBG_TEST () {
|
|
read -p "execute \"$*\"? " x;
|
|
case $x in
|
|
'y')
|
|
_TEST "$@"
|
|
;;
|
|
'q')
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "skipping"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
alias EXPECT='_EXPECT $LINENO'
|
|
alias EXPECT_NOT='_EXPECT_NOT $LINENO'
|
|
if [ -n "$GF_INTERACTIVE" ]; then
|
|
alias TEST='DBG_TEST $LINENO'
|
|
else
|
|
alias TEST='_TEST $LINENO'
|
|
fi
|
|
alias TEST_WITHIN='_TEST_WITHIN $LINENO'
|
|
alias EXPECT_WITHIN='_EXPECT_WITHIN $LINENO'
|
|
alias EXPECT_KEYWORD='_EXPECT_KEYWORD $LINENO'
|
|
alias TEST_IN_LOOP='_TEST_IN_LOOP $LINENO'
|
|
alias EXPECT_WITHIN_TEST_IN_LOOP='_EXPECT_WITHIN_TEST_IN_LOOP $LINENO'
|
|
shopt -s expand_aliases
|
|
|
|
if [ x"$OSTYPE" = x"Linux" ]; then
|
|
alias dd="dd status=none"
|
|
elif [ x"$OSTYPE" = x"NetBSD" ]; then
|
|
alias dd="dd msgfmt=quiet"
|
|
fi
|
|
# MacOS doesn't seem to support either option. Doing nothing at all is
|
|
# probably the safest option there and on anything we don't recognize, but
|
|
# if you want to reduce the noise level and know the correct option for
|
|
# your favorite platform please feel free to add it here.
|
|
|
|
function SETUP_LOOP ()
|
|
{
|
|
if [ $# != 1 ] ; then
|
|
echo "SETUP_LOOP usage" >&2
|
|
return 1;
|
|
fi
|
|
|
|
backend=$1
|
|
|
|
case ${OSTYPE} in
|
|
Linux)
|
|
dev="$(losetup --find --show ${backend})"
|
|
ln -sf "${dev}" "${DEVDIR}/$(basename "${dev}")"
|
|
echo "${dev}"
|
|
;;
|
|
NetBSD)
|
|
vnd=`vnconfig -l|awk -F: '/not in use/{print $1; exit}'`
|
|
if [ "x${vnd}" = "x" ] ; then
|
|
echo "no more vnd" >&2
|
|
return 1;
|
|
fi
|
|
vnconfig ${vnd} ${backend}
|
|
echo ${vnd}
|
|
;;
|
|
*)
|
|
echo "Please define SETUP_LOOP for ${OSTYPE} in include.rc" >&2
|
|
return 1;
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function MKFS_LOOP ()
|
|
{
|
|
args=`getopt i: $*`
|
|
if [ $? -ne 0 ] ; then
|
|
echo "MKFS_LOOP usage" >&2
|
|
return 1;
|
|
fi
|
|
set -- ${args}
|
|
|
|
isize=""
|
|
while test $# -gt 0; do
|
|
case "$1" in
|
|
-i) isize=$2; shift ;;
|
|
--) shift; break ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
dev=$1
|
|
|
|
case ${OSTYPE} in
|
|
Linux)
|
|
test "x${isize}" != "x" && isize="-i size=${isize}"
|
|
mkfs.xfs -f ${isize} ${dev}
|
|
;;
|
|
NetBSD)
|
|
test "x${isize}" != "x" && isize="-i ${isize}"
|
|
|
|
echo ${dev} | grep -q '^vnd'
|
|
if [ $? -ne 0 ] ; then
|
|
vnd=`vnconfig -l|awk -F: '/not in use/{print $1; exit}'`
|
|
if [ "x${vnd}" = "x" ] ; then
|
|
echo "no more vnd" >&2
|
|
return 1;
|
|
fi
|
|
vnconfig ${vnd} ${dev}
|
|
else
|
|
vnd=${dev}
|
|
fi
|
|
newfs ${isize} /dev/r${vnd}a
|
|
;;
|
|
*)
|
|
echo "Please define MKFS_LOOP for ${OSTYPE} in include.rc" >&2
|
|
return 1;
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# usage: log_newer timestamp "string"
|
|
# search in glusterfs logs for "string" logged after timestamp seconds
|
|
# since the Epoch (usually obtained by date +%s)
|
|
log_newer()
|
|
{
|
|
ts=$1
|
|
msg=$2
|
|
logdir=`$CLI --print-logdir`
|
|
|
|
local x_ifs=$IFS
|
|
IFS="["
|
|
for date in `grep -hr "$msg" $logdir | grep -v "G_LOG" | awk -F '[\]]' '{print $1}'` ; do
|
|
if [ `date -d "$date" +%s` -gt $ts ] ; then
|
|
IFS=$x_ifs
|
|
return 0;
|
|
fi
|
|
done 2>/dev/null
|
|
IFS=$x_ifs
|
|
return 1
|
|
}
|
|
|
|
function MOUNT_LOOP ()
|
|
{
|
|
if [ $# != 2 ] ; then
|
|
echo "MOUNT_LOOP usage" >&2
|
|
return 1;
|
|
fi
|
|
|
|
dev=$1
|
|
target=$2
|
|
|
|
case ${OSTYPE} in
|
|
Linux)
|
|
echo ${dev} | grep -q '^/dev/loop'
|
|
if [ $? -eq 0 ] ; then
|
|
mount -t xfs ${dev} ${target}
|
|
else
|
|
mount -o loop ${dev} ${target}
|
|
fi
|
|
;;
|
|
NetBSD)
|
|
echo ${dev} | grep -q '^vnd'
|
|
if [ $? -ne 0 ] ; then
|
|
ino=`/usr/bin/stat -f %i ${dev}`
|
|
dev=`vnconfig -l | awk -v ino=${ino} -F'[: ]*' '($5 == ino) {print $1}'`
|
|
fi
|
|
|
|
mount /dev/${dev}a ${target} >&2
|
|
if [ $? -ne 0 ] ; then
|
|
echo "failed to mount /dev/${dev}a on ${target}" >&2
|
|
return 1;
|
|
fi
|
|
|
|
mkdir -p ${target}/.attribute/system ${target}/.attribute/user
|
|
mount -u -o extattr ${target} >&2
|
|
|
|
;;
|
|
*)
|
|
echo "Please define MOUNT_LOOP for ${OSTYPE} in include.rc" >&2
|
|
return 1;
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function UMOUNT_LOOP ()
|
|
{
|
|
case ${OSTYPE} in
|
|
Linux)
|
|
force_umount $*
|
|
;;
|
|
NetBSD)
|
|
for target in $* ; do
|
|
dev=`mount | awk -v target=${target} '($3 == target) {print $1}'`
|
|
force_umount ${target}
|
|
echo ${dev} | grep -q '^/dev/vnd'
|
|
if [ $? -eq 0 ] ; then
|
|
dev=`echo ${dev} | sed 's|^/dev/||; s|a$||'`
|
|
vnconfig -u ${dev}
|
|
else
|
|
ino=`/usr/bin/stat -f %i ${dev}`
|
|
dev=`vnconfig -l | awk -v ino=${ino} -F'[: ]*' '($5 == ino) {print $1}'`
|
|
if [ "x${dev}" != "x" ] ; then
|
|
vnconfig -u ${dev}
|
|
fi
|
|
fi
|
|
done
|
|
;;
|
|
*)
|
|
echo "Please define UMOUNT_LOOP for ${OSTYPE} in include.rc" >&2
|
|
return 1;
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function STAT()
|
|
{
|
|
stat $1
|
|
echo $?
|
|
}
|
|
|
|
function STAT_INO()
|
|
{
|
|
local ino=$(stat -c '%i' $1)
|
|
if [ $? -eq 0 ]; then
|
|
echo $ino
|
|
else
|
|
echo 0
|
|
fi
|
|
}
|
|
|
|
function get_md5_sum()
|
|
{
|
|
local file=$1;
|
|
md5_sum=$(md5sum $file | awk '{print $1}');
|
|
echo $md5_sum
|
|
}
|