summaryrefslogtreecommitdiff
path: root/test/lib/check.sh
diff options
context:
space:
mode:
Diffstat (limited to 'test/lib/check.sh')
-rw-r--r--test/lib/check.sh366
1 files changed, 275 insertions, 91 deletions
diff --git a/test/lib/check.sh b/test/lib/check.sh
index 6b7849f..1f26194 100644
--- a/test/lib/check.sh
+++ b/test/lib/check.sh
@@ -1,5 +1,5 @@
-#!/bin/bash
-# Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
+#!/usr/bin/env bash
+# Copyright (C) 2010-2013 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
@@ -7,7 +7,7 @@
#
# 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
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# check.sh: assert various things about volumes
@@ -25,7 +25,8 @@
test -z "$BASH" || set -e -o pipefail
die() {
- echo "$@" >&2
+ rm -f debug.log
+ echo -e "$@" >&2
return 1
}
@@ -39,36 +40,71 @@ lvdevices() {
mirror_images_redundant() {
local vg=$1
- local lv=$vg/$2
- lvs -a $vg -o+devices
- for i in $(lvdevices $lv); do
+ local lv="$vg/$2"
+ for i in $(lvdevices "$lv"); do
echo "# $i:"
- lvdevices $vg/$i | sort | uniq
+ lvdevices "$vg/$i" | sort | uniq
done > check.tmp.all
(grep -v ^# check.tmp.all || true) | sort | uniq -d > check.tmp
- test $(cat check.tmp | wc -l) -eq 0 || \
+ test "$(wc -l < check.tmp)" -eq 0 || \
die "mirror images of $lv expected redundant, but are not:" \
- $(cat check.tmp.all)
+ "$(cat check.tmp.all)"
}
+lv_err_list_() {
+ (echo "$2" | not grep -m 1 -q "$1") || \
+ echo "$3 on [ $(echo "$2" | grep "$1" | cut -b3- | tr '\n' ' ')] "
+}
+
+lv_on_diff_() {
+ declare -a xdevs=("${!1}") # pass in shell array
+ local expect=( "${@:4}" ) # make an array starting from 4th args...
+ local diff_e
+
+ # Find diff between 2 shell arrays, print them as stdin files
+ printf "%s\\n" "${expect[@]}" | sort | uniq >_lv_on_diff1
+ printf "%s\\n" "${xdevs[@]}" >_lv_on_diff2
+ diff_e=$(diff _lv_on_diff1 _lv_on_diff2) ||
+ die "LV $2/$3 $(lv_err_list_ "^>" "${diff_e}" found)$(lv_err_list_ "^<" "${diff_e}" "not found")."
+}
+
+# list devices for given LV
lv_on() {
- local lv=$1/$2
- (lvdevices $lv | grep -F "$3") || \
- die "LV $lv expected on $3 but is not:" \
- $(lvdevices $lv)
- test $(lvdevices $lv | grep -vF "$3" | wc -l) -eq 0 || \
- die "LV $lv contains unexpected devices:" \
- $(lvdevices $lv)
+ local devs
+
+ devs=( $(lvdevices "$1/$2" | sort | uniq ) )
+
+ lv_on_diff_ devs[@] "$@"
}
+# list devices for given LV and all its subdevices
+lv_tree_on() {
+ local devs
+
+ # Get sorted list of devices
+ devs=( $(get lv_tree_devices "$1" "$2") )
+
+ lv_on_diff_ devs[@] "$@"
+}
+
+# Test if all mimage_X LV legs are sitting on given ordered list of PVs
+# When LV is composed of imagetmp, such leg is decomposed so only
+# real _mimage LVs are always checked
mirror_images_on() {
local vg=$1
local lv=$2
shift 2
- for i in $(lvdevices $lv); do
- lv_on $vg $lv $1
+ local mimages=()
+ local line
+
+ while IFS= read -r line ; do
+ mimages+=( "$line" )
+ done < <( get lv_field_lv_ "$vg" lv_name -a | grep "${lv}_mimage_" )
+
+ for i in "${mimages[@]}"; do
+ lv_on "$vg" "$i" "$1"
shift
done
}
@@ -78,170 +114,263 @@ mirror_log_on() {
local lv=$2
local where=$3
if test "$where" = "core"; then
- get lv_field $vg/$lv mirror_log | not grep mlog
+ get lv_field "$vg/$lv" mirror_log | not grep mlog
else
- lv_on $vg ${lv}_mlog "$where"
+ lv_on "$vg" "${lv}_mlog" "$where"
fi
}
lv_is_contiguous() {
- local lv=$1/$2
- test $(lvl --segments $lv | wc -l) -eq 1 || \
+ local lv="$1/$2"
+ test "$(lvl --segments "$lv" | wc -l)" -eq 1 || \
die "LV $lv expected to be contiguous, but is not:" \
- $(lvl --segments $lv)
+ "$(lvl --segments "$lv")"
}
lv_is_clung() {
- local lv=$1/$2
- test $(lvdevices $lv | sort | uniq | wc -l) -eq 1 || \
+ local lv="$1/$2"
+ test "$(lvdevices "$lv" | sort | uniq | wc -l)" -eq 1 || \
die "LV $lv expected to be clung, but is not:" \
- $(lvdevices $lv | sort | uniq)
+ "$(lvdevices "$lv" | sort | uniq)"
}
mirror_images_contiguous() {
- for i in $(lvdevices $1/$2); do
- lv_is_contiguous $1 $i
+ for i in $(lvdevices "$1/$2"); do
+ lv_is_contiguous "$1" "$i"
done
}
mirror_images_clung() {
- for i in $(lvdevices $1/$2); do
- lv_is_clung $1 $i
+ for i in $(lvdevices "$1/$2"); do
+ lv_is_clung "$1" "$i"
done
}
mirror() {
mirror_nonredundant "$@"
- mirror_images_redundant $1 $2
+ mirror_images_redundant "$1" "$2"
}
mirror_nonredundant() {
- local lv=$1/$2
- local attr=$(get lv_field $lv attr)
- (echo "$attr" | grep "^m........$" >/dev/null) || {
- if (echo "$attr" | grep "^o........$" >/dev/null) &&
- lvs -a | fgrep "[${2}_mimage" >/dev/null; then
+ local lv="$1/$2"
+ local attr
+ attr=$(get lv_field "$lv" attr)
+ (echo "$attr" | grep "^......m...$" >/dev/null) || {
+ if (echo "$attr" | grep "^o.........$" >/dev/null) &&
+ lvs -a "$1" | grep -F "[${2}_mimage" >/dev/null; then
echo "TEST WARNING: $lv is a snapshot origin and looks like a mirror,"
echo "assuming it is actually a mirror"
else
die "$lv expected a mirror, but is not:" \
- $(lvs $lv)
+ "$(lvs "$lv")"
fi
}
- test -z "$3" || mirror_log_on $1 $2 "$3"
+ test -z "$3" || mirror_log_on "$1" "$2" "$3"
}
mirror_legs() {
- local expect=$3
- test "$expect" -eq $(lvdevices $1/$2 | wc -w)
+ local expect_legs=$3
+ test "$expect_legs" -eq "$(lvdevices "$1/$2" | wc -w)"
}
mirror_no_temporaries() {
local vg=$1
local lv=$2
- (lvl -o name $vg | grep $lv | not grep "tmp") || \
+ (lvl -o name "$vg" | grep "$lv" | not grep "tmp") || \
die "$lv has temporary mirror images unexpectedly:" \
- $(lvl $vg | grep $lv)
+ "$(lvl "$vg" | grep "$lv")"
}
linear() {
- local lv=$1/$2
- test $(get lv_field $lv stripes -a) -eq 1 || \
+ local lv="$1/$2"
+ test "$(get lv_field "$lv" stripes -a)" -eq 1 || \
die "$lv expected linear, but is not:" \
- $(lvl $lv -o+devices)
+ "$(lvl "$lv" -o+devices)"
}
-# in_sync <VG> <LV>
+# in_sync <VG> <LV> <ignore 'a'>
# Works for "mirror" and "raid*"
in_sync() {
local a
local b
+ local c
local idx
local type
+ local snap=""
local lvm_name="$1/$2"
- local dm_name=$(echo $lvm_name | sed s:-:--: | sed s:/:-:)
+ local ignore_a=${3:-0}
+ local dm_name="$1-$2"
- if ! a=(`dmsetup status $dm_name`); then
+ a=( $(dmsetup status "$dm_name") ) || \
die "Unable to get sync status of $1"
- elif [ ${a[2]} = "snapshot-origin" ]; then
- if ! a=(`dmsetup status ${dm_name}-real`); then
+
+ if [ "${a[2]}" = "snapshot-origin" ]; then
+ a=( $(dmsetup status "${dm_name}-real") ) || \
die "Unable to get sync status of $1"
- fi
+ snap=": under snapshot"
fi
- if [ ${a[2]} = "raid" ]; then
- # Last argument is the sync ratio for RAID
- idx=$((${#a[@]} - 1))
+ case "${a[2]}" in
+ "raid")
+ # 6th argument is the sync ratio for RAID
+ idx=6
type=${a[3]}
- elif [ ${a[2]} = "mirror" ]; then
+ if [ "${a[$(( idx + 1 ))]}" != "idle" ]; then
+ echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}"
+ return 1
+ fi
+ ;;
+ "mirror")
# 4th Arg tells us how far to the sync ratio
- idx=$((${a[3]} + 4))
+ idx=$(( a[3] + 4 ))
type=${a[2]}
- else
+ ;;
+ *)
die "Unable to get sync ratio for target type '${a[2]}'"
- fi
+ ;;
+ esac
- b=( $(echo ${a[$idx]} | sed s:/:' ':) )
+ b=${a[$idx]%%/*} # split ratio x/y
+ c=${a[$idx]##*/}
- if [ ${b[0]} != ${b[1]} ]; then
- echo "$lvm_name ($type) is not in-sync"
+ if [ "$b" -eq 0 ] || [ "$b" != "$c" ]; then
+ echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}"
return 1
fi
- if [[ ${a[$(($idx - 1))]} =~ a ]]; then
- die "$lvm_name in-sync, but 'a' characters in health status"
+ if [[ ${a[$(( idx - 1 ))]} =~ a ]] ; then
+ [ "$ignore_a" = 0 ] && \
+ die "$lvm_name ($type$snap) in-sync, but 'a' characters in health status"
+ echo "$lvm_name ($type$snap) is not in-sync " "${a[@]}"
+ [ "$ignore_a" = 1 ] && return 0
+ return 1
fi
- echo "$lvm_name ($type) is in-sync"
- return 0
+ echo "$lvm_name ($type$snap) is in-sync " "${a[@]}"
}
active() {
- local lv=$1/$2
- (get lv_field $lv attr | grep "^....a....$" >/dev/null) || \
+ local lv="$1/$2"
+ (get lv_field "$lv" attr | grep "^....a.....$" >/dev/null) || \
die "$lv expected active, but lvs says it's not:" \
- $(lvl $lv -o+devices)
- dmsetup info $1-$2 >/dev/null ||
+ "$(lvl "$lv" -o+devices)"
+ dmsetup info "$1-$2" >/dev/null ||
die "$lv expected active, lvs thinks it is but there are no mappings!"
}
inactive() {
- local lv=$1/$2
- (get lv_field $lv attr | grep "^....[-isd]....$" >/dev/null) || \
+ local lv="$1/$2"
+ (get lv_field "$lv" attr | grep "^....[-isd].....$" >/dev/null) || \
die "$lv expected inactive, but lvs says it's not:" \
- $(lvl $lv -o+devices)
- not dmsetup info $1-$2 2>/dev/null || \
- die "$lv expected inactive, lvs thinks it is but there are mappings!"
+ "$(lvl "$lv" -o+devices)"
+ not dmsetup info "$1-$2" 2>/dev/null || \
+ die "$lv expected inactive, lvs thinks it is but there are mappings!"
}
# Check for list of LVs from given VG
lv_exists() {
local vg=$1
- local lv=
+ declare -a list=()
while [ $# -gt 1 ]; do
shift
- lv="$lv $vg/$1"
+ list+=( "$vg/$1" )
done
- lvl $lv &>/dev/null || \
- die "$lv expected to exist but does not"
+ test "${#list[@]}" -gt 0 || list=( "$vg" )
+ lvl "${list[@]}" &>/dev/null || \
+ die "${list[@]}" "expected to exist, but does not!"
+}
+
+lv_not_exists() {
+ local vg=$1
+ if test $# -le 1 ; then
+ if lvl "$vg" &>/dev/null ; then
+ die "$vg expected to not exist but it does!"
+ fi
+ else
+ while [ $# -gt 1 ]; do
+ shift
+ not lvl "$vg/$1" &>/dev/null || die "$vg/$1 expected to not exist but it does!"
+ done
+ fi
+ rm -f debug.log
}
pv_field() {
- local actual=$(get pv_field "$1" "$2" "${@:4}")
+ local actual
+ actual=$(get pv_field "$1" "$2" "${@:4}")
test "$actual" = "$3" || \
die "pv_field: PV=\"$1\", field=\"$2\", actual=\"$actual\", expected=\"$3\""
}
vg_field() {
- local actual=$(get vg_field $1 "$2" "${@:4}")
+ local actual
+ actual=$(get vg_field "$1" "$2" "${@:4}")
test "$actual" = "$3" || \
die "vg_field: vg=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
}
+vg_attr_bit() {
+ local actual
+ local offset=$1
+ actual=$(get vg_field "$2" vg_attr "${@:4}")
+ case "$offset" in
+ perm*) offset=0 ;;
+ resiz*) offset=1 ;;
+ export*) offset=2 ;;
+ partial) offset=3 ;;
+ alloc*) offset=4 ;;
+ cluster*) offset=5 ;;
+ esac
+ test "${actual:$offset:1}" = "$3" || \
+ die "vg_attr_bit: vg=$2, ${offset} bit of \"$actual\" is \"${actual:$offset:1}\", but expected \"$3\""
+}
+
lv_field() {
- local actual=$(get lv_field $1 "$2" "${@:4}")
+ local actual
+ actual=$(get lv_field "$1" "$2" "${@:4}")
test "$actual" = "$3" || \
- die "lv_field: lv=$lv, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+ die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+lv_first_seg_field() {
+ local actual
+ actual=$(get lv_first_seg_field "$1" "$2" "${@:4}")
+ test "$actual" = "$3" || \
+ die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+lvh_field() {
+ local actual
+ actual=$(get lvh_field "$1" "$2" "${@:4}")
+ test "$actual" = "$3" || \
+ die "lvh_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+lva_field() {
+ local actual
+ actual=$(get lva_field "$1" "$2" "${@:4}")
+ test "$actual" = "$3" || \
+ die "lva_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+lv_attr_bit() {
+ local actual
+ local offset=$1
+ actual=$(get lv_field "$2" lv_attr "${@:4}")
+ case "$offset" in
+ type) offset=0 ;;
+ perm*) offset=1 ;;
+ alloc*) offset=2 ;;
+ fixed*) offset=3 ;;
+ state) offset=4 ;;
+ open) offset=5 ;;
+ target) offset=6 ;;
+ zero) offset=7 ;;
+ health) offset=8 ;;
+ skip) offset=9 ;;
+ esac
+ test "${actual:$offset:1}" = "$3" || \
+ die "lv_attr_bit: lv=$2, ${offset} bit of \"$actual\" is \"${actual:$offset:1}\", but expected \"$3\""
}
compare_fields() {
@@ -251,8 +380,10 @@ compare_fields() {
local cmd2=$4
local obj2=$5
local field2=$6
- local val1=$($cmd1 --noheadings -o "$field1" "$obj1")
- local val2=$($cmd2 --noheadings -o "$field2" "$obj2")
+ local val1
+ local val2
+ val1=$("$cmd1" --noheadings -o "$field1" "$obj1")
+ val2=$("$cmd2" --noheadings -o "$field2" "$obj2")
test "$val1" = "$val2" || \
die "compare_fields $obj1($field1): $val1 $obj2($field2): $val2"
}
@@ -261,8 +392,10 @@ compare_vg_field() {
local vg1=$1
local vg2=$2
local field=$3
- local val1=$(vgs --noheadings -o "$field" $vg1)
- local val2=$(vgs --noheadings -o "$field" $vg2)
+ local val1
+ local val2
+ val1=$(vgs --noheadings -o "$field" "$vg1")
+ val2=$(vgs --noheadings -o "$field" "$vg2")
test "$val1" = "$val2" || \
die "compare_vg_field: $vg1: $val1, $vg2: $val2"
}
@@ -272,11 +405,62 @@ pvlv_counts() {
local num_pvs=$2
local num_lvs=$3
local num_snaps=$4
- lvs -o+devices $local_vg
- vg_field $local_vg pv_count $num_pvs
- vg_field $local_vg lv_count $num_lvs
- vg_field $local_vg snap_count $num_snaps
+ lvs -o+devices "$local_vg"
+ vg_field "$local_vg" pv_count "$num_pvs"
+ vg_field "$local_vg" lv_count "$num_lvs"
+ vg_field "$local_vg" snap_count "$num_snaps"
+}
+
+# Compare md5 check generated from get dev_md5sum
+dev_md5sum() {
+ md5sum -c "md5.$1-$2" || \
+ (get lv_field "$1/$2" "name,size,seg_pe_ranges"
+ die "LV $1/$2 has different MD5 check sum!")
+}
+
+sysfs() {
+ # read maj min and also convert hex to decimal
+ local maj
+ local min
+ local P
+ local val
+ maj=$(($(stat -L --printf=0x%t "$1")))
+ min=$(($(stat -L --printf=0x%T "$1")))
+ P="/sys/dev/block/$maj:$min/$2"
+ val=$(< "$P") || return 0 # no sysfs ?
+ test "$val" -eq "$3" || \
+ die "$1: $P = $val differs from expected value $3!"
+}
+
+# check raid_leg_status $vg $lv "Aaaaa"
+raid_leg_status() {
+ local st
+ local val
+
+ # Ignore inconsisten raid status 0/xxxxx idle
+ for i in {100..0} ; do
+ st=( $(dmsetup status "$1-$2") ) || die "Unable to get status of $vg/$lv1"
+ b=( $(echo "${st[6]}" | sed s:/:' ':) )
+ [ "${b[0]}" = "0" ] || {
+ test "${st[5]}" = "$3" || break
+ return 0
+ }
+ sleep .1
+ done
+
+ die "$1-$2 status ${st[5]} != $3 (${st[*]})"
+}
+
+grep_dmsetup() {
+ dmsetup "$1" "$2" | tee out
+ grep -q "${@:3}" out || die "Expected output \"" "${@:3}" "\" from dmsetup $1 not found!"
+}
+
+grep_lvmlockd_dump() {
+ lvmlockctl --dump | tee out
+ grep -q "${@:1}" out || die "Expected output \"" "${@:1}" "\" from lvmlockctl --dump not found!"
}
+#set -x
unset LVM_VALGRIND
"$@"