cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     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    elif interface == 'scsi':
     37        return 'scsi-cd'
     38    else:
     39        return None
     40
     41class 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
     74class 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
    283class 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
    326class 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)
    358def 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
    374create_basic_test_classes()
    375
    376class 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
    620GeneralChangeTestsBaseClass = None
    621TestInitiallyFilled = None
    622TestInitiallyEmpty = None
    623
    624
    625class 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
    698if __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'])