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# we need common.config 44if [ "$iam" != "check" ] 45then 46 if ! . ./common.config 47 then 48 echo "$iam: failed to source common.config" 49 exit 1 50 fi 51fi 52 53# make sure we have a standard umask 54umask 022 55 56if [ "$IMGPROTO" = "file" ]; then 57 TEST_IMG=$TEST_DIR/t.$IMGFMT 58elif [ "$IMGPROTO" = "nbd" ]; then 59 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 60 TEST_IMG="nbd:127.0.0.1:10810" 61elif [ "$IMGPROTO" = "ssh" ]; then 62 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 63 TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" 64else 65 TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT 66fi 67 68function valgrind_qemu_io() 69{ 70 valgrind --log-file=/tmp/$$.valgrind --error-exitcode=99 $REAL_QEMU_IO "$@" 71 if [ $? != 0 ]; then 72 cat /tmp/$$.valgrind 73 fi 74 rm -f /tmp/$$.valgrind 75} 76 77 78_optstr_add() 79{ 80 if [ -n "$1" ]; then 81 echo "$1,$2" 82 else 83 echo "$2" 84 fi 85} 86 87_set_default_imgopts() 88{ 89 if [ "$IMGFMT" == "qcow2" ] && ! (echo "$IMGOPTS" | grep "compat=" > /dev/null); then 90 IMGOPTS=$(_optstr_add "$IMGOPTS" "compat=1.1") 91 fi 92} 93 94_use_sample_img() 95{ 96 SAMPLE_IMG_FILE="${1%\.bz2}" 97 TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE" 98 bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG" 99 if [ $? -ne 0 ] 100 then 101 echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'" 102 exit 1 103 fi 104} 105 106_make_test_img() 107{ 108 # extra qemu-img options can be added by tests 109 # at least one argument (the image size) needs to be added 110 local extra_img_options="" 111 local image_size=$* 112 local optstr="" 113 local img_name="" 114 115 if [ -n "$TEST_IMG_FILE" ]; then 116 img_name=$TEST_IMG_FILE 117 else 118 img_name=$TEST_IMG 119 fi 120 121 if [ -n "$IMGOPTS" ]; then 122 optstr=$(_optstr_add "$optstr" "$IMGOPTS") 123 fi 124 125 if [ "$1" = "-b" ]; then 126 extra_img_options="$1 $2" 127 image_size=$3 128 fi 129 if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then 130 optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE") 131 fi 132 133 if [ -n "$optstr" ]; then 134 extra_img_options="-o $optstr $extra_img_options" 135 fi 136 137 # XXX(hch): have global image options? 138 $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size 2>&1 | \ 139 sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ 140 -e "s#$TEST_DIR#TEST_DIR#g" \ 141 -e "s#$IMGFMT#IMGFMT#g" \ 142 -e "s# encryption=off##g" \ 143 -e "s# cluster_size=[0-9]\\+##g" \ 144 -e "s# table_size=[0-9]\\+##g" \ 145 -e "s# compat='[^']*'##g" \ 146 -e "s# compat6=\\(on\\|off\\)##g" \ 147 -e "s# static=\\(on\\|off\\)##g" \ 148 -e "s# zeroed_grain=\\(on\\|off\\)##g" \ 149 -e "s# subformat='[^']*'##g" \ 150 -e "s# adapter_type='[^']*'##g" \ 151 -e "s# lazy_refcounts=\\(on\\|off\\)##g" 152 153 # Start an NBD server on the image file, which is what we'll be talking to 154 if [ $IMGPROTO = "nbd" ]; then 155 eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 $TEST_IMG_FILE &" 156 QEMU_NBD_PID=$! 157 sleep 1 # FIXME: qemu-nbd needs to be listening before we continue 158 fi 159} 160 161_cleanup_test_img() 162{ 163 case "$IMGPROTO" in 164 165 nbd) 166 kill $QEMU_NBD_PID 167 rm -f "$TEST_IMG_FILE" 168 ;; 169 file) 170 rm -f "$TEST_DIR/t.$IMGFMT" 171 rm -f "$TEST_DIR/t.$IMGFMT.orig" 172 rm -f "$TEST_DIR/t.$IMGFMT.base" 173 if [ -n "$SAMPLE_IMG_FILE" ] 174 then 175 rm -f "$TEST_DIR/$SAMPLE_IMG_FILE" 176 fi 177 ;; 178 179 rbd) 180 rbd rm "$TEST_DIR/t.$IMGFMT" > /dev/null 181 ;; 182 183 sheepdog) 184 collie vdi delete "$TEST_DIR/t.$IMGFMT" 185 ;; 186 187 esac 188} 189 190_check_test_img() 191{ 192 $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \ 193 sed -e '/allocated.*fragmented.*compressed clusters/d' \ 194 -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \ 195 -e '/Image end offset: [0-9]\+/d' 196} 197 198_img_info() 199{ 200 discard=0 201 regex_json_spec_start='^ *"format-specific": \{' 202 $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ 203 sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ 204 -e "s#$TEST_DIR#TEST_DIR#g" \ 205 -e "s#$IMGFMT#IMGFMT#g" \ 206 -e "/^disk size:/ D" \ 207 -e "/actual-size/ D" | \ 208 while IFS='' read line; do 209 if [[ $line == "Format specific information:" ]]; then 210 discard=1 211 elif [[ $line =~ $regex_json_spec_start ]]; then 212 discard=2 213 regex_json_spec_end="^${line%%[^ ]*}\\},? *$" 214 fi 215 if [[ $discard == 0 ]]; then 216 echo "$line" 217 elif [[ $discard == 1 && ! $line ]]; then 218 echo 219 discard=0 220 elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then 221 discard=0 222 fi 223 done 224} 225 226_get_pids_by_name() 227{ 228 if [ $# -ne 1 ] 229 then 230 echo "Usage: _get_pids_by_name process-name" 1>&2 231 exit 1 232 fi 233 234 # Algorithm ... all ps(1) variants have a time of the form MM:SS or 235 # HH:MM:SS before the psargs field, use this as the search anchor. 236 # 237 # Matches with $1 (process-name) occur if the first psarg is $1 238 # or ends in /$1 ... the matching uses sed's regular expressions, 239 # so passing a regex into $1 will work. 240 241 ps $PS_ALL_FLAGS \ 242 | sed -n \ 243 -e 's/$/ /' \ 244 -e 's/[ ][ ]*/ /g' \ 245 -e 's/^ //' \ 246 -e 's/^[^ ]* //' \ 247 -e "/[0-9]:[0-9][0-9] *[^ ]*\/$1 /s/ .*//p" \ 248 -e "/[0-9]:[0-9][0-9] *$1 /s/ .*//p" 249} 250 251# fqdn for localhost 252# 253_get_fqdn() 254{ 255 host=`hostname` 256 $NSLOOKUP_PROG $host | $AWK_PROG '{ if ($1 == "Name:") print $2 }' 257} 258 259# check if run as root 260# 261_need_to_be_root() 262{ 263 id=`id | $SED_PROG -e 's/(.*//' -e 's/.*=//'` 264 if [ "$id" -ne 0 ] 265 then 266 echo "Arrgh ... you need to be root (not uid=$id) to run this test" 267 exit 1 268 fi 269} 270 271 272# Do a command, log it to $seq.full, optionally test return status 273# and die if command fails. If called with one argument _do executes the 274# command, logs it, and returns its exit status. With two arguments _do 275# first prints the message passed in the first argument, and then "done" 276# or "fail" depending on the return status of the command passed in the 277# second argument. If the command fails and the variable _do_die_on_error 278# is set to "always" or the two argument form is used and _do_die_on_error 279# is set to "message_only" _do will print an error message to 280# $seq.out and exit. 281 282_do() 283{ 284 if [ $# -eq 1 ]; then 285 _cmd=$1 286 elif [ $# -eq 2 ]; then 287 _note=$1 288 _cmd=$2 289 echo -n "$_note... " 290 else 291 echo "Usage: _do [note] cmd" 1>&2 292 status=1; exit 293 fi 294 295 (eval "echo '---' \"$_cmd\"") >>$here/$seq.full 296 (eval "$_cmd") >$tmp._out 2>&1; ret=$? 297 cat $tmp._out >>$here/$seq.full 298 if [ $# -eq 2 ]; then 299 if [ $ret -eq 0 ]; then 300 echo "done" 301 else 302 echo "fail" 303 fi 304 fi 305 if [ $ret -ne 0 ] \ 306 && [ "$_do_die_on_error" = "always" \ 307 -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ] 308 then 309 [ $# -ne 2 ] && echo 310 eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full" 311 status=1; exit 312 fi 313 314 return $ret 315} 316 317# bail out, setting up .notrun file 318# 319_notrun() 320{ 321 echo "$*" >$seq.notrun 322 echo "$seq not run: $*" 323 status=0 324 exit 325} 326 327# just plain bail out 328# 329_fail() 330{ 331 echo "$*" | tee -a $here/$seq.full 332 echo "(see $seq.full for details)" 333 status=1 334 exit 1 335} 336 337# tests whether $IMGFMT is one of the supported image formats for a test 338# 339_supported_fmt() 340{ 341 for f; do 342 if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then 343 return 344 fi 345 done 346 347 _notrun "not suitable for this image format: $IMGFMT" 348} 349 350# tests whether $IMGPROTO is one of the supported image protocols for a test 351# 352_supported_proto() 353{ 354 for f; do 355 if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then 356 return 357 fi 358 done 359 360 _notrun "not suitable for this image protocol: $IMGPROTO" 361} 362 363# tests whether the host OS is one of the supported OSes for a test 364# 365_supported_os() 366{ 367 for h 368 do 369 if [ "$h" = "$HOSTOS" ] 370 then 371 return 372 fi 373 done 374 375 _notrun "not suitable for this OS: $HOSTOS" 376} 377 378_unsupported_qemu_io_options() 379{ 380 for bad_opt 381 do 382 for opt in $QEMU_IO_OPTIONS 383 do 384 if [ "$bad_opt" = "$opt" ] 385 then 386 _notrun "not suitable for qemu-io option: $bad_opt" 387 fi 388 done 389 done 390} 391 392# this test requires that a specified command (executable) exists 393# 394_require_command() 395{ 396 [ -x "$1" ] || _notrun "$1 utility required, skipped this test" 397} 398 399_full_imgfmt_details() 400{ 401 if [ -n "$IMGOPTS" ]; then 402 echo "$IMGFMT ($IMGOPTS)" 403 else 404 echo "$IMGFMT" 405 fi 406} 407 408_full_imgproto_details() 409{ 410 echo "$IMGPROTO" 411} 412 413_full_platform_details() 414{ 415 os=`uname -s` 416 host=`hostname -s` 417 kernel=`uname -r` 418 platform=`uname -m` 419 echo "$os/$platform $host $kernel" 420} 421 422_link_out_file() 423{ 424 if [ -z "$1" ]; then 425 echo Error must pass \$seq. 426 exit 427 fi 428 rm -f $1 429 if [ "`uname`" == "IRIX64" ] || [ "`uname`" == "IRIX" ]; then 430 ln -s $1.irix $1 431 elif [ "`uname`" == "Linux" ]; then 432 ln -s $1.linux $1 433 else 434 echo Error test $seq does not run on the operating system: `uname` 435 exit 436 fi 437} 438 439_die() 440{ 441 echo $@ 442 exit 1 443} 444 445# make sure this script returns success 446/bin/true 447