Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
[qemu/kevin.git] / tests / qemu-iotests / 055
blob1d3fd04b6562a75c3d69c914f102320efc6dee04
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(test_img).add_drive(blockdev_target_img)
52 if iotests.qemu_default_machine == 'pc':
53 self.vm.add_drive(None, 'media=cdrom', 'ide')
54 self.vm.launch()
56 def tearDown(self):
57 self.vm.shutdown()
58 os.remove(blockdev_target_img)
59 try:
60 os.remove(target_img)
61 except OSError:
62 pass
64 def do_test_cancel(self, cmd, target):
65 self.assert_no_active_block_jobs()
67 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
68 self.assert_qmp(result, 'return', {})
70 event = self.cancel_and_wait()
71 self.assert_qmp(event, 'data/type', 'backup')
73 def test_cancel_drive_backup(self):
74 self.do_test_cancel('drive-backup', target_img)
76 def test_cancel_blockdev_backup(self):
77 self.do_test_cancel('blockdev-backup', 'drive1')
79 def do_test_pause(self, cmd, target, image):
80 self.assert_no_active_block_jobs()
82 self.vm.pause_drive('drive0')
83 result = self.vm.qmp(cmd, device='drive0',
84 target=target, sync='full')
85 self.assert_qmp(result, 'return', {})
87 result = self.vm.qmp('block-job-pause', device='drive0')
88 self.assert_qmp(result, 'return', {})
90 self.vm.resume_drive('drive0')
91 time.sleep(1)
92 result = self.vm.qmp('query-block-jobs')
93 offset = self.dictpath(result, 'return[0]/offset')
95 time.sleep(1)
96 result = self.vm.qmp('query-block-jobs')
97 self.assert_qmp(result, 'return[0]/offset', offset)
99 result = self.vm.qmp('block-job-resume', device='drive0')
100 self.assert_qmp(result, 'return', {})
102 self.wait_until_completed()
104 self.vm.shutdown()
105 self.assertTrue(iotests.compare_images(test_img, image),
106 'target image does not match source after backup')
108 def test_pause_drive_backup(self):
109 self.do_test_pause('drive-backup', target_img, target_img)
111 def test_pause_blockdev_backup(self):
112 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
114 def test_medium_not_found(self):
115 if iotests.qemu_default_machine != 'pc':
116 return
118 result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM
119 target=target_img, sync='full')
120 self.assert_qmp(result, 'error/class', 'GenericError')
122 def test_medium_not_found_blockdev_backup(self):
123 if iotests.qemu_default_machine != 'pc':
124 return
126 result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
127 target='drive1', sync='full')
128 self.assert_qmp(result, 'error/class', 'GenericError')
130 def test_image_not_found(self):
131 result = self.vm.qmp('drive-backup', device='drive0',
132 target=target_img, sync='full', mode='existing')
133 self.assert_qmp(result, 'error/class', 'GenericError')
135 def test_invalid_format(self):
136 result = self.vm.qmp('drive-backup', device='drive0',
137 target=target_img, sync='full',
138 format='spaghetti-noodles')
139 self.assert_qmp(result, 'error/class', 'GenericError')
141 def do_test_device_not_found(self, cmd, **args):
142 result = self.vm.qmp(cmd, **args)
143 self.assert_qmp(result, 'error/class', 'GenericError')
145 def test_device_not_found(self):
146 self.do_test_device_not_found('drive-backup', device='nonexistent',
147 target=target_img, sync='full')
149 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
150 target='drive0', sync='full')
152 self.do_test_device_not_found('blockdev-backup', device='drive0',
153 target='nonexistent', sync='full')
155 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
156 target='nonexistent', sync='full')
158 def test_target_is_source(self):
159 result = self.vm.qmp('blockdev-backup', device='drive0',
160 target='drive0', sync='full')
161 self.assert_qmp(result, 'error/class', 'GenericError')
163 class TestSetSpeed(iotests.QMPTestCase):
164 def setUp(self):
165 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
167 self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
168 self.vm.launch()
170 def tearDown(self):
171 self.vm.shutdown()
172 os.remove(blockdev_target_img)
173 try:
174 os.remove(target_img)
175 except OSError:
176 pass
178 def do_test_set_speed(self, cmd, target):
179 self.assert_no_active_block_jobs()
181 self.vm.pause_drive('drive0')
182 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
183 self.assert_qmp(result, 'return', {})
185 # Default speed is 0
186 result = self.vm.qmp('query-block-jobs')
187 self.assert_qmp(result, 'return[0]/device', 'drive0')
188 self.assert_qmp(result, 'return[0]/speed', 0)
190 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
191 self.assert_qmp(result, 'return', {})
193 # Ensure the speed we set was accepted
194 result = self.vm.qmp('query-block-jobs')
195 self.assert_qmp(result, 'return[0]/device', 'drive0')
196 self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
198 event = self.cancel_and_wait(resume=True)
199 self.assert_qmp(event, 'data/type', 'backup')
201 # Check setting speed option works
202 self.vm.pause_drive('drive0')
203 result = self.vm.qmp(cmd, device='drive0',
204 target=target, sync='full', speed=4*1024*1024)
205 self.assert_qmp(result, 'return', {})
207 result = self.vm.qmp('query-block-jobs')
208 self.assert_qmp(result, 'return[0]/device', 'drive0')
209 self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
211 event = self.cancel_and_wait(resume=True)
212 self.assert_qmp(event, 'data/type', 'backup')
214 def test_set_speed_drive_backup(self):
215 self.do_test_set_speed('drive-backup', target_img)
217 def test_set_speed_blockdev_backup(self):
218 self.do_test_set_speed('blockdev-backup', 'drive1')
220 def do_test_set_speed_invalid(self, cmd, target):
221 self.assert_no_active_block_jobs()
223 result = self.vm.qmp(cmd, device='drive0',
224 target=target, sync='full', speed=-1)
225 self.assert_qmp(result, 'error/class', 'GenericError')
227 self.assert_no_active_block_jobs()
229 self.vm.pause_drive('drive0')
230 result = self.vm.qmp(cmd, device='drive0',
231 target=target, sync='full')
232 self.assert_qmp(result, 'return', {})
234 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
235 self.assert_qmp(result, 'error/class', 'GenericError')
237 event = self.cancel_and_wait(resume=True)
238 self.assert_qmp(event, 'data/type', 'backup')
240 def test_set_speed_invalid_drive_backup(self):
241 self.do_test_set_speed_invalid('drive-backup', target_img)
243 def test_set_speed_invalid_blockdev_backup(self):
244 self.do_test_set_speed_invalid('blockdev-backup', 'drive1')
246 class TestSingleTransaction(iotests.QMPTestCase):
247 def setUp(self):
248 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
250 self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
251 if iotests.qemu_default_machine == 'pc':
252 self.vm.add_drive(None, 'media=cdrom', 'ide')
253 self.vm.launch()
255 def tearDown(self):
256 self.vm.shutdown()
257 os.remove(blockdev_target_img)
258 try:
259 os.remove(target_img)
260 except OSError:
261 pass
263 def do_test_cancel(self, cmd, target):
264 self.assert_no_active_block_jobs()
266 result = self.vm.qmp('transaction', actions=[{
267 'type': cmd,
268 'data': { 'device': 'drive0',
269 'target': target,
270 'sync': 'full' },
274 self.assert_qmp(result, 'return', {})
276 event = self.cancel_and_wait()
277 self.assert_qmp(event, 'data/type', 'backup')
279 def test_cancel_drive_backup(self):
280 self.do_test_cancel('drive-backup', target_img)
282 def test_cancel_blockdev_backup(self):
283 self.do_test_cancel('blockdev-backup', 'drive1')
285 def do_test_pause(self, cmd, target, image):
286 self.assert_no_active_block_jobs()
288 self.vm.pause_drive('drive0')
289 result = self.vm.qmp('transaction', actions=[{
290 'type': cmd,
291 'data': { 'device': 'drive0',
292 'target': target,
293 'sync': 'full' },
296 self.assert_qmp(result, 'return', {})
298 result = self.vm.qmp('block-job-pause', device='drive0')
299 self.assert_qmp(result, 'return', {})
301 self.vm.resume_drive('drive0')
302 time.sleep(1)
303 result = self.vm.qmp('query-block-jobs')
304 offset = self.dictpath(result, 'return[0]/offset')
306 time.sleep(1)
307 result = self.vm.qmp('query-block-jobs')
308 self.assert_qmp(result, 'return[0]/offset', offset)
310 result = self.vm.qmp('block-job-resume', device='drive0')
311 self.assert_qmp(result, 'return', {})
313 self.wait_until_completed()
315 self.vm.shutdown()
316 self.assertTrue(iotests.compare_images(test_img, image),
317 'target image does not match source after backup')
319 def test_pause_drive_backup(self):
320 self.do_test_pause('drive-backup', target_img, target_img)
322 def test_pause_blockdev_backup(self):
323 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
325 def do_test_medium_not_found(self, cmd, target):
326 if iotests.qemu_default_machine != 'pc':
327 return
329 result = self.vm.qmp('transaction', actions=[{
330 'type': cmd,
331 'data': { 'device': 'drive2', # CD-ROM
332 'target': target,
333 'sync': 'full' },
336 self.assert_qmp(result, 'error/class', 'GenericError')
338 def test_medium_not_found_drive_backup(self):
339 self.do_test_medium_not_found('drive-backup', target_img)
341 def test_medium_not_found_blockdev_backup(self):
342 self.do_test_medium_not_found('blockdev-backup', 'drive1')
344 def test_image_not_found(self):
345 result = self.vm.qmp('transaction', actions=[{
346 'type': 'drive-backup',
347 'data': { 'device': 'drive0',
348 'mode': 'existing',
349 'target': target_img,
350 'sync': 'full' },
353 self.assert_qmp(result, 'error/class', 'GenericError')
355 def test_device_not_found(self):
356 result = self.vm.qmp('transaction', actions=[{
357 'type': 'drive-backup',
358 'data': { 'device': 'nonexistent',
359 'mode': 'existing',
360 'target': target_img,
361 'sync': 'full' },
364 self.assert_qmp(result, 'error/class', 'GenericError')
366 result = self.vm.qmp('transaction', actions=[{
367 'type': 'blockdev-backup',
368 'data': { 'device': 'nonexistent',
369 'target': 'drive1',
370 'sync': 'full' },
373 self.assert_qmp(result, 'error/class', 'GenericError')
375 result = self.vm.qmp('transaction', actions=[{
376 'type': 'blockdev-backup',
377 'data': { 'device': 'drive0',
378 'target': 'nonexistent',
379 'sync': 'full' },
382 self.assert_qmp(result, 'error/class', 'GenericError')
384 result = self.vm.qmp('transaction', actions=[{
385 'type': 'blockdev-backup',
386 'data': { 'device': 'nonexistent',
387 'target': 'nonexistent',
388 'sync': 'full' },
391 self.assert_qmp(result, 'error/class', 'GenericError')
393 def test_target_is_source(self):
394 result = self.vm.qmp('transaction', actions=[{
395 'type': 'blockdev-backup',
396 'data': { 'device': 'drive0',
397 'target': 'drive0',
398 'sync': 'full' },
401 self.assert_qmp(result, 'error/class', 'GenericError')
403 def test_abort(self):
404 result = self.vm.qmp('transaction', actions=[{
405 'type': 'drive-backup',
406 'data': { 'device': 'nonexistent',
407 'mode': 'existing',
408 'target': target_img,
409 'sync': 'full' },
410 }, {
411 'type': 'Abort',
412 'data': {},
415 self.assert_qmp(result, 'error/class', 'GenericError')
416 self.assert_no_active_block_jobs()
418 result = self.vm.qmp('transaction', actions=[{
419 'type': 'blockdev-backup',
420 'data': { 'device': 'nonexistent',
421 'target': 'drive1',
422 'sync': 'full' },
423 }, {
424 'type': 'Abort',
425 'data': {},
428 self.assert_qmp(result, 'error/class', 'GenericError')
429 self.assert_no_active_block_jobs()
431 result = self.vm.qmp('transaction', actions=[{
432 'type': 'blockdev-backup',
433 'data': { 'device': 'drive0',
434 'target': 'nonexistent',
435 'sync': 'full' },
436 }, {
437 'type': 'Abort',
438 'data': {},
441 self.assert_qmp(result, 'error/class', 'GenericError')
442 self.assert_no_active_block_jobs()
445 class TestDriveCompression(iotests.QMPTestCase):
446 image_len = 64 * 1024 * 1024 # MB
447 fmt_supports_compression = [{'type': 'qcow2', 'args': ()},
448 {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized')}]
450 def tearDown(self):
451 self.vm.shutdown()
452 os.remove(blockdev_target_img)
453 try:
454 os.remove(target_img)
455 except OSError:
456 pass
458 def do_prepare_drives(self, fmt, args):
459 self.vm = iotests.VM().add_drive(test_img)
461 qemu_img('create', '-f', fmt, blockdev_target_img,
462 str(TestDriveCompression.image_len), *args)
463 self.vm.add_drive(blockdev_target_img, format=fmt)
465 self.vm.launch()
467 def do_test_compress_complete(self, cmd, format, **args):
468 self.do_prepare_drives(format['type'], format['args'])
470 self.assert_no_active_block_jobs()
472 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
473 self.assert_qmp(result, 'return', {})
475 self.wait_until_completed()
477 self.vm.shutdown()
478 self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
479 iotests.imgfmt, format['type']),
480 'target image does not match source after backup')
482 def test_complete_compress_drive_backup(self):
483 for format in TestDriveCompression.fmt_supports_compression:
484 self.do_test_compress_complete('drive-backup', format,
485 target=blockdev_target_img, mode='existing')
487 def test_complete_compress_blockdev_backup(self):
488 for format in TestDriveCompression.fmt_supports_compression:
489 self.do_test_compress_complete('blockdev-backup', format, target='drive1')
491 def do_test_compress_cancel(self, cmd, format, **args):
492 self.do_prepare_drives(format['type'], format['args'])
494 self.assert_no_active_block_jobs()
496 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
497 self.assert_qmp(result, 'return', {})
499 event = self.cancel_and_wait()
500 self.assert_qmp(event, 'data/type', 'backup')
502 self.vm.shutdown()
504 def test_compress_cancel_drive_backup(self):
505 for format in TestDriveCompression.fmt_supports_compression:
506 self.do_test_compress_cancel('drive-backup', format,
507 target=blockdev_target_img, mode='existing')
509 def test_compress_cancel_blockdev_backup(self):
510 for format in TestDriveCompression.fmt_supports_compression:
511 self.do_test_compress_cancel('blockdev-backup', format, target='drive1')
513 def do_test_compress_pause(self, cmd, format, **args):
514 self.do_prepare_drives(format['type'], format['args'])
516 self.assert_no_active_block_jobs()
518 self.vm.pause_drive('drive0')
519 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
520 self.assert_qmp(result, 'return', {})
522 result = self.vm.qmp('block-job-pause', device='drive0')
523 self.assert_qmp(result, 'return', {})
525 self.vm.resume_drive('drive0')
526 time.sleep(1)
527 result = self.vm.qmp('query-block-jobs')
528 offset = self.dictpath(result, 'return[0]/offset')
530 time.sleep(1)
531 result = self.vm.qmp('query-block-jobs')
532 self.assert_qmp(result, 'return[0]/offset', offset)
534 result = self.vm.qmp('block-job-resume', device='drive0')
535 self.assert_qmp(result, 'return', {})
537 self.wait_until_completed()
539 self.vm.shutdown()
540 self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
541 iotests.imgfmt, format['type']),
542 'target image does not match source after backup')
544 def test_compress_pause_drive_backup(self):
545 for format in TestDriveCompression.fmt_supports_compression:
546 self.do_test_compress_pause('drive-backup', format,
547 target=blockdev_target_img, mode='existing')
549 def test_compress_pause_blockdev_backup(self):
550 for format in TestDriveCompression.fmt_supports_compression:
551 self.do_test_compress_pause('blockdev-backup', format, target='drive1')
553 if __name__ == '__main__':
554 iotests.main(supported_fmts=['raw', 'qcow2'])