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