xref: /openbmc/qemu/tests/qemu-iotests/common.rc (revision e6e03dcf)
1#!/usr/bin/env 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
20SED=
21for sed in sed gsed; do
22    ($sed --version | grep 'GNU sed') > /dev/null 2>&1
23    if [ "$?" -eq 0 ]; then
24        SED=$sed
25        break
26    fi
27done
28if [ -z "$SED" ]; then
29    echo "$0: GNU sed not found"
30    exit 1
31fi
32
33dd()
34{
35   if [ "$HOSTOS" == "Linux" ]
36   then
37        command dd --help | grep noxfer > /dev/null 2>&1
38
39        if [ "$?" -eq 0 ]
40            then
41                command dd status=noxfer $@
42            else
43                command dd $@
44            fi
45   else
46        command dd $@
47   fi
48}
49
50# poke_file 'test.img' 512 '\xff\xfe'
51poke_file()
52{
53    printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null
54}
55
56
57if ! . ./common.config
58    then
59    echo "$0: failed to source common.config"
60    exit 1
61fi
62
63# Set the variables to the empty string to turn Valgrind off
64# for specific processes, e.g.
65# $ VALGRIND_QEMU_IO= ./check -qcow2 -valgrind 015
66
67: ${VALGRIND_QEMU_VM=$VALGRIND_QEMU}
68: ${VALGRIND_QEMU_IMG=$VALGRIND_QEMU}
69: ${VALGRIND_QEMU_IO=$VALGRIND_QEMU}
70: ${VALGRIND_QEMU_NBD=$VALGRIND_QEMU}
71: ${VALGRIND_QEMU_VXHS=$VALGRIND_QEMU}
72
73# The Valgrind own parameters may be set with
74# its environment variable VALGRIND_OPTS, e.g.
75# $ VALGRIND_OPTS="--leak-check=yes" ./check -qcow2 -valgrind 015
76
77_qemu_proc_exec()
78{
79    local VALGRIND_LOGFILE="$1"
80    shift
81    if [[ "${VALGRIND_QEMU}" == "y" && "${NO_VALGRIND}" != "y" ]]; then
82        exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$@"
83    else
84        exec "$@"
85    fi
86}
87
88_qemu_proc_valgrind_log()
89{
90    local VALGRIND_LOGFILE="$1"
91    local RETVAL="$2"
92    if [[ "${VALGRIND_QEMU}" == "y" && "${NO_VALGRIND}" != "y" ]]; then
93        if [ $RETVAL == 99 ]; then
94            cat "${VALGRIND_LOGFILE}"
95        fi
96        rm -f "${VALGRIND_LOGFILE}"
97    fi
98}
99
100_qemu_wrapper()
101{
102    local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
103    (
104        if [ -n "${QEMU_NEED_PID}" ]; then
105            echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"
106        fi
107        VALGRIND_QEMU="${VALGRIND_QEMU_VM}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
108            "$QEMU_PROG" $QEMU_OPTIONS "$@"
109    )
110    RETVAL=$?
111    _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
112    return $RETVAL
113}
114
115_qemu_img_wrapper()
116{
117    local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
118    (
119        VALGRIND_QEMU="${VALGRIND_QEMU_IMG}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
120            "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS "$@"
121    )
122    RETVAL=$?
123    _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
124    return $RETVAL
125}
126
127_qemu_io_wrapper()
128{
129    local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
130    local QEMU_IO_ARGS="$QEMU_IO_OPTIONS"
131    if [ "$IMGOPTSSYNTAX" = "true" ]; then
132        QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS"
133        if [ -n "$IMGKEYSECRET" ]; then
134            QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS"
135        fi
136    fi
137    (
138        VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
139            "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@"
140    )
141    RETVAL=$?
142    _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
143    return $RETVAL
144}
145
146_qemu_nbd_wrapper()
147{
148    local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
149    (
150        VALGRIND_QEMU="${VALGRIND_QEMU_NBD}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
151            "$QEMU_NBD_PROG" --pid-file="${QEMU_TEST_DIR}/qemu-nbd.pid" \
152             $QEMU_NBD_OPTIONS "$@"
153    )
154    RETVAL=$?
155    _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
156    return $RETVAL
157}
158
159_qemu_vxhs_wrapper()
160{
161    local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
162    (
163        echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
164        VALGRIND_QEMU="${VALGRIND_QEMU_VXHS}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
165            "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
166    )
167    RETVAL=$?
168    _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
169    return $RETVAL
170}
171
172# Valgrind bug #409141 https://bugs.kde.org/show_bug.cgi?id=409141
173# Until valgrind 3.16+ is ubiquitous, we must work around a hang in
174# valgrind when issuing sigkill. Disable valgrind for this invocation.
175_NO_VALGRIND()
176{
177    NO_VALGRIND="y" "$@"
178}
179
180export QEMU=_qemu_wrapper
181export QEMU_IMG=_qemu_img_wrapper
182export QEMU_IO=_qemu_io_wrapper
183export QEMU_NBD=_qemu_nbd_wrapper
184export QEMU_VXHS=_qemu_vxhs_wrapper
185
186if [ "$IMGOPTSSYNTAX" = "true" ]; then
187    DRIVER="driver=$IMGFMT"
188    QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS"
189    if [ -n "$IMGKEYSECRET" ]; then
190        QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS"
191    fi
192    if [ "$IMGFMT" = "luks" ]; then
193        DRIVER="$DRIVER,key-secret=keysec0"
194    fi
195    if [ "$IMGPROTO" = "file" ]; then
196        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
197        TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT"
198    elif [ "$IMGPROTO" = "nbd" ]; then
199        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
200        TEST_IMG="$DRIVER,file.driver=nbd,file.host=127.0.0.1,file.port=10810"
201    elif [ "$IMGPROTO" = "ssh" ]; then
202        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
203        TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE"
204    elif [ "$IMGPROTO" = "nfs" ]; then
205        TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR"
206        TEST_IMG=$TEST_DIR/t.$IMGFMT
207    else
208        TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT"
209    fi
210else
211    QEMU_IMG_EXTRA_ARGS=
212    if [ "$IMGPROTO" = "file" ]; then
213        TEST_IMG=$TEST_DIR/t.$IMGFMT
214    elif [ "$IMGPROTO" = "nbd" ]; then
215        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
216        TEST_IMG="nbd:127.0.0.1:10810"
217    elif [ "$IMGPROTO" = "ssh" ]; then
218        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
219        REMOTE_TEST_DIR="ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?$TEST_DIR"
220        TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
221    elif [ "$IMGPROTO" = "nfs" ]; then
222        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
223        REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR"
224        TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE"
225    elif [ "$IMGPROTO" = "vxhs" ]; then
226        TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
227        TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT"
228    else
229        TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
230    fi
231fi
232ORIG_TEST_IMG="$TEST_IMG"
233
234if [ -z "$TEST_DIR" ]; then
235        TEST_DIR=$PWD/scratch
236fi
237
238QEMU_TEST_DIR="${TEST_DIR}"
239
240if [ ! -e "$TEST_DIR" ]; then
241        mkdir "$TEST_DIR"
242fi
243
244if [ ! -d "$TEST_DIR" ]; then
245    echo "common.rc: Error: \$TEST_DIR ($TEST_DIR) is not a directory"
246    exit 1
247fi
248
249if [ -z "$REMOTE_TEST_DIR" ]; then
250    REMOTE_TEST_DIR="$TEST_DIR"
251fi
252
253if [ ! -d "$SAMPLE_IMG_DIR" ]; then
254    echo "common.rc: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory"
255    exit 1
256fi
257
258_use_sample_img()
259{
260    SAMPLE_IMG_FILE="${1%\.bz2}"
261    TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE"
262    bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG"
263    if [ $? -ne 0 ]
264    then
265        echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'"
266        exit 1
267    fi
268}
269
270_stop_nbd_server()
271{
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}
279
280_make_test_img()
281{
282    # extra qemu-img options can be added by tests
283    # at least one argument (the image size) needs to be added
284    local extra_img_options=""
285    local image_size=$*
286    local optstr=""
287    local img_name=""
288    local use_backing=0
289    local backing_file=""
290    local object_options=""
291
292    if [ -n "$TEST_IMG_FILE" ]; then
293        img_name=$TEST_IMG_FILE
294    else
295        img_name=$TEST_IMG
296    fi
297
298    if [ -n "$IMGOPTS" ]; then
299        optstr=$(_optstr_add "$optstr" "$IMGOPTS")
300    fi
301    if [ -n "$IMGKEYSECRET" ]; then
302        object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
303        optstr=$(_optstr_add "$optstr" "key-secret=keysec0")
304    fi
305
306    if [ "$1" = "-b" ]; then
307        use_backing=1
308        backing_file=$2
309        image_size=$3
310    fi
311    if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
312        optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE")
313    fi
314
315    if [ -n "$optstr" ]; then
316        extra_img_options="-o $optstr $extra_img_options"
317    fi
318
319    if [ $IMGPROTO = "nbd" ]; then
320        _stop_nbd_server
321    fi
322
323    # XXX(hch): have global image options?
324    (
325     if [ $use_backing = 1 ]; then
326        $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
327     else
328        $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
329     fi
330    ) | _filter_img_create
331
332    # Start an NBD server on the image file, which is what we'll be talking to
333    if [ $IMGPROTO = "nbd" ]; then
334        # Pass a sufficiently high number to -e that should be enough for all
335        # tests
336        eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT -e 42 -x '' $TEST_IMG_FILE >/dev/null &"
337        sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
338    fi
339
340    # Start QNIO server on image directory for vxhs protocol
341    if [ $IMGPROTO = "vxhs" ]; then
342        eval "$QEMU_VXHS -d  $TEST_DIR > /dev/null &"
343        sleep 1 # Wait for server to come up.
344    fi
345}
346
347_rm_test_img()
348{
349    local img=$1
350    if [ "$IMGFMT" = "vmdk" ]; then
351        # Remove all the extents for vmdk
352        "$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
353            | xargs -I {} rm -f "{}"
354    fi
355    rm -f "$img"
356}
357
358_cleanup_test_img()
359{
360    case "$IMGPROTO" in
361
362        nbd)
363            _stop_nbd_server
364            rm -f "$TEST_IMG_FILE"
365            ;;
366        vxhs)
367            if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
368                local QEMU_VXHS_PID
369                read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
370                kill ${QEMU_VXHS_PID} >/dev/null 2>&1
371                rm -f "${TEST_DIR}/qemu-vxhs.pid"
372            fi
373            rm -f "$TEST_IMG_FILE"
374            ;;
375
376        file)
377            _rm_test_img "$TEST_DIR/t.$IMGFMT"
378            _rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
379            _rm_test_img "$TEST_DIR/t.$IMGFMT.base"
380            if [ -n "$SAMPLE_IMG_FILE" ]
381            then
382                rm -f "$TEST_DIR/$SAMPLE_IMG_FILE"
383                SAMPLE_IMG_FILE=
384                TEST_IMG="$ORIG_TEST_IMG"
385            fi
386            ;;
387
388        rbd)
389            rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null
390            ;;
391
392        sheepdog)
393            collie vdi delete "$TEST_DIR/t.$IMGFMT"
394            ;;
395
396    esac
397}
398
399_check_test_img()
400{
401    (
402        if [ "$IMGOPTSSYNTAX" = "true" ]; then
403            $QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1
404        else
405            $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
406        fi
407    ) | _filter_testdir | _filter_qemu_img_check
408
409    # return real qemu_img check status, to analyze in
410    # _check_test_img_ignore_leaks
411    return ${PIPESTATUS[0]}
412}
413
414_check_test_img_ignore_leaks()
415{
416    out=$(_check_test_img "$@")
417    status=$?
418    if [ $status = 3 ]; then
419        # This must correspond to success output in dump_human_image_check()
420        echo "No errors were found on the image."
421        return 0
422    fi
423    echo "$out"
424    return $status
425}
426
427_img_info()
428{
429    if [[ "$1" == "--format-specific" ]]; then
430        local format_specific=1
431        shift
432    else
433        local format_specific=0
434    fi
435
436    discard=0
437    regex_json_spec_start='^ *"format-specific": \{'
438    $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
439        sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
440            -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
441            -e "s#$TEST_DIR#TEST_DIR#g" \
442            -e "s#$IMGFMT#IMGFMT#g" \
443            -e "/^disk size:/ D" \
444            -e "/actual-size/ D" | \
445        while IFS='' read -r line; do
446            if [[ $format_specific == 1 ]]; then
447                discard=0
448            elif [[ $line == "Format specific information:" ]]; then
449                discard=1
450            elif [[ $line =~ $regex_json_spec_start ]]; then
451                discard=2
452                regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
453            fi
454            if [[ $discard == 0 ]]; then
455                echo "$line"
456            elif [[ $discard == 1 && ! $line ]]; then
457                echo
458                discard=0
459            elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
460                discard=0
461            fi
462        done
463}
464
465# bail out, setting up .notrun file
466#
467_notrun()
468{
469    echo "$*" >"$OUTPUT_DIR/$seq.notrun"
470    echo "$seq not run: $*"
471    status=0
472    exit
473}
474
475# bail out, setting up .casenotrun file
476# The function _casenotrun() is used as a notifier. It is the
477# caller's responsibility to make skipped a particular test.
478#
479_casenotrun()
480{
481    echo "    [case not run] $*" >>"$OUTPUT_DIR/$seq.casenotrun"
482}
483
484# just plain bail out
485#
486_fail()
487{
488    echo "$*" | tee -a "$OUTPUT_DIR/$seq.full"
489    echo "(see $seq.full for details)"
490    status=1
491    exit 1
492}
493
494# tests whether $IMGFMT is one of the supported image formats for a test
495#
496_supported_fmt()
497{
498    # "generic" is suitable for most image formats. For some formats it doesn't
499    # work, however (most notably read-only formats), so they can opt out by
500    # setting IMGFMT_GENERIC to false.
501    for f; do
502        if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
503            return
504        fi
505    done
506
507    _notrun "not suitable for this image format: $IMGFMT"
508}
509
510# tests whether $IMGFMT is one of the unsupported image format for a test
511#
512_unsupported_fmt()
513{
514    for f; do
515        if [ "$f" = "$IMGFMT" ]; then
516            _notrun "not suitable for this image format: $IMGFMT"
517        fi
518    done
519}
520
521# tests whether $IMGPROTO is one of the supported image protocols for a test
522#
523_supported_proto()
524{
525    for f; do
526        if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then
527            return
528        fi
529    done
530
531    _notrun "not suitable for this image protocol: $IMGPROTO"
532}
533
534# tests whether $IMGPROTO is specified as an unsupported image protocol for a test
535#
536_unsupported_proto()
537{
538    for f; do
539        if [ "$f" = "$IMGPROTO" ]; then
540            _notrun "not suitable for this image protocol: $IMGPROTO"
541            return
542        fi
543    done
544}
545
546# tests whether the host OS is one of the supported OSes for a test
547#
548_supported_os()
549{
550    for h
551    do
552        if [ "$h" = "$HOSTOS" ]
553        then
554            return
555        fi
556    done
557
558    _notrun "not suitable for this OS: $HOSTOS"
559}
560
561_supported_cache_modes()
562{
563    for mode; do
564        if [ "$mode" = "$CACHEMODE" ]; then
565            return
566        fi
567    done
568    _notrun "not suitable for cache mode: $CACHEMODE"
569}
570
571_default_cache_mode()
572{
573    if $CACHEMODE_IS_DEFAULT; then
574        CACHEMODE="$1"
575        QEMU_IO="$QEMU_IO --cache $1"
576        return
577    fi
578}
579
580_unsupported_imgopts()
581{
582    for bad_opt
583    do
584        if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt"
585        then
586            _notrun "not suitable for image option: $bad_opt"
587        fi
588    done
589}
590
591# this test requires that a specified command (executable) exists
592#
593_require_command()
594{
595    if [ "$1" = "QEMU" ]; then
596        c=$QEMU_PROG
597    elif [ "$1" = "QEMU_IMG" ]; then
598        c=$QEMU_IMG_PROG
599    elif [ "$1" = "QEMU_IO" ]; then
600        c=$QEMU_IO_PROG
601    elif [ "$1" = "QEMU_NBD" ]; then
602        c=$QEMU_NBD_PROG
603    else
604        eval c=\$$1
605    fi
606    [ -x "$c" ] || _notrun "$1 utility required, skipped this test"
607}
608
609# Check that a set of drivers has been whitelisted in the QEMU binary
610#
611_require_drivers()
612{
613    available=$($QEMU -drive format=help | \
614                sed -e '/Supported formats:/!d' -e 's/Supported formats://')
615    for driver
616    do
617        if ! echo "$available" | grep -q " $driver\( \|$\)"; then
618            _notrun "$driver not available"
619        fi
620    done
621}
622
623# make sure this script returns success
624true
625