]>
Commit | Line | Data |
---|---|---|
903cb1bf | 1 | #!/usr/bin/env python3 |
e5ca8fdd | 2 | # |
7c6a4ab8 | 3 | # Tests for drive-backup and blockdev-backup |
e5ca8fdd | 4 | # |
7c6a4ab8 | 5 | # Copyright (C) 2013, 2014 Red Hat, Inc. |
e5ca8fdd SH |
6 | # |
7 | # Based on 041. | |
8 | # | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 2 of the License, or | |
12 | # (at your option) any later version. | |
13 | # | |
14 | # This program is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | # | |
22 | ||
23 | import time | |
24 | import os | |
25 | import iotests | |
26 | from iotests import qemu_img, qemu_io | |
27 | ||
28 | test_img = os.path.join(iotests.test_dir, 'test.img') | |
29 | target_img = os.path.join(iotests.test_dir, 'target.img') | |
7c6a4ab8 | 30 | blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img') |
e5ca8fdd | 31 | |
819cec01 VSO |
32 | image_len = 64 * 1024 * 1024 # MB |
33 | ||
34 | def setUpModule(): | |
35 | qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len)) | |
36 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img) | |
37 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img) | |
38 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img) | |
39 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) | |
40 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) | |
41 | qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img) | |
e5ca8fdd | 42 | |
819cec01 VSO |
43 | def tearDownModule(): |
44 | os.remove(test_img) | |
45 | ||
46 | ||
47 | class TestSingleDrive(iotests.QMPTestCase): | |
e5ca8fdd | 48 | def setUp(self): |
819cec01 | 49 | qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) |
e5ca8fdd | 50 | |
0a82a927 KW |
51 | self.vm = iotests.VM() |
52 | self.vm.add_drive('blkdebug::' + test_img, 'node-name=source') | |
53 | self.vm.add_drive(blockdev_target_img, 'node-name=target', | |
54 | interface="none") | |
0ed82f7a HR |
55 | if iotests.qemu_default_machine == 'pc': |
56 | self.vm.add_drive(None, 'media=cdrom', 'ide') | |
e5ca8fdd SH |
57 | self.vm.launch() |
58 | ||
59 | def tearDown(self): | |
60 | self.vm.shutdown() | |
7c6a4ab8 | 61 | os.remove(blockdev_target_img) |
e5ca8fdd SH |
62 | try: |
63 | os.remove(target_img) | |
64 | except OSError: | |
65 | pass | |
66 | ||
7c6a4ab8 | 67 | def do_test_cancel(self, cmd, target): |
e5ca8fdd SH |
68 | self.assert_no_active_block_jobs() |
69 | ||
bc11aee2 | 70 | self.vm.pause_drive('drive0') |
7c6a4ab8 | 71 | result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') |
e5ca8fdd SH |
72 | self.assert_qmp(result, 'return', {}) |
73 | ||
bc11aee2 | 74 | event = self.cancel_and_wait(resume=True) |
e5ca8fdd SH |
75 | self.assert_qmp(event, 'data/type', 'backup') |
76 | ||
7c6a4ab8 FZ |
77 | def test_cancel_drive_backup(self): |
78 | self.do_test_cancel('drive-backup', target_img) | |
79 | ||
80 | def test_cancel_blockdev_backup(self): | |
81 | self.do_test_cancel('blockdev-backup', 'drive1') | |
82 | ||
83 | def do_test_pause(self, cmd, target, image): | |
e5ca8fdd SH |
84 | self.assert_no_active_block_jobs() |
85 | ||
b59b3d57 | 86 | self.vm.pause_drive('drive0') |
7c6a4ab8 FZ |
87 | result = self.vm.qmp(cmd, device='drive0', |
88 | target=target, sync='full') | |
e5ca8fdd SH |
89 | self.assert_qmp(result, 'return', {}) |
90 | ||
f03d9d24 | 91 | self.pause_job('drive0', wait=False) |
b59b3d57 | 92 | self.vm.resume_drive('drive0') |
f03d9d24 | 93 | self.pause_wait('drive0') |
2c93c5cb | 94 | |
e5ca8fdd SH |
95 | result = self.vm.qmp('query-block-jobs') |
96 | offset = self.dictpath(result, 'return[0]/offset') | |
97 | ||
2c93c5cb | 98 | time.sleep(0.5) |
e5ca8fdd SH |
99 | result = self.vm.qmp('query-block-jobs') |
100 | self.assert_qmp(result, 'return[0]/offset', offset) | |
101 | ||
102 | result = self.vm.qmp('block-job-resume', device='drive0') | |
103 | self.assert_qmp(result, 'return', {}) | |
104 | ||
105 | self.wait_until_completed() | |
106 | ||
107 | self.vm.shutdown() | |
7c6a4ab8 | 108 | self.assertTrue(iotests.compare_images(test_img, image), |
e5ca8fdd SH |
109 | 'target image does not match source after backup') |
110 | ||
7c6a4ab8 FZ |
111 | def test_pause_drive_backup(self): |
112 | self.do_test_pause('drive-backup', target_img, target_img) | |
113 | ||
114 | def test_pause_blockdev_backup(self): | |
115 | self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) | |
116 | ||
0a82a927 KW |
117 | def do_test_resize_blockdev_backup(self, device, node): |
118 | def pre_finalize(): | |
119 | result = self.vm.qmp('block_resize', device=device, size=65536) | |
120 | self.assert_qmp(result, 'error/class', 'GenericError') | |
121 | ||
122 | result = self.vm.qmp('block_resize', node_name=node, size=65536) | |
123 | self.assert_qmp(result, 'error/class', 'GenericError') | |
124 | ||
125 | result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', | |
126 | target='drive1', sync='full', auto_finalize=False, | |
127 | auto_dismiss=False) | |
128 | self.assert_qmp(result, 'return', {}) | |
129 | ||
130 | self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize) | |
131 | ||
132 | def test_source_resize_blockdev_backup(self): | |
133 | self.do_test_resize_blockdev_backup('drive0', 'source') | |
134 | ||
135 | def test_target_resize_blockdev_backup(self): | |
136 | self.do_test_resize_blockdev_backup('drive1', 'target') | |
137 | ||
138 | def do_test_target_size(self, size): | |
139 | result = self.vm.qmp('block_resize', device='drive1', size=size) | |
140 | self.assert_qmp(result, 'return', {}) | |
141 | ||
142 | result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', | |
143 | target='drive1', sync='full') | |
144 | self.assert_qmp(result, 'error/class', 'GenericError') | |
145 | ||
146 | def test_small_target(self): | |
147 | self.do_test_target_size(image_len // 2) | |
148 | ||
149 | def test_large_target(self): | |
150 | self.do_test_target_size(image_len * 2) | |
151 | ||
e5ca8fdd | 152 | def test_medium_not_found(self): |
d8683155 BT |
153 | if iotests.qemu_default_machine != 'pc': |
154 | return | |
155 | ||
0ed82f7a | 156 | result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM |
b53169ea | 157 | target=target_img, sync='full') |
e5ca8fdd SH |
158 | self.assert_qmp(result, 'error/class', 'GenericError') |
159 | ||
7c6a4ab8 | 160 | def test_medium_not_found_blockdev_backup(self): |
d8683155 BT |
161 | if iotests.qemu_default_machine != 'pc': |
162 | return | |
163 | ||
0ed82f7a | 164 | result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM |
7c6a4ab8 FZ |
165 | target='drive1', sync='full') |
166 | self.assert_qmp(result, 'error/class', 'GenericError') | |
167 | ||
e5ca8fdd SH |
168 | def test_image_not_found(self): |
169 | result = self.vm.qmp('drive-backup', device='drive0', | |
b53169ea | 170 | target=target_img, sync='full', mode='existing') |
e5ca8fdd SH |
171 | self.assert_qmp(result, 'error/class', 'GenericError') |
172 | ||
e3409362 IM |
173 | def test_invalid_format(self): |
174 | result = self.vm.qmp('drive-backup', device='drive0', | |
175 | target=target_img, sync='full', | |
176 | format='spaghetti-noodles') | |
177 | self.assert_qmp(result, 'error/class', 'GenericError') | |
178 | ||
7c6a4ab8 FZ |
179 | def do_test_device_not_found(self, cmd, **args): |
180 | result = self.vm.qmp(cmd, **args) | |
b7e4fa22 | 181 | self.assert_qmp(result, 'error/class', 'GenericError') |
e5ca8fdd | 182 | |
7c6a4ab8 FZ |
183 | def test_device_not_found(self): |
184 | self.do_test_device_not_found('drive-backup', device='nonexistent', | |
185 | target=target_img, sync='full') | |
186 | ||
187 | self.do_test_device_not_found('blockdev-backup', device='nonexistent', | |
188 | target='drive0', sync='full') | |
189 | ||
190 | self.do_test_device_not_found('blockdev-backup', device='drive0', | |
191 | target='nonexistent', sync='full') | |
192 | ||
193 | self.do_test_device_not_found('blockdev-backup', device='nonexistent', | |
194 | target='nonexistent', sync='full') | |
195 | ||
196 | def test_target_is_source(self): | |
197 | result = self.vm.qmp('blockdev-backup', device='drive0', | |
198 | target='drive0', sync='full') | |
199 | self.assert_qmp(result, 'error/class', 'GenericError') | |
200 | ||
e5ca8fdd | 201 | class TestSetSpeed(iotests.QMPTestCase): |
e5ca8fdd | 202 | def setUp(self): |
819cec01 | 203 | qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) |
7c6a4ab8 | 204 | |
bc11aee2 | 205 | self.vm = iotests.VM().add_drive('blkdebug::' + test_img) |
4e9e4323 | 206 | self.vm.add_drive(blockdev_target_img, interface="none") |
e5ca8fdd SH |
207 | self.vm.launch() |
208 | ||
209 | def tearDown(self): | |
210 | self.vm.shutdown() | |
7c6a4ab8 FZ |
211 | os.remove(blockdev_target_img) |
212 | try: | |
213 | os.remove(target_img) | |
214 | except OSError: | |
215 | pass | |
e5ca8fdd | 216 | |
7c6a4ab8 | 217 | def do_test_set_speed(self, cmd, target): |
e5ca8fdd SH |
218 | self.assert_no_active_block_jobs() |
219 | ||
b59b3d57 | 220 | self.vm.pause_drive('drive0') |
7c6a4ab8 | 221 | result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') |
e5ca8fdd SH |
222 | self.assert_qmp(result, 'return', {}) |
223 | ||
224 | # Default speed is 0 | |
225 | result = self.vm.qmp('query-block-jobs') | |
226 | self.assert_qmp(result, 'return[0]/device', 'drive0') | |
227 | self.assert_qmp(result, 'return[0]/speed', 0) | |
228 | ||
229 | result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) | |
230 | self.assert_qmp(result, 'return', {}) | |
231 | ||
232 | # Ensure the speed we set was accepted | |
233 | result = self.vm.qmp('query-block-jobs') | |
234 | self.assert_qmp(result, 'return[0]/device', 'drive0') | |
235 | self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) | |
236 | ||
b59b3d57 | 237 | event = self.cancel_and_wait(resume=True) |
e5ca8fdd SH |
238 | self.assert_qmp(event, 'data/type', 'backup') |
239 | ||
7c6a4ab8 | 240 | # Check setting speed option works |
b59b3d57 | 241 | self.vm.pause_drive('drive0') |
7c6a4ab8 FZ |
242 | result = self.vm.qmp(cmd, device='drive0', |
243 | target=target, sync='full', speed=4*1024*1024) | |
e5ca8fdd SH |
244 | self.assert_qmp(result, 'return', {}) |
245 | ||
246 | result = self.vm.qmp('query-block-jobs') | |
247 | self.assert_qmp(result, 'return[0]/device', 'drive0') | |
248 | self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) | |
249 | ||
b59b3d57 | 250 | event = self.cancel_and_wait(resume=True) |
e5ca8fdd SH |
251 | self.assert_qmp(event, 'data/type', 'backup') |
252 | ||
7c6a4ab8 FZ |
253 | def test_set_speed_drive_backup(self): |
254 | self.do_test_set_speed('drive-backup', target_img) | |
255 | ||
256 | def test_set_speed_blockdev_backup(self): | |
257 | self.do_test_set_speed('blockdev-backup', 'drive1') | |
258 | ||
259 | def do_test_set_speed_invalid(self, cmd, target): | |
e5ca8fdd SH |
260 | self.assert_no_active_block_jobs() |
261 | ||
7c6a4ab8 FZ |
262 | result = self.vm.qmp(cmd, device='drive0', |
263 | target=target, sync='full', speed=-1) | |
e5ca8fdd SH |
264 | self.assert_qmp(result, 'error/class', 'GenericError') |
265 | ||
266 | self.assert_no_active_block_jobs() | |
267 | ||
b59b3d57 | 268 | self.vm.pause_drive('drive0') |
7c6a4ab8 FZ |
269 | result = self.vm.qmp(cmd, device='drive0', |
270 | target=target, sync='full') | |
e5ca8fdd SH |
271 | self.assert_qmp(result, 'return', {}) |
272 | ||
273 | result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) | |
274 | self.assert_qmp(result, 'error/class', 'GenericError') | |
275 | ||
b59b3d57 | 276 | event = self.cancel_and_wait(resume=True) |
e5ca8fdd SH |
277 | self.assert_qmp(event, 'data/type', 'backup') |
278 | ||
7c6a4ab8 FZ |
279 | def test_set_speed_invalid_drive_backup(self): |
280 | self.do_test_set_speed_invalid('drive-backup', target_img) | |
281 | ||
282 | def test_set_speed_invalid_blockdev_backup(self): | |
283 | self.do_test_set_speed_invalid('blockdev-backup', 'drive1') | |
284 | ||
bc11aee2 HR |
285 | # Note: We cannot use pause_drive() here, or the transaction command |
286 | # would stall. Instead, we limit the block job speed here. | |
e5ca8fdd | 287 | class TestSingleTransaction(iotests.QMPTestCase): |
e5ca8fdd | 288 | def setUp(self): |
819cec01 | 289 | qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) |
e5ca8fdd | 290 | |
4e9e4323 KW |
291 | self.vm = iotests.VM().add_drive(test_img) |
292 | self.vm.add_drive(blockdev_target_img, interface="none") | |
0ed82f7a HR |
293 | if iotests.qemu_default_machine == 'pc': |
294 | self.vm.add_drive(None, 'media=cdrom', 'ide') | |
e5ca8fdd SH |
295 | self.vm.launch() |
296 | ||
297 | def tearDown(self): | |
298 | self.vm.shutdown() | |
7c6a4ab8 | 299 | os.remove(blockdev_target_img) |
e5ca8fdd SH |
300 | try: |
301 | os.remove(target_img) | |
302 | except OSError: | |
303 | pass | |
304 | ||
7c6a4ab8 | 305 | def do_test_cancel(self, cmd, target): |
e5ca8fdd SH |
306 | self.assert_no_active_block_jobs() |
307 | ||
308 | result = self.vm.qmp('transaction', actions=[{ | |
7c6a4ab8 | 309 | 'type': cmd, |
e5ca8fdd | 310 | 'data': { 'device': 'drive0', |
7c6a4ab8 | 311 | 'target': target, |
bc11aee2 HR |
312 | 'sync': 'full', |
313 | 'speed': 64 * 1024 }, | |
e5ca8fdd SH |
314 | } |
315 | ]) | |
7c6a4ab8 | 316 | |
e5ca8fdd SH |
317 | self.assert_qmp(result, 'return', {}) |
318 | ||
319 | event = self.cancel_and_wait() | |
320 | self.assert_qmp(event, 'data/type', 'backup') | |
321 | ||
7c6a4ab8 FZ |
322 | def test_cancel_drive_backup(self): |
323 | self.do_test_cancel('drive-backup', target_img) | |
324 | ||
325 | def test_cancel_blockdev_backup(self): | |
326 | self.do_test_cancel('blockdev-backup', 'drive1') | |
327 | ||
328 | def do_test_pause(self, cmd, target, image): | |
e5ca8fdd SH |
329 | self.assert_no_active_block_jobs() |
330 | ||
331 | result = self.vm.qmp('transaction', actions=[{ | |
7c6a4ab8 | 332 | 'type': cmd, |
e5ca8fdd | 333 | 'data': { 'device': 'drive0', |
7c6a4ab8 | 334 | 'target': target, |
bc11aee2 HR |
335 | 'sync': 'full', |
336 | 'speed': 64 * 1024 }, | |
e5ca8fdd SH |
337 | } |
338 | ]) | |
339 | self.assert_qmp(result, 'return', {}) | |
340 | ||
f03d9d24 | 341 | self.pause_job('drive0', wait=False) |
e5ca8fdd | 342 | |
bc11aee2 HR |
343 | result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0) |
344 | self.assert_qmp(result, 'return', {}) | |
345 | ||
f03d9d24 | 346 | self.pause_wait('drive0') |
2c93c5cb | 347 | |
e5ca8fdd SH |
348 | result = self.vm.qmp('query-block-jobs') |
349 | offset = self.dictpath(result, 'return[0]/offset') | |
350 | ||
2c93c5cb | 351 | time.sleep(0.5) |
e5ca8fdd SH |
352 | result = self.vm.qmp('query-block-jobs') |
353 | self.assert_qmp(result, 'return[0]/offset', offset) | |
354 | ||
355 | result = self.vm.qmp('block-job-resume', device='drive0') | |
356 | self.assert_qmp(result, 'return', {}) | |
357 | ||
358 | self.wait_until_completed() | |
359 | ||
360 | self.vm.shutdown() | |
7c6a4ab8 | 361 | self.assertTrue(iotests.compare_images(test_img, image), |
e5ca8fdd SH |
362 | 'target image does not match source after backup') |
363 | ||
7c6a4ab8 FZ |
364 | def test_pause_drive_backup(self): |
365 | self.do_test_pause('drive-backup', target_img, target_img) | |
366 | ||
367 | def test_pause_blockdev_backup(self): | |
368 | self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) | |
369 | ||
370 | def do_test_medium_not_found(self, cmd, target): | |
d8683155 BT |
371 | if iotests.qemu_default_machine != 'pc': |
372 | return | |
373 | ||
e5ca8fdd | 374 | result = self.vm.qmp('transaction', actions=[{ |
7c6a4ab8 | 375 | 'type': cmd, |
0ed82f7a | 376 | 'data': { 'device': 'drive2', # CD-ROM |
7c6a4ab8 | 377 | 'target': target, |
b53169ea | 378 | 'sync': 'full' }, |
e5ca8fdd SH |
379 | } |
380 | ]) | |
381 | self.assert_qmp(result, 'error/class', 'GenericError') | |
382 | ||
7c6a4ab8 FZ |
383 | def test_medium_not_found_drive_backup(self): |
384 | self.do_test_medium_not_found('drive-backup', target_img) | |
385 | ||
386 | def test_medium_not_found_blockdev_backup(self): | |
387 | self.do_test_medium_not_found('blockdev-backup', 'drive1') | |
388 | ||
e5ca8fdd SH |
389 | def test_image_not_found(self): |
390 | result = self.vm.qmp('transaction', actions=[{ | |
391 | 'type': 'drive-backup', | |
392 | 'data': { 'device': 'drive0', | |
393 | 'mode': 'existing', | |
b53169ea SH |
394 | 'target': target_img, |
395 | 'sync': 'full' }, | |
e5ca8fdd SH |
396 | } |
397 | ]) | |
398 | self.assert_qmp(result, 'error/class', 'GenericError') | |
399 | ||
400 | def test_device_not_found(self): | |
401 | result = self.vm.qmp('transaction', actions=[{ | |
402 | 'type': 'drive-backup', | |
403 | 'data': { 'device': 'nonexistent', | |
404 | 'mode': 'existing', | |
b53169ea SH |
405 | 'target': target_img, |
406 | 'sync': 'full' }, | |
e5ca8fdd SH |
407 | } |
408 | ]) | |
b7e4fa22 | 409 | self.assert_qmp(result, 'error/class', 'GenericError') |
e5ca8fdd | 410 | |
7c6a4ab8 FZ |
411 | result = self.vm.qmp('transaction', actions=[{ |
412 | 'type': 'blockdev-backup', | |
413 | 'data': { 'device': 'nonexistent', | |
414 | 'target': 'drive1', | |
415 | 'sync': 'full' }, | |
416 | } | |
417 | ]) | |
5b347c54 | 418 | self.assert_qmp(result, 'error/class', 'GenericError') |
7c6a4ab8 FZ |
419 | |
420 | result = self.vm.qmp('transaction', actions=[{ | |
421 | 'type': 'blockdev-backup', | |
422 | 'data': { 'device': 'drive0', | |
423 | 'target': 'nonexistent', | |
424 | 'sync': 'full' }, | |
425 | } | |
426 | ]) | |
5b347c54 | 427 | self.assert_qmp(result, 'error/class', 'GenericError') |
7c6a4ab8 FZ |
428 | |
429 | result = self.vm.qmp('transaction', actions=[{ | |
430 | 'type': 'blockdev-backup', | |
431 | 'data': { 'device': 'nonexistent', | |
432 | 'target': 'nonexistent', | |
433 | 'sync': 'full' }, | |
434 | } | |
435 | ]) | |
5b347c54 | 436 | self.assert_qmp(result, 'error/class', 'GenericError') |
7c6a4ab8 FZ |
437 | |
438 | def test_target_is_source(self): | |
439 | result = self.vm.qmp('transaction', actions=[{ | |
440 | 'type': 'blockdev-backup', | |
441 | 'data': { 'device': 'drive0', | |
442 | 'target': 'drive0', | |
443 | 'sync': 'full' }, | |
444 | } | |
445 | ]) | |
446 | self.assert_qmp(result, 'error/class', 'GenericError') | |
447 | ||
e5ca8fdd SH |
448 | def test_abort(self): |
449 | result = self.vm.qmp('transaction', actions=[{ | |
450 | 'type': 'drive-backup', | |
451 | 'data': { 'device': 'nonexistent', | |
452 | 'mode': 'existing', | |
b53169ea SH |
453 | 'target': target_img, |
454 | 'sync': 'full' }, | |
e5ca8fdd SH |
455 | }, { |
456 | 'type': 'Abort', | |
457 | 'data': {}, | |
458 | } | |
459 | ]) | |
460 | self.assert_qmp(result, 'error/class', 'GenericError') | |
461 | self.assert_no_active_block_jobs() | |
462 | ||
7c6a4ab8 FZ |
463 | result = self.vm.qmp('transaction', actions=[{ |
464 | 'type': 'blockdev-backup', | |
465 | 'data': { 'device': 'nonexistent', | |
466 | 'target': 'drive1', | |
467 | 'sync': 'full' }, | |
468 | }, { | |
469 | 'type': 'Abort', | |
470 | 'data': {}, | |
471 | } | |
472 | ]) | |
473 | self.assert_qmp(result, 'error/class', 'GenericError') | |
474 | self.assert_no_active_block_jobs() | |
475 | ||
476 | result = self.vm.qmp('transaction', actions=[{ | |
477 | 'type': 'blockdev-backup', | |
478 | 'data': { 'device': 'drive0', | |
479 | 'target': 'nonexistent', | |
480 | 'sync': 'full' }, | |
481 | }, { | |
482 | 'type': 'Abort', | |
483 | 'data': {}, | |
484 | } | |
485 | ]) | |
486 | self.assert_qmp(result, 'error/class', 'GenericError') | |
487 | self.assert_no_active_block_jobs() | |
488 | ||
e1b5c51f | 489 | |
8e837294 | 490 | class TestCompressedToQcow2(iotests.QMPTestCase): |
e1b5c51f | 491 | image_len = 64 * 1024 * 1024 # MB |
8e837294 | 492 | target_fmt = {'type': 'qcow2', 'args': ()} |
e1b5c51f | 493 | |
e1b5c51f PB |
494 | def tearDown(self): |
495 | self.vm.shutdown() | |
e1b5c51f PB |
496 | os.remove(blockdev_target_img) |
497 | try: | |
498 | os.remove(target_img) | |
499 | except OSError: | |
500 | pass | |
501 | ||
8e837294 | 502 | def do_prepare_drives(self, attach_target): |
bc11aee2 | 503 | self.vm = iotests.VM().add_drive('blkdebug::' + test_img) |
00198ecc | 504 | |
8e837294 VSO |
505 | qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img, |
506 | str(self.image_len), *self.target_fmt['args']) | |
4797aeab | 507 | if attach_target: |
1d3d4b63 | 508 | self.vm.add_drive(blockdev_target_img, |
8e837294 VSO |
509 | img_format=self.target_fmt['type'], |
510 | interface="none") | |
00198ecc PB |
511 | |
512 | self.vm.launch() | |
513 | ||
8e837294 VSO |
514 | def do_test_compress_complete(self, cmd, attach_target, **args): |
515 | self.do_prepare_drives(attach_target) | |
00198ecc | 516 | |
e1b5c51f PB |
517 | self.assert_no_active_block_jobs() |
518 | ||
519 | result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) | |
520 | self.assert_qmp(result, 'return', {}) | |
521 | ||
522 | self.wait_until_completed() | |
523 | ||
524 | self.vm.shutdown() | |
525 | self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, | |
8e837294 VSO |
526 | iotests.imgfmt, |
527 | self.target_fmt['type']), | |
e1b5c51f PB |
528 | 'target image does not match source after backup') |
529 | ||
530 | def test_complete_compress_drive_backup(self): | |
8e837294 VSO |
531 | self.do_test_compress_complete('drive-backup', False, |
532 | target=blockdev_target_img, | |
533 | mode='existing') | |
e1b5c51f PB |
534 | |
535 | def test_complete_compress_blockdev_backup(self): | |
8e837294 VSO |
536 | self.do_test_compress_complete('blockdev-backup', |
537 | True, target='drive1') | |
00198ecc | 538 | |
8e837294 VSO |
539 | def do_test_compress_cancel(self, cmd, attach_target, **args): |
540 | self.do_prepare_drives(attach_target) | |
e1b5c51f | 541 | |
e1b5c51f PB |
542 | self.assert_no_active_block_jobs() |
543 | ||
bc11aee2 | 544 | self.vm.pause_drive('drive0') |
e1b5c51f PB |
545 | result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) |
546 | self.assert_qmp(result, 'return', {}) | |
547 | ||
bc11aee2 | 548 | event = self.cancel_and_wait(resume=True) |
e1b5c51f PB |
549 | self.assert_qmp(event, 'data/type', 'backup') |
550 | ||
00198ecc PB |
551 | self.vm.shutdown() |
552 | ||
e1b5c51f | 553 | def test_compress_cancel_drive_backup(self): |
8e837294 VSO |
554 | self.do_test_compress_cancel('drive-backup', False, |
555 | target=blockdev_target_img, | |
556 | mode='existing') | |
e1b5c51f PB |
557 | |
558 | def test_compress_cancel_blockdev_backup(self): | |
8e837294 VSO |
559 | self.do_test_compress_cancel('blockdev-backup', True, |
560 | target='drive1') | |
00198ecc | 561 | |
8e837294 VSO |
562 | def do_test_compress_pause(self, cmd, attach_target, **args): |
563 | self.do_prepare_drives(attach_target) | |
e1b5c51f | 564 | |
e1b5c51f PB |
565 | self.assert_no_active_block_jobs() |
566 | ||
567 | self.vm.pause_drive('drive0') | |
568 | result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) | |
569 | self.assert_qmp(result, 'return', {}) | |
570 | ||
f03d9d24 | 571 | self.pause_job('drive0', wait=False) |
e1b5c51f | 572 | self.vm.resume_drive('drive0') |
f03d9d24 | 573 | self.pause_wait('drive0') |
2c93c5cb | 574 | |
e1b5c51f PB |
575 | result = self.vm.qmp('query-block-jobs') |
576 | offset = self.dictpath(result, 'return[0]/offset') | |
577 | ||
2c93c5cb | 578 | time.sleep(0.5) |
e1b5c51f PB |
579 | result = self.vm.qmp('query-block-jobs') |
580 | self.assert_qmp(result, 'return[0]/offset', offset) | |
581 | ||
582 | result = self.vm.qmp('block-job-resume', device='drive0') | |
583 | self.assert_qmp(result, 'return', {}) | |
584 | ||
585 | self.wait_until_completed() | |
586 | ||
587 | self.vm.shutdown() | |
588 | self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, | |
8e837294 VSO |
589 | iotests.imgfmt, |
590 | self.target_fmt['type']), | |
e1b5c51f PB |
591 | 'target image does not match source after backup') |
592 | ||
593 | def test_compress_pause_drive_backup(self): | |
8e837294 VSO |
594 | self.do_test_compress_pause('drive-backup', False, |
595 | target=blockdev_target_img, | |
596 | mode='existing') | |
e1b5c51f PB |
597 | |
598 | def test_compress_pause_blockdev_backup(self): | |
8e837294 VSO |
599 | self.do_test_compress_pause('blockdev-backup', True, |
600 | target='drive1') | |
601 | ||
602 | ||
603 | class TestCompressedToVmdk(TestCompressedToQcow2): | |
604 | target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')} | |
605 | ||
761cd2e7 VSO |
606 | @iotests.skip_if_unsupported(['vmdk']) |
607 | def setUp(self): | |
608 | pass | |
609 | ||
e1b5c51f | 610 | |
e5ca8fdd | 611 | if __name__ == '__main__': |
103cbc77 HR |
612 | iotests.main(supported_fmts=['raw', 'qcow2'], |
613 | supported_protocols=['file']) |