1adfe2030SMax Reitz#!/usr/bin/env python 2adfe2030SMax Reitz# 3adfe2030SMax Reitz# Test case for the QMP 'change' command and all other associated 4adfe2030SMax Reitz# commands 5adfe2030SMax Reitz# 6adfe2030SMax Reitz# Copyright (C) 2015 Red Hat, Inc. 7adfe2030SMax Reitz# 8adfe2030SMax Reitz# This program is free software; you can redistribute it and/or modify 9adfe2030SMax Reitz# it under the terms of the GNU General Public License as published by 10adfe2030SMax Reitz# the Free Software Foundation; either version 2 of the License, or 11adfe2030SMax Reitz# (at your option) any later version. 12adfe2030SMax Reitz# 13adfe2030SMax Reitz# This program is distributed in the hope that it will be useful, 14adfe2030SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 15adfe2030SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16adfe2030SMax Reitz# GNU General Public License for more details. 17adfe2030SMax Reitz# 18adfe2030SMax Reitz# You should have received a copy of the GNU General Public License 19adfe2030SMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 20adfe2030SMax Reitz# 21adfe2030SMax Reitz 22adfe2030SMax Reitzimport os 23adfe2030SMax Reitzimport stat 24adfe2030SMax Reitzimport time 25adfe2030SMax Reitzimport iotests 26adfe2030SMax Reitzfrom iotests import qemu_img 27adfe2030SMax Reitz 28adfe2030SMax Reitzold_img = os.path.join(iotests.test_dir, 'test0.img') 29adfe2030SMax Reitznew_img = os.path.join(iotests.test_dir, 'test1.img') 30adfe2030SMax Reitz 311d701e0eSMax Reitzdef interface_to_device_name(interface): 321d701e0eSMax Reitz if interface == 'ide': 331d701e0eSMax Reitz return 'ide-cd' 341d701e0eSMax Reitz elif interface == 'floppy': 351d701e0eSMax Reitz return 'floppy' 36dfa26a11SKevin Wolf elif interface == 'scsi': 37dfa26a11SKevin Wolf return 'scsi-cd' 381d701e0eSMax Reitz else: 391d701e0eSMax Reitz return None 401d701e0eSMax Reitz 41adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase): 42adfe2030SMax Reitz has_opened = False 43adfe2030SMax Reitz has_closed = False 44adfe2030SMax Reitz 4519462c4bSKevin Wolf device_name = 'qdev0' 4619462c4bSKevin Wolf use_drive = False 4719462c4bSKevin Wolf 48adfe2030SMax Reitz def process_events(self): 49adfe2030SMax Reitz for event in self.vm.get_qmp_events(wait=False): 50adfe2030SMax Reitz if (event['event'] == 'DEVICE_TRAY_MOVED' and 5119462c4bSKevin Wolf (event['data']['device'] == 'drive0' or 5219462c4bSKevin Wolf event['data']['id'] == self.device_name)): 53adfe2030SMax Reitz if event['data']['tray-open'] == False: 54adfe2030SMax Reitz self.has_closed = True 55adfe2030SMax Reitz else: 56adfe2030SMax Reitz self.has_opened = True 57adfe2030SMax Reitz 58adfe2030SMax Reitz def wait_for_open(self): 59abb3e55bSMax Reitz if not self.has_real_tray: 60abb3e55bSMax Reitz return 61abb3e55bSMax Reitz 62d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to open'): 63d8336c6bSKevin Wolf while not self.has_opened: 64adfe2030SMax Reitz self.process_events() 65adfe2030SMax Reitz 66adfe2030SMax Reitz def wait_for_close(self): 67abb3e55bSMax Reitz if not self.has_real_tray: 68abb3e55bSMax Reitz return 69abb3e55bSMax Reitz 70d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to close'): 71d8336c6bSKevin Wolf while not self.has_closed: 72adfe2030SMax Reitz self.process_events() 73adfe2030SMax Reitz 74adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass): 75486b88bdSKevin Wolf 76adfe2030SMax Reitz def test_change(self): 7719462c4bSKevin Wolf # 'change' requires a drive name, so skip the test for blockdev 7819462c4bSKevin Wolf if not self.use_drive: 7919462c4bSKevin Wolf return 8019462c4bSKevin Wolf 81adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 82adfe2030SMax Reitz arg=iotests.imgfmt) 83adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 84adfe2030SMax Reitz 85adfe2030SMax Reitz self.wait_for_open() 86adfe2030SMax Reitz self.wait_for_close() 87adfe2030SMax Reitz 88adfe2030SMax Reitz result = self.vm.qmp('query-block') 89abb3e55bSMax Reitz if self.has_real_tray: 90adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 91adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 92adfe2030SMax Reitz 93adfe2030SMax Reitz def test_blockdev_change_medium(self): 94486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 95486b88bdSKevin Wolf id=self.device_name, filename=new_img, 96adfe2030SMax Reitz format=iotests.imgfmt) 97486b88bdSKevin Wolf 98adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 99adfe2030SMax Reitz 100adfe2030SMax Reitz self.wait_for_open() 101adfe2030SMax Reitz self.wait_for_close() 102adfe2030SMax Reitz 103adfe2030SMax Reitz result = self.vm.qmp('query-block') 104abb3e55bSMax Reitz if self.has_real_tray: 105adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 106adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 107adfe2030SMax Reitz 108adfe2030SMax Reitz def test_eject(self): 109486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 110adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 111adfe2030SMax Reitz 112adfe2030SMax Reitz self.wait_for_open() 113adfe2030SMax Reitz 114adfe2030SMax Reitz result = self.vm.qmp('query-block') 115abb3e55bSMax Reitz if self.has_real_tray: 116adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 117adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 118adfe2030SMax Reitz 119adfe2030SMax Reitz def test_tray_eject_change(self): 120486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 121adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 122adfe2030SMax Reitz 123adfe2030SMax Reitz self.wait_for_open() 124adfe2030SMax Reitz 125adfe2030SMax Reitz result = self.vm.qmp('query-block') 126abb3e55bSMax Reitz if self.has_real_tray: 127adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 128adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 129adfe2030SMax Reitz 130486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 131486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 132adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 133adfe2030SMax Reitz 134adfe2030SMax Reitz self.wait_for_close() 135adfe2030SMax Reitz 136adfe2030SMax Reitz result = self.vm.qmp('query-block') 137abb3e55bSMax Reitz if self.has_real_tray: 138adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 139adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 140adfe2030SMax Reitz 141adfe2030SMax Reitz def test_tray_open_close(self): 142486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 143486b88bdSKevin Wolf id=self.device_name, force=True) 144adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 145adfe2030SMax Reitz 146adfe2030SMax Reitz self.wait_for_open() 147adfe2030SMax Reitz 148adfe2030SMax Reitz result = self.vm.qmp('query-block') 149abb3e55bSMax Reitz if self.has_real_tray: 150adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 151adfe2030SMax Reitz if self.was_empty == True: 152adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 153adfe2030SMax Reitz else: 154adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 155adfe2030SMax Reitz 156486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 157adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 158adfe2030SMax Reitz 159adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 160adfe2030SMax Reitz self.wait_for_close() 161adfe2030SMax Reitz 162adfe2030SMax Reitz result = self.vm.qmp('query-block') 163abb3e55bSMax Reitz if self.has_real_tray: 164adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 165adfe2030SMax Reitz if self.was_empty == True: 166adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 167adfe2030SMax Reitz else: 168adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 169adfe2030SMax Reitz 170adfe2030SMax Reitz def test_tray_eject_close(self): 1711d701e0eSMax Reitz result = self.vm.qmp('eject', id=self.device_name, force=True) 172adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 173adfe2030SMax Reitz 174adfe2030SMax Reitz self.wait_for_open() 175adfe2030SMax Reitz 176adfe2030SMax Reitz result = self.vm.qmp('query-block') 177abb3e55bSMax Reitz if self.has_real_tray: 178adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 179adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 180adfe2030SMax Reitz 181486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 182adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 183adfe2030SMax Reitz 184adfe2030SMax Reitz self.wait_for_close() 185adfe2030SMax Reitz 186adfe2030SMax Reitz result = self.vm.qmp('query-block') 187adfe2030SMax Reitz if self.has_real_tray: 188adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 189adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 190adfe2030SMax Reitz 191adfe2030SMax Reitz def test_tray_open_change(self): 1921d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name, 1931d701e0eSMax Reitz force=True) 194adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 195adfe2030SMax Reitz 196adfe2030SMax Reitz self.wait_for_open() 197adfe2030SMax Reitz 198adfe2030SMax Reitz result = self.vm.qmp('query-block') 199abb3e55bSMax Reitz if self.has_real_tray: 200adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 201adfe2030SMax Reitz if self.was_empty == True: 202adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 203adfe2030SMax Reitz else: 204adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 205adfe2030SMax Reitz 2061d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 207adfe2030SMax Reitz filename=new_img, 208adfe2030SMax Reitz format=iotests.imgfmt) 209adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 210adfe2030SMax Reitz 211adfe2030SMax Reitz self.wait_for_close() 212adfe2030SMax Reitz 213adfe2030SMax Reitz result = self.vm.qmp('query-block') 214abb3e55bSMax Reitz if self.has_real_tray: 215adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 216adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 217adfe2030SMax Reitz 21868174160SKevin Wolf def test_cycle(self, read_only_node=False): 219adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2200153d2f5SKevin Wolf node_name='new', 2210153d2f5SKevin Wolf driver=iotests.imgfmt, 22268174160SKevin Wolf read_only=read_only_node, 2230153d2f5SKevin Wolf file={'filename': new_img, 2240153d2f5SKevin Wolf 'driver': 'file'}) 225adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 226adfe2030SMax Reitz 227486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 228486b88bdSKevin Wolf id=self.device_name, force=True) 229adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 230adfe2030SMax Reitz 231adfe2030SMax Reitz self.wait_for_open() 232adfe2030SMax Reitz 233adfe2030SMax Reitz result = self.vm.qmp('query-block') 234abb3e55bSMax Reitz if self.has_real_tray: 235adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 236adfe2030SMax Reitz if self.was_empty == True: 237adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 238adfe2030SMax Reitz else: 239adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 240adfe2030SMax Reitz 24134ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', 242486b88bdSKevin Wolf id=self.device_name) 243adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 244adfe2030SMax Reitz 245adfe2030SMax Reitz result = self.vm.qmp('query-block') 246abb3e55bSMax Reitz if self.has_real_tray: 247adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 248adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 249adfe2030SMax Reitz 25034ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', 251486b88bdSKevin Wolf id=self.device_name, node_name='new') 252adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 253adfe2030SMax Reitz 254adfe2030SMax Reitz result = self.vm.qmp('query-block') 255abb3e55bSMax Reitz if self.has_real_tray: 256adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 257adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 258adfe2030SMax Reitz 259486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 260adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 261adfe2030SMax Reitz 262adfe2030SMax Reitz self.wait_for_close() 263adfe2030SMax Reitz 264adfe2030SMax Reitz result = self.vm.qmp('query-block') 265abb3e55bSMax Reitz if self.has_real_tray: 266adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 267adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 268adfe2030SMax Reitz 26968174160SKevin Wolf def test_cycle_read_only_media(self): 27068174160SKevin Wolf self.test_cycle(True) 27168174160SKevin Wolf 272adfe2030SMax Reitz def test_close_on_closed(self): 2731d701e0eSMax Reitz result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 274adfe2030SMax Reitz # Should be a no-op 275adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 276fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 277adfe2030SMax Reitz 278adfe2030SMax Reitz def test_remove_on_closed(self): 279abb3e55bSMax Reitz if not self.has_real_tray: 280adfe2030SMax Reitz return 281adfe2030SMax Reitz 28234ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 283adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 284adfe2030SMax Reitz 285adfe2030SMax Reitz def test_insert_on_closed(self): 286abb3e55bSMax Reitz if not self.has_real_tray: 287adfe2030SMax Reitz return 288adfe2030SMax Reitz 289adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2900153d2f5SKevin Wolf node_name='new', 2910153d2f5SKevin Wolf driver=iotests.imgfmt, 2920153d2f5SKevin Wolf file={'filename': new_img, 2930153d2f5SKevin Wolf 'driver': 'file'}) 294adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 295adfe2030SMax Reitz 29634ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 297adfe2030SMax Reitz node_name='new') 298adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 299adfe2030SMax Reitz 300adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 301adfe2030SMax Reitz was_empty = False 302adfe2030SMax Reitz 303dfc82894SKevin Wolf def setUp(self): 304adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 305adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 306486b88bdSKevin Wolf self.vm = iotests.VM() 30719462c4bSKevin Wolf if self.use_drive: 308dfc82894SKevin Wolf self.vm.add_drive(old_img, 'media=%s' % self.media, 'none') 30919462c4bSKevin Wolf else: 31019462c4bSKevin Wolf self.vm.add_blockdev([ 'node-name=drive0', 31119462c4bSKevin Wolf 'driver=%s' % iotests.imgfmt, 31219462c4bSKevin Wolf 'file.driver=file', 31319462c4bSKevin Wolf 'file.filename=%s' % old_img ]) 314dfc82894SKevin Wolf if self.interface == 'scsi': 315dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 3161d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 317dfc82894SKevin Wolf (interface_to_device_name(self.interface), 3181d701e0eSMax Reitz self.device_name)) 319adfe2030SMax Reitz self.vm.launch() 320adfe2030SMax Reitz 321adfe2030SMax Reitz def tearDown(self): 322adfe2030SMax Reitz self.vm.shutdown() 323adfe2030SMax Reitz os.remove(old_img) 324adfe2030SMax Reitz os.remove(new_img) 325adfe2030SMax Reitz 326adfe2030SMax Reitz def test_insert_on_filled(self): 327adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 3280153d2f5SKevin Wolf node_name='new', 3290153d2f5SKevin Wolf driver=iotests.imgfmt, 3300153d2f5SKevin Wolf file={'filename': new_img, 3310153d2f5SKevin Wolf 'driver': 'file'}) 332adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 333adfe2030SMax Reitz 3341d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 335adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 336adfe2030SMax Reitz 337adfe2030SMax Reitz self.wait_for_open() 338adfe2030SMax Reitz 33934ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 340adfe2030SMax Reitz node_name='new') 341adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 342adfe2030SMax Reitz 343adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 344adfe2030SMax Reitz was_empty = True 345adfe2030SMax Reitz 346dfc82894SKevin Wolf def setUp(self): 347adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 34819462c4bSKevin Wolf self.vm = iotests.VM() 34919462c4bSKevin Wolf if self.use_drive: 35019462c4bSKevin Wolf self.vm.add_drive(None, 'media=%s' % self.media, 'none') 351dfc82894SKevin Wolf if self.interface == 'scsi': 352dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 35319462c4bSKevin Wolf self.vm.add_device('%s,%sid=%s' % 354dfc82894SKevin Wolf (interface_to_device_name(self.interface), 35519462c4bSKevin Wolf 'drive=drive0,' if self.use_drive else '', 3561d701e0eSMax Reitz self.device_name)) 357adfe2030SMax Reitz self.vm.launch() 358adfe2030SMax Reitz 359adfe2030SMax Reitz def tearDown(self): 360adfe2030SMax Reitz self.vm.shutdown() 361adfe2030SMax Reitz os.remove(new_img) 362adfe2030SMax Reitz 363adfe2030SMax Reitz def test_remove_on_empty(self): 3641d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 365adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 366adfe2030SMax Reitz 367adfe2030SMax Reitz self.wait_for_open() 368adfe2030SMax Reitz 36934ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 370adfe2030SMax Reitz # Should be a no-op 371adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 372adfe2030SMax Reitz 373dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global 374dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes) 375dfc82894SKevin Wolfdef create_basic_test_classes(): 376dfc82894SKevin Wolf for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True), 377dfc82894SKevin Wolf ('cdrom', 'scsi', True), 378dfc82894SKevin Wolf ('disk', 'floppy', False) ]: 379adfe2030SMax Reitz 380dfc82894SKevin Wolf for case in [ TestInitiallyFilled, TestInitiallyEmpty ]: 38119462c4bSKevin Wolf for use_drive in [ True, False ]: 382dfc82894SKevin Wolf attr = { 'media': media, 383dfc82894SKevin Wolf 'interface': interface, 38419462c4bSKevin Wolf 'has_real_tray': has_real_tray, 38519462c4bSKevin Wolf 'use_drive': use_drive } 386adfe2030SMax Reitz 38719462c4bSKevin Wolf name = '%s_%s_%s_%s' % (case.__name__, media, interface, 38819462c4bSKevin Wolf 'drive' if use_drive else 'blockdev') 389dfc82894SKevin Wolf globals()[name] = type(name, (case, ), attr) 390adfe2030SMax Reitz 391dfc82894SKevin Wolfcreate_basic_test_classes() 392adfe2030SMax Reitz 393adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 3941d701e0eSMax Reitz device_name = 'qdev0' 3951d701e0eSMax Reitz 396adfe2030SMax Reitz def setUp(self): 397adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 398adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 399adfe2030SMax Reitz self.vm = iotests.VM() 400adfe2030SMax Reitz 401adfe2030SMax Reitz def tearDown(self): 402adfe2030SMax Reitz self.vm.shutdown() 4034803c5cdSEduardo Habkost os.chmod(old_img, 0o666) 4044803c5cdSEduardo Habkost os.chmod(new_img, 0o666) 405adfe2030SMax Reitz os.remove(old_img) 406adfe2030SMax Reitz os.remove(new_img) 407adfe2030SMax Reitz 408adfe2030SMax Reitz def test_ro_ro_retain(self): 4094803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4104803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4111d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4121d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 413adfe2030SMax Reitz self.vm.launch() 414adfe2030SMax Reitz 415adfe2030SMax Reitz result = self.vm.qmp('query-block') 416adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 417adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 418adfe2030SMax Reitz 4191d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 420adfe2030SMax Reitz filename=new_img, 421adfe2030SMax Reitz format=iotests.imgfmt, 422adfe2030SMax Reitz read_only_mode='retain') 423adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 424adfe2030SMax Reitz 425adfe2030SMax Reitz result = self.vm.qmp('query-block') 426adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 427adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 428adfe2030SMax Reitz 429adfe2030SMax Reitz def test_ro_rw_retain(self): 4304803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4311d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4321d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 433adfe2030SMax Reitz self.vm.launch() 434adfe2030SMax Reitz 435adfe2030SMax Reitz result = self.vm.qmp('query-block') 436adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 437adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 438adfe2030SMax Reitz 4391d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 440adfe2030SMax Reitz filename=new_img, 441adfe2030SMax Reitz format=iotests.imgfmt, 442adfe2030SMax Reitz read_only_mode='retain') 443adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 444adfe2030SMax Reitz 445adfe2030SMax Reitz result = self.vm.qmp('query-block') 446adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 447adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 448adfe2030SMax Reitz 449*d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 450adfe2030SMax Reitz def test_rw_ro_retain(self): 4514803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4521d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4531d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 454adfe2030SMax Reitz self.vm.launch() 455adfe2030SMax Reitz 456adfe2030SMax Reitz result = self.vm.qmp('query-block') 457adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 458adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 459adfe2030SMax Reitz 4601d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 461adfe2030SMax Reitz filename=new_img, 462adfe2030SMax Reitz format=iotests.imgfmt, 463adfe2030SMax Reitz read_only_mode='retain') 464adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 465adfe2030SMax Reitz 466fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 467adfe2030SMax Reitz 468adfe2030SMax Reitz result = self.vm.qmp('query-block') 469adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 470adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 471adfe2030SMax Reitz 472adfe2030SMax Reitz def test_ro_rw(self): 4734803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4741d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4751d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 476adfe2030SMax Reitz self.vm.launch() 477adfe2030SMax Reitz 478adfe2030SMax Reitz result = self.vm.qmp('query-block') 479adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 480adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 481adfe2030SMax Reitz 482adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4831d701e0eSMax Reitz id=self.device_name, 484adfe2030SMax Reitz filename=new_img, 485adfe2030SMax Reitz format=iotests.imgfmt, 486adfe2030SMax Reitz read_only_mode='read-write') 487adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 488adfe2030SMax Reitz 489adfe2030SMax Reitz result = self.vm.qmp('query-block') 490adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 491adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 492adfe2030SMax Reitz 493adfe2030SMax Reitz def test_rw_ro(self): 4944803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4951d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4961d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 497adfe2030SMax Reitz self.vm.launch() 498adfe2030SMax Reitz 499adfe2030SMax Reitz result = self.vm.qmp('query-block') 500adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 501adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 502adfe2030SMax Reitz 503adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5041d701e0eSMax Reitz id=self.device_name, 505adfe2030SMax Reitz filename=new_img, 506adfe2030SMax Reitz format=iotests.imgfmt, 507adfe2030SMax Reitz read_only_mode='read-only') 508adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 509adfe2030SMax Reitz 510adfe2030SMax Reitz result = self.vm.qmp('query-block') 511adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 512adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 513adfe2030SMax Reitz 514adfe2030SMax Reitz def test_make_rw_ro(self): 5151d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5161d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 517adfe2030SMax Reitz self.vm.launch() 518adfe2030SMax Reitz 519adfe2030SMax Reitz result = self.vm.qmp('query-block') 520adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 521adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 522adfe2030SMax Reitz 523adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5241d701e0eSMax Reitz id=self.device_name, 525adfe2030SMax Reitz filename=new_img, 526adfe2030SMax Reitz format=iotests.imgfmt, 527adfe2030SMax Reitz read_only_mode='read-only') 528adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 529adfe2030SMax Reitz 530adfe2030SMax Reitz result = self.vm.qmp('query-block') 531adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 532adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 533adfe2030SMax Reitz 534*d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 535adfe2030SMax Reitz def test_make_ro_rw(self): 5364803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5371d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5381d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 539adfe2030SMax Reitz self.vm.launch() 540adfe2030SMax Reitz 541adfe2030SMax Reitz result = self.vm.qmp('query-block') 542adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 543adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 544adfe2030SMax Reitz 545adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5461d701e0eSMax Reitz id=self.device_name, 547adfe2030SMax Reitz filename=new_img, 548adfe2030SMax Reitz format=iotests.imgfmt, 549adfe2030SMax Reitz read_only_mode='read-write') 550adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 551adfe2030SMax Reitz 552adfe2030SMax Reitz result = self.vm.qmp('query-block') 553adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 554adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 555adfe2030SMax Reitz 556adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 5574803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5581d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 5591d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 560adfe2030SMax Reitz self.vm.launch() 561adfe2030SMax Reitz 562adfe2030SMax Reitz result = self.vm.qmp('query-block') 563adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 564adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 565adfe2030SMax Reitz 5661d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 567adfe2030SMax Reitz filename=new_img, 568adfe2030SMax Reitz format=iotests.imgfmt, 569adfe2030SMax Reitz read_only_mode='retain') 570adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 571adfe2030SMax Reitz 572adfe2030SMax Reitz result = self.vm.qmp('query-block') 573adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 574adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 575adfe2030SMax Reitz 576*d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 577adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 5784803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5791d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5801d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 581adfe2030SMax Reitz self.vm.launch() 582adfe2030SMax Reitz 583adfe2030SMax Reitz result = self.vm.qmp('query-block') 584adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 585adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 586adfe2030SMax Reitz 5871d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 588adfe2030SMax Reitz filename=new_img, 589adfe2030SMax Reitz format=iotests.imgfmt, 590adfe2030SMax Reitz read_only_mode='retain') 591adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 592adfe2030SMax Reitz 593adfe2030SMax Reitz result = self.vm.qmp('query-block') 594adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 595adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 596adfe2030SMax Reitz 597adfe2030SMax Reitz def test_rw_ro_cycle(self): 5984803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5991d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 6001d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 601adfe2030SMax Reitz self.vm.launch() 602adfe2030SMax Reitz 603adfe2030SMax Reitz result = self.vm.qmp('query-block') 604adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 605adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 606adfe2030SMax Reitz 607adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6080153d2f5SKevin Wolf node_name='new', 6090153d2f5SKevin Wolf driver=iotests.imgfmt, 6100153d2f5SKevin Wolf read_only=True, 6110153d2f5SKevin Wolf file={'filename': new_img, 6120153d2f5SKevin Wolf 'driver': 'file'}) 613adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 614adfe2030SMax Reitz 615adfe2030SMax Reitz result = self.vm.qmp('query-block') 616adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 617adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 618adfe2030SMax Reitz 61934ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 620adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 621adfe2030SMax Reitz 622adfe2030SMax Reitz result = self.vm.qmp('query-block') 623adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 624adfe2030SMax Reitz 62534ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 626adfe2030SMax Reitz node_name='new') 627adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 628adfe2030SMax Reitz 629adfe2030SMax Reitz result = self.vm.qmp('query-block') 630adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 631adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 632adfe2030SMax Reitz 633adfe2030SMax Reitz result = self.vm.qmp('query-block') 634adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 635adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 636adfe2030SMax Reitz 637adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 638adfe2030SMax ReitzTestInitiallyFilled = None 639adfe2030SMax ReitzTestInitiallyEmpty = None 640adfe2030SMax Reitz 641adfe2030SMax Reitz 642adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 6431d701e0eSMax Reitz device_name = 'qdev0' 6441d701e0eSMax Reitz 645adfe2030SMax Reitz def setUp(self): 6461d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 647adfe2030SMax Reitz 648adfe2030SMax Reitz self.vm = iotests.VM() 649e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6501d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 651adfe2030SMax Reitz self.vm.launch() 652adfe2030SMax Reitz 653adfe2030SMax Reitz result = self.vm.qmp('query-block') 654adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 655adfe2030SMax Reitz 656adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 657adfe2030SMax Reitz # is not necessary 65834ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 659adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 660adfe2030SMax Reitz 661adfe2030SMax Reitz result = self.vm.qmp('query-block') 662adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 663adfe2030SMax Reitz 664adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6650153d2f5SKevin Wolf node_name='node0', 6660153d2f5SKevin Wolf driver=iotests.imgfmt, 6670153d2f5SKevin Wolf file={'filename': old_img, 6680153d2f5SKevin Wolf 'driver': 'file'}) 669adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 670adfe2030SMax Reitz 67134ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 672adfe2030SMax Reitz node_name='node0') 673adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 674adfe2030SMax Reitz 675adfe2030SMax Reitz result = self.vm.qmp('query-block') 676adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 677adfe2030SMax Reitz 678adfe2030SMax Reitz def tearDown(self): 679adfe2030SMax Reitz self.vm.shutdown() 680adfe2030SMax Reitz os.remove(old_img) 681adfe2030SMax Reitz try: 682adfe2030SMax Reitz os.remove(new_img) 683adfe2030SMax Reitz except OSError: 684adfe2030SMax Reitz pass 685adfe2030SMax Reitz 686adfe2030SMax Reitz def test_snapshot_and_commit(self): 687adfe2030SMax Reitz # We need backing file support 688adfe2030SMax Reitz if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 689adfe2030SMax Reitz return 690adfe2030SMax Reitz 691adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 692adfe2030SMax Reitz snapshot_file=new_img, 693adfe2030SMax Reitz format=iotests.imgfmt) 694adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 695adfe2030SMax Reitz 696adfe2030SMax Reitz result = self.vm.qmp('query-block') 697adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 698adfe2030SMax Reitz self.assert_qmp(result, 699adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 700adfe2030SMax Reitz old_img) 701adfe2030SMax Reitz 702adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 703adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 704adfe2030SMax Reitz 705adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 706adfe2030SMax Reitz 707adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 708adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 709adfe2030SMax Reitz 710adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 711adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 712adfe2030SMax Reitz 713adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 714adfe2030SMax Reitz 715adfe2030SMax Reitz 716adfe2030SMax Reitzif __name__ == '__main__': 717adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 718adfe2030SMax Reitz # We need floppy and IDE CD-ROM 719adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 720adfe2030SMax Reitz iotests.qemu_default_machine) 721cc8c46b7SMax Reitz # Need to support image creation 722cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 723103cbc77SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed'], 724103cbc77SMax Reitz supported_protocols=['file']) 725