1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 2*9dd003a9SVladimir Sementsov-Ogievskiy# group: rw 3adfe2030SMax Reitz# 4adfe2030SMax Reitz# Test case for the QMP 'change' command and all other associated 5adfe2030SMax Reitz# commands 6adfe2030SMax Reitz# 7adfe2030SMax Reitz# Copyright (C) 2015 Red Hat, Inc. 8adfe2030SMax Reitz# 9adfe2030SMax Reitz# This program is free software; you can redistribute it and/or modify 10adfe2030SMax Reitz# it under the terms of the GNU General Public License as published by 11adfe2030SMax Reitz# the Free Software Foundation; either version 2 of the License, or 12adfe2030SMax Reitz# (at your option) any later version. 13adfe2030SMax Reitz# 14adfe2030SMax Reitz# This program is distributed in the hope that it will be useful, 15adfe2030SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 16adfe2030SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17adfe2030SMax Reitz# GNU General Public License for more details. 18adfe2030SMax Reitz# 19adfe2030SMax Reitz# You should have received a copy of the GNU General Public License 20adfe2030SMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 21adfe2030SMax Reitz# 22adfe2030SMax Reitz 23adfe2030SMax Reitzimport os 24adfe2030SMax Reitzimport stat 25adfe2030SMax Reitzimport time 26adfe2030SMax Reitzimport iotests 27adfe2030SMax Reitzfrom iotests import qemu_img 28adfe2030SMax Reitz 29adfe2030SMax Reitzold_img = os.path.join(iotests.test_dir, 'test0.img') 30adfe2030SMax Reitznew_img = os.path.join(iotests.test_dir, 'test1.img') 31adfe2030SMax Reitz 321d701e0eSMax Reitzdef interface_to_device_name(interface): 331d701e0eSMax Reitz if interface == 'ide': 341d701e0eSMax Reitz return 'ide-cd' 351d701e0eSMax Reitz elif interface == 'floppy': 361d701e0eSMax Reitz return 'floppy' 37dfa26a11SKevin Wolf elif interface == 'scsi': 38dfa26a11SKevin Wolf return 'scsi-cd' 391d701e0eSMax Reitz else: 401d701e0eSMax Reitz return None 411d701e0eSMax Reitz 42adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase): 43adfe2030SMax Reitz has_opened = False 44adfe2030SMax Reitz has_closed = False 45adfe2030SMax Reitz 4619462c4bSKevin Wolf device_name = 'qdev0' 4719462c4bSKevin Wolf use_drive = False 4819462c4bSKevin Wolf 49adfe2030SMax Reitz def process_events(self): 50adfe2030SMax Reitz for event in self.vm.get_qmp_events(wait=False): 51adfe2030SMax Reitz if (event['event'] == 'DEVICE_TRAY_MOVED' and 5219462c4bSKevin Wolf (event['data']['device'] == 'drive0' or 5319462c4bSKevin Wolf event['data']['id'] == self.device_name)): 54adfe2030SMax Reitz if event['data']['tray-open'] == False: 55adfe2030SMax Reitz self.has_closed = True 56adfe2030SMax Reitz else: 57adfe2030SMax Reitz self.has_opened = True 58adfe2030SMax Reitz 59adfe2030SMax Reitz def wait_for_open(self): 60abb3e55bSMax Reitz if not self.has_real_tray: 61abb3e55bSMax Reitz return 62abb3e55bSMax Reitz 63d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to open'): 64d8336c6bSKevin Wolf while not self.has_opened: 65adfe2030SMax Reitz self.process_events() 66adfe2030SMax Reitz 67adfe2030SMax Reitz def wait_for_close(self): 68abb3e55bSMax Reitz if not self.has_real_tray: 69abb3e55bSMax Reitz return 70abb3e55bSMax Reitz 71d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to close'): 72d8336c6bSKevin Wolf while not self.has_closed: 73adfe2030SMax Reitz self.process_events() 74adfe2030SMax Reitz 75adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass): 76486b88bdSKevin Wolf 77adfe2030SMax Reitz def test_change(self): 7819462c4bSKevin Wolf # 'change' requires a drive name, so skip the test for blockdev 7919462c4bSKevin Wolf if not self.use_drive: 8019462c4bSKevin Wolf return 8119462c4bSKevin Wolf 82adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 83adfe2030SMax Reitz arg=iotests.imgfmt) 84adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 85adfe2030SMax Reitz 86adfe2030SMax Reitz self.wait_for_open() 87adfe2030SMax Reitz self.wait_for_close() 88adfe2030SMax Reitz 89adfe2030SMax Reitz result = self.vm.qmp('query-block') 90abb3e55bSMax Reitz if self.has_real_tray: 91adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 92adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 93adfe2030SMax Reitz 94adfe2030SMax Reitz def test_blockdev_change_medium(self): 95486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 96486b88bdSKevin Wolf id=self.device_name, filename=new_img, 97adfe2030SMax Reitz format=iotests.imgfmt) 98486b88bdSKevin Wolf 99adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 100adfe2030SMax Reitz 101adfe2030SMax Reitz self.wait_for_open() 102adfe2030SMax Reitz self.wait_for_close() 103adfe2030SMax Reitz 104adfe2030SMax Reitz result = self.vm.qmp('query-block') 105abb3e55bSMax Reitz if self.has_real_tray: 106adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 107adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 108adfe2030SMax Reitz 109adfe2030SMax Reitz def test_eject(self): 110486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 111adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 112adfe2030SMax Reitz 113adfe2030SMax Reitz self.wait_for_open() 114adfe2030SMax Reitz 115adfe2030SMax Reitz result = self.vm.qmp('query-block') 116abb3e55bSMax Reitz if self.has_real_tray: 117adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 118adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 119adfe2030SMax Reitz 120adfe2030SMax Reitz def test_tray_eject_change(self): 121486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 122adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 123adfe2030SMax Reitz 124adfe2030SMax Reitz self.wait_for_open() 125adfe2030SMax Reitz 126adfe2030SMax Reitz result = self.vm.qmp('query-block') 127abb3e55bSMax Reitz if self.has_real_tray: 128adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 129adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 130adfe2030SMax Reitz 131486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 132486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 133adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 134adfe2030SMax Reitz 135adfe2030SMax Reitz self.wait_for_close() 136adfe2030SMax Reitz 137adfe2030SMax Reitz result = self.vm.qmp('query-block') 138abb3e55bSMax Reitz if self.has_real_tray: 139adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 140adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 141adfe2030SMax Reitz 142adfe2030SMax Reitz def test_tray_open_close(self): 143486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 144486b88bdSKevin Wolf id=self.device_name, force=True) 145adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 146adfe2030SMax Reitz 147adfe2030SMax Reitz self.wait_for_open() 148adfe2030SMax Reitz 149adfe2030SMax Reitz result = self.vm.qmp('query-block') 150abb3e55bSMax Reitz if self.has_real_tray: 151adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 152adfe2030SMax Reitz if self.was_empty == True: 153adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 154adfe2030SMax Reitz else: 155adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 156adfe2030SMax Reitz 157486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 158adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 159adfe2030SMax Reitz 160adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 161adfe2030SMax Reitz self.wait_for_close() 162adfe2030SMax Reitz 163adfe2030SMax Reitz result = self.vm.qmp('query-block') 164abb3e55bSMax Reitz if self.has_real_tray: 165adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 166adfe2030SMax Reitz if self.was_empty == True: 167adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 168adfe2030SMax Reitz else: 169adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 170adfe2030SMax Reitz 171adfe2030SMax Reitz def test_tray_eject_close(self): 1721d701e0eSMax Reitz result = self.vm.qmp('eject', id=self.device_name, force=True) 173adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 174adfe2030SMax Reitz 175adfe2030SMax Reitz self.wait_for_open() 176adfe2030SMax Reitz 177adfe2030SMax Reitz result = self.vm.qmp('query-block') 178abb3e55bSMax Reitz if self.has_real_tray: 179adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 180adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 181adfe2030SMax Reitz 182486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 183adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 184adfe2030SMax Reitz 185adfe2030SMax Reitz self.wait_for_close() 186adfe2030SMax Reitz 187adfe2030SMax Reitz result = self.vm.qmp('query-block') 188adfe2030SMax Reitz if self.has_real_tray: 189adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 190adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 191adfe2030SMax Reitz 192adfe2030SMax Reitz def test_tray_open_change(self): 1931d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name, 1941d701e0eSMax Reitz force=True) 195adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 196adfe2030SMax Reitz 197adfe2030SMax Reitz self.wait_for_open() 198adfe2030SMax Reitz 199adfe2030SMax Reitz result = self.vm.qmp('query-block') 200abb3e55bSMax Reitz if self.has_real_tray: 201adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 202adfe2030SMax Reitz if self.was_empty == True: 203adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 204adfe2030SMax Reitz else: 205adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 206adfe2030SMax Reitz 2071d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 208adfe2030SMax Reitz filename=new_img, 209adfe2030SMax Reitz format=iotests.imgfmt) 210adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 211adfe2030SMax Reitz 212adfe2030SMax Reitz self.wait_for_close() 213adfe2030SMax Reitz 214adfe2030SMax Reitz result = self.vm.qmp('query-block') 215abb3e55bSMax Reitz if self.has_real_tray: 216adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 217adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 218adfe2030SMax Reitz 21968174160SKevin Wolf def test_cycle(self, read_only_node=False): 220adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2210153d2f5SKevin Wolf node_name='new', 2220153d2f5SKevin Wolf driver=iotests.imgfmt, 22368174160SKevin Wolf read_only=read_only_node, 2240153d2f5SKevin Wolf file={'filename': new_img, 2250153d2f5SKevin Wolf 'driver': 'file'}) 226adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 227adfe2030SMax Reitz 228486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 229486b88bdSKevin Wolf id=self.device_name, force=True) 230adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 231adfe2030SMax Reitz 232adfe2030SMax Reitz self.wait_for_open() 233adfe2030SMax Reitz 234adfe2030SMax Reitz result = self.vm.qmp('query-block') 235abb3e55bSMax Reitz if self.has_real_tray: 236adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 237adfe2030SMax Reitz if self.was_empty == True: 238adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 239adfe2030SMax Reitz else: 240adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 241adfe2030SMax Reitz 24234ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', 243486b88bdSKevin Wolf id=self.device_name) 244adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 245adfe2030SMax Reitz 246adfe2030SMax Reitz result = self.vm.qmp('query-block') 247abb3e55bSMax Reitz if self.has_real_tray: 248adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 249adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 250adfe2030SMax Reitz 25134ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', 252486b88bdSKevin Wolf id=self.device_name, node_name='new') 253adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 254adfe2030SMax Reitz 255adfe2030SMax Reitz result = self.vm.qmp('query-block') 256abb3e55bSMax Reitz if self.has_real_tray: 257adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 258adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 259adfe2030SMax Reitz 260486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 261adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 262adfe2030SMax Reitz 263adfe2030SMax Reitz self.wait_for_close() 264adfe2030SMax Reitz 265adfe2030SMax Reitz result = self.vm.qmp('query-block') 266abb3e55bSMax Reitz if self.has_real_tray: 267adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 268adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 269adfe2030SMax Reitz 27068174160SKevin Wolf def test_cycle_read_only_media(self): 27168174160SKevin Wolf self.test_cycle(True) 27268174160SKevin Wolf 273adfe2030SMax Reitz def test_close_on_closed(self): 2741d701e0eSMax Reitz result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 275adfe2030SMax Reitz # Should be a no-op 276adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 277fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 278adfe2030SMax Reitz 279adfe2030SMax Reitz def test_remove_on_closed(self): 280abb3e55bSMax Reitz if not self.has_real_tray: 281adfe2030SMax Reitz return 282adfe2030SMax Reitz 28334ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 284adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 285adfe2030SMax Reitz 286adfe2030SMax Reitz def test_insert_on_closed(self): 287abb3e55bSMax Reitz if not self.has_real_tray: 288adfe2030SMax Reitz return 289adfe2030SMax Reitz 290adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2910153d2f5SKevin Wolf node_name='new', 2920153d2f5SKevin Wolf driver=iotests.imgfmt, 2930153d2f5SKevin Wolf file={'filename': new_img, 2940153d2f5SKevin Wolf 'driver': 'file'}) 295adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 296adfe2030SMax Reitz 29734ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 298adfe2030SMax Reitz node_name='new') 299adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 300adfe2030SMax Reitz 301adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 302adfe2030SMax Reitz was_empty = False 303adfe2030SMax Reitz 304dfc82894SKevin Wolf def setUp(self): 305adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 306adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 307486b88bdSKevin Wolf self.vm = iotests.VM() 30819462c4bSKevin Wolf if self.use_drive: 309dfc82894SKevin Wolf self.vm.add_drive(old_img, 'media=%s' % self.media, 'none') 31019462c4bSKevin Wolf else: 31119462c4bSKevin Wolf self.vm.add_blockdev([ 'node-name=drive0', 31219462c4bSKevin Wolf 'driver=%s' % iotests.imgfmt, 31319462c4bSKevin Wolf 'file.driver=file', 31419462c4bSKevin Wolf 'file.filename=%s' % old_img ]) 315dfc82894SKevin Wolf if self.interface == 'scsi': 316dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 3171d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 318dfc82894SKevin Wolf (interface_to_device_name(self.interface), 3191d701e0eSMax Reitz self.device_name)) 320adfe2030SMax Reitz self.vm.launch() 321adfe2030SMax Reitz 322adfe2030SMax Reitz def tearDown(self): 323adfe2030SMax Reitz self.vm.shutdown() 324adfe2030SMax Reitz os.remove(old_img) 325adfe2030SMax Reitz os.remove(new_img) 326adfe2030SMax Reitz 327adfe2030SMax Reitz def test_insert_on_filled(self): 328adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 3290153d2f5SKevin Wolf node_name='new', 3300153d2f5SKevin Wolf driver=iotests.imgfmt, 3310153d2f5SKevin Wolf file={'filename': new_img, 3320153d2f5SKevin Wolf 'driver': 'file'}) 333adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 334adfe2030SMax Reitz 3351d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 336adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 337adfe2030SMax Reitz 338adfe2030SMax Reitz self.wait_for_open() 339adfe2030SMax Reitz 34034ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 341adfe2030SMax Reitz node_name='new') 342adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 343adfe2030SMax Reitz 344adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 345adfe2030SMax Reitz was_empty = True 346adfe2030SMax Reitz 347dfc82894SKevin Wolf def setUp(self): 348adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 34919462c4bSKevin Wolf self.vm = iotests.VM() 35019462c4bSKevin Wolf if self.use_drive: 35119462c4bSKevin Wolf self.vm.add_drive(None, 'media=%s' % self.media, 'none') 352dfc82894SKevin Wolf if self.interface == 'scsi': 353dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 35419462c4bSKevin Wolf self.vm.add_device('%s,%sid=%s' % 355dfc82894SKevin Wolf (interface_to_device_name(self.interface), 35619462c4bSKevin Wolf 'drive=drive0,' if self.use_drive else '', 3571d701e0eSMax Reitz self.device_name)) 358adfe2030SMax Reitz self.vm.launch() 359adfe2030SMax Reitz 360adfe2030SMax Reitz def tearDown(self): 361adfe2030SMax Reitz self.vm.shutdown() 362adfe2030SMax Reitz os.remove(new_img) 363adfe2030SMax Reitz 364adfe2030SMax Reitz def test_remove_on_empty(self): 3651d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 366adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 367adfe2030SMax Reitz 368adfe2030SMax Reitz self.wait_for_open() 369adfe2030SMax Reitz 37034ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 371adfe2030SMax Reitz # Should be a no-op 372adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 373adfe2030SMax Reitz 374dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global 375dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes) 376dfc82894SKevin Wolfdef create_basic_test_classes(): 377dfc82894SKevin Wolf for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True), 378dfc82894SKevin Wolf ('cdrom', 'scsi', True), 379dfc82894SKevin Wolf ('disk', 'floppy', False) ]: 380adfe2030SMax Reitz 381dfc82894SKevin Wolf for case in [ TestInitiallyFilled, TestInitiallyEmpty ]: 38219462c4bSKevin Wolf for use_drive in [ True, False ]: 383dfc82894SKevin Wolf attr = { 'media': media, 384dfc82894SKevin Wolf 'interface': interface, 38519462c4bSKevin Wolf 'has_real_tray': has_real_tray, 38619462c4bSKevin Wolf 'use_drive': use_drive } 387adfe2030SMax Reitz 38819462c4bSKevin Wolf name = '%s_%s_%s_%s' % (case.__name__, media, interface, 38919462c4bSKevin Wolf 'drive' if use_drive else 'blockdev') 390dfc82894SKevin Wolf globals()[name] = type(name, (case, ), attr) 391adfe2030SMax Reitz 392dfc82894SKevin Wolfcreate_basic_test_classes() 393adfe2030SMax Reitz 394adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 3951d701e0eSMax Reitz device_name = 'qdev0' 3961d701e0eSMax Reitz 397adfe2030SMax Reitz def setUp(self): 398adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 399adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 400adfe2030SMax Reitz self.vm = iotests.VM() 401adfe2030SMax Reitz 402adfe2030SMax Reitz def tearDown(self): 403adfe2030SMax Reitz self.vm.shutdown() 4044803c5cdSEduardo Habkost os.chmod(old_img, 0o666) 4054803c5cdSEduardo Habkost os.chmod(new_img, 0o666) 406adfe2030SMax Reitz os.remove(old_img) 407adfe2030SMax Reitz os.remove(new_img) 408adfe2030SMax Reitz 409adfe2030SMax Reitz def test_ro_ro_retain(self): 4104803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4114803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4121d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4131d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 414adfe2030SMax Reitz self.vm.launch() 415adfe2030SMax Reitz 416adfe2030SMax Reitz result = self.vm.qmp('query-block') 417adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 418adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 419adfe2030SMax Reitz 4201d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 421adfe2030SMax Reitz filename=new_img, 422adfe2030SMax Reitz format=iotests.imgfmt, 423adfe2030SMax Reitz read_only_mode='retain') 424adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 425adfe2030SMax Reitz 426adfe2030SMax Reitz result = self.vm.qmp('query-block') 427adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 428adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 429adfe2030SMax Reitz 430adfe2030SMax Reitz def test_ro_rw_retain(self): 4314803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4321d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4331d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 434adfe2030SMax Reitz self.vm.launch() 435adfe2030SMax Reitz 436adfe2030SMax Reitz result = self.vm.qmp('query-block') 437adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 438adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 439adfe2030SMax Reitz 4401d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 441adfe2030SMax Reitz filename=new_img, 442adfe2030SMax Reitz format=iotests.imgfmt, 443adfe2030SMax Reitz read_only_mode='retain') 444adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 445adfe2030SMax Reitz 446adfe2030SMax Reitz result = self.vm.qmp('query-block') 447adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 448adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 449adfe2030SMax Reitz 450d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 451adfe2030SMax Reitz def test_rw_ro_retain(self): 4524803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4531d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4541d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 455adfe2030SMax Reitz self.vm.launch() 456adfe2030SMax Reitz 457adfe2030SMax Reitz result = self.vm.qmp('query-block') 458adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 459adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 460adfe2030SMax Reitz 4611d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 462adfe2030SMax Reitz filename=new_img, 463adfe2030SMax Reitz format=iotests.imgfmt, 464adfe2030SMax Reitz read_only_mode='retain') 465adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 466adfe2030SMax Reitz 467fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 468adfe2030SMax Reitz 469adfe2030SMax Reitz result = self.vm.qmp('query-block') 470adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 471adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 472adfe2030SMax Reitz 473adfe2030SMax Reitz def test_ro_rw(self): 4744803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4751d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4761d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 477adfe2030SMax Reitz self.vm.launch() 478adfe2030SMax Reitz 479adfe2030SMax Reitz result = self.vm.qmp('query-block') 480adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 481adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 482adfe2030SMax Reitz 483adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4841d701e0eSMax Reitz id=self.device_name, 485adfe2030SMax Reitz filename=new_img, 486adfe2030SMax Reitz format=iotests.imgfmt, 487adfe2030SMax Reitz read_only_mode='read-write') 488adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 489adfe2030SMax Reitz 490adfe2030SMax Reitz result = self.vm.qmp('query-block') 491adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 492adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 493adfe2030SMax Reitz 494adfe2030SMax Reitz def test_rw_ro(self): 4954803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4961d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4971d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 498adfe2030SMax Reitz self.vm.launch() 499adfe2030SMax Reitz 500adfe2030SMax Reitz result = self.vm.qmp('query-block') 501adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 502adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 503adfe2030SMax Reitz 504adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5051d701e0eSMax Reitz id=self.device_name, 506adfe2030SMax Reitz filename=new_img, 507adfe2030SMax Reitz format=iotests.imgfmt, 508adfe2030SMax Reitz read_only_mode='read-only') 509adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 510adfe2030SMax Reitz 511adfe2030SMax Reitz result = self.vm.qmp('query-block') 512adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 513adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 514adfe2030SMax Reitz 515adfe2030SMax Reitz def test_make_rw_ro(self): 5161d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5171d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 518adfe2030SMax Reitz self.vm.launch() 519adfe2030SMax Reitz 520adfe2030SMax Reitz result = self.vm.qmp('query-block') 521adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 522adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 523adfe2030SMax Reitz 524adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5251d701e0eSMax Reitz id=self.device_name, 526adfe2030SMax Reitz filename=new_img, 527adfe2030SMax Reitz format=iotests.imgfmt, 528adfe2030SMax Reitz read_only_mode='read-only') 529adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 530adfe2030SMax Reitz 531adfe2030SMax Reitz result = self.vm.qmp('query-block') 532adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 533adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 534adfe2030SMax Reitz 535d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 536adfe2030SMax Reitz def test_make_ro_rw(self): 5374803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5381d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5391d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 540adfe2030SMax Reitz self.vm.launch() 541adfe2030SMax Reitz 542adfe2030SMax Reitz result = self.vm.qmp('query-block') 543adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 544adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 545adfe2030SMax Reitz 546adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5471d701e0eSMax Reitz id=self.device_name, 548adfe2030SMax Reitz filename=new_img, 549adfe2030SMax Reitz format=iotests.imgfmt, 550adfe2030SMax Reitz read_only_mode='read-write') 551adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 552adfe2030SMax Reitz 553adfe2030SMax Reitz result = self.vm.qmp('query-block') 554adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 555adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 556adfe2030SMax Reitz 557adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 5584803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5591d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 5601d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 561adfe2030SMax Reitz self.vm.launch() 562adfe2030SMax Reitz 563adfe2030SMax Reitz result = self.vm.qmp('query-block') 564adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 565adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 566adfe2030SMax Reitz 5671d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 568adfe2030SMax Reitz filename=new_img, 569adfe2030SMax Reitz format=iotests.imgfmt, 570adfe2030SMax Reitz read_only_mode='retain') 571adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 572adfe2030SMax Reitz 573adfe2030SMax Reitz result = self.vm.qmp('query-block') 574adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 575adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 576adfe2030SMax Reitz 577d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 578adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 5794803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5801d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5811d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 582adfe2030SMax Reitz self.vm.launch() 583adfe2030SMax Reitz 584adfe2030SMax Reitz result = self.vm.qmp('query-block') 585adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 586adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 587adfe2030SMax Reitz 5881d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 589adfe2030SMax Reitz filename=new_img, 590adfe2030SMax Reitz format=iotests.imgfmt, 591adfe2030SMax Reitz read_only_mode='retain') 592adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 593adfe2030SMax Reitz 594adfe2030SMax Reitz result = self.vm.qmp('query-block') 595adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 596adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 597adfe2030SMax Reitz 598adfe2030SMax Reitz def test_rw_ro_cycle(self): 5994803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 6001d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 6011d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 602adfe2030SMax Reitz self.vm.launch() 603adfe2030SMax Reitz 604adfe2030SMax Reitz result = self.vm.qmp('query-block') 605adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 606adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 607adfe2030SMax Reitz 608adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6090153d2f5SKevin Wolf node_name='new', 6100153d2f5SKevin Wolf driver=iotests.imgfmt, 6110153d2f5SKevin Wolf read_only=True, 6120153d2f5SKevin Wolf file={'filename': new_img, 6130153d2f5SKevin Wolf 'driver': 'file'}) 614adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 615adfe2030SMax Reitz 616adfe2030SMax Reitz result = self.vm.qmp('query-block') 617adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 618adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 619adfe2030SMax Reitz 62034ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 621adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 622adfe2030SMax Reitz 623adfe2030SMax Reitz result = self.vm.qmp('query-block') 624adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 625adfe2030SMax Reitz 62634ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 627adfe2030SMax Reitz node_name='new') 628adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 629adfe2030SMax Reitz 630adfe2030SMax Reitz result = self.vm.qmp('query-block') 631adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 632adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 633adfe2030SMax Reitz 634adfe2030SMax Reitz result = self.vm.qmp('query-block') 635adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 636adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 637adfe2030SMax Reitz 638adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 639adfe2030SMax ReitzTestInitiallyFilled = None 640adfe2030SMax ReitzTestInitiallyEmpty = None 641adfe2030SMax Reitz 642adfe2030SMax Reitz 643adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 6441d701e0eSMax Reitz device_name = 'qdev0' 6451d701e0eSMax Reitz 646adfe2030SMax Reitz def setUp(self): 6471d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 648adfe2030SMax Reitz 649adfe2030SMax Reitz self.vm = iotests.VM() 650e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6511d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 652adfe2030SMax Reitz self.vm.launch() 653adfe2030SMax Reitz 654adfe2030SMax Reitz result = self.vm.qmp('query-block') 655adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 656adfe2030SMax Reitz 657adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 658adfe2030SMax Reitz # is not necessary 65934ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 660adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 661adfe2030SMax Reitz 662adfe2030SMax Reitz result = self.vm.qmp('query-block') 663adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 664adfe2030SMax Reitz 665adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6660153d2f5SKevin Wolf node_name='node0', 6670153d2f5SKevin Wolf driver=iotests.imgfmt, 6680153d2f5SKevin Wolf file={'filename': old_img, 6690153d2f5SKevin Wolf 'driver': 'file'}) 670adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 671adfe2030SMax Reitz 67234ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 673adfe2030SMax Reitz node_name='node0') 674adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 675adfe2030SMax Reitz 676adfe2030SMax Reitz result = self.vm.qmp('query-block') 677adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 678adfe2030SMax Reitz 679adfe2030SMax Reitz def tearDown(self): 680adfe2030SMax Reitz self.vm.shutdown() 681adfe2030SMax Reitz os.remove(old_img) 682adfe2030SMax Reitz try: 683adfe2030SMax Reitz os.remove(new_img) 684adfe2030SMax Reitz except OSError: 685adfe2030SMax Reitz pass 686adfe2030SMax Reitz 687adfe2030SMax Reitz # We need backing file support 688ff3caf5aSMax Reitz @iotests.skip_for_formats(('vpc', 'parallels', 'qcow', 'vdi', 'vmdk', 'raw', 689ff3caf5aSMax Reitz 'vhdx')) 690ff3caf5aSMax Reitz def test_snapshot_and_commit(self): 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