This is a combination of three previous low-impact changes, combined to reduce patch-pushing burden. ((( GF_INTERACTIVE ))) To use this, just define GF_INTERACTIVE (value doesn't matter as long as the length is non-zero) before running your test. It replaces the TEST alias with one that will prompt you before executing that line. You can answer: 'y' to execute the line 'q' to exit the test immediately anything else to skip this line and continue This is particularly useful to inspect state in another window while a test is paused, or to do manual experimentation in the (often complex) configuration created during a test. ((( CLEANUP.SH ))) tests: add cleanup.sh Often, a developer might want to run a test up to some point, then bail out and poke around manually. That leaves state that needs to be cleaned up before the next test can run properly. This patch adds a trivial script to invoke that cleanup machinery. Along the way, code in include.rc to find env.rc was changed to be more robust across arbitrarily deep (or shallow) directory hierarchies. ((( REPLACE EXISTING TAR FILES INSTEAD OF APPENDING ))) We currently use "tar rf" to collect log files from each test. This *appends* the new data to whatever's there already, which has two bad effects when a test is run repeatedly. * Ever-increasing size of the tar file. * Ever-increasing time to extract logs from the tar file, with each copy completely overwriting any previous. This doesn't seem to be a problem in our regression tests, because the entire directory is nuked during package removal and reinstallation. However, when running a test repeatedly during a debug session, the effects can be quite severe. This is particularly evident with JBR, because the "logs" that get archived include large journal files. Certain other translators, such as changelog and CTR, might be prone to similar effects. There's no point to having multiple copies of the logs in each tar file. As far as I know, nobody ever takes advantage of that. Therefore, use "tar cf" to overwrite any existing archive instead of appending. This change also handles excluding other .tar files in a portable way. Change-Id: Iebf77d496a71976c321bbacb49776338a9da586f Signed-off-by: Jeff Darcy <jdarcy@redhat.com> Reviewed-on: http://review.gluster.org/14874 Smoke: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
1190 lines
27 KiB
Plaintext
1190 lines
27 KiB
Plaintext
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
|
|
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:=master}; # master volume name to use in geo-rep tests
|
|
GSV0=${GSV0:=slave}; # slave volume name to use in geo-rep tests
|
|
B0=${B0:=/d/backends}; # top level of brick directories
|
|
WORKDIRS="$B0 $M0 $M1 $M2 $N0 $N1"
|
|
|
|
ROOT_GFID="00000000-0000-0000-0000-000000000001"
|
|
|
|
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)
|
|
|
|
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
|
|
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:=`hostname`}; # 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?
|
|
|
|
PROCESS_UP_TIMEOUT=20
|
|
NFS_EXPORT_TIMEOUT=20
|
|
CHILD_UP_TIMEOUT=20
|
|
PROBE_TIMEOUT=60
|
|
REBALANCE_TIMEOUT=360
|
|
REOPEN_TIMEOUT=20
|
|
HEAL_TIMEOUT=80
|
|
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
|
|
|
|
LOGDIR=$(gluster --print-logdir)
|
|
|
|
statedumpdir=`gluster --print-statedumpdir`; # Default directory for statedump
|
|
|
|
CLI="gluster --mode=script --wignore";
|
|
GFS="glusterfs --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|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="$*"
|
|
}
|
|
|
|
|
|
function test_footer()
|
|
{
|
|
RET=$?
|
|
local lineno=$1
|
|
local err=$2
|
|
|
|
if [ $RET -eq 0 ]; then
|
|
echo "ok $t, LINENUM:$lineno";
|
|
else
|
|
echo "not ok $t $err, LINENUM:$lineno";
|
|
# With DEBUG, this was already printed out, so skip it.
|
|
if [ x"$DEBUG" = x"0" ]; then
|
|
echo "FAILED COMMAND: $saved_cmd"
|
|
fi
|
|
if [ "$EXIT_EARLY" = "1" ]; then
|
|
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 _EXPECT_WITHIN()
|
|
{
|
|
TESTLINE=$1
|
|
shift;
|
|
|
|
local timeout=$1
|
|
shift;
|
|
|
|
G_LOG $TESTLINE "$@";
|
|
test_header "$@"
|
|
|
|
e=$1;
|
|
a="";
|
|
shift;
|
|
|
|
local endtime=$(( ${timeout}+`date +%s` ))
|
|
|
|
while [ `date +%s` -lt $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 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;" ;&
|
|
*%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 cleanup()
|
|
{
|
|
|
|
# Prepare flags for umount
|
|
case `uname -s` in
|
|
Linux)
|
|
flag="-l"
|
|
;;
|
|
NetBSD)
|
|
flag="-f -R"
|
|
;;
|
|
FreeBSD|Darwin)
|
|
flag="-f"
|
|
;;
|
|
*)
|
|
flag=""
|
|
;;
|
|
esac
|
|
|
|
# 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 SIGKILL to all gluster processes that are still running
|
|
killall -9 glusterfs glusterfsd glusterd 2>/dev/null || true;
|
|
test x"$OSTYPE" = x"NetBSD" && pkill -9 perfused rpc.statd || 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=`mount | grep "$B0/" | awk '{print $3}'`
|
|
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)
|
|
LOOPDEVICES=`losetup -a | grep "$B0/" | \
|
|
awk '{print $1}' | tr -d :`
|
|
for l in $LOOPDEVICES;
|
|
do
|
|
losetup -d $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
|
|
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
|
|
|
|
# tar logs at the start and end of every test
|
|
if [ -n "$LOGDIR" -a -z "$STOP_WASTING_SPACE" ]
|
|
then
|
|
tarname=$(basename $0 .t)
|
|
# Can't use --exclude here because NetBSD doesn't have it.
|
|
# However, both it and Linux have -X to take patterns from
|
|
# a file, so use that.
|
|
(echo '*.tar'; echo .notar) > ${LOGDIR}/.notar \
|
|
&& \
|
|
tar -cf ${LOGDIR}/${tarname}.tar -X ${LOGDIR}/.notar \
|
|
${LOGDIR}/* 2> /dev/null \
|
|
&& \
|
|
find $LOGDIR/* -maxdepth 0 -name '*.tar' -prune \
|
|
-o -exec rm -rf '{}' ';'
|
|
else
|
|
echo "LOGDIR is not set"
|
|
fi
|
|
|
|
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 volinfo_field()
|
|
{
|
|
local vol=$1;
|
|
local field=$2;
|
|
|
|
$CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
|
|
}
|
|
|
|
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=$*
|
|
$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 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)
|
|
losetup --find --show ${backend}
|
|
;;
|
|
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 SETUP_LOOP ()
|
|
{
|
|
if [ $# != 1 ] ; then
|
|
echo "SETUP_LOOP usage" >&2
|
|
return 1;
|
|
fi
|
|
|
|
backend=$1
|
|
|
|
case ${OSTYPE} in
|
|
Linux)
|
|
losetup --find --show ${backend}
|
|
;;
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|