1*4089f7c6SJeff Cody#!/bin/bash 2*4089f7c6SJeff Cody# 3*4089f7c6SJeff Cody# Live snapshot tests 4*4089f7c6SJeff Cody# 5*4089f7c6SJeff Cody# This tests live snapshots of images on a running QEMU instance, using 6*4089f7c6SJeff Cody# QMP commands. Both single disk snapshots, and transactional group 7*4089f7c6SJeff Cody# snapshots are performed. 8*4089f7c6SJeff Cody# 9*4089f7c6SJeff Cody# Copyright (C) 2014 Red Hat, Inc. 10*4089f7c6SJeff Cody# 11*4089f7c6SJeff Cody# This program is free software; you can redistribute it and/or modify 12*4089f7c6SJeff Cody# it under the terms of the GNU General Public License as published by 13*4089f7c6SJeff Cody# the Free Software Foundation; either version 2 of the License, or 14*4089f7c6SJeff Cody# (at your option) any later version. 15*4089f7c6SJeff Cody# 16*4089f7c6SJeff Cody# This program is distributed in the hope that it will be useful, 17*4089f7c6SJeff Cody# but WITHOUT ANY WARRANTY; without even the implied warranty of 18*4089f7c6SJeff Cody# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19*4089f7c6SJeff Cody# GNU General Public License for more details. 20*4089f7c6SJeff Cody# 21*4089f7c6SJeff Cody# You should have received a copy of the GNU General Public License 22*4089f7c6SJeff Cody# along with this program. If not, see <http://www.gnu.org/licenses/>. 23*4089f7c6SJeff Cody# 24*4089f7c6SJeff Cody 25*4089f7c6SJeff Cody# creator 26*4089f7c6SJeff Codyowner=jcody@redhat.com 27*4089f7c6SJeff Cody 28*4089f7c6SJeff Codyseq=`basename $0` 29*4089f7c6SJeff Codyecho "QA output created by $seq" 30*4089f7c6SJeff Cody 31*4089f7c6SJeff Codyhere=`pwd` 32*4089f7c6SJeff Codystatus=1 # failure is the default! 33*4089f7c6SJeff Codyqemu_pid= 34*4089f7c6SJeff Cody 35*4089f7c6SJeff CodyQMP_IN="${TEST_DIR}/qmp-in-$$" 36*4089f7c6SJeff CodyQMP_OUT="${TEST_DIR}/qmp-out-$$" 37*4089f7c6SJeff Cody 38*4089f7c6SJeff Codysnapshot_virt0="snapshot-v0.qcow2" 39*4089f7c6SJeff Codysnapshot_virt1="snapshot-v1.qcow2" 40*4089f7c6SJeff Cody 41*4089f7c6SJeff CodyMAX_SNAPSHOTS=10 42*4089f7c6SJeff Cody 43*4089f7c6SJeff Cody_cleanup() 44*4089f7c6SJeff Cody{ 45*4089f7c6SJeff Cody kill -KILL ${qemu_pid} 46*4089f7c6SJeff Cody wait ${qemu_pid} 2>/dev/null # silent kill 47*4089f7c6SJeff Cody 48*4089f7c6SJeff Cody rm -f "${QMP_IN}" "${QMP_OUT}" 49*4089f7c6SJeff Cody for i in $(seq 1 ${MAX_SNAPSHOTS}) 50*4089f7c6SJeff Cody do 51*4089f7c6SJeff Cody rm -f "${TEST_DIR}/${i}-${snapshot_virt0}" 52*4089f7c6SJeff Cody rm -f "${TEST_DIR}/${i}-${snapshot_virt1}" 53*4089f7c6SJeff Cody done 54*4089f7c6SJeff Cody _cleanup_test_img 55*4089f7c6SJeff Cody 56*4089f7c6SJeff Cody} 57*4089f7c6SJeff Codytrap "_cleanup; exit \$status" 0 1 2 3 15 58*4089f7c6SJeff Cody 59*4089f7c6SJeff Cody# get standard environment, filters and checks 60*4089f7c6SJeff Cody. ./common.rc 61*4089f7c6SJeff Cody. ./common.filter 62*4089f7c6SJeff Cody 63*4089f7c6SJeff Cody_supported_fmt qcow2 64*4089f7c6SJeff Cody_supported_proto file 65*4089f7c6SJeff Cody_supported_os Linux 66*4089f7c6SJeff Cody 67*4089f7c6SJeff Cody# Wait for expected QMP response from QEMU. Will time out 68*4089f7c6SJeff Cody# after 10 seconds, which counts as failure. 69*4089f7c6SJeff Cody# 70*4089f7c6SJeff Cody# $1 is the string to expect 71*4089f7c6SJeff Cody# 72*4089f7c6SJeff Cody# If $silent is set to anything but an empty string, then 73*4089f7c6SJeff Cody# response is not echoed out. 74*4089f7c6SJeff Codyfunction timed_wait_for() 75*4089f7c6SJeff Cody{ 76*4089f7c6SJeff Cody while read -t 10 resp <&5 77*4089f7c6SJeff Cody do 78*4089f7c6SJeff Cody if [ "${silent}" == "" ]; then 79*4089f7c6SJeff Cody echo "${resp}" | _filter_testdir | _filter_qemu 80*4089f7c6SJeff Cody fi 81*4089f7c6SJeff Cody grep -q "${1}" < <(echo ${resp}) 82*4089f7c6SJeff Cody if [ $? -eq 0 ]; then 83*4089f7c6SJeff Cody return 84*4089f7c6SJeff Cody fi 85*4089f7c6SJeff Cody done 86*4089f7c6SJeff Cody echo "Timeout waiting for ${1}" 87*4089f7c6SJeff Cody exit 1 # Timeout means the test failed 88*4089f7c6SJeff Cody} 89*4089f7c6SJeff Cody 90*4089f7c6SJeff Cody# Sends QMP command to QEMU, and waits for the expected response 91*4089f7c6SJeff Cody# 92*4089f7c6SJeff Cody# ${1}: String of the QMP command to send 93*4089f7c6SJeff Cody# ${2}: String that the QEMU response should contain 94*4089f7c6SJeff Codyfunction send_qmp_cmd() 95*4089f7c6SJeff Cody{ 96*4089f7c6SJeff Cody echo "${1}" >&6 97*4089f7c6SJeff Cody timed_wait_for "${2}" 98*4089f7c6SJeff Cody} 99*4089f7c6SJeff Cody 100*4089f7c6SJeff Cody# ${1}: unique identifier for the snapshot filename 101*4089f7c6SJeff Codyfunction create_single_snapshot() 102*4089f7c6SJeff Cody{ 103*4089f7c6SJeff Cody cmd="{ 'execute': 'blockdev-snapshot-sync', 104*4089f7c6SJeff Cody 'arguments': { 'device': 'virtio0', 105*4089f7c6SJeff Cody 'snapshot-file':'"${TEST_DIR}/${1}-${snapshot_virt0}"', 106*4089f7c6SJeff Cody 'format': 'qcow2' } }" 107*4089f7c6SJeff Cody send_qmp_cmd "${cmd}" "return" 108*4089f7c6SJeff Cody} 109*4089f7c6SJeff Cody 110*4089f7c6SJeff Cody# ${1}: unique identifier for the snapshot filename 111*4089f7c6SJeff Codyfunction create_group_snapshot() 112*4089f7c6SJeff Cody{ 113*4089f7c6SJeff Cody cmd="{ 'execute': 'transaction', 'arguments': 114*4089f7c6SJeff Cody {'actions': [ 115*4089f7c6SJeff Cody { 'type': 'blockdev-snapshot-sync', 'data' : 116*4089f7c6SJeff Cody { 'device': 'virtio0', 117*4089f7c6SJeff Cody 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt0}"' } }, 118*4089f7c6SJeff Cody { 'type': 'blockdev-snapshot-sync', 'data' : 119*4089f7c6SJeff Cody { 'device': 'virtio1', 120*4089f7c6SJeff Cody 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt1}"' } } ] 121*4089f7c6SJeff Cody } }" 122*4089f7c6SJeff Cody 123*4089f7c6SJeff Cody send_qmp_cmd "${cmd}" "return" 124*4089f7c6SJeff Cody} 125*4089f7c6SJeff Cody 126*4089f7c6SJeff Codysize=128M 127*4089f7c6SJeff Cody 128*4089f7c6SJeff Codymkfifo "${QMP_IN}" 129*4089f7c6SJeff Codymkfifo "${QMP_OUT}" 130*4089f7c6SJeff Cody 131*4089f7c6SJeff Cody_make_test_img $size 132*4089f7c6SJeff Codymv "${TEST_IMG}" "${TEST_IMG}.orig" 133*4089f7c6SJeff Cody_make_test_img $size 134*4089f7c6SJeff Cody 135*4089f7c6SJeff Codyecho 136*4089f7c6SJeff Codyecho === Running QEMU === 137*4089f7c6SJeff Codyecho 138*4089f7c6SJeff Cody 139*4089f7c6SJeff Cody"${QEMU}" -nographic -monitor none -serial none -qmp stdio\ 140*4089f7c6SJeff Cody -drive file="${TEST_IMG}.orig",if=virtio\ 141*4089f7c6SJeff Cody -drive file="${TEST_IMG}",if=virtio 2>&1 >"${QMP_OUT}" <"${QMP_IN}"& 142*4089f7c6SJeff Codyqemu_pid=$! 143*4089f7c6SJeff Cody 144*4089f7c6SJeff Cody# redirect fifos to file descriptors, to keep from blocking 145*4089f7c6SJeff Codyexec 5<"${QMP_OUT}" 146*4089f7c6SJeff Codyexec 6>"${QMP_IN}" 147*4089f7c6SJeff Cody 148*4089f7c6SJeff Cody# Don't print response, since it has version information in it 149*4089f7c6SJeff Codysilent=yes timed_wait_for "capabilities" 150*4089f7c6SJeff Cody 151*4089f7c6SJeff Codyecho 152*4089f7c6SJeff Codyecho === Sending capabilities === 153*4089f7c6SJeff Codyecho 154*4089f7c6SJeff Cody 155*4089f7c6SJeff Codysend_qmp_cmd "{ 'execute': 'qmp_capabilities' }" "return" 156*4089f7c6SJeff Cody 157*4089f7c6SJeff Codyecho 158*4089f7c6SJeff Codyecho === Create a single snapshot on virtio0 === 159*4089f7c6SJeff Codyecho 160*4089f7c6SJeff Cody 161*4089f7c6SJeff Codycreate_single_snapshot 1 162*4089f7c6SJeff Cody 163*4089f7c6SJeff Cody 164*4089f7c6SJeff Codyecho 165*4089f7c6SJeff Codyecho === Invalid command - missing device and nodename === 166*4089f7c6SJeff Codyecho 167*4089f7c6SJeff Cody 168*4089f7c6SJeff Codysend_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync', 169*4089f7c6SJeff Cody 'arguments': { 'snapshot-file':'"${TEST_DIR}"/1-${snapshot_virt0}', 170*4089f7c6SJeff Cody 'format': 'qcow2' } }" "error" 171*4089f7c6SJeff Cody 172*4089f7c6SJeff Codyecho 173*4089f7c6SJeff Codyecho === Invalid command - missing snapshot-file === 174*4089f7c6SJeff Codyecho 175*4089f7c6SJeff Cody 176*4089f7c6SJeff Codysend_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync', 177*4089f7c6SJeff Cody 'arguments': { 'device': 'virtio0', 178*4089f7c6SJeff Cody 'format': 'qcow2' } }" "error" 179*4089f7c6SJeff Codyecho 180*4089f7c6SJeff Codyecho 181*4089f7c6SJeff Codyecho === Create several transactional group snapshots === 182*4089f7c6SJeff Codyecho 183*4089f7c6SJeff Cody 184*4089f7c6SJeff Codyfor i in $(seq 2 ${MAX_SNAPSHOTS}) 185*4089f7c6SJeff Codydo 186*4089f7c6SJeff Cody create_group_snapshot ${i} 187*4089f7c6SJeff Codydone 188*4089f7c6SJeff Cody 189*4089f7c6SJeff Cody# success, all done 190*4089f7c6SJeff Codyecho "*** done" 191*4089f7c6SJeff Codyrm -f $seq.full 192*4089f7c6SJeff Codystatus=0 193