xref: /qemu/tests/qemu-iotests/085 (revision b83a80e8)
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
106create_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}
112
113# ${1}: unique identifier for the snapshot filename
114add_snapshot_image()
115{
116    snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
117    create_snapshot_image "$1"
118    do_blockdev_add "$1" "'backing': null, " "${snapshot_file}"
119}
120
121# ${1}: unique identifier for the snapshot filename
122# ${2}: expected response, defaults to 'return'
123blockdev_snapshot()
124{
125    cmd="{ 'execute': 'blockdev-snapshot',
126                      'arguments': { 'node': 'virtio0',
127                                     'overlay':'snap_${1}' } }"
128    _send_qemu_cmd $h "${cmd}" "${2:-return}"
129}
130
131size=128M
132
133TEST_IMG="$TEST_IMG.1" _make_test_img $size
134TEST_IMG="$TEST_IMG.2" _make_test_img $size
135
136echo
137echo === Running QEMU ===
138echo
139
140qemu_comm_method="qmp"
141_launch_qemu -drive file="${TEST_IMG}.1",if=virtio -drive file="${TEST_IMG}.2",if=virtio
142h=$QEMU_HANDLE
143
144echo
145echo === Sending capabilities ===
146echo
147
148_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
149
150# Tests for the blockdev-snapshot-sync command
151
152echo
153echo === Create a single snapshot on virtio0 ===
154echo
155
156create_single_snapshot 1
157
158
159echo
160echo === Invalid command - missing device and nodename ===
161echo
162
163_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
164                         'arguments': { 'snapshot-file':'${TEST_DIR}/1-${snapshot_virt0}',
165                                     'format': 'qcow2' } }" "error"
166
167echo
168echo === Invalid command - missing snapshot-file ===
169echo
170
171_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
172                         'arguments': { 'device': 'virtio0',
173                                     'format': 'qcow2' } }" "error"
174echo
175echo
176echo === Create several transactional group snapshots ===
177echo
178
179for i in $(seq 2 ${SNAPSHOTS})
180do
181    create_group_snapshot ${i}
182done
183
184# Tests for the blockdev-snapshot command
185
186echo
187echo === Create a couple of snapshots using blockdev-snapshot ===
188echo
189
190SNAPSHOTS=$((${SNAPSHOTS}+1))
191add_snapshot_image ${SNAPSHOTS}
192blockdev_snapshot ${SNAPSHOTS}
193
194SNAPSHOTS=$((${SNAPSHOTS}+1))
195add_snapshot_image ${SNAPSHOTS}
196blockdev_snapshot ${SNAPSHOTS}
197
198echo
199echo === Invalid command - cannot create a snapshot using a file BDS ===
200echo
201
202_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
203                     'arguments': { 'node':'virtio0',
204                                    'overlay':'file_${SNAPSHOTS}' }
205                   }" "error"
206
207echo
208echo === Invalid command - snapshot node used as active layer ===
209echo
210
211blockdev_snapshot ${SNAPSHOTS} error
212
213_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
214                     'arguments': { 'node':'virtio0',
215                                    'overlay':'virtio0' }
216                   }" "error"
217
218_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
219                     'arguments': { 'node':'virtio0',
220                                    'overlay':'virtio1' }
221                   }" "error"
222
223echo
224echo === Invalid command - snapshot node used as backing hd ===
225echo
226
227blockdev_snapshot $((${SNAPSHOTS}-1)) error
228
229echo
230echo === Invalid command - snapshot node has a backing image ===
231echo
232
233SNAPSHOTS=$((${SNAPSHOTS}+1))
234
235TEST_IMG="$TEST_IMG.base" _make_test_img "$size"
236_make_test_img -b "${TEST_IMG}.base" -F $IMGFMT "$size"
237do_blockdev_add ${SNAPSHOTS} "" "${TEST_IMG}"
238blockdev_snapshot ${SNAPSHOTS} error
239
240echo
241echo === Invalid command - creating loops ===
242echo
243
244SNAPSHOTS=$((${SNAPSHOTS}+1))
245add_snapshot_image ${SNAPSHOTS}
246
247_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
248                     'arguments': { 'node':'snap_${SNAPSHOTS}',
249                                    'overlay':'snap_${SNAPSHOTS}' }
250                   }" "error"
251
252SNAPSHOTS=$((${SNAPSHOTS}+1))
253create_snapshot_image ${SNAPSHOTS}
254do_blockdev_add ${SNAPSHOTS} "'backing': 'snap_$((${SNAPSHOTS}-1))', " \
255    "${TEST_DIR}/${SNAPSHOTS}-${snapshot_virt0}"
256
257_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
258                     'arguments': { 'node':'snap_${SNAPSHOTS}',
259                                    'overlay':'snap_$((${SNAPSHOTS}-1))' }
260                   }" "error"
261
262echo
263echo === Invalid command - The node does not exist ===
264echo
265
266blockdev_snapshot $((${SNAPSHOTS}+1)) error
267
268_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
269                     'arguments': { 'node':'nodevice',
270                                    'overlay':'snap_${SNAPSHOTS}' }
271                   }" "error"
272
273# success, all done
274echo "*** done"
275rm -f $seq.full
276status=0
277