]> git.proxmox.com Git - mirror_qemu.git/blob - tests/qemu-iotests/055
socket_scm_helper: Accept fd directly
[mirror_qemu.git] / tests / qemu-iotests / 055
1 #!/usr/bin/env python
2 #
3 # Tests for drive-backup and blockdev-backup
4 #
5 # Copyright (C) 2013, 2014 Red Hat, Inc.
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')
30 blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img')
31
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)
42
43 def tearDownModule():
44 os.remove(test_img)
45
46
47 class TestSingleDrive(iotests.QMPTestCase):
48 def setUp(self):
49 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
50
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()
55
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
63
64 def do_test_cancel(self, cmd, target):
65 self.assert_no_active_block_jobs()
66
67 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
68 self.assert_qmp(result, 'return', {})
69
70 event = self.cancel_and_wait()
71 self.assert_qmp(event, 'data/type', 'backup')
72
73 def test_cancel_drive_backup(self):
74 self.do_test_cancel('drive-backup', target_img)
75
76 def test_cancel_blockdev_backup(self):
77 self.do_test_cancel('blockdev-backup', 'drive1')
78
79 def do_test_pause(self, cmd, target, image):
80 self.assert_no_active_block_jobs()
81
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', {})
86
87 result = self.vm.qmp('block-job-pause', device='drive0')
88 self.assert_qmp(result, 'return', {})
89
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')
94
95 time.sleep(1)
96 result = self.vm.qmp('query-block-jobs')
97 self.assert_qmp(result, 'return[0]/offset', offset)
98
99 result = self.vm.qmp('block-job-resume', device='drive0')
100 self.assert_qmp(result, 'return', {})
101
102 self.wait_until_completed()
103
104 self.vm.shutdown()
105 self.assertTrue(iotests.compare_images(test_img, image),
106 'target image does not match source after backup')
107
108 def test_pause_drive_backup(self):
109 self.do_test_pause('drive-backup', target_img, target_img)
110
111 def test_pause_blockdev_backup(self):
112 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
113
114 def test_medium_not_found(self):
115 if iotests.qemu_default_machine != 'pc':
116 return
117
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')
121
122 def test_medium_not_found_blockdev_backup(self):
123 if iotests.qemu_default_machine != 'pc':
124 return
125
126 result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
127 target='drive1', sync='full')
128 self.assert_qmp(result, 'error/class', 'GenericError')
129
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')
134
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')
140
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')
144
145 def test_device_not_found(self):
146 self.do_test_device_not_found('drive-backup', device='nonexistent',
147 target=target_img, sync='full')
148
149 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
150 target='drive0', sync='full')
151
152 self.do_test_device_not_found('blockdev-backup', device='drive0',
153 target='nonexistent', sync='full')
154
155 self.do_test_device_not_found('blockdev-backup', device='nonexistent',
156 target='nonexistent', sync='full')
157
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')
162
163 class TestSetSpeed(iotests.QMPTestCase):
164 def setUp(self):
165 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
166
167 self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
168 self.vm.launch()
169
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
177
178 def do_test_set_speed(self, cmd, target):
179 self.assert_no_active_block_jobs()
180
181 self.vm.pause_drive('drive0')
182 result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
183 self.assert_qmp(result, 'return', {})
184
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)
189
190 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
191 self.assert_qmp(result, 'return', {})
192
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)
197
198 event = self.cancel_and_wait(resume=True)
199 self.assert_qmp(event, 'data/type', 'backup')
200
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', {})
206
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)
210
211 event = self.cancel_and_wait(resume=True)
212 self.assert_qmp(event, 'data/type', 'backup')
213
214 def test_set_speed_drive_backup(self):
215 self.do_test_set_speed('drive-backup', target_img)
216
217 def test_set_speed_blockdev_backup(self):
218 self.do_test_set_speed('blockdev-backup', 'drive1')
219
220 def do_test_set_speed_invalid(self, cmd, target):
221 self.assert_no_active_block_jobs()
222
223 result = self.vm.qmp(cmd, device='drive0',
224 target=target, sync='full', speed=-1)
225 self.assert_qmp(result, 'error/class', 'GenericError')
226
227 self.assert_no_active_block_jobs()
228
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', {})
233
234 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
235 self.assert_qmp(result, 'error/class', 'GenericError')
236
237 event = self.cancel_and_wait(resume=True)
238 self.assert_qmp(event, 'data/type', 'backup')
239
240 def test_set_speed_invalid_drive_backup(self):
241 self.do_test_set_speed_invalid('drive-backup', target_img)
242
243 def test_set_speed_invalid_blockdev_backup(self):
244 self.do_test_set_speed_invalid('blockdev-backup', 'drive1')
245
246 class TestSingleTransaction(iotests.QMPTestCase):
247 def setUp(self):
248 qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
249
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()
254
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
262
263 def do_test_cancel(self, cmd, target):
264 self.assert_no_active_block_jobs()
265
266 result = self.vm.qmp('transaction', actions=[{
267 'type': cmd,
268 'data': { 'device': 'drive0',
269 'target': target,
270 'sync': 'full' },
271 }
272 ])
273
274 self.assert_qmp(result, 'return', {})
275
276 event = self.cancel_and_wait()
277 self.assert_qmp(event, 'data/type', 'backup')
278
279 def test_cancel_drive_backup(self):
280 self.do_test_cancel('drive-backup', target_img)
281
282 def test_cancel_blockdev_backup(self):
283 self.do_test_cancel('blockdev-backup', 'drive1')
284
285 def do_test_pause(self, cmd, target, image):
286 self.assert_no_active_block_jobs()
287
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' },
294 }
295 ])
296 self.assert_qmp(result, 'return', {})
297
298 result = self.vm.qmp('block-job-pause', device='drive0')
299 self.assert_qmp(result, 'return', {})
300
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')
305
306 time.sleep(1)
307 result = self.vm.qmp('query-block-jobs')
308 self.assert_qmp(result, 'return[0]/offset', offset)
309
310 result = self.vm.qmp('block-job-resume', device='drive0')
311 self.assert_qmp(result, 'return', {})
312
313 self.wait_until_completed()
314
315 self.vm.shutdown()
316 self.assertTrue(iotests.compare_images(test_img, image),
317 'target image does not match source after backup')
318
319 def test_pause_drive_backup(self):
320 self.do_test_pause('drive-backup', target_img, target_img)
321
322 def test_pause_blockdev_backup(self):
323 self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
324
325 def do_test_medium_not_found(self, cmd, target):
326 if iotests.qemu_default_machine != 'pc':
327 return
328
329 result = self.vm.qmp('transaction', actions=[{
330 'type': cmd,
331 'data': { 'device': 'drive2', # CD-ROM
332 'target': target,
333 'sync': 'full' },
334 }
335 ])
336 self.assert_qmp(result, 'error/class', 'GenericError')
337
338 def test_medium_not_found_drive_backup(self):
339 self.do_test_medium_not_found('drive-backup', target_img)
340
341 def test_medium_not_found_blockdev_backup(self):
342 self.do_test_medium_not_found('blockdev-backup', 'drive1')
343
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' },
351 }
352 ])
353 self.assert_qmp(result, 'error/class', 'GenericError')
354
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' },
362 }
363 ])
364 self.assert_qmp(result, 'error/class', 'GenericError')
365
366 result = self.vm.qmp('transaction', actions=[{
367 'type': 'blockdev-backup',
368 'data': { 'device': 'nonexistent',
369 'target': 'drive1',
370 'sync': 'full' },
371 }
372 ])
373 self.assert_qmp(result, 'error/class', 'GenericError')
374
375 result = self.vm.qmp('transaction', actions=[{
376 'type': 'blockdev-backup',
377 'data': { 'device': 'drive0',
378 'target': 'nonexistent',
379 'sync': 'full' },
380 }
381 ])
382 self.assert_qmp(result, 'error/class', 'GenericError')
383
384 result = self.vm.qmp('transaction', actions=[{
385 'type': 'blockdev-backup',
386 'data': { 'device': 'nonexistent',
387 'target': 'nonexistent',
388 'sync': 'full' },
389 }
390 ])
391 self.assert_qmp(result, 'error/class', 'GenericError')
392
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' },
399 }
400 ])
401 self.assert_qmp(result, 'error/class', 'GenericError')
402
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': {},
413 }
414 ])
415 self.assert_qmp(result, 'error/class', 'GenericError')
416 self.assert_no_active_block_jobs()
417
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': {},
426 }
427 ])
428 self.assert_qmp(result, 'error/class', 'GenericError')
429 self.assert_no_active_block_jobs()
430
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': {},
439 }
440 ])
441 self.assert_qmp(result, 'error/class', 'GenericError')
442 self.assert_no_active_block_jobs()
443
444
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')}]
449
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
457
458 def do_prepare_drives(self, fmt, args):
459 self.vm = iotests.VM().add_drive(test_img)
460
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)
464
465 self.vm.launch()
466
467 def do_test_compress_complete(self, cmd, format, **args):
468 self.do_prepare_drives(format['type'], format['args'])
469
470 self.assert_no_active_block_jobs()
471
472 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
473 self.assert_qmp(result, 'return', {})
474
475 self.wait_until_completed()
476
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')
481
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')
486
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')
490
491 def do_test_compress_cancel(self, cmd, format, **args):
492 self.do_prepare_drives(format['type'], format['args'])
493
494 self.assert_no_active_block_jobs()
495
496 result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
497 self.assert_qmp(result, 'return', {})
498
499 event = self.cancel_and_wait()
500 self.assert_qmp(event, 'data/type', 'backup')
501
502 self.vm.shutdown()
503
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')
508
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')
512
513 def do_test_compress_pause(self, cmd, format, **args):
514 self.do_prepare_drives(format['type'], format['args'])
515
516 self.assert_no_active_block_jobs()
517
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', {})
521
522 result = self.vm.qmp('block-job-pause', device='drive0')
523 self.assert_qmp(result, 'return', {})
524
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')
529
530 time.sleep(1)
531 result = self.vm.qmp('query-block-jobs')
532 self.assert_qmp(result, 'return[0]/offset', offset)
533
534 result = self.vm.qmp('block-job-resume', device='drive0')
535 self.assert_qmp(result, 'return', {})
536
537 self.wait_until_completed()
538
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')
543
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')
548
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')
552
553 if __name__ == '__main__':
554 iotests.main(supported_fmts=['raw', 'qcow2'])