]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/qemu-iotests/057
4 # Tests for internal snapshot.
6 # Copyright (C) 2013 IBM, Inc.
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, see <http://www.gnu.org/licenses/>.
27 from iotests
import qemu_img
, qemu_io
29 test_drv_base_name
= 'drive'
31 class ImageSnapshotTestCase(iotests
.QMPTestCase
):
32 image_len
= 120 * 1024 * 1024 # MB
34 def __init__(self
, *args
):
36 super(ImageSnapshotTestCase
, self
).__init
__(*args
)
38 def _setUp(self
, test_img_base_name
, image_num
):
39 self
.vm
= iotests
.VM()
40 for i
in range(0, image_num
):
41 filename
= '%s%d' % (test_img_base_name
, i
)
42 img
= os
.path
.join(iotests
.test_dir
, filename
)
43 device
= '%s%d' % (test_drv_base_name
, i
)
44 qemu_img('create', '-f', iotests
.imgfmt
, img
, str(self
.image_len
))
45 self
.vm
.add_drive(img
)
46 self
.expect
.append({'image': img
, 'device': device
,
48 'snapshots_name_counter': 0})
53 for dev_expect
in self
.expect
:
54 os
.remove(dev_expect
['image'])
56 def createSnapshotInTransaction(self
, snapshot_num
, abort
= False):
58 for dev_expect
in self
.expect
:
59 num
= dev_expect
['snapshots_name_counter']
60 for j
in range(0, snapshot_num
):
61 name
= '%s_sn%d' % (dev_expect
['device'], num
)
64 dev_expect
['snapshots'].append({'name': name
})
65 dev_expect
['snapshots_name_counter'] = num
67 'type': 'blockdev-snapshot-internal-sync',
68 'data': { 'device': dev_expect
['device'],
78 result
= self
.vm
.qmp('transaction', actions
= actions
)
81 self
.assert_qmp(result
, 'error/class', 'GenericError')
83 self
.assert_qmp(result
, 'return', {})
85 def verifySnapshotInfo(self
):
86 result
= self
.vm
.qmp('query-block')
88 # Verify each expected result
89 for dev_expect
in self
.expect
:
90 # 1. Find the returned image value and snapshot info
92 for device
in result
['return']:
93 if device
['device'] == dev_expect
['device']:
94 image_result
= device
['inserted']['image']
96 self
.assertTrue(image_result
!= None)
97 # Do not consider zero snapshot case now
98 sn_list_result
= image_result
['snapshots']
99 sn_list_expect
= dev_expect
['snapshots']
101 # 2. Verify it with expect
102 self
.assertTrue(len(sn_list_result
) == len(sn_list_expect
))
104 for sn_expect
in sn_list_expect
:
106 for sn
in sn_list_result
:
107 if sn_expect
['name'] == sn
['name']:
110 self
.assertTrue(sn_result
!= None)
111 # Fill in the detail info
112 sn_expect
.update(sn_result
)
114 def deleteSnapshot(self
, device
, id = None, name
= None):
115 sn_list_expect
= None
118 self
.assertTrue(id != None or name
!= None)
120 # Fill in the detail info include ID
121 self
.verifySnapshotInfo()
123 #find the expected snapshot list
124 for dev_expect
in self
.expect
:
125 if dev_expect
['device'] == device
:
126 sn_list_expect
= dev_expect
['snapshots']
128 self
.assertTrue(sn_list_expect
!= None)
130 if id != None and name
!= None:
131 for sn
in sn_list_expect
:
132 if sn
['id'] == id and sn
['name'] == name
:
135 self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
141 for sn
in sn_list_expect
:
145 self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
150 for sn
in sn_list_expect
:
151 if sn
['name'] == name
:
154 self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
159 self
.assertTrue(sn_expect
!= None)
161 self
.assert_qmp(result
, 'return', sn_expect
)
162 sn_list_expect
.remove(sn_expect
)
164 class TestSingleTransaction(ImageSnapshotTestCase
):
166 self
._setUp
('test_a.img', 1)
168 def test_create(self
):
169 self
.createSnapshotInTransaction(1)
170 self
.verifySnapshotInfo()
172 def test_error_name_empty(self
):
173 actions
= [{'type': 'blockdev-snapshot-internal-sync',
174 'data': { 'device': self
.expect
[0]['device'],
177 result
= self
.vm
.qmp('transaction', actions
= actions
)
178 self
.assert_qmp(result
, 'error/class', 'GenericError')
180 def test_error_device(self
):
181 actions
= [{'type': 'blockdev-snapshot-internal-sync',
182 'data': { 'device': 'drive_error',
185 result
= self
.vm
.qmp('transaction', actions
= actions
)
186 self
.assert_qmp(result
, 'error/class', 'GenericError')
188 def test_error_exist(self
):
189 self
.createSnapshotInTransaction(1)
190 self
.verifySnapshotInfo()
191 actions
= [{'type': 'blockdev-snapshot-internal-sync',
192 'data': { 'device': self
.expect
[0]['device'],
193 'name': self
.expect
[0]['snapshots'][0] },
195 result
= self
.vm
.qmp('transaction', actions
= actions
)
196 self
.assert_qmp(result
, 'error/class', 'GenericError')
198 class TestMultipleTransaction(ImageSnapshotTestCase
):
200 self
._setUp
('test_b.img', 2)
202 def test_create(self
):
203 self
.createSnapshotInTransaction(3)
204 self
.verifySnapshotInfo()
206 def test_abort(self
):
207 self
.createSnapshotInTransaction(2)
208 self
.verifySnapshotInfo()
209 self
.createSnapshotInTransaction(3, abort
= True)
210 self
.verifySnapshotInfo()
212 class TestSnapshotDelete(ImageSnapshotTestCase
):
214 self
._setUp
('test_c.img', 1)
216 def test_delete_with_id(self
):
217 self
.createSnapshotInTransaction(2)
218 self
.verifySnapshotInfo()
219 self
.deleteSnapshot(self
.expect
[0]['device'],
220 id = self
.expect
[0]['snapshots'][0]['id'])
221 self
.verifySnapshotInfo()
223 def test_delete_with_name(self
):
224 self
.createSnapshotInTransaction(3)
225 self
.verifySnapshotInfo()
226 self
.deleteSnapshot(self
.expect
[0]['device'],
227 name
= self
.expect
[0]['snapshots'][1]['name'])
228 self
.verifySnapshotInfo()
230 def test_delete_with_id_and_name(self
):
231 self
.createSnapshotInTransaction(4)
232 self
.verifySnapshotInfo()
233 self
.deleteSnapshot(self
.expect
[0]['device'],
234 id = self
.expect
[0]['snapshots'][2]['id'],
235 name
= self
.expect
[0]['snapshots'][2]['name'])
236 self
.verifySnapshotInfo()
239 def test_error_device(self
):
240 result
= self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
241 device
= 'drive_error',
243 self
.assert_qmp(result
, 'error/class', 'GenericError')
245 def test_error_no_id_and_name(self
):
246 result
= self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
247 device
= self
.expect
[0]['device'])
248 self
.assert_qmp(result
, 'error/class', 'GenericError')
250 def test_error_snapshot_not_exist(self
):
251 self
.createSnapshotInTransaction(2)
252 self
.verifySnapshotInfo()
253 result
= self
.vm
.qmp('blockdev-snapshot-delete-internal-sync',
254 device
= self
.expect
[0]['device'],
255 id = self
.expect
[0]['snapshots'][0]['id'],
256 name
= self
.expect
[0]['snapshots'][1]['name'])
257 self
.assert_qmp(result
, 'error/class', 'GenericError')
259 if __name__
== '__main__':
260 iotests
.main(supported_fmts
=['qcow2'],
261 supported_protocols
=['file'])