iotests: Make 055 less flaky
[qemu/ar7.git] / tests / qemu-iotests / 055
blob8a5d9fd26913c0d7aeb9da19742506c0a0865c03
1 #!/usr/bin/env python
3 # Tests for drive-backup and blockdev-backup
5 # Copyright (C) 2013, 2014 Red Hat, Inc.
7 # Based on 041.
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.
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.
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/>.
23 import time
24 import os
25 import iotests
26 from iotests import qemu_img, qemu_io
28 test_img = os.path.join(iotests.test_dir, 'test.img')
29 target_img = os.path.join(iotests.test_dir, 'target.img')
30 blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img')
32 image_len = 64 * 1024 * 1024 # MB
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)
43 def tearDownModule():
44 os.remove(test_img)
47 class TestSingleDrive(iotests.QMPTestCase):
48 def setUp(self):
49 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
51 self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
52 self.vm.add_drive(blockdev_target_img, interface="none")
53 if iotests.qemu_default_machine == 'pc':
54 self.vm.add_drive(None, 'media=cdrom', 'ide')
55 self.vm.launch()
57 def tearDown(self):
58 self.vm.shutdown()
59 os.remove(blockdev_target_img)
60 try:
61 os.remove(target_img)
62 except OSError:
63 pass
65 def do_test_cancel(self, cmd, target):
66 self.assert_no_active_block_jobs()
68 self.vm.pause_drive('drive0')
69 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
70 self.assert_qmp(result, 'return', {})
72 event = self.cancel_and_wait(resume=True)
73 self.assert_qmp(event, 'data/type', 'backup')
75 def test_cancel_drive_backup(self):
76 self.do_test_cancel('drive-backup', target_img)
78 def test_cancel_blockdev_backup(self):
79 self.do_test_cancel('blockdev-backup', 'drive1')
81 def do_test_pause(self, cmd, target, image):
82 self.assert_no_active_block_jobs()
84 self.vm.pause_drive('drive0')
85 result = self.vm.qmp(cmd, device='drive0',
86 target=target, sync='full')
87 self.assert_qmp(result, 'return', {})
89 result = self.vm.qmp('block-job-pause', device='drive0')
90 self.assert_qmp(result, 'return', {})
92 self.vm.resume_drive('drive0')
93 self.pause_job('drive0')
95 result = self.vm.qmp('query-block-jobs')
96 offset = self.dictpath(result, 'return[0]/offset')
98 time.sleep(0.5)
99 result = self.vm.qmp('query-block-jobs')
100 self.assert_qmp(result, 'return[0]/offset', offset)
102 result = self.vm.qmp('block-job-resume', device='drive0')
103 self.assert_qmp(result, 'return', {})
105 self.wait_until_completed()
107 self.vm.shutdown()
108 self.assertTrue(iotests.compare_images(test_img, image),
109 'target image does not match source after backup')
111 def test_pause_drive_backup(self):
112 self.do_test_pause('drive-backup', target_img, target_img)
114 def test_pause_blockdev_backup(self):
115 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
117 def test_medium_not_found(self):
118 if iotests.qemu_default_machine != 'pc':
119 return
121 result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM
122 target=target_img, sync='full')
123 self.assert_qmp(result, 'error/class', 'GenericError')
125 def test_medium_not_found_blockdev_backup(self):
126 if iotests.qemu_default_machine != 'pc':
127 return
129 result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
130 target='drive1', sync='full')
131 self.assert_qmp(result, 'error/class', 'GenericError')
133 def test_image_not_found(self):
134 result = self.vm.qmp('drive-backup', device='drive0',
135 target=target_img, sync='full', mode='existing')
136 self.assert_qmp(result, 'error/class', 'GenericError')
138 def test_invalid_format(self):
139 result = self.vm.qmp('drive-backup', device='drive0',
140 target=target_img, sync='full',
141 format='spaghetti-noodles')
142 self.assert_qmp(result, 'error/class', 'GenericError')
144 def do_test_device_not_found(self, cmd, **args):
145 result = self.vm.qmp(cmd, **args)
146 self.assert_qmp(result, 'error/class', 'GenericError')
148 def test_device_not_found(self):
149 self.do_test_device_not_found('drive-backup', device='nonexistent',
150 target=target_img, sync='full')
152 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
153 target='drive0', sync='full')
155 self.do_test_device_not_found('blockdev-backup', device='drive0',
156 target='nonexistent', sync='full')
158 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
159 target='nonexistent', sync='full')
161 def test_target_is_source(self):
162 result = self.vm.qmp('blockdev-backup', device='drive0',
163 target='drive0', sync='full')
164 self.assert_qmp(result, 'error/class', 'GenericError')
166 class TestSetSpeed(iotests.QMPTestCase):
167 def setUp(self):
168 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
170 self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
171 self.vm.add_drive(blockdev_target_img, interface="none")
172 self.vm.launch()
174 def tearDown(self):
175 self.vm.shutdown()
176 os.remove(blockdev_target_img)
177 try:
178 os.remove(target_img)
179 except OSError:
180 pass
182 def do_test_set_speed(self, cmd, target):
183 self.assert_no_active_block_jobs()
185 self.vm.pause_drive('drive0')
186 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
187 self.assert_qmp(result, 'return', {})
189 # Default speed is 0
190 result = self.vm.qmp('query-block-jobs')
191 self.assert_qmp(result, 'return[0]/device', 'drive0')
192 self.assert_qmp(result, 'return[0]/speed', 0)
194 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
195 self.assert_qmp(result, 'return', {})
197 # Ensure the speed we set was accepted
198 result = self.vm.qmp('query-block-jobs')
199 self.assert_qmp(result, 'return[0]/device', 'drive0')
200 self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
202 event = self.cancel_and_wait(resume=True)
203 self.assert_qmp(event, 'data/type', 'backup')
205 # Check setting speed option works
206 self.vm.pause_drive('drive0')
207 result = self.vm.qmp(cmd, device='drive0',
208 target=target, sync='full', speed=4*1024*1024)
209 self.assert_qmp(result, 'return', {})
211 result = self.vm.qmp('query-block-jobs')
212 self.assert_qmp(result, 'return[0]/device', 'drive0')
213 self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
215 event = self.cancel_and_wait(resume=True)
216 self.assert_qmp(event, 'data/type', 'backup')
218 def test_set_speed_drive_backup(self):
219 self.do_test_set_speed('drive-backup', target_img)
221 def test_set_speed_blockdev_backup(self):
222 self.do_test_set_speed('blockdev-backup', 'drive1')
224 def do_test_set_speed_invalid(self, cmd, target):
225 self.assert_no_active_block_jobs()
227 result = self.vm.qmp(cmd, device='drive0',
228 target=target, sync='full', speed=-1)
229 self.assert_qmp(result, 'error/class', 'GenericError')
231 self.assert_no_active_block_jobs()
233 self.vm.pause_drive('drive0')
234 result = self.vm.qmp(cmd, device='drive0',
235 target=target, sync='full')
236 self.assert_qmp(result, 'return', {})
238 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
239 self.assert_qmp(result, 'error/class', 'GenericError')
241 event = self.cancel_and_wait(resume=True)
242 self.assert_qmp(event, 'data/type', 'backup')
244 def test_set_speed_invalid_drive_backup(self):
245 self.do_test_set_speed_invalid('drive-backup', target_img)
247 def test_set_speed_invalid_blockdev_backup(self):
248 self.do_test_set_speed_invalid('blockdev-backup', 'drive1')
250 # Note: We cannot use pause_drive() here, or the transaction command
251 # would stall. Instead, we limit the block job speed here.
252 class TestSingleTransaction(iotests.QMPTestCase):
253 def setUp(self):
254 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
256 self.vm = iotests.VM().add_drive(test_img)
257 self.vm.add_drive(blockdev_target_img, interface="none")
258 if iotests.qemu_default_machine == 'pc':
259 self.vm.add_drive(None, 'media=cdrom', 'ide')
260 self.vm.launch()
262 def tearDown(self):
263 self.vm.shutdown()
264 os.remove(blockdev_target_img)
265 try:
266 os.remove(target_img)
267 except OSError:
268 pass
270 def do_test_cancel(self, cmd, target):
271 self.assert_no_active_block_jobs()
273 result = self.vm.qmp('transaction', actions=[{
274 'type': cmd,
275 'data': { 'device': 'drive0',
276 'target': target,
277 'sync': 'full',
278 'speed': 64 * 1024 },
282 self.assert_qmp(result, 'return', {})
284 event = self.cancel_and_wait()
285 self.assert_qmp(event, 'data/type', 'backup')
287 def test_cancel_drive_backup(self):
288 self.do_test_cancel('drive-backup', target_img)
290 def test_cancel_blockdev_backup(self):
291 self.do_test_cancel('blockdev-backup', 'drive1')
293 def do_test_pause(self, cmd, target, image):
294 self.assert_no_active_block_jobs()
296 result = self.vm.qmp('transaction', actions=[{
297 'type': cmd,
298 'data': { 'device': 'drive0',
299 'target': target,
300 'sync': 'full',
301 'speed': 64 * 1024 },
304 self.assert_qmp(result, 'return', {})
306 result = self.vm.qmp('block-job-pause', device='drive0')
307 self.assert_qmp(result, 'return', {})
309 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
310 self.assert_qmp(result, 'return', {})
312 self.pause_job('drive0')
314 result = self.vm.qmp('query-block-jobs')
315 offset = self.dictpath(result, 'return[0]/offset')
317 time.sleep(0.5)
318 result = self.vm.qmp('query-block-jobs')
319 self.assert_qmp(result, 'return[0]/offset', offset)
321 result = self.vm.qmp('block-job-resume', device='drive0')
322 self.assert_qmp(result, 'return', {})
324 self.wait_until_completed()
326 self.vm.shutdown()
327 self.assertTrue(iotests.compare_images(test_img, image),
328 'target image does not match source after backup')
330 def test_pause_drive_backup(self):
331 self.do_test_pause('drive-backup', target_img, target_img)
333 def test_pause_blockdev_backup(self):
334 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
336 def do_test_medium_not_found(self, cmd, target):
337 if iotests.qemu_default_machine != 'pc':
338 return
340 result = self.vm.qmp('transaction', actions=[{
341 'type': cmd,
342 'data': { 'device': 'drive2', # CD-ROM
343 'target': target,
344 'sync': 'full' },
347 self.assert_qmp(result, 'error/class', 'GenericError')
349 def test_medium_not_found_drive_backup(self):
350 self.do_test_medium_not_found('drive-backup', target_img)
352 def test_medium_not_found_blockdev_backup(self):
353 self.do_test_medium_not_found('blockdev-backup', 'drive1')
355 def test_image_not_found(self):
356 result = self.vm.qmp('transaction', actions=[{
357 'type': 'drive-backup',
358 'data': { 'device': 'drive0',
359 'mode': 'existing',
360 'target': target_img,
361 'sync': 'full' },
364 self.assert_qmp(result, 'error/class', 'GenericError')
366 def test_device_not_found(self):
367 result = self.vm.qmp('transaction', actions=[{
368 'type': 'drive-backup',
369 'data': { 'device': 'nonexistent',
370 'mode': 'existing',
371 'target': target_img,
372 'sync': 'full' },
375 self.assert_qmp(result, 'error/class', 'GenericError')
377 result = self.vm.qmp('transaction', actions=[{
378 'type': 'blockdev-backup',
379 'data': { 'device': 'nonexistent',
380 'target': 'drive1',
381 'sync': 'full' },
384 self.assert_qmp(result, 'error/class', 'GenericError')
386 result = self.vm.qmp('transaction', actions=[{
387 'type': 'blockdev-backup',
388 'data': { 'device': 'drive0',
389 'target': 'nonexistent',
390 'sync': 'full' },
393 self.assert_qmp(result, 'error/class', 'GenericError')
395 result = self.vm.qmp('transaction', actions=[{
396 'type': 'blockdev-backup',
397 'data': { 'device': 'nonexistent',
398 'target': 'nonexistent',
399 'sync': 'full' },
402 self.assert_qmp(result, 'error/class', 'GenericError')
404 def test_target_is_source(self):
405 result = self.vm.qmp('transaction', actions=[{
406 'type': 'blockdev-backup',
407 'data': { 'device': 'drive0',
408 'target': 'drive0',
409 'sync': 'full' },
412 self.assert_qmp(result, 'error/class', 'GenericError')
414 def test_abort(self):
415 result = self.vm.qmp('transaction', actions=[{
416 'type': 'drive-backup',
417 'data': { 'device': 'nonexistent',
418 'mode': 'existing',
419 'target': target_img,
420 'sync': 'full' },
421 }, {
422 'type': 'Abort',
423 'data': {},
426 self.assert_qmp(result, 'error/class', 'GenericError')
427 self.assert_no_active_block_jobs()
429 result = self.vm.qmp('transaction', actions=[{
430 'type': 'blockdev-backup',
431 'data': { 'device': 'nonexistent',
432 'target': 'drive1',
433 'sync': 'full' },
434 }, {
435 'type': 'Abort',
436 'data': {},
439 self.assert_qmp(result, 'error/class', 'GenericError')
440 self.assert_no_active_block_jobs()
442 result = self.vm.qmp('transaction', actions=[{
443 'type': 'blockdev-backup',
444 'data': { 'device': 'drive0',
445 'target': 'nonexistent',
446 'sync': 'full' },
447 }, {
448 'type': 'Abort',
449 'data': {},
452 self.assert_qmp(result, 'error/class', 'GenericError')
453 self.assert_no_active_block_jobs()
456 class TestDriveCompression(iotests.QMPTestCase):
457 image_len = 64 * 1024 * 1024 # MB
458 fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
459 {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
461 def tearDown(self):
462 self.vm.shutdown()
463 os.remove(blockdev_target_img)
464 try:
465 os.remove(target_img)
466 except OSError:
467 pass
469 def do_prepare_drives(self, fmt, args, attach_target):
470 self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
472 qemu_img('create', '-f', fmt, blockdev_target_img,
473 str(TestDriveCompression.image_len), *args)
474 if attach_target:
475 self.vm.add_drive(blockdev_target_img, format=fmt, interface="none")
477 self.vm.launch()
479 def do_test_compress_complete(self, cmd, format, attach_target, **args):
480 self.do_prepare_drives(format['type'], format['args'], attach_target)
482 self.assert_no_active_block_jobs()
484 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
485 self.assert_qmp(result, 'return', {})
487 self.wait_until_completed()
489 self.vm.shutdown()
490 self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
491 iotests.imgfmt, format['type']),
492 'target image does not match source after backup')
494 def test_complete_compress_drive_backup(self):
495 for format in TestDriveCompression.fmt_supports_compression:
496 self.do_test_compress_complete('drive-backup', format, False,
497 target=blockdev_target_img, mode='existing')
499 def test_complete_compress_blockdev_backup(self):
500 for format in TestDriveCompression.fmt_supports_compression:
501 self.do_test_compress_complete('blockdev-backup', format, True,
502 target='drive1')
504 def do_test_compress_cancel(self, cmd, format, attach_target, **args):
505 self.do_prepare_drives(format['type'], format['args'], attach_target)
507 self.assert_no_active_block_jobs()
509 self.vm.pause_drive('drive0')
510 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
511 self.assert_qmp(result, 'return', {})
513 event = self.cancel_and_wait(resume=True)
514 self.assert_qmp(event, 'data/type', 'backup')
516 self.vm.shutdown()
518 def test_compress_cancel_drive_backup(self):
519 for format in TestDriveCompression.fmt_supports_compression:
520 self.do_test_compress_cancel('drive-backup', format, False,
521 target=blockdev_target_img, mode='existing')
523 def test_compress_cancel_blockdev_backup(self):
524 for format in TestDriveCompression.fmt_supports_compression:
525 self.do_test_compress_cancel('blockdev-backup', format, True,
526 target='drive1')
528 def do_test_compress_pause(self, cmd, format, attach_target, **args):
529 self.do_prepare_drives(format['type'], format['args'], attach_target)
531 self.assert_no_active_block_jobs()
533 self.vm.pause_drive('drive0')
534 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
535 self.assert_qmp(result, 'return', {})
537 result = self.vm.qmp('block-job-pause', device='drive0')
538 self.assert_qmp(result, 'return', {})
540 self.vm.resume_drive('drive0')
541 self.pause_job('drive0')
543 result = self.vm.qmp('query-block-jobs')
544 offset = self.dictpath(result, 'return[0]/offset')
546 time.sleep(0.5)
547 result = self.vm.qmp('query-block-jobs')
548 self.assert_qmp(result, 'return[0]/offset', offset)
550 result = self.vm.qmp('block-job-resume', device='drive0')
551 self.assert_qmp(result, 'return', {})
553 self.wait_until_completed()
555 self.vm.shutdown()
556 self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
557 iotests.imgfmt, format['type']),
558 'target image does not match source after backup')
560 def test_compress_pause_drive_backup(self):
561 for format in TestDriveCompression.fmt_supports_compression:
562 self.do_test_compress_pause('drive-backup', format, False,
563 target=blockdev_target_img, mode='existing')
565 def test_compress_pause_blockdev_backup(self):
566 for format in TestDriveCompression.fmt_supports_compression:
567 self.do_test_compress_pause('blockdev-backup', format, True,
568 target='drive1')
570 if __name__ == '__main__':
571 iotests.main(supported_fmts=['raw', 'qcow2'])