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.sh282
1 files changed, 282 insertions, 0 deletions
diff --git a/test/lib/check.sh b/test/lib/check.sh
new file mode 100644
index 0000000..6b7849f
--- /dev/null
+++ b/test/lib/check.sh
@@ -0,0 +1,282 @@
+#!/bin/bash
+# Copyright (C) 2010-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
+
+# check.sh: assert various things about volumes
+
+# USAGE:
+# check linear VG LV
+# check lv_on VG LV PV
+
+# check mirror VG LV [LOGDEV|core]
+# check mirror_nonredundant VG LV
+# check mirror_legs VG LV N
+# check mirror_images_on VG LV DEV [DEV...]
+
+# ...
+
+test -z "$BASH" || set -e -o pipefail
+
+die() {
+ echo "$@" >&2
+ return 1
+}
+
+lvl() {
+ lvs -a --noheadings "$@"
+}
+
+lvdevices() {
+ get lv_devices "$@"
+}
+
+mirror_images_redundant() {
+ local vg=$1
+ local lv=$vg/$2
+ lvs -a $vg -o+devices
+ for i in $(lvdevices $lv); do
+ echo "# $i:"
+ 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 || \
+ die "mirror images of $lv expected redundant, but are not:" \
+ $(cat check.tmp.all)
+}
+
+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)
+}
+
+mirror_images_on() {
+ local vg=$1
+ local lv=$2
+ shift 2
+ for i in $(lvdevices $lv); do
+ lv_on $vg $lv $1
+ shift
+ done
+}
+
+mirror_log_on() {
+ local vg=$1
+ local lv=$2
+ local where=$3
+ if test "$where" = "core"; then
+ get lv_field $vg/$lv mirror_log | not grep mlog
+ else
+ lv_on $vg ${lv}_mlog "$where"
+ fi
+}
+
+lv_is_contiguous() {
+ 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)
+}
+
+lv_is_clung() {
+ 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)
+}
+
+mirror_images_contiguous() {
+ 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
+ done
+}
+
+mirror() {
+ mirror_nonredundant "$@"
+ 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
+ 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)
+ fi
+ }
+ test -z "$3" || mirror_log_on $1 $2 "$3"
+}
+
+mirror_legs() {
+ local expect=$3
+ test "$expect" -eq $(lvdevices $1/$2 | wc -w)
+}
+
+mirror_no_temporaries() {
+ local vg=$1
+ local lv=$2
+ (lvl -o name $vg | grep $lv | not grep "tmp") || \
+ die "$lv has temporary mirror images unexpectedly:" \
+ $(lvl $vg | grep $lv)
+}
+
+linear() {
+ local lv=$1/$2
+ test $(get lv_field $lv stripes -a) -eq 1 || \
+ die "$lv expected linear, but is not:" \
+ $(lvl $lv -o+devices)
+}
+
+# in_sync <VG> <LV>
+# Works for "mirror" and "raid*"
+in_sync() {
+ local a
+ local b
+ local idx
+ local type
+ local lvm_name="$1/$2"
+ local dm_name=$(echo $lvm_name | sed s:-:--: | sed s:/:-:)
+
+ if ! a=(`dmsetup status $dm_name`); then
+ die "Unable to get sync status of $1"
+ elif [ ${a[2]} = "snapshot-origin" ]; then
+ if ! a=(`dmsetup status ${dm_name}-real`); then
+ die "Unable to get sync status of $1"
+ fi
+ fi
+
+ if [ ${a[2]} = "raid" ]; then
+ # Last argument is the sync ratio for RAID
+ idx=$((${#a[@]} - 1))
+ type=${a[3]}
+ elif [ ${a[2]} = "mirror" ]; then
+ # 4th Arg tells us how far to the sync ratio
+ idx=$((${a[3]} + 4))
+ type=${a[2]}
+ else
+ die "Unable to get sync ratio for target type '${a[2]}'"
+ fi
+
+ b=( $(echo ${a[$idx]} | sed s:/:' ':) )
+
+ if [ ${b[0]} != ${b[1]} ]; then
+ echo "$lvm_name ($type) is not in-sync"
+ return 1
+ fi
+
+ if [[ ${a[$(($idx - 1))]} =~ a ]]; then
+ die "$lvm_name in-sync, but 'a' characters in health status"
+ fi
+
+ echo "$lvm_name ($type) is in-sync"
+ return 0
+}
+
+active() {
+ 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 ||
+ 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) || \
+ 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!"
+}
+
+# Check for list of LVs from given VG
+lv_exists() {
+ local vg=$1
+ local lv=
+ while [ $# -gt 1 ]; do
+ shift
+ lv="$lv $vg/$1"
+ done
+ lvl $lv &>/dev/null || \
+ die "$lv expected to exist but does not"
+}
+
+pv_field() {
+ local 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}")
+ test "$actual" = "$3" || \
+ die "vg_field: vg=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+lv_field() {
+ local actual=$(get lv_field $1 "$2" "${@:4}")
+ test "$actual" = "$3" || \
+ die "lv_field: lv=$lv, field=\"$2\", actual=\"$actual\", expected=\"$3\""
+}
+
+compare_fields() {
+ local cmd1=$1
+ local obj1=$2
+ local field1=$3
+ local cmd2=$4
+ local obj2=$5
+ local field2=$6
+ local val1=$($cmd1 --noheadings -o "$field1" "$obj1")
+ local val2=$($cmd2 --noheadings -o "$field2" "$obj2")
+ test "$val1" = "$val2" || \
+ die "compare_fields $obj1($field1): $val1 $obj2($field2): $val2"
+}
+
+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)
+ test "$val1" = "$val2" || \
+ die "compare_vg_field: $vg1: $val1, $vg2: $val2"
+}
+
+pvlv_counts() {
+ local local_vg=$1
+ 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
+}
+
+unset LVM_VALGRIND
+"$@"