These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / 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 class TestSingleDrive(iotests.QMPTestCase):
33     image_len = 64 * 1024 * 1024 # MB
34
35     def setUp(self):
36         # Write data to the image so we can compare later
37         qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len))
38         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', 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 -P0xdc 67043328 64k', test_img)
42         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
43
44         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
45         if iotests.qemu_default_machine == 'pc':
46             self.vm.add_drive(None, 'media=cdrom', 'ide')
47         self.vm.launch()
48
49     def tearDown(self):
50         self.vm.shutdown()
51         os.remove(test_img)
52         os.remove(blockdev_target_img)
53         try:
54             os.remove(target_img)
55         except OSError:
56             pass
57
58     def do_test_cancel(self, cmd, target):
59         self.assert_no_active_block_jobs()
60
61         result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
62         self.assert_qmp(result, 'return', {})
63
64         event = self.cancel_and_wait()
65         self.assert_qmp(event, 'data/type', 'backup')
66
67     def test_cancel_drive_backup(self):
68         self.do_test_cancel('drive-backup', target_img)
69
70     def test_cancel_blockdev_backup(self):
71         self.do_test_cancel('blockdev-backup', 'drive1')
72
73     def do_test_pause(self, cmd, target, image):
74         self.assert_no_active_block_jobs()
75
76         self.vm.pause_drive('drive0')
77         result = self.vm.qmp(cmd, device='drive0',
78                              target=target, sync='full')
79         self.assert_qmp(result, 'return', {})
80
81         result = self.vm.qmp('block-job-pause', device='drive0')
82         self.assert_qmp(result, 'return', {})
83
84         self.vm.resume_drive('drive0')
85         time.sleep(1)
86         result = self.vm.qmp('query-block-jobs')
87         offset = self.dictpath(result, 'return[0]/offset')
88
89         time.sleep(1)
90         result = self.vm.qmp('query-block-jobs')
91         self.assert_qmp(result, 'return[0]/offset', offset)
92
93         result = self.vm.qmp('block-job-resume', device='drive0')
94         self.assert_qmp(result, 'return', {})
95
96         self.wait_until_completed()
97
98         self.vm.shutdown()
99         self.assertTrue(iotests.compare_images(test_img, image),
100                         'target image does not match source after backup')
101
102     def test_pause_drive_backup(self):
103         self.do_test_pause('drive-backup', target_img, target_img)
104
105     def test_pause_blockdev_backup(self):
106         self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
107
108     def test_medium_not_found(self):
109         if iotests.qemu_default_machine != 'pc':
110             return
111
112         result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM
113                              target=target_img, sync='full')
114         self.assert_qmp(result, 'error/class', 'GenericError')
115
116     def test_medium_not_found_blockdev_backup(self):
117         if iotests.qemu_default_machine != 'pc':
118             return
119
120         result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
121                              target='drive1', sync='full')
122         self.assert_qmp(result, 'error/class', 'GenericError')
123
124     def test_image_not_found(self):
125         result = self.vm.qmp('drive-backup', device='drive0',
126                              target=target_img, sync='full', mode='existing')
127         self.assert_qmp(result, 'error/class', 'GenericError')
128
129     def test_invalid_format(self):
130         result = self.vm.qmp('drive-backup', device='drive0',
131                              target=target_img, sync='full',
132                              format='spaghetti-noodles')
133         self.assert_qmp(result, 'error/class', 'GenericError')
134
135     def do_test_device_not_found(self, cmd, **args):
136         result = self.vm.qmp(cmd, **args)
137         if cmd == 'drive-backup':
138             self.assert_qmp(result, 'error/class', 'DeviceNotFound')
139         else:
140             self.assert_qmp(result, 'error/class', 'GenericError')
141
142     def test_device_not_found(self):
143         self.do_test_device_not_found('drive-backup', device='nonexistent',
144                                       target=target_img, sync='full')
145
146         self.do_test_device_not_found('blockdev-backup', device='nonexistent',
147                                       target='drive0', sync='full')
148
149         self.do_test_device_not_found('blockdev-backup', device='drive0',
150                                       target='nonexistent', sync='full')
151
152         self.do_test_device_not_found('blockdev-backup', device='nonexistent',
153                                       target='nonexistent', sync='full')
154
155     def test_target_is_source(self):
156         result = self.vm.qmp('blockdev-backup', device='drive0',
157                              target='drive0', sync='full')
158         self.assert_qmp(result, 'error/class', 'GenericError')
159
160 class TestSetSpeed(iotests.QMPTestCase):
161     image_len = 80 * 1024 * 1024 # MB
162
163     def setUp(self):
164         qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len))
165         qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img)
166         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
167
168         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
169         self.vm.launch()
170
171     def tearDown(self):
172         self.vm.shutdown()
173         os.remove(test_img)
174         os.remove(blockdev_target_img)
175         try:
176             os.remove(target_img)
177         except OSError:
178             pass
179
180     def do_test_set_speed(self, cmd, target):
181         self.assert_no_active_block_jobs()
182
183         self.vm.pause_drive('drive0')
184         result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
185         self.assert_qmp(result, 'return', {})
186
187         # Default speed is 0
188         result = self.vm.qmp('query-block-jobs')
189         self.assert_qmp(result, 'return[0]/device', 'drive0')
190         self.assert_qmp(result, 'return[0]/speed', 0)
191
192         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
193         self.assert_qmp(result, 'return', {})
194
195         # Ensure the speed we set was accepted
196         result = self.vm.qmp('query-block-jobs')
197         self.assert_qmp(result, 'return[0]/device', 'drive0')
198         self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
199
200         event = self.cancel_and_wait(resume=True)
201         self.assert_qmp(event, 'data/type', 'backup')
202
203         # Check setting speed option works
204         self.vm.pause_drive('drive0')
205         result = self.vm.qmp(cmd, device='drive0',
206                              target=target, sync='full', speed=4*1024*1024)
207         self.assert_qmp(result, 'return', {})
208
209         result = self.vm.qmp('query-block-jobs')
210         self.assert_qmp(result, 'return[0]/device', 'drive0')
211         self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
212
213         event = self.cancel_and_wait(resume=True)
214         self.assert_qmp(event, 'data/type', 'backup')
215
216     def test_set_speed_drive_backup(self):
217         self.do_test_set_speed('drive-backup', target_img)
218
219     def test_set_speed_blockdev_backup(self):
220         self.do_test_set_speed('blockdev-backup', 'drive1')
221
222     def do_test_set_speed_invalid(self, cmd, target):
223         self.assert_no_active_block_jobs()
224
225         result = self.vm.qmp(cmd, device='drive0',
226                              target=target, sync='full', speed=-1)
227         self.assert_qmp(result, 'error/class', 'GenericError')
228
229         self.assert_no_active_block_jobs()
230
231         self.vm.pause_drive('drive0')
232         result = self.vm.qmp(cmd, device='drive0',
233                              target=target, sync='full')
234         self.assert_qmp(result, 'return', {})
235
236         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
237         self.assert_qmp(result, 'error/class', 'GenericError')
238
239         event = self.cancel_and_wait(resume=True)
240         self.assert_qmp(event, 'data/type', 'backup')
241
242     def test_set_speed_invalid_drive_backup(self):
243         self.do_test_set_speed_invalid('drive-backup', target_img)
244
245     def test_set_speed_invalid_blockdev_backup(self):
246         self.do_test_set_speed_invalid('blockdev-backup',  'drive1')
247
248 class TestSingleTransaction(iotests.QMPTestCase):
249     image_len = 64 * 1024 * 1024 # MB
250
251     def setUp(self):
252         qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len))
253         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img)
254         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
255         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
256         qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img)
257         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
258
259         self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
260         if iotests.qemu_default_machine == 'pc':
261             self.vm.add_drive(None, 'media=cdrom', 'ide')
262         self.vm.launch()
263
264     def tearDown(self):
265         self.vm.shutdown()
266         os.remove(test_img)
267         os.remove(blockdev_target_img)
268         try:
269             os.remove(target_img)
270         except OSError:
271             pass
272
273     def do_test_cancel(self, cmd, target):
274         self.assert_no_active_block_jobs()
275
276         result = self.vm.qmp('transaction', actions=[{
277                 'type': cmd,
278                 'data': { 'device': 'drive0',
279                           'target': target,
280                           'sync': 'full' },
281             }
282         ])
283
284         self.assert_qmp(result, 'return', {})
285
286         event = self.cancel_and_wait()
287         self.assert_qmp(event, 'data/type', 'backup')
288
289     def test_cancel_drive_backup(self):
290         self.do_test_cancel('drive-backup', target_img)
291
292     def test_cancel_blockdev_backup(self):
293         self.do_test_cancel('blockdev-backup', 'drive1')
294
295     def do_test_pause(self, cmd, target, image):
296         self.assert_no_active_block_jobs()
297
298         self.vm.pause_drive('drive0')
299         result = self.vm.qmp('transaction', actions=[{
300                 'type': cmd,
301                 'data': { 'device': 'drive0',
302                           'target': target,
303                           'sync': 'full' },
304             }
305         ])
306         self.assert_qmp(result, 'return', {})
307
308         result = self.vm.qmp('block-job-pause', device='drive0')
309         self.assert_qmp(result, 'return', {})
310
311         self.vm.resume_drive('drive0')
312         time.sleep(1)
313         result = self.vm.qmp('query-block-jobs')
314         offset = self.dictpath(result, 'return[0]/offset')
315
316         time.sleep(1)
317         result = self.vm.qmp('query-block-jobs')
318         self.assert_qmp(result, 'return[0]/offset', offset)
319
320         result = self.vm.qmp('block-job-resume', device='drive0')
321         self.assert_qmp(result, 'return', {})
322
323         self.wait_until_completed()
324
325         self.vm.shutdown()
326         self.assertTrue(iotests.compare_images(test_img, image),
327                         'target image does not match source after backup')
328
329     def test_pause_drive_backup(self):
330         self.do_test_pause('drive-backup', target_img, target_img)
331
332     def test_pause_blockdev_backup(self):
333         self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
334
335     def do_test_medium_not_found(self, cmd, target):
336         if iotests.qemu_default_machine != 'pc':
337             return
338
339         result = self.vm.qmp('transaction', actions=[{
340                 'type': cmd,
341                 'data': { 'device': 'drive2', # CD-ROM
342                           'target': target,
343                           'sync': 'full' },
344             }
345         ])
346         self.assert_qmp(result, 'error/class', 'GenericError')
347
348     def test_medium_not_found_drive_backup(self):
349         self.do_test_medium_not_found('drive-backup', target_img)
350
351     def test_medium_not_found_blockdev_backup(self):
352         self.do_test_medium_not_found('blockdev-backup', 'drive1')
353
354     def test_image_not_found(self):
355         result = self.vm.qmp('transaction', actions=[{
356                 'type': 'drive-backup',
357                 'data': { 'device': 'drive0',
358                           'mode': 'existing',
359                           'target': target_img,
360                           'sync': 'full' },
361             }
362         ])
363         self.assert_qmp(result, 'error/class', 'GenericError')
364
365     def test_device_not_found(self):
366         result = self.vm.qmp('transaction', actions=[{
367                 'type': 'drive-backup',
368                 'data': { 'device': 'nonexistent',
369                           'mode': 'existing',
370                           'target': target_img,
371                           'sync': 'full' },
372             }
373         ])
374         self.assert_qmp(result, 'error/class', 'DeviceNotFound')
375
376         result = self.vm.qmp('transaction', actions=[{
377                 'type': 'blockdev-backup',
378                 'data': { 'device': 'nonexistent',
379                           'target': 'drive1',
380                           'sync': 'full' },
381             }
382         ])
383         self.assert_qmp(result, 'error/class', 'GenericError')
384
385         result = self.vm.qmp('transaction', actions=[{
386                 'type': 'blockdev-backup',
387                 'data': { 'device': 'drive0',
388                           'target': 'nonexistent',
389                           'sync': 'full' },
390             }
391         ])
392         self.assert_qmp(result, 'error/class', 'GenericError')
393
394         result = self.vm.qmp('transaction', actions=[{
395                 'type': 'blockdev-backup',
396                 'data': { 'device': 'nonexistent',
397                           'target': 'nonexistent',
398                           'sync': 'full' },
399             }
400         ])
401         self.assert_qmp(result, 'error/class', 'GenericError')
402
403     def test_target_is_source(self):
404         result = self.vm.qmp('transaction', actions=[{
405                 'type': 'blockdev-backup',
406                 'data': { 'device': 'drive0',
407                           'target': 'drive0',
408                           'sync': 'full' },
409             }
410         ])
411         self.assert_qmp(result, 'error/class', 'GenericError')
412
413     def test_abort(self):
414         result = self.vm.qmp('transaction', actions=[{
415                 'type': 'drive-backup',
416                 'data': { 'device': 'nonexistent',
417                           'mode': 'existing',
418                           'target': target_img,
419                           'sync': 'full' },
420             }, {
421                 'type': 'Abort',
422                 'data': {},
423             }
424         ])
425         self.assert_qmp(result, 'error/class', 'GenericError')
426         self.assert_no_active_block_jobs()
427
428         result = self.vm.qmp('transaction', actions=[{
429                 'type': 'blockdev-backup',
430                 'data': { 'device': 'nonexistent',
431                           'target': 'drive1',
432                           'sync': 'full' },
433             }, {
434                 'type': 'Abort',
435                 'data': {},
436             }
437         ])
438         self.assert_qmp(result, 'error/class', 'GenericError')
439         self.assert_no_active_block_jobs()
440
441         result = self.vm.qmp('transaction', actions=[{
442                 'type': 'blockdev-backup',
443                 'data': { 'device': 'drive0',
444                           'target': 'nonexistent',
445                           'sync': 'full' },
446             }, {
447                 'type': 'Abort',
448                 'data': {},
449             }
450         ])
451         self.assert_qmp(result, 'error/class', 'GenericError')
452         self.assert_no_active_block_jobs()
453
454 if __name__ == '__main__':
455     iotests.main(supported_fmts=['raw', 'qcow2'])