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 for i in $(seq 1 ${SNAPSHOTS}) 43 do 44 _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt0}" 45 _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt1}" 46 done 47 for img in "${TEST_IMG}".{1,2,base} 48 do 49 _rm_test_img "$img" 50 done 51 52} 53trap "_cleanup; exit \$status" 0 1 2 3 15 54 55# get standard environment, filters and checks 56. ./common.rc 57. ./common.filter 58. ./common.qemu 59 60_supported_fmt qcow2 61_supported_proto file 62 63 64# ${1}: unique identifier for the snapshot filename 65create_single_snapshot() 66{ 67 cmd="{ 'execute': 'blockdev-snapshot-sync', 68 'arguments': { 'device': 'virtio0', 69 'snapshot-file':'${TEST_DIR}/${1}-${snapshot_virt0}', 70 'format': 'qcow2' } }" 71 _send_qemu_cmd $h "${cmd}" "return" 72} 73 74# ${1}: unique identifier for the snapshot filename 75create_group_snapshot() 76{ 77 cmd="{ 'execute': 'transaction', 'arguments': 78 {'actions': [ 79 { 'type': 'blockdev-snapshot-sync', 'data' : 80 { 'device': 'virtio0', 81 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt0}' } }, 82 { 'type': 'blockdev-snapshot-sync', 'data' : 83 { 'device': 'virtio1', 84 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt1}' } } ] 85 } }" 86 87 _send_qemu_cmd $h "${cmd}" "return" 88} 89 90# ${1}: unique identifier for the snapshot filename 91# ${2}: extra_params to the blockdev-add command 92# ${3}: filename 93do_blockdev_add() 94{ 95 cmd="{ 'execute': 'blockdev-add', 'arguments': 96 { 'driver': 'qcow2', 'node-name': 'snap_${1}', ${2} 97 'file': 98 { 'driver': 'file', 'filename': '${3}', 99 'node-name': 'file_${1}' } } }" 100 _send_qemu_cmd $h "${cmd}" "return" 101} 102 103# ${1}: unique identifier for the snapshot filename 104add_snapshot_image() 105{ 106 base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}" 107 snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}" 108 _make_test_img -u -b "${base_image}" "$size" 109 mv "${TEST_IMG}" "${snapshot_file}" 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 125_make_test_img $size 126mv "${TEST_IMG}" "${TEST_IMG}.1" 127_make_test_img $size 128mv "${TEST_IMG}" "${TEST_IMG}.2" 129 130echo 131echo === Running QEMU === 132echo 133 134qemu_comm_method="qmp" 135_launch_qemu -drive file="${TEST_IMG}.1",if=virtio -drive file="${TEST_IMG}.2",if=virtio 136h=$QEMU_HANDLE 137 138echo 139echo === Sending capabilities === 140echo 141 142_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return" 143 144# Tests for the blockdev-snapshot-sync command 145 146echo 147echo === Create a single snapshot on virtio0 === 148echo 149 150create_single_snapshot 1 151 152 153echo 154echo === Invalid command - missing device and nodename === 155echo 156 157_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync', 158 'arguments': { 'snapshot-file':'${TEST_DIR}/1-${snapshot_virt0}', 159 'format': 'qcow2' } }" "error" 160 161echo 162echo === Invalid command - missing snapshot-file === 163echo 164 165_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync', 166 'arguments': { 'device': 'virtio0', 167 'format': 'qcow2' } }" "error" 168echo 169echo 170echo === Create several transactional group snapshots === 171echo 172 173for i in $(seq 2 ${SNAPSHOTS}) 174do 175 create_group_snapshot ${i} 176done 177 178# Tests for the blockdev-snapshot command 179 180echo 181echo === Create a couple of snapshots using blockdev-snapshot === 182echo 183 184SNAPSHOTS=$((${SNAPSHOTS}+1)) 185add_snapshot_image ${SNAPSHOTS} 186blockdev_snapshot ${SNAPSHOTS} 187 188SNAPSHOTS=$((${SNAPSHOTS}+1)) 189add_snapshot_image ${SNAPSHOTS} 190blockdev_snapshot ${SNAPSHOTS} 191 192echo 193echo === Invalid command - cannot create a snapshot using a file BDS === 194echo 195 196_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 197 'arguments': { 'node':'virtio0', 198 'overlay':'file_${SNAPSHOTS}' } 199 }" "error" 200 201echo 202echo === Invalid command - snapshot node used as active layer === 203echo 204 205blockdev_snapshot ${SNAPSHOTS} error 206 207_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 208 'arguments': { 'node':'virtio0', 209 'overlay':'virtio0' } 210 }" "error" 211 212_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 213 'arguments': { 'node':'virtio0', 214 'overlay':'virtio1' } 215 }" "error" 216 217echo 218echo === Invalid command - snapshot node used as backing hd === 219echo 220 221blockdev_snapshot $((${SNAPSHOTS}-1)) error 222 223echo 224echo === Invalid command - snapshot node has a backing image === 225echo 226 227SNAPSHOTS=$((${SNAPSHOTS}+1)) 228 229TEST_IMG="$TEST_IMG.base" _make_test_img "$size" 230_make_test_img -b "${TEST_IMG}.base" "$size" 231do_blockdev_add ${SNAPSHOTS} "" "${TEST_IMG}" 232blockdev_snapshot ${SNAPSHOTS} error 233 234echo 235echo === Invalid command - The node does not exist === 236echo 237 238blockdev_snapshot $((${SNAPSHOTS}+1)) error 239 240_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot', 241 'arguments': { 'node':'nodevice', 242 'overlay':'snap_${SNAPSHOTS}' } 243 }" "error" 244 245# success, all done 246echo "*** done" 247rm -f $seq.full 248status=0 249