1#!/usr/bin/env bash 2# 3# Test exiting qemu while jobs are still running 4# 5# Copyright (C) 2017 Red Hat, Inc. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20 21# creator 22owner=kwolf@redhat.com 23 24seq=`basename $0` 25echo "QA output created by $seq" 26 27status=1 # failure is the default! 28 29_cleanup() 30{ 31 rm -f "${TEST_IMG}.mid" 32 rm -f "${TEST_IMG}.copy" 33 _cleanup_test_img 34 _cleanup_qemu 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. ./common.qemu 42 43_supported_fmt qcow2 44_supported_proto file 45_supported_os Linux 46 47size=64M 48TEST_IMG="${TEST_IMG}.base" _make_test_img $size 49 50echo 51echo === Starting VM === 52echo 53 54qemu_comm_method="qmp" 55 56_launch_qemu \ 57 -drive file="${TEST_IMG}.base",cache=$CACHEMODE,driver=$IMGFMT,id=disk 58h=$QEMU_HANDLE 59_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 60 61echo 62echo === Creating backing chain === 63echo 64 65_send_qemu_cmd $h \ 66 "{ 'execute': 'blockdev-snapshot-sync', 67 'arguments': { 'device': 'disk', 68 'snapshot-file': '$TEST_IMG.mid', 69 'format': '$IMGFMT', 70 'mode': 'absolute-paths' } }" \ 71 "return" 72 73_send_qemu_cmd $h \ 74 "{ 'execute': 'human-monitor-command', 75 'arguments': { 'command-line': 76 'qemu-io disk \"write 0 4M\"' } }" \ 77 "return" 78 79_send_qemu_cmd $h \ 80 "{ 'execute': 'blockdev-snapshot-sync', 81 'arguments': { 'device': 'disk', 82 'snapshot-file': '$TEST_IMG', 83 'format': '$IMGFMT', 84 'mode': 'absolute-paths' } }" \ 85 "return" 86 87echo 88echo === Start commit job and exit qemu === 89echo 90 91# Note that the reference output intentionally includes the 'offset' field in 92# BLOCK_JOB_* events for all of the following block jobs. They are predictable 93# and any change in the offsets would hint at a bug in the job throttling code. 94# 95# In order to achieve these predictable offsets, all of the following tests 96# use speed=65536. Each job will perform exactly one iteration before it has 97# to sleep at least for a second, which is plenty of time for the 'quit' QMP 98# command to be received (after receiving the command, the rest runs 99# synchronously, so jobs can arbitrarily continue or complete). 100# 101# The buffer size for commit and streaming is 512k (waiting for 8 seconds after 102# the first request), for active commit and mirror it's large enough to cover 103# the full 4M, and for backup it's the qcow2 cluster size, which we know is 104# 64k. As all of these are at least as large as the speed, we are sure that the 105# offset advances exactly once before qemu exits. 106 107_send_qemu_cmd $h \ 108 "{ 'execute': 'block-commit', 109 'arguments': { 'device': 'disk', 110 'base':'$TEST_IMG.base', 111 'top': '$TEST_IMG.mid', 112 'speed': 65536 } }" \ 113 "return" 114 115# If we don't sleep here 'quit' command races with disk I/O 116sleep 0.5 117 118# Ignore the JOB_STATUS_CHANGE events while shutting down the VM. Depending on 119# the timing, jobs may or may not transition through a paused state. 120_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 121wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 122 123echo 124echo === Start active commit job and exit qemu === 125echo 126 127_launch_qemu \ 128 -drive file="${TEST_IMG}",cache=$CACHEMODE,driver=$IMGFMT,id=disk 129h=$QEMU_HANDLE 130_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 131 132_send_qemu_cmd $h \ 133 "{ 'execute': 'block-commit', 134 'arguments': { 'device': 'disk', 135 'base':'$TEST_IMG.base', 136 'speed': 65536 } }" \ 137 "return" 138 139# If we don't sleep here 'quit' command races with disk I/O 140sleep 0.5 141 142_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 143wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 144 145echo 146echo === Start mirror job and exit qemu === 147echo 148 149_launch_qemu \ 150 -drive file="${TEST_IMG}",cache=$CACHEMODE,driver=$IMGFMT,id=disk 151h=$QEMU_HANDLE 152_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 153 154_send_qemu_cmd $h \ 155 "{ 'execute': 'drive-mirror', 156 'arguments': { 'device': 'disk', 157 'target': '$TEST_IMG.copy', 158 'format': '$IMGFMT', 159 'sync': 'full', 160 'speed': 65536 } }" \ 161 "return" 162 163# If we don't sleep here 'quit' command may be handled before 164# the first mirror iteration is done 165sleep 0.5 166 167_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 168wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 169 170echo 171echo === Start backup job and exit qemu === 172echo 173 174_launch_qemu \ 175 -drive file="${TEST_IMG}",cache=$CACHEMODE,driver=$IMGFMT,id=disk 176h=$QEMU_HANDLE 177_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 178 179_send_qemu_cmd $h \ 180 "{ 'execute': 'drive-backup', 181 'arguments': { 'device': 'disk', 182 'target': '$TEST_IMG.copy', 183 'format': '$IMGFMT', 184 'sync': 'full', 185 'speed': 65536 } }" \ 186 "return" 187 188# If we don't sleep here 'quit' command races with disk I/O 189sleep 0.5 190 191_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 192wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 193 194echo 195echo === Start streaming job and exit qemu === 196echo 197 198_launch_qemu \ 199 -drive file="${TEST_IMG}",cache=$CACHEMODE,driver=$IMGFMT,id=disk 200h=$QEMU_HANDLE 201_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 202 203_send_qemu_cmd $h \ 204 "{ 'execute': 'block-stream', 205 'arguments': { 'device': 'disk', 206 'speed': 65536 } }" \ 207 "return" 208 209# If we don't sleep here 'quit' command races with disk I/O 210sleep 0.5 211 212_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 213wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 214 215_check_test_img 216 217# success, all done 218echo "*** done" 219rm -f $seq.full 220status=0 221