qemu/tests/qemu-iotests/081
<<
>>
Prefs
   1#!/usr/bin/env bash
   2# group: rw quick
   3#
   4# Test Quorum block driver
   5#
   6# Copyright (C) 2013 Nodalink, SARL.
   7#
   8# This program is free software; you can redistribute it and/or modify
   9# it under the terms of the GNU General Public License as published by
  10# the Free Software Foundation; either version 2 of the License, or
  11# (at your option) any later version.
  12#
  13# This program is distributed in the hope that it will be useful,
  14# but WITHOUT ANY WARRANTY; without even the implied warranty of
  15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16# GNU General Public License for more details.
  17#
  18# You should have received a copy of the GNU General Public License
  19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20#
  21
  22# creator
  23owner=benoit@irqsave.net
  24
  25seq=`basename $0`
  26echo "QA output created by $seq"
  27
  28status=1        # failure is the default!
  29
  30_cleanup()
  31{
  32    _rm_test_img "$TEST_DIR/1.raw"
  33    _rm_test_img "$TEST_DIR/2.raw"
  34    _rm_test_img "$TEST_DIR/3.raw"
  35}
  36trap "_cleanup; exit \$status" 0 1 2 3 15
  37
  38# get standard environment, filters and checks
  39. ./common.rc
  40. ./common.filter
  41
  42_supported_fmt raw
  43_supported_proto file
  44_supported_os Linux
  45_require_drivers quorum
  46_require_devices virtio-scsi
  47
  48do_run_qemu()
  49{
  50    echo Testing: "$@"
  51    $QEMU -nographic -qmp stdio -serial none "$@"
  52    echo
  53}
  54
  55run_qemu()
  56{
  57    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_imgfmt | _filter_qemu \
  58                          | _filter_qmp | _filter_qemu_io \
  59                          | _filter_generated_node_ids
  60}
  61
  62quorum="driver=raw,file.driver=quorum,file.vote-threshold=2"
  63quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
  64quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
  65quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
  66quorum="$quorum,file.children.0.driver=raw"
  67quorum="$quorum,file.children.1.driver=raw"
  68quorum="$quorum,file.children.2.driver=raw"
  69
  70echo
  71echo "== creating quorum files =="
  72
  73size=10M
  74
  75TEST_IMG="$TEST_DIR/1.raw" _make_test_img $size
  76TEST_IMG="$TEST_DIR/2.raw" _make_test_img $size
  77TEST_IMG="$TEST_DIR/3.raw" _make_test_img $size
  78
  79echo
  80echo "== writing images =="
  81
  82$QEMU_IO -c "open -o $quorum" -c "write -P 0x32 0 $size" | _filter_qemu_io
  83
  84echo
  85echo "== checking quorum write =="
  86
  87$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
  88$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
  89$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/3.raw" | _filter_qemu_io
  90
  91echo
  92echo "== corrupting image =="
  93
  94$QEMU_IO -c "write -P 0x42 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
  95
  96echo
  97echo "== checking quorum correction =="
  98
  99$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 100
 101echo
 102echo "== checking mixed reference/option specification =="
 103
 104run_qemu <<EOF
 105{ "execute": "qmp_capabilities" }
 106{ "execute": "blockdev-add",
 107    "arguments": {
 108        "node-name": "drive2",
 109        "driver": "$IMGFMT",
 110        "file": {
 111            "driver": "file",
 112            "filename": "$TEST_DIR/2.raw"
 113        }
 114    }
 115}
 116{ "execute": "blockdev-add",
 117    "arguments": {
 118        "driver": "quorum",
 119        "node-name": "drive0-quorum",
 120        "vote-threshold": 2,
 121        "children": [
 122            {
 123                "driver": "$IMGFMT",
 124                "file": {
 125                    "driver": "file",
 126                    "filename": "$TEST_DIR/1.raw"
 127                }
 128            },
 129            "drive2",
 130            {
 131                "driver": "$IMGFMT",
 132                "file": {
 133                    "driver": "file",
 134                    "filename": "$TEST_DIR/3.raw"
 135                }
 136            }
 137        ]
 138    }
 139}
 140{ "execute": "human-monitor-command",
 141    "arguments": {
 142        "command-line": 'qemu-io drive0-quorum "read -P 0x32 0 $size"'
 143    }
 144}
 145{ "execute": "quit" }
 146EOF
 147
 148echo
 149echo "== using quorum rewrite corrupted mode =="
 150
 151quorum="$quorum,file.rewrite-corrupted=on"
 152
 153$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 154
 155echo
 156echo "== checking that quorum has corrected the corrupted file =="
 157
 158$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
 159
 160echo
 161echo "== using quorum rewrite corrupted mode without WRITE permission =="
 162
 163# The same as above, but this time, do it on a quorum node whose only
 164# parent will not take the WRITE permission
 165
 166echo '-- corrupting --'
 167# Only corrupt a portion: The guest device (scsi-hd on virtio-scsi)
 168# will read some data (looking for a partition table to guess the
 169# disk's geometry), which would trigger a quorum mismatch if the
 170# beginning of the image was corrupted.  The subsequent
 171# QUORUM_REPORT_BAD event would be suppressed (because at that point,
 172# there cannot have been a qmp_capabilities on the monitor).  Because
 173# that event is rate-limited, the next QUORUM_REPORT_BAD that happens
 174# thanks to our qemu-io read (which should trigger a mismatch) would
 175# then be delayed past the VM quit and not appear in the output.
 176# So we keep the first 1M intact to see a QUORUM_REPORT_BAD resulting
 177# from the qemu-io invocation.
 178$QEMU_IO -c "write -P 0x42 1M 1M" "$TEST_DIR/2.raw" | _filter_qemu_io
 179
 180# Fix the corruption (on a read-only quorum node, i.e. without taking
 181# the WRITE permission on it -- its child nodes need to be R/W OTOH,
 182# so that rewrite-corrupted works)
 183echo
 184echo '-- running quorum --'
 185run_qemu \
 186    -blockdev file,node-name=file1,filename="$TEST_DIR/1.raw" \
 187    -blockdev file,node-name=file2,filename="$TEST_DIR/2.raw" \
 188    -blockdev file,node-name=file3,filename="$TEST_DIR/3.raw" \
 189    -blockdev '{
 190        "driver": "quorum",
 191        "node-name": "quorum",
 192        "read-only": true,
 193        "vote-threshold": 2,
 194        "rewrite-corrupted": true,
 195        "children": [ "file1", "file2", "file3" ]
 196    }' \
 197    -device virtio-scsi,id=scsi \
 198    -device scsi-hd,id=quorum-drive,bus=scsi.0,drive=quorum \
 199    <<EOF
 200{ "execute": "qmp_capabilities" }
 201{
 202    "execute": "human-monitor-command",
 203    "arguments": {
 204        "command-line": 'qemu-io -d quorum-drive "read -P 0x32 0 $size"'
 205    }
 206}
 207{ "execute": "quit" }
 208EOF
 209
 210echo '-- checking that the image has been corrected --'
 211$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
 212
 213echo
 214echo "== breaking quorum =="
 215
 216$QEMU_IO -c "write -P 0x41 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
 217$QEMU_IO -c "write -P 0x42 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
 218
 219echo
 220echo "== checking that quorum is broken =="
 221
 222$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 223
 224echo
 225echo "== checking the blkverify mode with broken content =="
 226
 227quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
 228quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
 229quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
 230quorum="$quorum,file.children.0.driver=raw"
 231quorum="$quorum,file.children.1.driver=raw"
 232
 233$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 234
 235echo
 236echo "== writing the same data to both files =="
 237
 238$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
 239$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
 240
 241echo
 242echo "== checking the blkverify mode with valid content =="
 243
 244$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
 245
 246echo
 247echo "== checking the blkverify mode with invalid settings =="
 248
 249quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
 250quorum="$quorum,file.children.2.driver=raw"
 251
 252$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
 253
 254echo
 255echo "== dynamically adding a child to a quorum =="
 256
 257for verify in false true; do
 258    run_qemu <<EOF
 259    { "execute": "qmp_capabilities" }
 260    { "execute": "blockdev-add",
 261        "arguments": {
 262            "driver": "quorum",
 263            "node-name": "drive0-quorum",
 264            "vote-threshold": 2,
 265            "blkverify": ${verify},
 266            "children": [
 267                {
 268                    "driver": "$IMGFMT",
 269                    "file": {
 270                        "driver": "file",
 271                        "filename": "$TEST_DIR/1.raw"
 272                    }
 273                },
 274                {
 275                    "driver": "$IMGFMT",
 276                    "file": {
 277                        "driver": "file",
 278                        "filename": "$TEST_DIR/2.raw"
 279                    }
 280                }
 281            ]
 282        }
 283    }
 284    { "execute": "blockdev-add",
 285        "arguments": {
 286            "node-name": "drive3",
 287            "driver": "$IMGFMT",
 288            "file": {
 289                "driver": "file",
 290                "filename": "$TEST_DIR/2.raw"
 291            }
 292        }
 293    }
 294    { "execute": "x-blockdev-change",
 295      "arguments": { "parent": "drive0-quorum",
 296                     "node": "drive3" } }
 297    { "execute": "quit" }
 298EOF
 299done
 300
 301echo
 302echo "== dynamically removing a child from a quorum =="
 303
 304for verify in false true; do
 305    for vote_threshold in 1 2; do
 306        run_qemu <<EOF
 307        { "execute": "qmp_capabilities" }
 308        { "execute": "blockdev-add",
 309            "arguments": {
 310                "driver": "quorum",
 311                "node-name": "drive0-quorum",
 312                "vote-threshold": ${vote_threshold},
 313                "blkverify": ${verify},
 314                "children": [
 315                    {
 316                        "driver": "$IMGFMT",
 317                        "file": {
 318                            "driver": "file",
 319                            "filename": "$TEST_DIR/1.raw"
 320                        }
 321                    },
 322                    {
 323                        "driver": "$IMGFMT",
 324                        "file": {
 325                            "driver": "file",
 326                            "filename": "$TEST_DIR/2.raw"
 327                        }
 328                    }
 329                ]
 330            }
 331        }
 332        { "execute": "x-blockdev-change",
 333          "arguments": { "parent": "drive0-quorum",
 334                         "child": "children.1" } }
 335        { "execute": "quit" }
 336EOF
 337    done
 338done
 339
 340# success, all done
 341echo "*** done"
 342rm -f $seq.full
 343status=0
 344