1#!/usr/bin/env 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# Copyright (C) 2015 Igalia, S.L. 11# 12# This program is free software; you can redistribute it and/or modify 13# it under the terms of the GNU General Public License as published by 14# the Free Software Foundation; either version 2 of the License, or 15# (at your option) any later version. 16# 17# This program is distributed in the hope that it will be useful, 18# but WITHOUT ANY WARRANTY; without even the implied warranty of 19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20# GNU General Public License for more details. 21# 22# You should have received a copy of the GNU General Public License 23# along with this program. If not, see <http://www.gnu.org/licenses/>. 24# 25 26# creator 27owner=jcody@redhat.com 28 29seq=`basename $0` 30echo "QA output created by $seq" 31 32status=1 # failure is the default! 33 34snapshot_virt0="snapshot-v0.qcow2" 35snapshot_virt1="snapshot-v1.qcow2" 36 37SNAPSHOTS=10 38 39_cleanup() 40{ 41 _cleanup_qemu 42 _cleanup_test_img 43 for i in $(seq 1 ${SNAPSHOTS}) 44 do 45 _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt0}" 46 _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt1}" 47 done 48 for img in "${TEST_IMG}".{1,2,base} 49 do 50 _rm_test_img "$img" 51 done 52 53} 54trap "_cleanup; exit \$status" 0 1 2 3 15 55 56# get standard environment, filters and checks 57. ./common.rc 58. ./common.filter 59. ./common.qemu 60 61_supported_fmt qcow2 62_supported_proto file 63 64 65# ${1}: unique identifier for the snapshot filename 66create_single_snapshot() 67{ 68 cmd="{ 'execute': 'blockdev-snapshot-sync', 69 'arguments': { 'device': 'virtio0', 70 'snapshot-file':'${TEST_DIR}/${1}-${snapshot_virt0}', 71 'format': 'qcow2' } }" 72 _send_qemu_cmd $h "${cmd}" "return" 73} 74 75# ${1}: unique identifier for the snapshot filename 76create_group_snapshot() 77{ 78 cmd="{ 'execute': 'transaction', 'arguments': 79 {'actions': [ 80 { 'type': 'blockdev-snapshot-sync', 'data' : 81 { 'device': 'virtio0', 82 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt0}' } }, 83 { 'type': 'blockdev-snapshot-sync', 'data' : 84 { 'device': 'virtio1', 85 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt1}' } } ] 86 } }" 87 88 _send_qemu_cmd $h "${cmd}" "return" 89} 90 91# ${1}: unique identifier for the snapshot filename 92# ${2}: extra_params to the blockdev-add command 93# ${3}: filename 94do_blockdev_add() 95{ 96 cmd="{ 'execute': 'blockdev-add', 'arguments': 97 { 'driver': 'qcow2', 'node-name': 'snap_${1}', ${2} 98 'file': 99 { 'driver': 'file', 'filename': '${3}', 100 'node-name': 'file_${1}' } } }" 101 _send_qemu_cmd $h "${cmd}" "return" 102} 103 104# ${1}: unique identifier for the snapshot filename 105add_snapshot_image() 106{ 107 base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}" 108 snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}" 109 TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" -F $IMGFMT "$size" 110 do_blockdev_add "$1" "'backing': null, " "${snapshot_file}" 111} 112 113# ${1}: unique identifier for the snapshot filename 114# ${2}: expected response, defaults to 'return' 115blockdev_snapshot() 116{ 117 cmd="{ 'execute': 'blockdev-snapshot', 118 'arguments': { 'node': 'virtio0', 119 'overlay':'snap_${1}' } }" 120 _send_qemu_cmd $h "${cmd}" "${2:-return}" 121} 122 123size=128M 124 125TEST_IMG="$TEST_IMG.1" _make_test_img $size 126TEST_IMG="$TEST_IMG.2" _make_test_img $size 127 128echo 129echo === Running QEMU === 130echo 131 132qemu_comm_method="qmp" 133_launch_qemu -drive file="${TEST_IMG}.1",if=virtio -drive file="${TEST_IMG}.2",if=virtio 134h=$QEMU_HANDLE 135 136echo 137echo === Sending capabilities === 138echo 139 140_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return" 141 142# Tests for the blockdev-snapshot-sync command 143 144echo 145echo === Create a single snapshot on virtio0 === 146echo 147 148create_single_snapshot 1 149 150 151echo 152echo === Invalid command - missing device and nodename === 153echo 154 155_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync', 156 'arguments': { 'snapshot-file':'${TEST_DIR}/1-${snapshot_virt0}', 157 'format': 'qcow2' } }" "error" 158 159echo 160echo === Invalid command - missing snapshot-file === 161echo 162 163_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync', 164 'arguments': { 'device': 'virtio0', 165 'format': 'qcow2' } }" "error" 166echo 167echo 168echo === Create several transactional group snapshots === 169echo 170 171for i in $(seq 2 ${SNAPSHOTS}) 172do 173 create_group_snapshot ${i} 174done 175 176# Tests for the blockdev-snapshot command 177 178echo 179echo === Create a couple of snapshots using blockdev-snapshot === 180echo 181 182SNAPSHOTS=$((${SNAPSHOTS}+1)) 183add_snapshot_image ${SNAPSHOTS} 184blockdev_snapshot ${SNAPSHOTS} 185 186SNAPSHOTS=$((${SNAPSHOTS}+1)) 187add_snapshot_image ${SNAPSHOTS} 188blockdev_snapshot ${SNAPSHOTS} 189 190echo 191echo === Invalid command - cannot create a snapshot using a file BDS === 192echo 193 194_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 195 'arguments': { 'node':'virtio0', 196 'overlay':'file_${SNAPSHOTS}' } 197 }" "error" 198 199echo 200echo === Invalid command - snapshot node used as active layer === 201echo 202 203blockdev_snapshot ${SNAPSHOTS} error 204 205_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 206 'arguments': { 'node':'virtio0', 207 'overlay':'virtio0' } 208 }" "error" 209 210_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 211 'arguments': { 'node':'virtio0', 212 'overlay':'virtio1' } 213 }" "error" 214 215echo 216echo === Invalid command - snapshot node used as backing hd === 217echo 218 219blockdev_snapshot $((${SNAPSHOTS}-1)) error 220 221echo 222echo === Invalid command - snapshot node has a backing image === 223echo 224 225SNAPSHOTS=$((${SNAPSHOTS}+1)) 226 227TEST_IMG="$TEST_IMG.base" _make_test_img "$size" 228_make_test_img -b "${TEST_IMG}.base" -F $IMGFMT "$size" 229do_blockdev_add ${SNAPSHOTS} "" "${TEST_IMG}" 230blockdev_snapshot ${SNAPSHOTS} error 231 232echo 233echo === Invalid command - The node does not exist === 234echo 235 236blockdev_snapshot $((${SNAPSHOTS}+1)) error 237 238_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 239 'arguments': { 'node':'nodevice', 240 'overlay':'snap_${SNAPSHOTS}' } 241 }" "error" 242 243# success, all done 244echo "*** done" 245rm -f $seq.full 246status=0 247