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