1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 29dd003a9SVladimir Sementsov-Ogievskiy# group: rw 3adfe2030SMax Reitz# 4014bb4b0SMax Reitz# Test case for media change monitor 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_blockdev_change_medium(self): 77b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', 78486b88bdSKevin Wolf id=self.device_name, filename=new_img, 79adfe2030SMax Reitz format=iotests.imgfmt) 80486b88bdSKevin Wolf 81adfe2030SMax Reitz self.wait_for_open() 82adfe2030SMax Reitz self.wait_for_close() 83adfe2030SMax Reitz 84adfe2030SMax Reitz result = self.vm.qmp('query-block') 85abb3e55bSMax Reitz if self.has_real_tray: 86adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 87adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 88adfe2030SMax Reitz 89adfe2030SMax Reitz def test_eject(self): 90b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('eject', id=self.device_name, force=True) 91adfe2030SMax Reitz 92adfe2030SMax Reitz self.wait_for_open() 93adfe2030SMax Reitz 94adfe2030SMax Reitz result = self.vm.qmp('query-block') 95abb3e55bSMax Reitz if self.has_real_tray: 96adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 97adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 98adfe2030SMax Reitz 99adfe2030SMax Reitz def test_tray_eject_change(self): 100b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('eject', id=self.device_name, force=True) 101adfe2030SMax Reitz 102adfe2030SMax Reitz self.wait_for_open() 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', True) 107adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 108adfe2030SMax Reitz 109b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', id=self.device_name, 110486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 111adfe2030SMax Reitz 112adfe2030SMax Reitz self.wait_for_close() 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', False) 117adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 118adfe2030SMax Reitz 119adfe2030SMax Reitz def test_tray_open_close(self): 120b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-open-tray', 121486b88bdSKevin Wolf id=self.device_name, force=True) 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 if self.was_empty == True: 129adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 130adfe2030SMax Reitz else: 131adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 132adfe2030SMax Reitz 133b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-close-tray', id=self.device_name) 134adfe2030SMax Reitz 135adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 136adfe2030SMax Reitz self.wait_for_close() 137adfe2030SMax Reitz 138adfe2030SMax Reitz result = self.vm.qmp('query-block') 139abb3e55bSMax Reitz if self.has_real_tray: 140adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 141adfe2030SMax Reitz if self.was_empty == True: 142adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 143adfe2030SMax Reitz else: 144adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 145adfe2030SMax Reitz 146adfe2030SMax Reitz def test_tray_eject_close(self): 147b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('eject', id=self.device_name, force=True) 148adfe2030SMax Reitz 149adfe2030SMax Reitz self.wait_for_open() 150adfe2030SMax Reitz 151adfe2030SMax Reitz result = self.vm.qmp('query-block') 152abb3e55bSMax Reitz if self.has_real_tray: 153adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 154adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 155adfe2030SMax Reitz 156b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-close-tray', id=self.device_name) 157adfe2030SMax Reitz 158adfe2030SMax Reitz self.wait_for_close() 159adfe2030SMax Reitz 160adfe2030SMax Reitz result = self.vm.qmp('query-block') 161adfe2030SMax Reitz if self.has_real_tray: 162adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 163adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 164adfe2030SMax Reitz 165adfe2030SMax Reitz def test_tray_open_change(self): 166b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-open-tray', id=self.device_name, 1671d701e0eSMax Reitz force=True) 168adfe2030SMax Reitz 169adfe2030SMax Reitz self.wait_for_open() 170adfe2030SMax Reitz 171adfe2030SMax Reitz result = self.vm.qmp('query-block') 172abb3e55bSMax Reitz if self.has_real_tray: 173adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 174adfe2030SMax Reitz if self.was_empty == True: 175adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 176adfe2030SMax Reitz else: 177adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 178adfe2030SMax Reitz 179b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', id=self.device_name, 180adfe2030SMax Reitz filename=new_img, 181adfe2030SMax Reitz format=iotests.imgfmt) 182adfe2030SMax Reitz 183adfe2030SMax Reitz self.wait_for_close() 184adfe2030SMax Reitz 185adfe2030SMax Reitz result = self.vm.qmp('query-block') 186abb3e55bSMax Reitz if self.has_real_tray: 187adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 188adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 189adfe2030SMax Reitz 19068174160SKevin Wolf def test_cycle(self, read_only_node=False): 191b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-add', 1920153d2f5SKevin Wolf node_name='new', 1930153d2f5SKevin Wolf driver=iotests.imgfmt, 19468174160SKevin Wolf read_only=read_only_node, 1950153d2f5SKevin Wolf file={'filename': new_img, 1960153d2f5SKevin Wolf 'driver': 'file'}) 197adfe2030SMax Reitz 198b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-open-tray', 199486b88bdSKevin Wolf id=self.device_name, force=True) 200adfe2030SMax Reitz 201adfe2030SMax Reitz self.wait_for_open() 202adfe2030SMax Reitz 203adfe2030SMax Reitz result = self.vm.qmp('query-block') 204abb3e55bSMax Reitz if self.has_real_tray: 205adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 206adfe2030SMax Reitz if self.was_empty == True: 207adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 208adfe2030SMax Reitz else: 209adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 210adfe2030SMax Reitz 211b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-remove-medium', 212486b88bdSKevin Wolf id=self.device_name) 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', True) 217adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 218adfe2030SMax Reitz 219b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-insert-medium', 220486b88bdSKevin Wolf id=self.device_name, node_name='new') 221adfe2030SMax Reitz 222adfe2030SMax Reitz result = self.vm.qmp('query-block') 223abb3e55bSMax Reitz if self.has_real_tray: 224adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 225adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 226adfe2030SMax Reitz 227b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-close-tray', id=self.device_name) 228adfe2030SMax Reitz 229adfe2030SMax Reitz self.wait_for_close() 230adfe2030SMax Reitz 231adfe2030SMax Reitz result = self.vm.qmp('query-block') 232abb3e55bSMax Reitz if self.has_real_tray: 233adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 234adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 235adfe2030SMax Reitz 23668174160SKevin Wolf def test_cycle_read_only_media(self): 23768174160SKevin Wolf self.test_cycle(True) 23868174160SKevin Wolf 239adfe2030SMax Reitz def test_close_on_closed(self): 240adfe2030SMax Reitz # Should be a no-op 241b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-close-tray', id=self.device_name) 242fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 243adfe2030SMax Reitz 244adfe2030SMax Reitz def test_remove_on_closed(self): 245abb3e55bSMax Reitz if not self.has_real_tray: 246adfe2030SMax Reitz return 247adfe2030SMax Reitz 24834ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 249adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 250adfe2030SMax Reitz 251adfe2030SMax Reitz def test_insert_on_closed(self): 252abb3e55bSMax Reitz if not self.has_real_tray: 253adfe2030SMax Reitz return 254adfe2030SMax Reitz 255b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-add', 2560153d2f5SKevin Wolf node_name='new', 2570153d2f5SKevin Wolf driver=iotests.imgfmt, 2580153d2f5SKevin Wolf file={'filename': new_img, 2590153d2f5SKevin Wolf 'driver': 'file'}) 260adfe2030SMax Reitz 26134ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 262adfe2030SMax Reitz node_name='new') 263adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 264adfe2030SMax Reitz 265adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 266adfe2030SMax Reitz was_empty = False 267adfe2030SMax Reitz 268dfc82894SKevin Wolf def setUp(self): 269adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 270adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 271486b88bdSKevin Wolf self.vm = iotests.VM() 27219462c4bSKevin Wolf if self.use_drive: 273dfc82894SKevin Wolf self.vm.add_drive(old_img, 'media=%s' % self.media, 'none') 27419462c4bSKevin Wolf else: 27519462c4bSKevin Wolf self.vm.add_blockdev([ 'node-name=drive0', 27619462c4bSKevin Wolf 'driver=%s' % iotests.imgfmt, 27719462c4bSKevin Wolf 'file.driver=file', 27819462c4bSKevin Wolf 'file.filename=%s' % old_img ]) 279dfc82894SKevin Wolf if self.interface == 'scsi': 280*3be57622SKevin Wolf self.vm.add_object('iothread,id=iothread0') 281*3be57622SKevin Wolf self.vm.add_device('virtio-scsi-pci,iothread=iothread0') 2821d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 283dfc82894SKevin Wolf (interface_to_device_name(self.interface), 2841d701e0eSMax Reitz self.device_name)) 285adfe2030SMax Reitz self.vm.launch() 286adfe2030SMax Reitz 287adfe2030SMax Reitz def tearDown(self): 288adfe2030SMax Reitz self.vm.shutdown() 289adfe2030SMax Reitz os.remove(old_img) 290adfe2030SMax Reitz os.remove(new_img) 291adfe2030SMax Reitz 292adfe2030SMax Reitz def test_insert_on_filled(self): 293b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-add', 2940153d2f5SKevin Wolf node_name='new', 2950153d2f5SKevin Wolf driver=iotests.imgfmt, 2960153d2f5SKevin Wolf file={'filename': new_img, 2970153d2f5SKevin Wolf 'driver': 'file'}) 298adfe2030SMax Reitz 299b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-open-tray', id=self.device_name) 300adfe2030SMax Reitz 301adfe2030SMax Reitz self.wait_for_open() 302adfe2030SMax Reitz 30334ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 304adfe2030SMax Reitz node_name='new') 305adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 306adfe2030SMax Reitz 307adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 308adfe2030SMax Reitz was_empty = True 309adfe2030SMax Reitz 310dfc82894SKevin Wolf def setUp(self): 311adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 31219462c4bSKevin Wolf self.vm = iotests.VM() 31319462c4bSKevin Wolf if self.use_drive: 31419462c4bSKevin Wolf self.vm.add_drive(None, 'media=%s' % self.media, 'none') 315dfc82894SKevin Wolf if self.interface == 'scsi': 316*3be57622SKevin Wolf self.vm.add_object('iothread,id=iothread0') 317*3be57622SKevin Wolf self.vm.add_device('virtio-scsi-pci,iothread=iothread0') 31819462c4bSKevin Wolf self.vm.add_device('%s,%sid=%s' % 319dfc82894SKevin Wolf (interface_to_device_name(self.interface), 32019462c4bSKevin Wolf 'drive=drive0,' if self.use_drive else '', 3211d701e0eSMax Reitz self.device_name)) 322adfe2030SMax Reitz self.vm.launch() 323adfe2030SMax Reitz 324adfe2030SMax Reitz def tearDown(self): 325adfe2030SMax Reitz self.vm.shutdown() 326adfe2030SMax Reitz os.remove(new_img) 327adfe2030SMax Reitz 328adfe2030SMax Reitz def test_remove_on_empty(self): 329b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-open-tray', id=self.device_name) 330adfe2030SMax Reitz 331adfe2030SMax Reitz self.wait_for_open() 332adfe2030SMax Reitz 333adfe2030SMax Reitz # Should be a no-op 334b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-remove-medium', id=self.device_name) 335adfe2030SMax Reitz 336dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global 337dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes) 338dfc82894SKevin Wolfdef create_basic_test_classes(): 339dfc82894SKevin Wolf for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True), 340dfc82894SKevin Wolf ('cdrom', 'scsi', True), 341dfc82894SKevin Wolf ('disk', 'floppy', False) ]: 342adfe2030SMax Reitz 343dfc82894SKevin Wolf for case in [ TestInitiallyFilled, TestInitiallyEmpty ]: 34419462c4bSKevin Wolf for use_drive in [ True, False ]: 345dfc82894SKevin Wolf attr = { 'media': media, 346dfc82894SKevin Wolf 'interface': interface, 34719462c4bSKevin Wolf 'has_real_tray': has_real_tray, 34819462c4bSKevin Wolf 'use_drive': use_drive } 349adfe2030SMax Reitz 35019462c4bSKevin Wolf name = '%s_%s_%s_%s' % (case.__name__, media, interface, 35119462c4bSKevin Wolf 'drive' if use_drive else 'blockdev') 352dfc82894SKevin Wolf globals()[name] = type(name, (case, ), attr) 353adfe2030SMax Reitz 354dfc82894SKevin Wolfcreate_basic_test_classes() 355adfe2030SMax Reitz 356adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 3571d701e0eSMax Reitz device_name = 'qdev0' 3581d701e0eSMax Reitz 359adfe2030SMax Reitz def setUp(self): 360adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 361adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 362adfe2030SMax Reitz self.vm = iotests.VM() 363adfe2030SMax Reitz 364adfe2030SMax Reitz def tearDown(self): 365adfe2030SMax Reitz self.vm.shutdown() 3664803c5cdSEduardo Habkost os.chmod(old_img, 0o666) 3674803c5cdSEduardo Habkost os.chmod(new_img, 0o666) 368adfe2030SMax Reitz os.remove(old_img) 369adfe2030SMax Reitz os.remove(new_img) 370adfe2030SMax Reitz 371adfe2030SMax Reitz def test_ro_ro_retain(self): 3724803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 3734803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 3741d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 3751d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 376adfe2030SMax Reitz self.vm.launch() 377adfe2030SMax Reitz 378adfe2030SMax Reitz result = self.vm.qmp('query-block') 379adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 380adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 381adfe2030SMax Reitz 382b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', id=self.device_name, 383adfe2030SMax Reitz filename=new_img, 384adfe2030SMax Reitz format=iotests.imgfmt, 385adfe2030SMax Reitz read_only_mode='retain') 386adfe2030SMax Reitz 387adfe2030SMax Reitz result = self.vm.qmp('query-block') 388adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 389adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 390adfe2030SMax Reitz 391adfe2030SMax Reitz def test_ro_rw_retain(self): 3924803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 3931d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 3941d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 395adfe2030SMax Reitz self.vm.launch() 396adfe2030SMax Reitz 397adfe2030SMax Reitz result = self.vm.qmp('query-block') 398adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 399adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 400adfe2030SMax Reitz 401b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', id=self.device_name, 402adfe2030SMax Reitz filename=new_img, 403adfe2030SMax Reitz format=iotests.imgfmt, 404adfe2030SMax Reitz read_only_mode='retain') 405adfe2030SMax Reitz 406adfe2030SMax Reitz result = self.vm.qmp('query-block') 407adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 408adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 409adfe2030SMax Reitz 410d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 411adfe2030SMax Reitz def test_rw_ro_retain(self): 4124803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4131d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4141d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 415adfe2030SMax Reitz self.vm.launch() 416adfe2030SMax Reitz 417adfe2030SMax Reitz result = self.vm.qmp('query-block') 418adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 419adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 420adfe2030SMax Reitz 4211d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 422adfe2030SMax Reitz filename=new_img, 423adfe2030SMax Reitz format=iotests.imgfmt, 424adfe2030SMax Reitz read_only_mode='retain') 425adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 426adfe2030SMax Reitz 427fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 428adfe2030SMax Reitz 429adfe2030SMax Reitz result = self.vm.qmp('query-block') 430adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 431adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 432adfe2030SMax Reitz 433adfe2030SMax Reitz def test_ro_rw(self): 4344803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4351d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4361d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 437adfe2030SMax Reitz self.vm.launch() 438adfe2030SMax Reitz 439adfe2030SMax Reitz result = self.vm.qmp('query-block') 440adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 441adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 442adfe2030SMax Reitz 443b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', 4441d701e0eSMax Reitz id=self.device_name, 445adfe2030SMax Reitz filename=new_img, 446adfe2030SMax Reitz format=iotests.imgfmt, 447adfe2030SMax Reitz read_only_mode='read-write') 448adfe2030SMax Reitz 449adfe2030SMax Reitz result = self.vm.qmp('query-block') 450adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 451adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 452adfe2030SMax Reitz 453adfe2030SMax Reitz def test_rw_ro(self): 4544803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4551d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4561d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 457adfe2030SMax Reitz self.vm.launch() 458adfe2030SMax Reitz 459adfe2030SMax Reitz result = self.vm.qmp('query-block') 460adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 461adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 462adfe2030SMax Reitz 463b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', 4641d701e0eSMax Reitz id=self.device_name, 465adfe2030SMax Reitz filename=new_img, 466adfe2030SMax Reitz format=iotests.imgfmt, 467adfe2030SMax Reitz read_only_mode='read-only') 468adfe2030SMax Reitz 469adfe2030SMax Reitz result = self.vm.qmp('query-block') 470adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 471adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 472adfe2030SMax Reitz 473adfe2030SMax Reitz def test_make_rw_ro(self): 4741d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', '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', False) 480adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 481adfe2030SMax Reitz 482b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('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-only') 487adfe2030SMax Reitz 488adfe2030SMax Reitz result = self.vm.qmp('query-block') 489adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 490adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 491adfe2030SMax Reitz 492d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 493adfe2030SMax Reitz def test_make_ro_rw(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-write') 508adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 509adfe2030SMax Reitz 510adfe2030SMax Reitz result = self.vm.qmp('query-block') 511adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 512adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 513adfe2030SMax Reitz 514adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 5154803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5161d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', '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', True) 522adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 523adfe2030SMax Reitz 524b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-change-medium', id=self.device_name, 525adfe2030SMax Reitz filename=new_img, 526adfe2030SMax Reitz format=iotests.imgfmt, 527adfe2030SMax Reitz read_only_mode='retain') 528adfe2030SMax Reitz 529adfe2030SMax Reitz result = self.vm.qmp('query-block') 530adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 531adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 532adfe2030SMax Reitz 533d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 534adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 5354803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5361d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5371d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 538adfe2030SMax Reitz self.vm.launch() 539adfe2030SMax Reitz 540adfe2030SMax Reitz result = self.vm.qmp('query-block') 541adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 542adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 543adfe2030SMax Reitz 5441d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 545adfe2030SMax Reitz filename=new_img, 546adfe2030SMax Reitz format=iotests.imgfmt, 547adfe2030SMax Reitz read_only_mode='retain') 548adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 549adfe2030SMax Reitz 550adfe2030SMax Reitz result = self.vm.qmp('query-block') 551adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 552adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 553adfe2030SMax Reitz 554adfe2030SMax Reitz def test_rw_ro_cycle(self): 5554803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5561d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5571d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 558adfe2030SMax Reitz self.vm.launch() 559adfe2030SMax Reitz 560adfe2030SMax Reitz result = self.vm.qmp('query-block') 561adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 562adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 563adfe2030SMax Reitz 564b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-add', 5650153d2f5SKevin Wolf node_name='new', 5660153d2f5SKevin Wolf driver=iotests.imgfmt, 5670153d2f5SKevin Wolf read_only=True, 5680153d2f5SKevin Wolf file={'filename': new_img, 5690153d2f5SKevin Wolf 'driver': 'file'}) 570adfe2030SMax Reitz 571adfe2030SMax Reitz result = self.vm.qmp('query-block') 572adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 573adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 574adfe2030SMax Reitz 575b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-remove-medium', id=self.device_name) 576adfe2030SMax Reitz 577adfe2030SMax Reitz result = self.vm.qmp('query-block') 578adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 579adfe2030SMax Reitz 580b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-insert-medium', id=self.device_name, 581adfe2030SMax Reitz node_name='new') 582adfe2030SMax Reitz 583adfe2030SMax Reitz result = self.vm.qmp('query-block') 584adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 585adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 586adfe2030SMax Reitz 587adfe2030SMax Reitz result = self.vm.qmp('query-block') 588adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 589adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 590adfe2030SMax Reitz 591adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 592adfe2030SMax ReitzTestInitiallyFilled = None 593adfe2030SMax ReitzTestInitiallyEmpty = None 594adfe2030SMax Reitz 595adfe2030SMax Reitz 596adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 5971d701e0eSMax Reitz device_name = 'qdev0' 5981d701e0eSMax Reitz 599adfe2030SMax Reitz def setUp(self): 6001d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 601adfe2030SMax Reitz 602adfe2030SMax Reitz self.vm = iotests.VM() 603e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6041d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 605adfe2030SMax Reitz self.vm.launch() 606adfe2030SMax Reitz 607adfe2030SMax Reitz result = self.vm.qmp('query-block') 608adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 609adfe2030SMax Reitz 610adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 611adfe2030SMax Reitz # is not necessary 612b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-remove-medium', id=self.device_name) 613adfe2030SMax Reitz 614adfe2030SMax Reitz result = self.vm.qmp('query-block') 615adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 616adfe2030SMax Reitz 617b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-add', 6180153d2f5SKevin Wolf node_name='node0', 6190153d2f5SKevin Wolf driver=iotests.imgfmt, 6200153d2f5SKevin Wolf file={'filename': old_img, 6210153d2f5SKevin Wolf 'driver': 'file'}) 622adfe2030SMax Reitz 623b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-insert-medium', id=self.device_name, 624adfe2030SMax Reitz node_name='node0') 625adfe2030SMax Reitz 626adfe2030SMax Reitz result = self.vm.qmp('query-block') 627adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 628adfe2030SMax Reitz 629adfe2030SMax Reitz def tearDown(self): 630adfe2030SMax Reitz self.vm.shutdown() 631adfe2030SMax Reitz os.remove(old_img) 632adfe2030SMax Reitz try: 633adfe2030SMax Reitz os.remove(new_img) 634adfe2030SMax Reitz except OSError: 635adfe2030SMax Reitz pass 636adfe2030SMax Reitz 637adfe2030SMax Reitz # We need backing file support 638ff3caf5aSMax Reitz @iotests.skip_for_formats(('vpc', 'parallels', 'qcow', 'vdi', 'vmdk', 'raw', 639ff3caf5aSMax Reitz 'vhdx')) 640ff3caf5aSMax Reitz def test_snapshot_and_commit(self): 641b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('blockdev-snapshot-sync', device='drive0', 642adfe2030SMax Reitz snapshot_file=new_img, 643adfe2030SMax Reitz format=iotests.imgfmt) 644adfe2030SMax Reitz 645adfe2030SMax Reitz result = self.vm.qmp('query-block') 646adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 647adfe2030SMax Reitz self.assert_qmp(result, 648adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 649adfe2030SMax Reitz old_img) 650adfe2030SMax Reitz 651b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('block-commit', device='drive0') 652adfe2030SMax Reitz 653adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 654adfe2030SMax Reitz 655adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 656adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 657adfe2030SMax Reitz 658b6aed193SVladimir Sementsov-Ogievskiy self.vm.cmd('block-job-complete', device='drive0') 659adfe2030SMax Reitz 660adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 661adfe2030SMax Reitz 662adfe2030SMax Reitz 663adfe2030SMax Reitzif __name__ == '__main__': 664adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 665adfe2030SMax Reitz # We need floppy and IDE CD-ROM 666adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 667adfe2030SMax Reitz iotests.qemu_default_machine) 668cc8c46b7SMax Reitz # Need to support image creation 669cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 670103cbc77SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed'], 671103cbc77SMax Reitz supported_protocols=['file']) 672