qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

118 (28060B)


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