diff options
Diffstat (limited to 'test/lib/check.sh')
-rw-r--r-- | test/lib/check.sh | 366 |
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 "$@" |