qemu

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

055 (22815B)


      1 #!/usr/bin/env python3
      2 # group: rw
      3 #
      4 # Tests for drive-backup and blockdev-backup
      5 #
      6 # Copyright (C) 2013, 2014 Red Hat, Inc.
      7 #
      8 # Based on 041.
      9 #
     10 # This program is free software; you can redistribute it and/or modify
     11 # it under the terms of the GNU General Public License as published by
     12 # the Free Software Foundation; either version 2 of the License, or
     13 # (at your option) any later version.
     14 #
     15 # This program is distributed in the hope that it will be useful,
     16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18 # GNU General Public License for more details.
     19 #
     20 # You should have received a copy of the GNU General Public License
     21 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22 #
     23 
     24 import time
     25 import os
     26 import iotests
     27 from iotests import qemu_img, qemu_io
     28 
     29 test_img = os.path.join(iotests.test_dir, 'test.img')
     30 target_img = os.path.join(iotests.test_dir, 'target.img')
     31 blockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img')
     32 
     33 image_len = 64 * 1024 * 1024 # MB
     34 
     35 def setUpModule():
     36     qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len))
     37     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img)
     38     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img)
     39     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img)
     40     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img)
     41     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img)
     42     qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img)
     43 
     44 def tearDownModule():
     45     os.remove(test_img)
     46 
     47 
     48 class TestSingleDrive(iotests.QMPTestCase):
     49     def setUp(self):
     50         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
     51 
     52         self.vm = iotests.VM()
     53         self.vm.add_drive('blkdebug::' + test_img, 'node-name=source')
     54         self.vm.add_drive(blockdev_target_img, 'node-name=target',
     55                           interface="none")
     56         if iotests.qemu_default_machine == 'pc':
     57             self.vm.add_drive(None, 'media=cdrom', 'ide')
     58         self.vm.launch()
     59 
     60     def tearDown(self):
     61         self.vm.shutdown()
     62         os.remove(blockdev_target_img)
     63         try:
     64             os.remove(target_img)
     65         except OSError:
     66             pass
     67 
     68     def do_test_cancel(self, cmd, target):
     69         self.assert_no_active_block_jobs()
     70 
     71         self.vm.pause_drive('drive0')
     72         result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
     73         self.assert_qmp(result, 'return', {})
     74 
     75         event = self.cancel_and_wait(resume=True)
     76         self.assert_qmp(event, 'data/type', 'backup')
     77 
     78     def test_cancel_drive_backup(self):
     79         self.do_test_cancel('drive-backup', target_img)
     80 
     81     def test_cancel_blockdev_backup(self):
     82         self.do_test_cancel('blockdev-backup', 'drive1')
     83 
     84     def do_test_pause(self, cmd, target, image):
     85         self.assert_no_active_block_jobs()
     86 
     87         self.vm.pause_drive('drive0')
     88         result = self.vm.qmp(cmd, device='drive0',
     89                              target=target, sync='full')
     90         self.assert_qmp(result, 'return', {})
     91 
     92         self.pause_job('drive0', wait=False)
     93         self.vm.resume_drive('drive0')
     94         self.pause_wait('drive0')
     95 
     96         result = self.vm.qmp('query-block-jobs')
     97         offset = self.dictpath(result, 'return[0]/offset')
     98 
     99         time.sleep(0.5)
    100         result = self.vm.qmp('query-block-jobs')
    101         self.assert_qmp(result, 'return[0]/offset', offset)
    102 
    103         result = self.vm.qmp('block-job-resume', device='drive0')
    104         self.assert_qmp(result, 'return', {})
    105 
    106         self.wait_until_completed()
    107 
    108         self.vm.shutdown()
    109         self.assertTrue(iotests.compare_images(test_img, image),
    110                         'target image does not match source after backup')
    111 
    112     def test_pause_drive_backup(self):
    113         self.do_test_pause('drive-backup', target_img, target_img)
    114 
    115     def test_pause_blockdev_backup(self):
    116         self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
    117 
    118     def do_test_resize_blockdev_backup(self, device, node):
    119         def pre_finalize():
    120             result = self.vm.qmp('block_resize', device=device, size=65536)
    121             self.assert_qmp(result, 'error/class', 'GenericError')
    122 
    123             result = self.vm.qmp('block_resize', node_name=node, size=65536)
    124             self.assert_qmp(result, 'error/class', 'GenericError')
    125 
    126         result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0',
    127                              target='drive1', sync='full', auto_finalize=False,
    128                              auto_dismiss=False)
    129         self.assert_qmp(result, 'return', {})
    130 
    131         self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize)
    132 
    133     def test_source_resize_blockdev_backup(self):
    134         self.do_test_resize_blockdev_backup('drive0', 'source')
    135 
    136     def test_target_resize_blockdev_backup(self):
    137         self.do_test_resize_blockdev_backup('drive1', 'target')
    138 
    139     def do_test_target_size(self, size):
    140         result = self.vm.qmp('block_resize', device='drive1', size=size)
    141         self.assert_qmp(result, 'return', {})
    142 
    143         result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0',
    144                              target='drive1', sync='full')
    145         self.assert_qmp(result, 'error/class', 'GenericError')
    146 
    147     def test_small_target(self):
    148         self.do_test_target_size(image_len // 2)
    149 
    150     def test_large_target(self):
    151         self.do_test_target_size(image_len * 2)
    152 
    153     def test_medium_not_found(self):
    154         if iotests.qemu_default_machine != 'pc':
    155             return
    156 
    157         result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM
    158                              target=target_img, sync='full')
    159         self.assert_qmp(result, 'error/class', 'GenericError')
    160 
    161     def test_medium_not_found_blockdev_backup(self):
    162         if iotests.qemu_default_machine != 'pc':
    163             return
    164 
    165         result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
    166                              target='drive1', sync='full')
    167         self.assert_qmp(result, 'error/class', 'GenericError')
    168 
    169     def test_image_not_found(self):
    170         result = self.vm.qmp('drive-backup', device='drive0',
    171                              target=target_img, sync='full', mode='existing')
    172         self.assert_qmp(result, 'error/class', 'GenericError')
    173 
    174     def test_invalid_format(self):
    175         result = self.vm.qmp('drive-backup', device='drive0',
    176                              target=target_img, sync='full',
    177                              format='spaghetti-noodles')
    178         self.assert_qmp(result, 'error/class', 'GenericError')
    179 
    180     def do_test_device_not_found(self, cmd, **args):
    181         result = self.vm.qmp(cmd, **args)
    182         self.assert_qmp(result, 'error/class', 'GenericError')
    183 
    184     def test_device_not_found(self):
    185         self.do_test_device_not_found('drive-backup', device='nonexistent',
    186                                       target=target_img, sync='full')
    187 
    188         self.do_test_device_not_found('blockdev-backup', device='nonexistent',
    189                                       target='drive0', sync='full')
    190 
    191         self.do_test_device_not_found('blockdev-backup', device='drive0',
    192                                       target='nonexistent', sync='full')
    193 
    194         self.do_test_device_not_found('blockdev-backup', device='nonexistent',
    195                                       target='nonexistent', sync='full')
    196 
    197     def test_target_is_source(self):
    198         result = self.vm.qmp('blockdev-backup', device='drive0',
    199                              target='drive0', sync='full')
    200         self.assert_qmp(result, 'error/class', 'GenericError')
    201 
    202 class TestSetSpeed(iotests.QMPTestCase):
    203     def setUp(self):
    204         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
    205 
    206         self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
    207         self.vm.add_drive(blockdev_target_img, interface="none")
    208         self.vm.launch()
    209 
    210     def tearDown(self):
    211         self.vm.shutdown()
    212         os.remove(blockdev_target_img)
    213         try:
    214             os.remove(target_img)
    215         except OSError:
    216             pass
    217 
    218     def do_test_set_speed(self, cmd, target):
    219         self.assert_no_active_block_jobs()
    220 
    221         self.vm.pause_drive('drive0')
    222         result = self.vm.qmp(cmd, device='drive0', target=target, sync='full')
    223         self.assert_qmp(result, 'return', {})
    224 
    225         # Default speed is 0
    226         result = self.vm.qmp('query-block-jobs')
    227         self.assert_qmp(result, 'return[0]/device', 'drive0')
    228         self.assert_qmp(result, 'return[0]/speed', 0)
    229 
    230         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
    231         self.assert_qmp(result, 'return', {})
    232 
    233         # Ensure the speed we set was accepted
    234         result = self.vm.qmp('query-block-jobs')
    235         self.assert_qmp(result, 'return[0]/device', 'drive0')
    236         self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
    237 
    238         event = self.cancel_and_wait(resume=True)
    239         self.assert_qmp(event, 'data/type', 'backup')
    240 
    241         # Check setting speed option works
    242         self.vm.pause_drive('drive0')
    243         result = self.vm.qmp(cmd, device='drive0',
    244                              target=target, sync='full', speed=4*1024*1024)
    245         self.assert_qmp(result, 'return', {})
    246 
    247         result = self.vm.qmp('query-block-jobs')
    248         self.assert_qmp(result, 'return[0]/device', 'drive0')
    249         self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
    250 
    251         event = self.cancel_and_wait(resume=True)
    252         self.assert_qmp(event, 'data/type', 'backup')
    253 
    254     def test_set_speed_drive_backup(self):
    255         self.do_test_set_speed('drive-backup', target_img)
    256 
    257     def test_set_speed_blockdev_backup(self):
    258         self.do_test_set_speed('blockdev-backup', 'drive1')
    259 
    260     def do_test_set_speed_invalid(self, cmd, target):
    261         self.assert_no_active_block_jobs()
    262 
    263         result = self.vm.qmp(cmd, device='drive0',
    264                              target=target, sync='full', speed=-1)
    265         self.assert_qmp(result, 'error/class', 'GenericError')
    266 
    267         self.assert_no_active_block_jobs()
    268 
    269         self.vm.pause_drive('drive0')
    270         result = self.vm.qmp(cmd, device='drive0',
    271                              target=target, sync='full')
    272         self.assert_qmp(result, 'return', {})
    273 
    274         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
    275         self.assert_qmp(result, 'error/class', 'GenericError')
    276 
    277         event = self.cancel_and_wait(resume=True)
    278         self.assert_qmp(event, 'data/type', 'backup')
    279 
    280     def test_set_speed_invalid_drive_backup(self):
    281         self.do_test_set_speed_invalid('drive-backup', target_img)
    282 
    283     def test_set_speed_invalid_blockdev_backup(self):
    284         self.do_test_set_speed_invalid('blockdev-backup',  'drive1')
    285 
    286 # Note: We cannot use pause_drive() here, or the transaction command
    287 #       would stall.  Instead, we limit the block job speed here.
    288 class TestSingleTransaction(iotests.QMPTestCase):
    289     def setUp(self):
    290         qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len))
    291 
    292         self.vm = iotests.VM().add_drive(test_img)
    293         self.vm.add_drive(blockdev_target_img, interface="none")
    294         if iotests.qemu_default_machine == 'pc':
    295             self.vm.add_drive(None, 'media=cdrom', 'ide')
    296         self.vm.launch()
    297 
    298     def tearDown(self):
    299         self.vm.shutdown()
    300         os.remove(blockdev_target_img)
    301         try:
    302             os.remove(target_img)
    303         except OSError:
    304             pass
    305 
    306     def do_test_cancel(self, cmd, target):
    307         self.assert_no_active_block_jobs()
    308 
    309         result = self.vm.qmp('transaction', actions=[{
    310                 'type': cmd,
    311                 'data': { 'device': 'drive0',
    312                           'target': target,
    313                           'sync': 'full',
    314                           'speed': 64 * 1024 },
    315             }
    316         ])
    317 
    318         self.assert_qmp(result, 'return', {})
    319 
    320         event = self.cancel_and_wait()
    321         self.assert_qmp(event, 'data/type', 'backup')
    322 
    323     def test_cancel_drive_backup(self):
    324         self.do_test_cancel('drive-backup', target_img)
    325 
    326     def test_cancel_blockdev_backup(self):
    327         self.do_test_cancel('blockdev-backup', 'drive1')
    328 
    329     def do_test_pause(self, cmd, target, image):
    330         self.assert_no_active_block_jobs()
    331 
    332         result = self.vm.qmp('transaction', actions=[{
    333                 'type': cmd,
    334                 'data': { 'device': 'drive0',
    335                           'target': target,
    336                           'sync': 'full',
    337                           'speed': 64 * 1024 },
    338             }
    339         ])
    340         self.assert_qmp(result, 'return', {})
    341 
    342         self.pause_job('drive0', wait=False)
    343 
    344         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
    345         self.assert_qmp(result, 'return', {})
    346 
    347         self.pause_wait('drive0')
    348 
    349         result = self.vm.qmp('query-block-jobs')
    350         offset = self.dictpath(result, 'return[0]/offset')
    351 
    352         time.sleep(0.5)
    353         result = self.vm.qmp('query-block-jobs')
    354         self.assert_qmp(result, 'return[0]/offset', offset)
    355 
    356         result = self.vm.qmp('block-job-resume', device='drive0')
    357         self.assert_qmp(result, 'return', {})
    358 
    359         self.wait_until_completed()
    360 
    361         self.vm.shutdown()
    362         self.assertTrue(iotests.compare_images(test_img, image),
    363                         'target image does not match source after backup')
    364 
    365     def test_pause_drive_backup(self):
    366         self.do_test_pause('drive-backup', target_img, target_img)
    367 
    368     def test_pause_blockdev_backup(self):
    369         self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
    370 
    371     def do_test_medium_not_found(self, cmd, target):
    372         if iotests.qemu_default_machine != 'pc':
    373             return
    374 
    375         result = self.vm.qmp('transaction', actions=[{
    376                 'type': cmd,
    377                 'data': { 'device': 'drive2', # CD-ROM
    378                           'target': target,
    379                           'sync': 'full' },
    380             }
    381         ])
    382         self.assert_qmp(result, 'error/class', 'GenericError')
    383 
    384     def test_medium_not_found_drive_backup(self):
    385         self.do_test_medium_not_found('drive-backup', target_img)
    386 
    387     def test_medium_not_found_blockdev_backup(self):
    388         self.do_test_medium_not_found('blockdev-backup', 'drive1')
    389 
    390     def test_image_not_found(self):
    391         result = self.vm.qmp('transaction', actions=[{
    392                 'type': 'drive-backup',
    393                 'data': { 'device': 'drive0',
    394                           'mode': 'existing',
    395                           'target': target_img,
    396                           'sync': 'full' },
    397             }
    398         ])
    399         self.assert_qmp(result, 'error/class', 'GenericError')
    400 
    401     def test_device_not_found(self):
    402         result = self.vm.qmp('transaction', actions=[{
    403                 'type': 'drive-backup',
    404                 'data': { 'device': 'nonexistent',
    405                           'mode': 'existing',
    406                           'target': target_img,
    407                           'sync': 'full' },
    408             }
    409         ])
    410         self.assert_qmp(result, 'error/class', 'GenericError')
    411 
    412         result = self.vm.qmp('transaction', actions=[{
    413                 'type': 'blockdev-backup',
    414                 'data': { 'device': 'nonexistent',
    415                           'target': 'drive1',
    416                           'sync': 'full' },
    417             }
    418         ])
    419         self.assert_qmp(result, 'error/class', 'GenericError')
    420 
    421         result = self.vm.qmp('transaction', actions=[{
    422                 'type': 'blockdev-backup',
    423                 'data': { 'device': 'drive0',
    424                           'target': 'nonexistent',
    425                           'sync': 'full' },
    426             }
    427         ])
    428         self.assert_qmp(result, 'error/class', 'GenericError')
    429 
    430         result = self.vm.qmp('transaction', actions=[{
    431                 'type': 'blockdev-backup',
    432                 'data': { 'device': 'nonexistent',
    433                           'target': 'nonexistent',
    434                           'sync': 'full' },
    435             }
    436         ])
    437         self.assert_qmp(result, 'error/class', 'GenericError')
    438 
    439     def test_target_is_source(self):
    440         result = self.vm.qmp('transaction', actions=[{
    441                 'type': 'blockdev-backup',
    442                 'data': { 'device': 'drive0',
    443                           'target': 'drive0',
    444                           'sync': 'full' },
    445             }
    446         ])
    447         self.assert_qmp(result, 'error/class', 'GenericError')
    448 
    449     def test_abort(self):
    450         result = self.vm.qmp('transaction', actions=[{
    451                 'type': 'drive-backup',
    452                 'data': { 'device': 'nonexistent',
    453                           'mode': 'existing',
    454                           'target': target_img,
    455                           'sync': 'full' },
    456             }, {
    457                 'type': 'Abort',
    458                 'data': {},
    459             }
    460         ])
    461         self.assert_qmp(result, 'error/class', 'GenericError')
    462         self.assert_no_active_block_jobs()
    463 
    464         result = self.vm.qmp('transaction', actions=[{
    465                 'type': 'blockdev-backup',
    466                 'data': { 'device': 'nonexistent',
    467                           'target': 'drive1',
    468                           'sync': 'full' },
    469             }, {
    470                 'type': 'Abort',
    471                 'data': {},
    472             }
    473         ])
    474         self.assert_qmp(result, 'error/class', 'GenericError')
    475         self.assert_no_active_block_jobs()
    476 
    477         result = self.vm.qmp('transaction', actions=[{
    478                 'type': 'blockdev-backup',
    479                 'data': { 'device': 'drive0',
    480                           'target': 'nonexistent',
    481                           'sync': 'full' },
    482             }, {
    483                 'type': 'Abort',
    484                 'data': {},
    485             }
    486         ])
    487         self.assert_qmp(result, 'error/class', 'GenericError')
    488         self.assert_no_active_block_jobs()
    489 
    490 
    491 class TestCompressedToQcow2(iotests.QMPTestCase):
    492     image_len = 64 * 1024 * 1024 # MB
    493     target_fmt = {'type': 'qcow2', 'args': (), 'drive-opts': ''}
    494 
    495     def tearDown(self):
    496         self.vm.shutdown()
    497         os.remove(blockdev_target_img)
    498         try:
    499             os.remove(target_img)
    500         except OSError:
    501             pass
    502 
    503     def do_prepare_drives(self, attach_target):
    504         self.vm = iotests.VM().add_drive('blkdebug::' + test_img,
    505                                          opts=self.target_fmt['drive-opts'])
    506 
    507         qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img,
    508                  str(self.image_len), *self.target_fmt['args'])
    509         if attach_target:
    510             self.vm.add_drive(blockdev_target_img,
    511                               img_format=self.target_fmt['type'],
    512                               interface="none",
    513                               opts=self.target_fmt['drive-opts'])
    514 
    515         self.vm.launch()
    516 
    517     def do_test_compress_complete(self, cmd, attach_target, **args):
    518         self.do_prepare_drives(attach_target)
    519 
    520         self.assert_no_active_block_jobs()
    521 
    522         result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
    523         self.assert_qmp(result, 'return', {})
    524 
    525         self.wait_until_completed()
    526 
    527         self.vm.shutdown()
    528         self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
    529                                                iotests.imgfmt,
    530                                                self.target_fmt['type']),
    531                         'target image does not match source after backup')
    532 
    533     def test_complete_compress_drive_backup(self):
    534         self.do_test_compress_complete('drive-backup', False,
    535                                        target=blockdev_target_img,
    536                                        mode='existing')
    537 
    538     def test_complete_compress_blockdev_backup(self):
    539         self.do_test_compress_complete('blockdev-backup',
    540                                        True, target='drive1')
    541 
    542     def do_test_compress_cancel(self, cmd, attach_target, **args):
    543         self.do_prepare_drives(attach_target)
    544 
    545         self.assert_no_active_block_jobs()
    546 
    547         self.vm.pause_drive('drive0')
    548         result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
    549         self.assert_qmp(result, 'return', {})
    550 
    551         event = self.cancel_and_wait(resume=True)
    552         self.assert_qmp(event, 'data/type', 'backup')
    553 
    554         self.vm.shutdown()
    555 
    556     def test_compress_cancel_drive_backup(self):
    557         self.do_test_compress_cancel('drive-backup', False,
    558                                      target=blockdev_target_img,
    559                                      mode='existing')
    560 
    561     def test_compress_cancel_blockdev_backup(self):
    562         self.do_test_compress_cancel('blockdev-backup', True,
    563                                      target='drive1')
    564 
    565     def do_test_compress_pause(self, cmd, attach_target, **args):
    566         self.do_prepare_drives(attach_target)
    567 
    568         self.assert_no_active_block_jobs()
    569 
    570         self.vm.pause_drive('drive0')
    571         result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
    572         self.assert_qmp(result, 'return', {})
    573 
    574         self.pause_job('drive0', wait=False)
    575         self.vm.resume_drive('drive0')
    576         self.pause_wait('drive0')
    577 
    578         result = self.vm.qmp('query-block-jobs')
    579         offset = self.dictpath(result, 'return[0]/offset')
    580 
    581         time.sleep(0.5)
    582         result = self.vm.qmp('query-block-jobs')
    583         self.assert_qmp(result, 'return[0]/offset', offset)
    584 
    585         result = self.vm.qmp('block-job-resume', device='drive0')
    586         self.assert_qmp(result, 'return', {})
    587 
    588         self.wait_until_completed()
    589 
    590         self.vm.shutdown()
    591         self.assertTrue(iotests.compare_images(test_img, blockdev_target_img,
    592                                                iotests.imgfmt,
    593                                                self.target_fmt['type']),
    594                         'target image does not match source after backup')
    595 
    596     def test_compress_pause_drive_backup(self):
    597         self.do_test_compress_pause('drive-backup', False,
    598                                     target=blockdev_target_img,
    599                                     mode='existing')
    600 
    601     def test_compress_pause_blockdev_backup(self):
    602         self.do_test_compress_pause('blockdev-backup', True,
    603                                     target='drive1')
    604 
    605 
    606 class TestCompressedToVmdk(TestCompressedToQcow2):
    607     target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized'),
    608                   'drive-opts': 'cache.no-flush=on'}
    609 
    610     @iotests.skip_if_unsupported(['vmdk'])
    611     def setUp(self):
    612         pass
    613 
    614 
    615 if __name__ == '__main__':
    616     iotests.main(supported_fmts=['raw', 'qcow2'],
    617                  supported_protocols=['file'])