xref: /openbmc/qemu/tests/qemu-iotests/118 (revision d5938f29)
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        with iotests.Timeout(3, 'Timeout while waiting for the tray to open'):
57            while not self.has_opened:
58                self.process_events()
59
60    def wait_for_close(self):
61        if not self.has_real_tray:
62            return
63
64        with iotests.Timeout(3, 'Timeout while waiting for the tray to close'):
65            while not self.has_closed:
66                self.process_events()
67
68class GeneralChangeTestsBaseClass(ChangeBaseClass):
69
70    device_name = 'qdev0'
71
72    def test_change(self):
73        result = self.vm.qmp('change', device='drive0', target=new_img,
74                                       arg=iotests.imgfmt)
75        self.assert_qmp(result, 'return', {})
76
77        self.wait_for_open()
78        self.wait_for_close()
79
80        result = self.vm.qmp('query-block')
81        if self.has_real_tray:
82            self.assert_qmp(result, 'return[0]/tray_open', False)
83        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
84
85    def test_blockdev_change_medium(self):
86        result = self.vm.qmp('blockdev-change-medium',
87                             id=self.device_name, filename=new_img,
88                             format=iotests.imgfmt)
89
90        self.assert_qmp(result, 'return', {})
91
92        self.wait_for_open()
93        self.wait_for_close()
94
95        result = self.vm.qmp('query-block')
96        if self.has_real_tray:
97            self.assert_qmp(result, 'return[0]/tray_open', False)
98        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
99
100    def test_eject(self):
101        result = self.vm.qmp('eject', id=self.device_name, force=True)
102        self.assert_qmp(result, 'return', {})
103
104        self.wait_for_open()
105
106        result = self.vm.qmp('query-block')
107        if self.has_real_tray:
108            self.assert_qmp(result, 'return[0]/tray_open', True)
109        self.assert_qmp_absent(result, 'return[0]/inserted')
110
111    def test_tray_eject_change(self):
112        result = self.vm.qmp('eject', id=self.device_name, force=True)
113        self.assert_qmp(result, 'return', {})
114
115        self.wait_for_open()
116
117        result = self.vm.qmp('query-block')
118        if self.has_real_tray:
119            self.assert_qmp(result, 'return[0]/tray_open', True)
120        self.assert_qmp_absent(result, 'return[0]/inserted')
121
122        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
123                             filename=new_img, format=iotests.imgfmt)
124        self.assert_qmp(result, 'return', {})
125
126        self.wait_for_close()
127
128        result = self.vm.qmp('query-block')
129        if self.has_real_tray:
130            self.assert_qmp(result, 'return[0]/tray_open', False)
131        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
132
133    def test_tray_open_close(self):
134        result = self.vm.qmp('blockdev-open-tray',
135                             id=self.device_name, force=True)
136        self.assert_qmp(result, 'return', {})
137
138        self.wait_for_open()
139
140        result = self.vm.qmp('query-block')
141        if self.has_real_tray:
142            self.assert_qmp(result, 'return[0]/tray_open', True)
143        if self.was_empty == True:
144            self.assert_qmp_absent(result, 'return[0]/inserted')
145        else:
146            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
147
148        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
149        self.assert_qmp(result, 'return', {})
150
151        if self.has_real_tray or not self.was_empty:
152            self.wait_for_close()
153
154        result = self.vm.qmp('query-block')
155        if self.has_real_tray:
156            self.assert_qmp(result, 'return[0]/tray_open', False)
157        if self.was_empty == True:
158            self.assert_qmp_absent(result, 'return[0]/inserted')
159        else:
160            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
161
162    def test_tray_eject_close(self):
163        result = self.vm.qmp('eject', id=self.device_name, force=True)
164        self.assert_qmp(result, 'return', {})
165
166        self.wait_for_open()
167
168        result = self.vm.qmp('query-block')
169        if self.has_real_tray:
170            self.assert_qmp(result, 'return[0]/tray_open', True)
171        self.assert_qmp_absent(result, 'return[0]/inserted')
172
173        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
174        self.assert_qmp(result, 'return', {})
175
176        self.wait_for_close()
177
178        result = self.vm.qmp('query-block')
179        if self.has_real_tray:
180            self.assert_qmp(result, 'return[0]/tray_open', False)
181        self.assert_qmp_absent(result, 'return[0]/inserted')
182
183    def test_tray_open_change(self):
184        result = self.vm.qmp('blockdev-open-tray', id=self.device_name,
185                                                   force=True)
186        self.assert_qmp(result, 'return', {})
187
188        self.wait_for_open()
189
190        result = self.vm.qmp('query-block')
191        if self.has_real_tray:
192            self.assert_qmp(result, 'return[0]/tray_open', True)
193        if self.was_empty == True:
194            self.assert_qmp_absent(result, 'return[0]/inserted')
195        else:
196            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
197
198        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
199                                                       filename=new_img,
200                                                       format=iotests.imgfmt)
201        self.assert_qmp(result, 'return', {})
202
203        self.wait_for_close()
204
205        result = self.vm.qmp('query-block')
206        if self.has_real_tray:
207            self.assert_qmp(result, 'return[0]/tray_open', False)
208        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
209
210    def test_cycle(self, read_only_node=False):
211        result = self.vm.qmp('blockdev-add',
212                             node_name='new',
213                             driver=iotests.imgfmt,
214                             read_only=read_only_node,
215                             file={'filename': new_img,
216                                    'driver': 'file'})
217        self.assert_qmp(result, 'return', {})
218
219        result = self.vm.qmp('blockdev-open-tray',
220                             id=self.device_name, force=True)
221        self.assert_qmp(result, 'return', {})
222
223        self.wait_for_open()
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        if self.was_empty == True:
229            self.assert_qmp_absent(result, 'return[0]/inserted')
230        else:
231            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
232
233        result = self.vm.qmp('blockdev-remove-medium',
234                             id=self.device_name)
235        self.assert_qmp(result, 'return', {})
236
237        result = self.vm.qmp('query-block')
238        if self.has_real_tray:
239            self.assert_qmp(result, 'return[0]/tray_open', True)
240        self.assert_qmp_absent(result, 'return[0]/inserted')
241
242        result = self.vm.qmp('blockdev-insert-medium',
243                             id=self.device_name, node_name='new')
244        self.assert_qmp(result, 'return', {})
245
246        result = self.vm.qmp('query-block')
247        if self.has_real_tray:
248            self.assert_qmp(result, 'return[0]/tray_open', True)
249        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
250
251        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
252        self.assert_qmp(result, 'return', {})
253
254        self.wait_for_close()
255
256        result = self.vm.qmp('query-block')
257        if self.has_real_tray:
258            self.assert_qmp(result, 'return[0]/tray_open', False)
259        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
260
261    def test_cycle_read_only_media(self):
262        self.test_cycle(True)
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.assertEqual(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, 0o666)
394        os.chmod(new_img, 0o666)
395        os.remove(old_img)
396        os.remove(new_img)
397
398    def test_ro_ro_retain(self):
399        os.chmod(old_img, 0o444)
400        os.chmod(new_img, 0o444)
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, 0o444)
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, 0o444)
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.assertEqual(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, 0o444)
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, 0o444)
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, 0o444)
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, 0o444)
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, 0o444)
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, 0o444)
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