xref: /openbmc/qemu/tests/qemu-iotests/common.rc (revision 0b84b662)
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
410_img_info()
411{
412    if [[ "$1" == "--format-specific" ]]; then
413        local format_specific=1
414        shift
415    else
416        local format_specific=0
417    fi
418
419    discard=0
420    regex_json_spec_start='^ *"format-specific": \{'
421    $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
422        sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
423            -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
424            -e "s#$TEST_DIR#TEST_DIR#g" \
425            -e "s#$IMGFMT#IMGFMT#g" \
426            -e "/^disk size:/ D" \
427            -e "/actual-size/ D" | \
428        while IFS='' read -r line; do
429            if [[ $format_specific == 1 ]]; then
430                discard=0
431            elif [[ $line == "Format specific information:" ]]; then
432                discard=1
433            elif [[ $line =~ $regex_json_spec_start ]]; then
434                discard=2
435                regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
436            fi
437            if [[ $discard == 0 ]]; then
438                echo "$line"
439            elif [[ $discard == 1 && ! $line ]]; then
440                echo
441                discard=0
442            elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
443                discard=0
444            fi
445        done
446}
447
448# bail out, setting up .notrun file
449#
450_notrun()
451{
452    echo "$*" >"$OUTPUT_DIR/$seq.notrun"
453    echo "$seq not run: $*"
454    status=0
455    exit
456}
457
458# bail out, setting up .casenotrun file
459# The function _casenotrun() is used as a notifier. It is the
460# caller's responsibility to make skipped a particular test.
461#
462_casenotrun()
463{
464    echo "    [case not run] $*" >>"$OUTPUT_DIR/$seq.casenotrun"
465}
466
467# just plain bail out
468#
469_fail()
470{
471    echo "$*" | tee -a "$OUTPUT_DIR/$seq.full"
472    echo "(see $seq.full for details)"
473    status=1
474    exit 1
475}
476
477# tests whether $IMGFMT is one of the supported image formats for a test
478#
479_supported_fmt()
480{
481    # "generic" is suitable for most image formats. For some formats it doesn't
482    # work, however (most notably read-only formats), so they can opt out by
483    # setting IMGFMT_GENERIC to false.
484    for f; do
485        if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
486            return
487        fi
488    done
489
490    _notrun "not suitable for this image format: $IMGFMT"
491}
492
493# tests whether $IMGFMT is one of the unsupported image format for a test
494#
495_unsupported_fmt()
496{
497    for f; do
498        if [ "$f" = "$IMGFMT" ]; then
499            _notrun "not suitable for this image format: $IMGFMT"
500        fi
501    done
502}
503
504# tests whether $IMGPROTO is one of the supported image protocols for a test
505#
506_supported_proto()
507{
508    for f; do
509        if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then
510            return
511        fi
512    done
513
514    _notrun "not suitable for this image protocol: $IMGPROTO"
515}
516
517# tests whether $IMGPROTO is specified as an unsupported image protocol for a test
518#
519_unsupported_proto()
520{
521    for f; do
522        if [ "$f" = "$IMGPROTO" ]; then
523            _notrun "not suitable for this image protocol: $IMGPROTO"
524            return
525        fi
526    done
527}
528
529# tests whether the host OS is one of the supported OSes for a test
530#
531_supported_os()
532{
533    for h
534    do
535        if [ "$h" = "$HOSTOS" ]
536        then
537            return
538        fi
539    done
540
541    _notrun "not suitable for this OS: $HOSTOS"
542}
543
544_supported_cache_modes()
545{
546    for mode; do
547        if [ "$mode" = "$CACHEMODE" ]; then
548            return
549        fi
550    done
551    _notrun "not suitable for cache mode: $CACHEMODE"
552}
553
554_default_cache_mode()
555{
556    if $CACHEMODE_IS_DEFAULT; then
557        CACHEMODE="$1"
558        QEMU_IO="$QEMU_IO --cache $1"
559        return
560    fi
561}
562
563_unsupported_imgopts()
564{
565    for bad_opt
566    do
567        if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt"
568        then
569            _notrun "not suitable for image option: $bad_opt"
570        fi
571    done
572}
573
574# this test requires that a specified command (executable) exists
575#
576_require_command()
577{
578    if [ "$1" = "QEMU" ]; then
579        c=$QEMU_PROG
580    elif [ "$1" = "QEMU_IMG" ]; then
581        c=$QEMU_IMG_PROG
582    elif [ "$1" = "QEMU_IO" ]; then
583        c=$QEMU_IO_PROG
584    elif [ "$1" = "QEMU_NBD" ]; then
585        c=$QEMU_NBD_PROG
586    else
587        eval c=\$$1
588    fi
589    [ -x "$c" ] || _notrun "$1 utility required, skipped this test"
590}
591
592# Check that a set of drivers has been whitelisted in the QEMU binary
593#
594_require_drivers()
595{
596    available=$($QEMU -drive format=help | \
597                sed -e '/Supported formats:/!d' -e 's/Supported formats://')
598    for driver
599    do
600        if ! echo "$available" | grep -q " $driver\( \|$\)"; then
601            _notrun "$driver not available"
602        fi
603    done
604}
605
606# make sure this script returns success
607true
608