1#!/bin/bash 2# 3# Copyright (C) 2009 Red Hat, Inc. 4# Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18# 19 20dd() 21{ 22 if [ "$HOSTOS" == "Linux" ] 23 then 24 command dd --help | grep noxfer > /dev/null 2>&1 25 26 if [ "$?" -eq 0 ] 27 then 28 command dd status=noxfer $@ 29 else 30 command dd $@ 31 fi 32 else 33 command dd $@ 34 fi 35} 36 37# poke_file 'test.img' 512 '\xff\xfe' 38poke_file() 39{ 40 printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null 41} 42 43 44if ! . ./common.config 45 then 46 echo "$0: failed to source common.config" 47 exit 1 48fi 49 50_qemu_wrapper() 51{ 52 ( 53 if [ -n "${QEMU_NEED_PID}" ]; then 54 echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid" 55 fi 56 exec "$QEMU_PROG" $QEMU_OPTIONS "$@" 57 ) 58} 59 60_qemu_img_wrapper() 61{ 62 (exec "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS "$@") 63} 64 65_qemu_io_wrapper() 66{ 67 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 68 local QEMU_IO_ARGS="$QEMU_IO_OPTIONS" 69 if [ "$IMGOPTSSYNTAX" = "true" ]; then 70 QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS" 71 if [ -n "$IMGKEYSECRET" ]; then 72 QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS" 73 fi 74 fi 75 local RETVAL 76 ( 77 if [ "${VALGRIND_QEMU}" == "y" ]; then 78 exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" 79 else 80 exec "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" 81 fi 82 ) 83 RETVAL=$? 84 if [ "${VALGRIND_QEMU}" == "y" ]; then 85 if [ $RETVAL == 99 ]; then 86 cat "${VALGRIND_LOGFILE}" 87 fi 88 rm -f "${VALGRIND_LOGFILE}" 89 fi 90 (exit $RETVAL) 91} 92 93_qemu_nbd_wrapper() 94{ 95 ( 96 echo $BASHPID > "${QEMU_TEST_DIR}/qemu-nbd.pid" 97 exec "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS "$@" 98 ) 99} 100 101_qemu_vxhs_wrapper() 102{ 103 ( 104 echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid" 105 exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@" 106 ) 107} 108 109export QEMU=_qemu_wrapper 110export QEMU_IMG=_qemu_img_wrapper 111export QEMU_IO=_qemu_io_wrapper 112export QEMU_NBD=_qemu_nbd_wrapper 113export QEMU_VXHS=_qemu_vxhs_wrapper 114 115if [ "$IMGOPTSSYNTAX" = "true" ]; then 116 DRIVER="driver=$IMGFMT" 117 QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS" 118 if [ -n "$IMGKEYSECRET" ]; then 119 QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS" 120 fi 121 if [ "$IMGFMT" = "luks" ]; then 122 DRIVER="$DRIVER,key-secret=keysec0" 123 fi 124 if [ "$IMGPROTO" = "file" ]; then 125 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 126 TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT" 127 elif [ "$IMGPROTO" = "nbd" ]; then 128 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 129 TEST_IMG="$DRIVER,file.driver=nbd,file.host=127.0.0.1,file.port=10810" 130 elif [ "$IMGPROTO" = "ssh" ]; then 131 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 132 TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE" 133 elif [ "$IMGPROTO" = "nfs" ]; then 134 TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR" 135 TEST_IMG=$TEST_DIR/t.$IMGFMT 136 else 137 TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT" 138 fi 139else 140 QEMU_IMG_EXTRA_ARGS= 141 if [ "$IMGPROTO" = "file" ]; then 142 TEST_IMG=$TEST_DIR/t.$IMGFMT 143 elif [ "$IMGPROTO" = "nbd" ]; then 144 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 145 TEST_IMG="nbd:127.0.0.1:10810" 146 elif [ "$IMGPROTO" = "ssh" ]; then 147 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 148 TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" 149 elif [ "$IMGPROTO" = "nfs" ]; then 150 TEST_DIR="nfs://127.0.0.1/$TEST_DIR" 151 TEST_IMG=$TEST_DIR/t.$IMGFMT 152 elif [ "$IMGPROTO" = "vxhs" ]; then 153 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 154 TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" 155 else 156 TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT 157 fi 158fi 159ORIG_TEST_IMG="$TEST_IMG" 160 161if [ -z "$TEST_DIR" ]; then 162 TEST_DIR=`pwd`/scratch 163fi 164 165QEMU_TEST_DIR="${TEST_DIR}" 166 167if [ ! -e "$TEST_DIR" ]; then 168 mkdir "$TEST_DIR" 169fi 170 171if [ ! -d "$TEST_DIR" ]; then 172 echo "common.config: Error: \$TEST_DIR ($TEST_DIR) is not a directory" 173 exit 1 174fi 175 176if [ ! -d "$SAMPLE_IMG_DIR" ]; then 177 echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" 178 exit 1 179fi 180 181_use_sample_img() 182{ 183 SAMPLE_IMG_FILE="${1%\.bz2}" 184 TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE" 185 bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG" 186 if [ $? -ne 0 ] 187 then 188 echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'" 189 exit 1 190 fi 191} 192 193_make_test_img() 194{ 195 # extra qemu-img options can be added by tests 196 # at least one argument (the image size) needs to be added 197 local extra_img_options="" 198 local image_size=$* 199 local optstr="" 200 local img_name="" 201 local use_backing=0 202 local backing_file="" 203 local object_options="" 204 205 if [ -n "$TEST_IMG_FILE" ]; then 206 img_name=$TEST_IMG_FILE 207 else 208 img_name=$TEST_IMG 209 fi 210 211 if [ -n "$IMGOPTS" ]; then 212 optstr=$(_optstr_add "$optstr" "$IMGOPTS") 213 fi 214 if [ -n "$IMGKEYSECRET" ]; then 215 object_options="--object secret,id=keysec0,data=$IMGKEYSECRET" 216 optstr=$(_optstr_add "$optstr" "key-secret=keysec0") 217 fi 218 219 if [ "$1" = "-b" ]; then 220 use_backing=1 221 backing_file=$2 222 image_size=$3 223 fi 224 if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then 225 optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE") 226 fi 227 228 if [ -n "$optstr" ]; then 229 extra_img_options="-o $optstr $extra_img_options" 230 fi 231 232 # XXX(hch): have global image options? 233 ( 234 if [ $use_backing = 1 ]; then 235 $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1 236 else 237 $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1 238 fi 239 ) | _filter_img_create 240 241 # Start an NBD server on the image file, which is what we'll be talking to 242 if [ $IMGPROTO = "nbd" ]; then 243 # Pass a sufficiently high number to -e that should be enough for all 244 # tests 245 eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT -e 42 $TEST_IMG_FILE >/dev/null &" 246 sleep 1 # FIXME: qemu-nbd needs to be listening before we continue 247 fi 248 249 # Start QNIO server on image directory for vxhs protocol 250 if [ $IMGPROTO = "vxhs" ]; then 251 eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &" 252 sleep 1 # Wait for server to come up. 253 fi 254} 255 256_rm_test_img() 257{ 258 local img=$1 259 if [ "$IMGFMT" = "vmdk" ]; then 260 # Remove all the extents for vmdk 261 "$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \ 262 | xargs -I {} rm -f "{}" 263 fi 264 rm -f "$img" 265} 266 267_cleanup_test_img() 268{ 269 case "$IMGPROTO" in 270 271 nbd) 272 if [ -f "${QEMU_TEST_DIR}/qemu-nbd.pid" ]; then 273 local QEMU_NBD_PID 274 read QEMU_NBD_PID < "${QEMU_TEST_DIR}/qemu-nbd.pid" 275 kill ${QEMU_NBD_PID} 276 rm -f "${QEMU_TEST_DIR}/qemu-nbd.pid" 277 fi 278 rm -f "$TEST_IMG_FILE" 279 ;; 280 vxhs) 281 if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then 282 local QEMU_VXHS_PID 283 read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid" 284 kill ${QEMU_VXHS_PID} >/dev/null 2>&1 285 rm -f "${TEST_DIR}/qemu-vxhs.pid" 286 fi 287 rm -f "$TEST_IMG_FILE" 288 ;; 289 290 file) 291 _rm_test_img "$TEST_DIR/t.$IMGFMT" 292 _rm_test_img "$TEST_DIR/t.$IMGFMT.orig" 293 _rm_test_img "$TEST_DIR/t.$IMGFMT.base" 294 if [ -n "$SAMPLE_IMG_FILE" ] 295 then 296 rm -f "$TEST_DIR/$SAMPLE_IMG_FILE" 297 SAMPLE_IMG_FILE= 298 TEST_IMG="$ORIG_TEST_IMG" 299 fi 300 ;; 301 302 rbd) 303 rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null 304 ;; 305 306 sheepdog) 307 collie vdi delete "$TEST_DIR/t.$IMGFMT" 308 ;; 309 310 esac 311} 312 313_check_test_img() 314{ 315 ( 316 if [ "$IMGOPTSSYNTAX" = "true" ]; then 317 $QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 318 else 319 $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 320 fi 321 ) | _filter_testdir | _filter_qemu_img_check 322} 323 324_img_info() 325{ 326 if [[ "$1" == "--format-specific" ]]; then 327 local format_specific=1 328 shift 329 else 330 local format_specific=0 331 fi 332 333 discard=0 334 regex_json_spec_start='^ *"format-specific": \{' 335 $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ 336 sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ 337 -e "s#$TEST_DIR#TEST_DIR#g" \ 338 -e "s#$IMGFMT#IMGFMT#g" \ 339 -e "/^disk size:/ D" \ 340 -e "/actual-size/ D" | \ 341 while IFS='' read line; do 342 if [[ $format_specific == 1 ]]; then 343 discard=0 344 elif [[ $line == "Format specific information:" ]]; then 345 discard=1 346 elif [[ $line =~ $regex_json_spec_start ]]; then 347 discard=2 348 regex_json_spec_end="^${line%%[^ ]*}\\},? *$" 349 fi 350 if [[ $discard == 0 ]]; then 351 echo "$line" 352 elif [[ $discard == 1 && ! $line ]]; then 353 echo 354 discard=0 355 elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then 356 discard=0 357 fi 358 done 359} 360 361# bail out, setting up .notrun file 362# 363_notrun() 364{ 365 echo "$*" >"$OUTPUT_DIR/$seq.notrun" 366 echo "$seq not run: $*" 367 status=0 368 exit 369} 370 371# just plain bail out 372# 373_fail() 374{ 375 echo "$*" | tee -a "$OUTPUT_DIR/$seq.full" 376 echo "(see $seq.full for details)" 377 status=1 378 exit 1 379} 380 381# tests whether $IMGFMT is one of the supported image formats for a test 382# 383_supported_fmt() 384{ 385 # "generic" is suitable for most image formats. For some formats it doesn't 386 # work, however (most notably read-only formats), so they can opt out by 387 # setting IMGFMT_GENERIC to false. 388 for f; do 389 if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then 390 return 391 fi 392 done 393 394 _notrun "not suitable for this image format: $IMGFMT" 395} 396 397# tests whether $IMGFMT is one of the unsupported image format for a test 398# 399_unsupported_fmt() 400{ 401 for f; do 402 if [ "$f" = "$IMGFMT" ]; then 403 _notrun "not suitable for this image format: $IMGFMT" 404 fi 405 done 406} 407 408# tests whether $IMGPROTO is one of the supported image protocols for a test 409# 410_supported_proto() 411{ 412 for f; do 413 if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then 414 return 415 fi 416 done 417 418 _notrun "not suitable for this image protocol: $IMGPROTO" 419} 420 421# tests whether $IMGPROTO is specified as an unsupported image protocol for a test 422# 423_unsupported_proto() 424{ 425 for f; do 426 if [ "$f" = "$IMGPROTO" ]; then 427 _notrun "not suitable for this image protocol: $IMGPROTO" 428 return 429 fi 430 done 431} 432 433# tests whether the host OS is one of the supported OSes for a test 434# 435_supported_os() 436{ 437 for h 438 do 439 if [ "$h" = "$HOSTOS" ] 440 then 441 return 442 fi 443 done 444 445 _notrun "not suitable for this OS: $HOSTOS" 446} 447 448_supported_cache_modes() 449{ 450 for mode; do 451 if [ "$mode" = "$CACHEMODE" ]; then 452 return 453 fi 454 done 455 _notrun "not suitable for cache mode: $CACHEMODE" 456} 457 458_default_cache_mode() 459{ 460 if $CACHEMODE_IS_DEFAULT; then 461 CACHEMODE="$1" 462 QEMU_IO="$QEMU_IO --cache $1" 463 return 464 fi 465} 466 467_unsupported_imgopts() 468{ 469 for bad_opt 470 do 471 if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt" 472 then 473 _notrun "not suitable for image option: $bad_opt" 474 fi 475 done 476} 477 478# this test requires that a specified command (executable) exists 479# 480_require_command() 481{ 482 if [ "$1" = "QEMU" ]; then 483 c=$QEMU_PROG 484 elif [ "$1" = "QEMU_IMG" ]; then 485 c=$QEMU_IMG_PROG 486 elif [ "$1" = "QEMU_IO" ]; then 487 c=$QEMU_IO_PROG 488 elif [ "$1" = "QEMU_NBD" ]; then 489 c=$QEMU_NBD_PROG 490 else 491 eval c=\$$1 492 fi 493 [ -x "$c" ] || _notrun "$1 utility required, skipped this test" 494} 495 496# make sure this script returns success 497true 498