xref: /openbmc/qemu/tests/qemu-iotests/118 (revision 7ef295ea)
1#!/usr/bin/env python
2#
3# Test case for the QMP 'change' command and all other associated
4# commands
5#
6# Copyright (C) 2015 Red Hat, Inc.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20#
21
22import os
23import stat
24import time
25import iotests
26from iotests import qemu_img
27
28old_img = os.path.join(iotests.test_dir, 'test0.img')
29new_img = os.path.join(iotests.test_dir, 'test1.img')
30
31class ChangeBaseClass(iotests.QMPTestCase):
32    has_opened = False
33    has_closed = False
34
35    def process_events(self):
36        for event in self.vm.get_qmp_events(wait=False):
37            if (event['event'] == 'DEVICE_TRAY_MOVED' and
38                event['data']['device'] == 'drive0'):
39                if event['data']['tray-open'] == False:
40                    self.has_closed = True
41                else:
42                    self.has_opened = True
43
44    def wait_for_open(self):
45        if not self.has_real_tray:
46            return
47
48        timeout = time.clock() + 3
49        while not self.has_opened and time.clock() < timeout:
50            self.process_events()
51        if not self.has_opened:
52            self.fail('Timeout while waiting for the tray to open')
53
54    def wait_for_close(self):
55        if not self.has_real_tray:
56            return
57
58        timeout = time.clock() + 3
59        while not self.has_closed and time.clock() < timeout:
60            self.process_events()
61        if not self.has_opened:
62            self.fail('Timeout while waiting for the tray to close')
63
64class GeneralChangeTestsBaseClass(ChangeBaseClass):
65    def test_change(self):
66        result = self.vm.qmp('change', device='drive0', target=new_img,
67                                       arg=iotests.imgfmt)
68        self.assert_qmp(result, 'return', {})
69
70        self.wait_for_open()
71        self.wait_for_close()
72
73        result = self.vm.qmp('query-block')
74        if self.has_real_tray:
75            self.assert_qmp(result, 'return[0]/tray_open', False)
76        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
77
78    def test_blockdev_change_medium(self):
79        result = self.vm.qmp('blockdev-change-medium', device='drive0',
80                                                       filename=new_img,
81                                                       format=iotests.imgfmt)
82        self.assert_qmp(result, 'return', {})
83
84        self.wait_for_open()
85        self.wait_for_close()
86
87        result = self.vm.qmp('query-block')
88        if self.has_real_tray:
89            self.assert_qmp(result, 'return[0]/tray_open', False)
90        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
91
92    def test_eject(self):
93        result = self.vm.qmp('eject', device='drive0', force=True)
94        self.assert_qmp(result, 'return', {})
95
96        self.wait_for_open()
97
98        result = self.vm.qmp('query-block')
99        if self.has_real_tray:
100            self.assert_qmp(result, 'return[0]/tray_open', True)
101        self.assert_qmp_absent(result, 'return[0]/inserted')
102
103    def test_tray_eject_change(self):
104        result = self.vm.qmp('eject', device='drive0', force=True)
105        self.assert_qmp(result, 'return', {})
106
107        self.wait_for_open()
108
109        result = self.vm.qmp('query-block')
110        if self.has_real_tray:
111            self.assert_qmp(result, 'return[0]/tray_open', True)
112        self.assert_qmp_absent(result, 'return[0]/inserted')
113
114        result = self.vm.qmp('blockdev-change-medium', device='drive0',
115                                                       filename=new_img,
116                                                       format=iotests.imgfmt)
117        self.assert_qmp(result, 'return', {})
118
119        self.wait_for_close()
120
121        result = self.vm.qmp('query-block')
122        if self.has_real_tray:
123            self.assert_qmp(result, 'return[0]/tray_open', False)
124        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
125
126    def test_tray_open_close(self):
127        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
128        self.assert_qmp(result, 'return', {})
129
130        self.wait_for_open()
131
132        result = self.vm.qmp('query-block')
133        if self.has_real_tray:
134            self.assert_qmp(result, 'return[0]/tray_open', True)
135        if self.was_empty == True:
136            self.assert_qmp_absent(result, 'return[0]/inserted')
137        else:
138            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
139
140        result = self.vm.qmp('blockdev-close-tray', device='drive0')
141        self.assert_qmp(result, 'return', {})
142
143        if self.has_real_tray or not self.was_empty:
144            self.wait_for_close()
145
146        result = self.vm.qmp('query-block')
147        if self.has_real_tray:
148            self.assert_qmp(result, 'return[0]/tray_open', False)
149        if self.was_empty == True:
150            self.assert_qmp_absent(result, 'return[0]/inserted')
151        else:
152            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
153
154    def test_tray_eject_close(self):
155        result = self.vm.qmp('eject', device='drive0', force=True)
156        self.assert_qmp(result, 'return', {})
157
158        self.wait_for_open()
159
160        result = self.vm.qmp('query-block')
161        if self.has_real_tray:
162            self.assert_qmp(result, 'return[0]/tray_open', True)
163        self.assert_qmp_absent(result, 'return[0]/inserted')
164
165        result = self.vm.qmp('blockdev-close-tray', device='drive0')
166        self.assert_qmp(result, 'return', {})
167
168        self.wait_for_close()
169
170        result = self.vm.qmp('query-block')
171        if self.has_real_tray:
172            self.assert_qmp(result, 'return[0]/tray_open', False)
173        self.assert_qmp_absent(result, 'return[0]/inserted')
174
175    def test_tray_open_change(self):
176        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
177        self.assert_qmp(result, 'return', {})
178
179        self.wait_for_open()
180
181        result = self.vm.qmp('query-block')
182        if self.has_real_tray:
183            self.assert_qmp(result, 'return[0]/tray_open', True)
184        if self.was_empty == True:
185            self.assert_qmp_absent(result, 'return[0]/inserted')
186        else:
187            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
188
189        result = self.vm.qmp('blockdev-change-medium', device='drive0',
190                                                       filename=new_img,
191                                                       format=iotests.imgfmt)
192        self.assert_qmp(result, 'return', {})
193
194        self.wait_for_close()
195
196        result = self.vm.qmp('query-block')
197        if self.has_real_tray:
198            self.assert_qmp(result, 'return[0]/tray_open', False)
199        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
200
201    def test_cycle(self):
202        result = self.vm.qmp('blockdev-add',
203                             options={'node-name': 'new',
204                                      'driver': iotests.imgfmt,
205                                      'file': {'filename': new_img,
206                                               'driver': 'file'}})
207        self.assert_qmp(result, 'return', {})
208
209        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
210        self.assert_qmp(result, 'return', {})
211
212        self.wait_for_open()
213
214        result = self.vm.qmp('query-block')
215        if self.has_real_tray:
216            self.assert_qmp(result, 'return[0]/tray_open', True)
217        if self.was_empty == True:
218            self.assert_qmp_absent(result, 'return[0]/inserted')
219        else:
220            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
221
222        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
223        self.assert_qmp(result, 'return', {})
224
225        result = self.vm.qmp('query-block')
226        if self.has_real_tray:
227            self.assert_qmp(result, 'return[0]/tray_open', True)
228        self.assert_qmp_absent(result, 'return[0]/inserted')
229
230        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
231                                                       node_name='new')
232        self.assert_qmp(result, 'return', {})
233
234        result = self.vm.qmp('query-block')
235        if self.has_real_tray:
236            self.assert_qmp(result, 'return[0]/tray_open', True)
237        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
238
239        result = self.vm.qmp('blockdev-close-tray', device='drive0')
240        self.assert_qmp(result, 'return', {})
241
242        self.wait_for_close()
243
244        result = self.vm.qmp('query-block')
245        if self.has_real_tray:
246            self.assert_qmp(result, 'return[0]/tray_open', False)
247        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
248
249    def test_close_on_closed(self):
250        result = self.vm.qmp('blockdev-close-tray', device='drive0')
251        # Should be a no-op
252        self.assert_qmp(result, 'return', {})
253        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
254
255    def test_remove_on_closed(self):
256        if not self.has_real_tray:
257            return
258
259        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
260        self.assert_qmp(result, 'error/class', 'GenericError')
261
262    def test_insert_on_closed(self):
263        if not self.has_real_tray:
264            return
265
266        result = self.vm.qmp('blockdev-add',
267                             options={'node-name': 'new',
268                                      'driver': iotests.imgfmt,
269                                      'file': {'filename': new_img,
270                                               'driver': 'file'}})
271        self.assert_qmp(result, 'return', {})
272
273        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
274                                                       node_name='new')
275        self.assert_qmp(result, 'error/class', 'GenericError')
276
277class TestInitiallyFilled(GeneralChangeTestsBaseClass):
278    was_empty = False
279
280    def setUp(self, media, interface):
281        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
282        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
283        self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface)
284        self.vm.launch()
285
286    def tearDown(self):
287        self.vm.shutdown()
288        os.remove(old_img)
289        os.remove(new_img)
290
291    def test_insert_on_filled(self):
292        result = self.vm.qmp('blockdev-add',
293                             options={'node-name': 'new',
294                                      'driver': iotests.imgfmt,
295                                      'file': {'filename': new_img,
296                                               'driver': 'file'}})
297        self.assert_qmp(result, 'return', {})
298
299        result = self.vm.qmp('blockdev-open-tray', device='drive0')
300        self.assert_qmp(result, 'return', {})
301
302        self.wait_for_open()
303
304        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
305                                                       node_name='new')
306        self.assert_qmp(result, 'error/class', 'GenericError')
307
308class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
309    was_empty = True
310
311    def setUp(self, media, interface):
312        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
313        self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
314        self.vm.launch()
315
316    def tearDown(self):
317        self.vm.shutdown()
318        os.remove(new_img)
319
320    def test_remove_on_empty(self):
321        result = self.vm.qmp('blockdev-open-tray', device='drive0')
322        self.assert_qmp(result, 'return', {})
323
324        self.wait_for_open()
325
326        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
327        # Should be a no-op
328        self.assert_qmp(result, 'return', {})
329
330class TestCDInitiallyFilled(TestInitiallyFilled):
331    TestInitiallyFilled = TestInitiallyFilled
332    has_real_tray = True
333
334    def setUp(self):
335        self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
336
337class TestCDInitiallyEmpty(TestInitiallyEmpty):
338    TestInitiallyEmpty = TestInitiallyEmpty
339    has_real_tray = True
340
341    def setUp(self):
342        self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
343
344class TestFloppyInitiallyFilled(TestInitiallyFilled):
345    TestInitiallyFilled = TestInitiallyFilled
346    has_real_tray = False
347
348    def setUp(self):
349        self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
350
351class TestFloppyInitiallyEmpty(TestInitiallyEmpty):
352    TestInitiallyEmpty = TestInitiallyEmpty
353    has_real_tray = False
354
355    def setUp(self):
356        self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
357        # FDDs not having a real tray and there not being a medium inside the
358        # tray at startup means the tray will be considered open
359        self.has_opened = True
360
361class TestChangeReadOnly(ChangeBaseClass):
362    def setUp(self):
363        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
364        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
365        self.vm = iotests.VM()
366
367    def tearDown(self):
368        self.vm.shutdown()
369        os.chmod(old_img, 0666)
370        os.chmod(new_img, 0666)
371        os.remove(old_img)
372        os.remove(new_img)
373
374    def test_ro_ro_retain(self):
375        os.chmod(old_img, 0444)
376        os.chmod(new_img, 0444)
377        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
378        self.vm.launch()
379
380        result = self.vm.qmp('query-block')
381        self.assert_qmp(result, 'return[0]/inserted/ro', True)
382        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
383
384        result = self.vm.qmp('blockdev-change-medium', device='drive0',
385                                                       filename=new_img,
386                                                       format=iotests.imgfmt,
387                                                       read_only_mode='retain')
388        self.assert_qmp(result, 'return', {})
389
390        result = self.vm.qmp('query-block')
391        self.assert_qmp(result, 'return[0]/inserted/ro', True)
392        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
393
394    def test_ro_rw_retain(self):
395        os.chmod(old_img, 0444)
396        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
397        self.vm.launch()
398
399        result = self.vm.qmp('query-block')
400        self.assert_qmp(result, 'return[0]/inserted/ro', True)
401        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
402
403        result = self.vm.qmp('blockdev-change-medium', device='drive0',
404                                                       filename=new_img,
405                                                       format=iotests.imgfmt,
406                                                       read_only_mode='retain')
407        self.assert_qmp(result, 'return', {})
408
409        result = self.vm.qmp('query-block')
410        self.assert_qmp(result, 'return[0]/inserted/ro', True)
411        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
412
413    def test_rw_ro_retain(self):
414        os.chmod(new_img, 0444)
415        self.vm.add_drive(old_img, 'media=disk', 'floppy')
416        self.vm.launch()
417
418        result = self.vm.qmp('query-block')
419        self.assert_qmp(result, 'return[0]/inserted/ro', False)
420        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
421
422        result = self.vm.qmp('blockdev-change-medium', device='drive0',
423                                                       filename=new_img,
424                                                       format=iotests.imgfmt,
425                                                       read_only_mode='retain')
426        self.assert_qmp(result, 'error/class', 'GenericError')
427
428        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
429
430        result = self.vm.qmp('query-block')
431        self.assert_qmp(result, 'return[0]/inserted/ro', False)
432        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
433
434    def test_ro_rw(self):
435        os.chmod(old_img, 0444)
436        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
437        self.vm.launch()
438
439        result = self.vm.qmp('query-block')
440        self.assert_qmp(result, 'return[0]/inserted/ro', True)
441        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
442
443        result = self.vm.qmp('blockdev-change-medium',
444                             device='drive0',
445                             filename=new_img,
446                             format=iotests.imgfmt,
447                             read_only_mode='read-write')
448        self.assert_qmp(result, 'return', {})
449
450        result = self.vm.qmp('query-block')
451        self.assert_qmp(result, 'return[0]/inserted/ro', False)
452        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
453
454    def test_rw_ro(self):
455        os.chmod(new_img, 0444)
456        self.vm.add_drive(old_img, 'media=disk', 'floppy')
457        self.vm.launch()
458
459        result = self.vm.qmp('query-block')
460        self.assert_qmp(result, 'return[0]/inserted/ro', False)
461        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
462
463        result = self.vm.qmp('blockdev-change-medium',
464                             device='drive0',
465                             filename=new_img,
466                             format=iotests.imgfmt,
467                             read_only_mode='read-only')
468        self.assert_qmp(result, 'return', {})
469
470        result = self.vm.qmp('query-block')
471        self.assert_qmp(result, 'return[0]/inserted/ro', True)
472        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
473
474    def test_make_rw_ro(self):
475        self.vm.add_drive(old_img, 'media=disk', 'floppy')
476        self.vm.launch()
477
478        result = self.vm.qmp('query-block')
479        self.assert_qmp(result, 'return[0]/inserted/ro', False)
480        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
481
482        result = self.vm.qmp('blockdev-change-medium',
483                             device='drive0',
484                             filename=new_img,
485                             format=iotests.imgfmt,
486                             read_only_mode='read-only')
487        self.assert_qmp(result, 'return', {})
488
489        result = self.vm.qmp('query-block')
490        self.assert_qmp(result, 'return[0]/inserted/ro', True)
491        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
492
493    def test_make_ro_rw(self):
494        os.chmod(new_img, 0444)
495        self.vm.add_drive(old_img, 'media=disk', 'floppy')
496        self.vm.launch()
497
498        result = self.vm.qmp('query-block')
499        self.assert_qmp(result, 'return[0]/inserted/ro', False)
500        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
501
502        result = self.vm.qmp('blockdev-change-medium',
503                             device='drive0',
504                             filename=new_img,
505                             format=iotests.imgfmt,
506                             read_only_mode='read-write')
507        self.assert_qmp(result, 'error/class', 'GenericError')
508
509        result = self.vm.qmp('query-block')
510        self.assert_qmp(result, 'return[0]/inserted/ro', False)
511        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
512
513    def test_make_rw_ro_by_retain(self):
514        os.chmod(old_img, 0444)
515        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
516        self.vm.launch()
517
518        result = self.vm.qmp('query-block')
519        self.assert_qmp(result, 'return[0]/inserted/ro', True)
520        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
521
522        result = self.vm.qmp('blockdev-change-medium', device='drive0',
523                                                       filename=new_img,
524                                                       format=iotests.imgfmt,
525                                                       read_only_mode='retain')
526        self.assert_qmp(result, 'return', {})
527
528        result = self.vm.qmp('query-block')
529        self.assert_qmp(result, 'return[0]/inserted/ro', True)
530        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
531
532    def test_make_ro_rw_by_retain(self):
533        os.chmod(new_img, 0444)
534        self.vm.add_drive(old_img, 'media=disk', 'floppy')
535        self.vm.launch()
536
537        result = self.vm.qmp('query-block')
538        self.assert_qmp(result, 'return[0]/inserted/ro', False)
539        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
540
541        result = self.vm.qmp('blockdev-change-medium', device='drive0',
542                                                       filename=new_img,
543                                                       format=iotests.imgfmt,
544                                                       read_only_mode='retain')
545        self.assert_qmp(result, 'error/class', 'GenericError')
546
547        result = self.vm.qmp('query-block')
548        self.assert_qmp(result, 'return[0]/inserted/ro', False)
549        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
550
551    def test_rw_ro_cycle(self):
552        os.chmod(new_img, 0444)
553        self.vm.add_drive(old_img, 'media=disk', 'floppy')
554        self.vm.launch()
555
556        result = self.vm.qmp('query-block')
557        self.assert_qmp(result, 'return[0]/inserted/ro', False)
558        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
559
560        result = self.vm.qmp('blockdev-add',
561                             options={'node-name': 'new',
562                                      'driver': iotests.imgfmt,
563                                      'read-only': True,
564                                      'file': {'filename': new_img,
565                                               'driver': 'file'}})
566        self.assert_qmp(result, 'return', {})
567
568        result = self.vm.qmp('query-block')
569        self.assert_qmp(result, 'return[0]/inserted/ro', False)
570        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
571
572        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
573        self.assert_qmp(result, 'return', {})
574
575        result = self.vm.qmp('query-block')
576        self.assert_qmp_absent(result, 'return[0]/inserted')
577
578        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
579                                                       node_name='new')
580        self.assert_qmp(result, 'return', {})
581
582        result = self.vm.qmp('query-block')
583        self.assert_qmp(result, 'return[0]/inserted/ro', True)
584        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
585
586        result = self.vm.qmp('query-block')
587        self.assert_qmp(result, 'return[0]/inserted/ro', True)
588        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
589
590GeneralChangeTestsBaseClass = None
591TestInitiallyFilled = None
592TestInitiallyEmpty = None
593
594
595class TestBlockJobsAfterCycle(ChangeBaseClass):
596    def setUp(self):
597        qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
598
599        self.vm = iotests.VM()
600        self.vm.launch()
601
602        result = self.vm.qmp('blockdev-add',
603                             options={'id': 'drive0',
604                                      'driver': 'null-co'})
605        self.assert_qmp(result, 'return', {})
606
607        result = self.vm.qmp('query-block')
608        self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
609
610        # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
611        # is not necessary
612        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
613        self.assert_qmp(result, 'return', {})
614
615        result = self.vm.qmp('query-block')
616        self.assert_qmp_absent(result, 'return[0]/inserted')
617
618        result = self.vm.qmp('blockdev-add',
619                             options={'node-name': 'node0',
620                                      'driver': iotests.imgfmt,
621                                      'file': {'filename': old_img,
622                                               'driver': 'file'}})
623        self.assert_qmp(result, 'return', {})
624
625        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
626                                                       node_name='node0')
627        self.assert_qmp(result, 'return', {})
628
629        result = self.vm.qmp('query-block')
630        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
631
632    def tearDown(self):
633        self.vm.shutdown()
634        os.remove(old_img)
635        try:
636            os.remove(new_img)
637        except OSError:
638            pass
639
640    def test_snapshot_and_commit(self):
641        # We need backing file support
642        if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
643            return
644
645        result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
646                                                       snapshot_file=new_img,
647                                                       format=iotests.imgfmt)
648        self.assert_qmp(result, 'return', {})
649
650        result = self.vm.qmp('query-block')
651        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
652        self.assert_qmp(result,
653                        'return[0]/inserted/image/backing-image/filename',
654                        old_img)
655
656        result = self.vm.qmp('block-commit', device='drive0')
657        self.assert_qmp(result, 'return', {})
658
659        self.vm.event_wait(name='BLOCK_JOB_READY')
660
661        result = self.vm.qmp('query-block-jobs')
662        self.assert_qmp(result, 'return[0]/device', 'drive0')
663
664        result = self.vm.qmp('block-job-complete', device='drive0')
665        self.assert_qmp(result, 'return', {})
666
667        self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
668
669
670if __name__ == '__main__':
671    if iotests.qemu_default_machine != 'pc':
672        # We need floppy and IDE CD-ROM
673        iotests.notrun('not suitable for this machine type: %s' %
674                       iotests.qemu_default_machine)
675    # Need to support image creation
676    iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
677                                 'vmdk', 'raw', 'vhdx', 'qed'])
678