1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/test/lib/aux.sh
Zdenek Kabelac a59c3731c3 Improve test suite
Add make help target.
Add LVM_TEST_PARALLEL to support parallel runs of tests
Work around the problem the dmsetup table/info may return error
by using dmtable and dminfo function that will use 'should'.
(Error happens when some concurently running process removes table
entry while dmsetup command resolves table entries inside the loop.)
2012-03-28 11:10:08 +00:00

516 lines
13 KiB
Bash

#!/bin/bash
# Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
. lib/utils
run_valgrind() {
# Execute script which may use $TESTNAME for creating individual
# log files for each execute command
exec "${VALGRIND:-valg}" "$@"
}
prepare_clvmd() {
test "${LVM_TEST_LOCKING:-0}" -ne 3 && return # not needed
if pgrep clvmd ; then
echo "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running."
skip
fi
# skip if we don't have our own clvmd...
(which clvmd 2>/dev/null | grep "$abs_builddir") || skip
# skip if we singlenode is not compiled in
(clvmd --help 2>&1 | grep "Available cluster managers" | grep "singlenode") || skip
# lvmconf "activation/monitoring = 1"
local run_valgrind=
test -z "$LVM_VALGRIND_CLVMD" || run_valgrind="run_valgrind"
$run_valgrind lib/clvmd -Isinglenode -d 1 -f &
local local_clvmd=$!
sleep .3
# extra sleep for slow valgrind
test -z "$LVM_VALGRIND_CLVMD" || sleep 5
# check that it is really running now
ps $local_clvmd || die
echo $local_clvmd > LOCAL_CLVMD
}
prepare_dmeventd() {
if pgrep dmeventd ; then
echo "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running."
skip
fi
# skip if we don't have our own dmeventd...
(which dmeventd 2>/dev/null | grep "$abs_builddir") || skip
lvmconf "activation/monitoring = 1"
dmeventd -f "$@" &
echo $! > LOCAL_DMEVENTD
# FIXME wait for pipe in /var/run instead
sleep .3
}
prepare_lvmetad() {
# skip if we don't have our own lvmetad...
(which lvmetad 2>/dev/null | grep "$abs_builddir") || skip
lvmconf "global/use_lvmetad = 1"
lvmconf "devices/md_component_detection = 0"
echo "preparing lvmetad..."
lvmetad -f "$@" -s "$TESTDIR/lvmetad.socket" &
echo $! > LOCAL_LVMETAD
sleep .3
}
notify_lvmetad() {
if test -e LOCAL_LVMETAD; then
pvscan --cache "$@" || true
fi
}
teardown_devs_prefixed() {
local prefix=$1
local stray=${2:-0}
local IFS=$IFS_NL
local dm
# Resume suspended devices first
for dm in $(dm_info suspended,name | grep "^Suspended:.*$prefix"); do
echo "dmsetup resume \"${dm#Suspended:}\""
dmsetup resume "${dm#Suspended:}" || true
done
local mounts=( $(grep "$prefix" /proc/mounts | cut -d' ' -f1) )
if test ${#mounts[@]} -gt 0; then
test "$stray" -eq 0 || echo "Removing stray mounted devices containing $prefix: ${mounts[@]}"
if umount -fl "${mounts[@]}"; then
udev_wait
fi
fi
# Remove devices, start with closed (sorted by open count)
local remfail=no
local need_udev_wait=0
init_udev_transaction
for dm in $(dm_info name --sort open | grep "$prefix"); do
dmsetup remove "$dm" &>/dev/null || remfail=yes
need_udev_wait=1
done
finish_udev_transaction
test $need_udev_wait -eq 0 || udev_wait
if test $remfail = yes; then
local num_devs
local num_remaining_devs=999
while num_devs=$(dm_table | grep "$prefix" | wc -l) && \
test $num_devs -lt $num_remaining_devs -a $num_devs -ne 0; do
test "$stray" -eq 0 || echo "Removing $num_devs stray mapped devices with names beginning with $prefix: "
for dm in $(dm_info name --sort open | grep "$prefix") ; do
dmsetup remove -f "$dm" || true
done
num_remaining_devs=$num_devs
done
fi
}
teardown_devs() {
# Delete any remaining dm/udev semaphores
teardown_udev_cookies
test -z "$PREFIX" || {
rm -rf "$TESTDIR/dev/$PREFIX"*
teardown_devs_prefixed "$PREFIX"
}
# NOTE: SCSI_DEBUG_DEV test must come before the LOOP test because
# prepare_scsi_debug_dev() also sets LOOP to short-circuit prepare_loop()
if test -f SCSI_DEBUG_DEV; then
test ${LVM_TEST_PARALLEL:-0} -eq 1 || modprobe -r scsi_debug
else
test ! -f LOOP || losetup -d $(cat LOOP) || true
test ! -f LOOPFILE || rm -f $(cat LOOPFILE)
fi
rm -f DEVICES # devs is set in prepare_devs()
rm -f LOOP
# Attempt to remove any loop devices that failed to get torn down if earlier tests aborted
test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -z "$COMMON_PREFIX" || {
teardown_devs_prefixed "$COMMON_PREFIX" 1
local stray_loops=( $(losetup -a | grep "$COMMON_PREFIX" | cut -d: -f1) )
test ${#stray_loops[@]} -eq 0 || {
echo "Removing stray loop devices containing $COMMON_PREFIX: ${stray_loops[@]}"
losetup -d "${stray_loops[@]}"
}
}
}
teardown() {
echo -n "## teardown..."
dm_table | not egrep -q "$vg|$vg1|$vg2|$vg3|$vg4" || {
# Avoid activation of dmeventd if there is no pid
cfg=$(test -s LOCAL_DMEVENTD || echo "--config activation{monitoring=0}")
vgremove -ff $cfg \
$vg $vg1 $vg2 $vg3 $vg4 &>/dev/null || rm -f debug.log
}
test -s LOCAL_CLVMD && {
kill -INT "$(cat LOCAL_CLVMD)"
test -z "$LVM_VALGRIND_CLVMD" || sleep 1
sleep .1
kill -9 "$(cat LOCAL_CLVMD)" &>/dev/null || true
}
echo -n .
pgrep dmeventd || true
test ! -s LOCAL_DMEVENTD || kill -9 "$(cat LOCAL_DMEVENTD)" || true
test ! -s LOCAL_LVMETAD || kill -9 "$(cat LOCAL_LVMETAD)" || true
echo -n .
test -d "$DM_DEV_DIR/mapper" && teardown_devs
echo -n .
test -n "$TESTDIR" && {
cd "$TESTOLDPWD"
rm -rf "$TESTDIR" || echo BLA
}
echo "ok"
test ${LVM_TEST_PARALLEL:-0} -eq 1 -o -n "$RUNNING_DMEVENTD" || not pgrep dmeventd #&>/dev/null
}
make_ioerror() {
echo 0 10000000 error | dmsetup create -u ${PREFIX}-ioerror ioerror
ln -s "$DM_DEV_DIR/mapper/ioerror" "$DM_DEV_DIR/ioerror"
}
prepare_loop() {
local size=${1=32}
local i
local slash
test -f LOOP && LOOP=$(cat LOOP)
echo -n "## preparing loop device..."
# skip if prepare_scsi_debug_dev() was used
if test -f SCSI_DEBUG_DEV -a -f LOOP ; then
echo "(skipped)"
return 0
fi
test ! -e LOOP
test -n "$DM_DEV_DIR"
for i in 0 1 2 3 4 5 6 7; do
test -e "$DM_DEV_DIR/loop$i" || mknod "$DM_DEV_DIR/loop$i" b 7 $i
done
echo -n .
local LOOPFILE="$PWD/test.img"
dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=0 seek=$(($size-1)) 2> /dev/null
if LOOP=$(losetup -s -f "$LOOPFILE" 2>/dev/null); then
:
elif LOOP=$(losetup -f) && losetup "$LOOP" "$LOOPFILE"; then
# no -s support
:
else
# no -f support
# Iterate through $DM_DEV_DIR/loop{,/}{0,1,2,3,4,5,6,7}
for slash in '' /; do
for i in 0 1 2 3 4 5 6 7; do
local dev="$DM_DEV_DIR/loop$slash$i"
! losetup "$dev" >/dev/null 2>&1 || continue
# got a free
losetup "$dev" "$LOOPFILE"
LOOP=$dev
break
done
test -z "$LOOP" || break
done
fi
test -n "$LOOP" # confirm or fail
echo "$LOOP" > LOOP
echo "ok ($LOOP)"
}
# A drop-in replacement for prepare_loop() that uses scsi_debug to create
# a ramdisk-based SCSI device upon which all LVM devices will be created
# - scripts must take care not to use a DEV_SIZE that will enduce OOM-killer
prepare_scsi_debug_dev() {
local DEV_SIZE=$1
local SCSI_DEBUG_PARAMS=${@:2}
test -f "SCSI_DEBUG_DEV" && return 0
test -z "$LOOP"
test -n "$DM_DEV_DIR"
# Skip test if awk isn't available (required for get_sd_devs_)
which awk || skip
# Skip test if scsi_debug module is unavailable or is already in use
modprobe --dry-run scsi_debug || skip
lsmod | grep -q scsi_debug && skip
# Create the scsi_debug device and determine the new scsi device's name
# NOTE: it will _never_ make sense to pass num_tgts param;
# last param wins.. so num_tgts=1 is imposed
modprobe scsi_debug dev_size_mb=$DEV_SIZE $SCSI_DEBUG_PARAMS num_tgts=1 || skip
sleep 2 # allow for async Linux SCSI device registration
local DEBUG_DEV="/dev/$(grep -H scsi_debug /sys/block/*/device/model | cut -f4 -d /)"
test -b "$DEBUG_DEV" || return 1 # should not happen
# Create symlink to scsi_debug device in $DM_DEV_DIR
SCSI_DEBUG_DEV="$DM_DEV_DIR/$(basename $DEBUG_DEV)"
echo "$SCSI_DEBUG_DEV" > SCSI_DEBUG_DEV
echo "$SCSI_DEBUG_DEV" > LOOP
# Setting $LOOP provides means for prepare_devs() override
test "$LVM_TEST_DEVDIR" != "/dev" && ln -snf "$DEBUG_DEV" "$SCSI_DEBUG_DEV"
}
cleanup_scsi_debug_dev() {
teardown_devs
rm -f SCSI_DEBUG_DEV LOOP
}
prepare_devs() {
local n=${1:-3}
local devsize=${2:-34}
local pvname=${3:-pv}
local loopsz
prepare_loop $(($n*$devsize))
echo -n "## preparing $n devices..."
if ! loopsz=$(blockdev --getsz "$LOOP" 2>/dev/null); then
loopsz=$(blockdev --getsize "$LOOP" 2>/dev/null)
fi
local size=$(($loopsz/$n))
devs=
init_udev_transaction
for i in $(seq 1 $n); do
local name="${PREFIX}$pvname$i"
local dev="$DM_DEV_DIR/mapper/$name"
devs="$devs $dev"
echo 0 $size linear "$LOOP" $((($i-1)*$size)) > "$name.table"
dmsetup create -u "TEST-$name" "$name" "$name.table"
done
finish_udev_transaction
#for i in `seq 1 $n`; do
# local name="${PREFIX}$pvname$i"
# dmsetup info -c $name
#done
#for i in `seq 1 $n`; do
# local name="${PREFIX}$pvname$i"
# dmsetup table $name
#done
echo $devs > DEVICES
echo "ok"
}
disable_dev() {
local dev
init_udev_transaction
for dev in "$@"; do
maj=$(($(stat --printf=0x%t "$dev")))
min=$(($(stat --printf=0x%T "$dev")))
echo "Disabling device $dev ($maj:$min)"
dmsetup remove -f "$dev" || true
notify_lvmetad --major "$maj" --minor "$min"
done
finish_udev_transaction
}
enable_dev() {
local dev
init_udev_transaction
for dev in "$@"; do
local name=$(echo "$dev" | sed -e 's,.*/,,')
dmsetup create -u "TEST-$name" "$name" "$name.table" || \
dmsetup load "$name" "$name.table"
# using device name (since device path does not exists yes with udev)
dmsetup resume "$name"
notify_lvmetad "$dev"
done
finish_udev_transaction
}
backup_dev() {
local dev
for dev in "$@"; do
dd if="$dev" of="$dev.backup" bs=1024
done
}
restore_dev() {
local dev
for dev in "$@"; do
test -e "$dev.backup" || \
die "Internal error: $dev not backed up, can't restore!"
dd of="$dev" if="$dev.backup" bs=1024
done
}
prepare_pvs() {
prepare_devs "$@"
pvcreate -ff $devs
}
prepare_vg() {
teardown_devs
prepare_pvs "$@"
vgcreate -c n $vg $devs
}
lvmconf() {
LVM_TEST_LOCKING=${LVM_TEST_LOCKING:-1}
if test "$DM_DEV_DIR" = "/dev"; then
LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-0}
else
LVM_VERIFY_UDEV=${LVM_VERIFY_UDEV:-1}
fi
test -f CONFIG_VALUES || {
cat > CONFIG_VALUES <<-EOF
devices/dir = "$DM_DEV_DIR"
devices/scan = "$DM_DEV_DIR"
devices/filter = [ "a/dev\\\\/mirror/", "a/dev\\\\/mapper\\\\/.*pv[0-9_]*$/", "r/.*/" ]
devices/cache_dir = "$TESTDIR/etc"
devices/sysfs_scan = 0
devices/default_data_alignment = 1
devices/md_component_detection = 0
log/syslog = 0
log/indent = 1
log/level = 9
log/file = "$TESTDIR/debug.log"
log/overwrite = 1
log/activation = 1
log/verbose = 0
activation/retry_deactivation = 1
backup/backup = 0
backup/archive = 0
global/abort_on_internal_errors = 1
global/detect_internal_vg_cache_corruption = 1
global/library_dir = "$TESTDIR/lib"
global/locking_dir = "$TESTDIR/var/lock/lvm"
global/locking_type=$LVM_TEST_LOCKING
global/si_unit_consistency = 1
global/fallback_to_local_locking = 0
activation/checks = 1
activation/udev_sync = 1
activation/udev_rules = 1
activation/verify_udev_operations = $LVM_VERIFY_UDEV
activation/polling_interval = 0
activation/snapshot_autoextend_percent = 50
activation/snapshot_autoextend_threshold = 50
activation/monitoring = 0
EOF
}
local v
for v in "$@"; do
echo "$v" >> CONFIG_VALUES
done
rm -f CONFIG
local s
for s in $(cat CONFIG_VALUES | cut -f1 -d/ | sort | uniq); do
echo "$s {" >> CONFIG
local k
for k in $(grep ^"$s"/ CONFIG_VALUES | cut -f1 -d= | sed -e 's, *$,,' | sort | uniq); do
grep "^$k" CONFIG_VALUES | tail -n 1 | sed -e "s,^$s/, ," >> CONFIG
done
echo "}" >> CONFIG
echo >> CONFIG
done
mv -f CONFIG etc/lvm.conf
}
apitest() {
local t=$1
shift
test -x "$abs_top_builddir/test/api/$t.t" || skip
"$abs_top_builddir/test/api/$t.t" "$@" && rm -f debug.log
}
api() {
test -x "$abs_top_builddir/test/api/wrapper" || skip
"$abs_top_builddir/test/api/wrapper" "$@" && rm -f debug.log
}
udev_wait() {
pgrep udev >/dev/null || return 0
which udevadm >/dev/null || return 0
if test -n "$1" ; then
udevadm settle --exit-if-exists="$1" || true
else
udevadm settle --timeout=15 || true
fi
}
#
# Check wheter kernel [dm module] target exist
# at least in expected version
#
# [dm-]target-name major minor revision
#
# i.e. dm_target_at_least dm-thin-pool 1 0
target_at_least()
{
case "$1" in
dm-*) modprobe "$1" ;;
esac
local version=$(dmsetup targets 2>/dev/null | grep "${1##dm-} " 2>/dev/null)
version=${version##* v}
shift
local major=$(echo "$version" | cut -d. -f1)
test -z "$1" && return 0
test -n "$major" || return 1
test "$major" -gt "$1" && return 0
test "$major" -eq "$1" || return 1
test -z "$2" && return 0
local minor=$(echo "$version" | cut -d. -f2)
test -n "$minor" || return 1
test "$minor" -gt "$2" && return 0
test "$minor" -eq "$2" || return 1
test -z "$3" && return 0
local revision=$(echo "$version" | cut -d. -f3)
test "$revision" -ge "$3" 2>/dev/null || return 1
}
test -f DEVICES && devs=$(cat DEVICES)
unset LVM_VALGRIND
"$@"