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