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 45adfe2030SMax Reitz def process_events(self): 46adfe2030SMax Reitz for event in self.vm.get_qmp_events(wait=False): 47adfe2030SMax Reitz if (event['event'] == 'DEVICE_TRAY_MOVED' and 48adfe2030SMax Reitz event['data']['device'] == 'drive0'): 49adfe2030SMax Reitz if event['data']['tray-open'] == False: 50adfe2030SMax Reitz self.has_closed = True 51adfe2030SMax Reitz else: 52adfe2030SMax Reitz self.has_opened = True 53adfe2030SMax Reitz 54adfe2030SMax Reitz def wait_for_open(self): 55abb3e55bSMax Reitz if not self.has_real_tray: 56abb3e55bSMax Reitz return 57abb3e55bSMax Reitz 58d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to open'): 59d8336c6bSKevin Wolf while not self.has_opened: 60adfe2030SMax Reitz self.process_events() 61adfe2030SMax Reitz 62adfe2030SMax Reitz def wait_for_close(self): 63abb3e55bSMax Reitz if not self.has_real_tray: 64abb3e55bSMax Reitz return 65abb3e55bSMax Reitz 66d8336c6bSKevin Wolf with iotests.Timeout(3, 'Timeout while waiting for the tray to close'): 67d8336c6bSKevin Wolf while not self.has_closed: 68adfe2030SMax Reitz self.process_events() 69adfe2030SMax Reitz 70adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass): 71486b88bdSKevin Wolf 721d701e0eSMax Reitz device_name = 'qdev0' 73486b88bdSKevin Wolf 74adfe2030SMax Reitz def test_change(self): 75adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 76adfe2030SMax Reitz arg=iotests.imgfmt) 77adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 78adfe2030SMax Reitz 79adfe2030SMax Reitz self.wait_for_open() 80adfe2030SMax Reitz self.wait_for_close() 81adfe2030SMax Reitz 82adfe2030SMax Reitz result = self.vm.qmp('query-block') 83abb3e55bSMax Reitz if self.has_real_tray: 84adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 85adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 86adfe2030SMax Reitz 87adfe2030SMax Reitz def test_blockdev_change_medium(self): 88486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 89486b88bdSKevin Wolf id=self.device_name, filename=new_img, 90adfe2030SMax Reitz format=iotests.imgfmt) 91486b88bdSKevin Wolf 92adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 93adfe2030SMax Reitz 94adfe2030SMax Reitz self.wait_for_open() 95adfe2030SMax Reitz self.wait_for_close() 96adfe2030SMax Reitz 97adfe2030SMax Reitz result = self.vm.qmp('query-block') 98abb3e55bSMax Reitz if self.has_real_tray: 99adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 100adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 101adfe2030SMax Reitz 102adfe2030SMax Reitz def test_eject(self): 103486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 104adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 105adfe2030SMax Reitz 106adfe2030SMax Reitz self.wait_for_open() 107adfe2030SMax Reitz 108adfe2030SMax Reitz result = self.vm.qmp('query-block') 109abb3e55bSMax Reitz if self.has_real_tray: 110adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 111adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 112adfe2030SMax Reitz 113adfe2030SMax Reitz def test_tray_eject_change(self): 114486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 115adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 116adfe2030SMax Reitz 117adfe2030SMax Reitz self.wait_for_open() 118adfe2030SMax Reitz 119adfe2030SMax Reitz result = self.vm.qmp('query-block') 120abb3e55bSMax Reitz if self.has_real_tray: 121adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 122adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 123adfe2030SMax Reitz 124486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 125486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 126adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 127adfe2030SMax Reitz 128adfe2030SMax Reitz self.wait_for_close() 129adfe2030SMax Reitz 130adfe2030SMax Reitz result = self.vm.qmp('query-block') 131abb3e55bSMax Reitz if self.has_real_tray: 132adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 133adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 134adfe2030SMax Reitz 135adfe2030SMax Reitz def test_tray_open_close(self): 136486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 137486b88bdSKevin Wolf id=self.device_name, force=True) 138adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 139adfe2030SMax Reitz 140adfe2030SMax Reitz self.wait_for_open() 141adfe2030SMax Reitz 142adfe2030SMax Reitz result = self.vm.qmp('query-block') 143abb3e55bSMax Reitz if self.has_real_tray: 144adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 145adfe2030SMax Reitz if self.was_empty == True: 146adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 147adfe2030SMax Reitz else: 148adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 149adfe2030SMax Reitz 150486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 151adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 152adfe2030SMax Reitz 153adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 154adfe2030SMax Reitz self.wait_for_close() 155adfe2030SMax Reitz 156adfe2030SMax Reitz result = self.vm.qmp('query-block') 157abb3e55bSMax Reitz if self.has_real_tray: 158adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 159adfe2030SMax Reitz if self.was_empty == True: 160adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 161adfe2030SMax Reitz else: 162adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 163adfe2030SMax Reitz 164adfe2030SMax Reitz def test_tray_eject_close(self): 1651d701e0eSMax Reitz result = self.vm.qmp('eject', id=self.device_name, force=True) 166adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 167adfe2030SMax Reitz 168adfe2030SMax Reitz self.wait_for_open() 169adfe2030SMax Reitz 170adfe2030SMax Reitz result = self.vm.qmp('query-block') 171abb3e55bSMax Reitz if self.has_real_tray: 172adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 173adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 174adfe2030SMax Reitz 175486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 176adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 177adfe2030SMax Reitz 178adfe2030SMax Reitz self.wait_for_close() 179adfe2030SMax Reitz 180adfe2030SMax Reitz result = self.vm.qmp('query-block') 181adfe2030SMax Reitz if self.has_real_tray: 182adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 183adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 184adfe2030SMax Reitz 185adfe2030SMax Reitz def test_tray_open_change(self): 1861d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name, 1871d701e0eSMax Reitz force=True) 188adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 189adfe2030SMax Reitz 190adfe2030SMax Reitz self.wait_for_open() 191adfe2030SMax Reitz 192adfe2030SMax Reitz result = self.vm.qmp('query-block') 193abb3e55bSMax Reitz if self.has_real_tray: 194adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 195adfe2030SMax Reitz if self.was_empty == True: 196adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 197adfe2030SMax Reitz else: 198adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 199adfe2030SMax Reitz 2001d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 201adfe2030SMax Reitz filename=new_img, 202adfe2030SMax Reitz format=iotests.imgfmt) 203adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 204adfe2030SMax Reitz 205adfe2030SMax Reitz self.wait_for_close() 206adfe2030SMax Reitz 207adfe2030SMax Reitz result = self.vm.qmp('query-block') 208abb3e55bSMax Reitz if self.has_real_tray: 209adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 210adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 211adfe2030SMax Reitz 21268174160SKevin Wolf def test_cycle(self, read_only_node=False): 213adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2140153d2f5SKevin Wolf node_name='new', 2150153d2f5SKevin Wolf driver=iotests.imgfmt, 21668174160SKevin Wolf read_only=read_only_node, 2170153d2f5SKevin Wolf file={'filename': new_img, 2180153d2f5SKevin Wolf 'driver': 'file'}) 219adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 220adfe2030SMax Reitz 221486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 222486b88bdSKevin Wolf id=self.device_name, force=True) 223adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 224adfe2030SMax Reitz 225adfe2030SMax Reitz self.wait_for_open() 226adfe2030SMax Reitz 227adfe2030SMax Reitz result = self.vm.qmp('query-block') 228abb3e55bSMax Reitz if self.has_real_tray: 229adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 230adfe2030SMax Reitz if self.was_empty == True: 231adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 232adfe2030SMax Reitz else: 233adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 234adfe2030SMax Reitz 23534ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', 236486b88bdSKevin Wolf id=self.device_name) 237adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 238adfe2030SMax Reitz 239adfe2030SMax Reitz result = self.vm.qmp('query-block') 240abb3e55bSMax Reitz if self.has_real_tray: 241adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 242adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 243adfe2030SMax Reitz 24434ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', 245486b88bdSKevin Wolf id=self.device_name, node_name='new') 246adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 247adfe2030SMax Reitz 248adfe2030SMax Reitz result = self.vm.qmp('query-block') 249abb3e55bSMax Reitz if self.has_real_tray: 250adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 251adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 252adfe2030SMax Reitz 253486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 254adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 255adfe2030SMax Reitz 256adfe2030SMax Reitz self.wait_for_close() 257adfe2030SMax Reitz 258adfe2030SMax Reitz result = self.vm.qmp('query-block') 259abb3e55bSMax Reitz if self.has_real_tray: 260adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 261adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 262adfe2030SMax Reitz 26368174160SKevin Wolf def test_cycle_read_only_media(self): 26468174160SKevin Wolf self.test_cycle(True) 26568174160SKevin Wolf 266adfe2030SMax Reitz def test_close_on_closed(self): 2671d701e0eSMax Reitz result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 268adfe2030SMax Reitz # Should be a no-op 269adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 270fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 271adfe2030SMax Reitz 272adfe2030SMax Reitz def test_remove_on_closed(self): 273abb3e55bSMax Reitz if not self.has_real_tray: 274adfe2030SMax Reitz return 275adfe2030SMax Reitz 27634ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 277adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 278adfe2030SMax Reitz 279adfe2030SMax Reitz def test_insert_on_closed(self): 280abb3e55bSMax Reitz if not self.has_real_tray: 281adfe2030SMax Reitz return 282adfe2030SMax Reitz 283adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2840153d2f5SKevin Wolf node_name='new', 2850153d2f5SKevin Wolf driver=iotests.imgfmt, 2860153d2f5SKevin Wolf file={'filename': new_img, 2870153d2f5SKevin Wolf 'driver': 'file'}) 288adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 289adfe2030SMax Reitz 29034ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 291adfe2030SMax Reitz node_name='new') 292adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 293adfe2030SMax Reitz 294adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 295adfe2030SMax Reitz was_empty = False 296adfe2030SMax Reitz 297*dfc82894SKevin Wolf def setUp(self): 298adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 299adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 300486b88bdSKevin Wolf self.vm = iotests.VM() 301*dfc82894SKevin Wolf self.vm.add_drive(old_img, 'media=%s' % self.media, 'none') 302*dfc82894SKevin Wolf if self.interface == 'scsi': 303dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 3041d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 305*dfc82894SKevin Wolf (interface_to_device_name(self.interface), 3061d701e0eSMax Reitz self.device_name)) 307adfe2030SMax Reitz self.vm.launch() 308adfe2030SMax Reitz 309adfe2030SMax Reitz def tearDown(self): 310adfe2030SMax Reitz self.vm.shutdown() 311adfe2030SMax Reitz os.remove(old_img) 312adfe2030SMax Reitz os.remove(new_img) 313adfe2030SMax Reitz 314adfe2030SMax Reitz def test_insert_on_filled(self): 315adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 3160153d2f5SKevin Wolf node_name='new', 3170153d2f5SKevin Wolf driver=iotests.imgfmt, 3180153d2f5SKevin Wolf file={'filename': new_img, 3190153d2f5SKevin Wolf 'driver': 'file'}) 320adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 321adfe2030SMax Reitz 3221d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 323adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 324adfe2030SMax Reitz 325adfe2030SMax Reitz self.wait_for_open() 326adfe2030SMax Reitz 32734ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 328adfe2030SMax Reitz node_name='new') 329adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 330adfe2030SMax Reitz 331adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 332adfe2030SMax Reitz was_empty = True 333adfe2030SMax Reitz 334*dfc82894SKevin Wolf def setUp(self): 335adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 336*dfc82894SKevin Wolf self.vm = iotests.VM().add_drive(None, 'media=%s' % self.media, 'none') 337*dfc82894SKevin Wolf if self.interface == 'scsi': 338dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 3391d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 340*dfc82894SKevin Wolf (interface_to_device_name(self.interface), 3411d701e0eSMax Reitz self.device_name)) 342adfe2030SMax Reitz self.vm.launch() 343adfe2030SMax Reitz 344adfe2030SMax Reitz def tearDown(self): 345adfe2030SMax Reitz self.vm.shutdown() 346adfe2030SMax Reitz os.remove(new_img) 347adfe2030SMax Reitz 348adfe2030SMax Reitz def test_remove_on_empty(self): 3491d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 350adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 351adfe2030SMax Reitz 352adfe2030SMax Reitz self.wait_for_open() 353adfe2030SMax Reitz 35434ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 355adfe2030SMax Reitz # Should be a no-op 356adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 357adfe2030SMax Reitz 358*dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global 359*dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes) 360*dfc82894SKevin Wolfdef create_basic_test_classes(): 361*dfc82894SKevin Wolf for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True), 362*dfc82894SKevin Wolf ('cdrom', 'scsi', True), 363*dfc82894SKevin Wolf ('disk', 'floppy', False) ]: 364adfe2030SMax Reitz 365*dfc82894SKevin Wolf for case in [ TestInitiallyFilled, TestInitiallyEmpty ]: 366adfe2030SMax Reitz 367*dfc82894SKevin Wolf attr = { 'media': media, 368*dfc82894SKevin Wolf 'interface': interface, 369*dfc82894SKevin Wolf 'has_real_tray': has_real_tray } 370adfe2030SMax Reitz 371*dfc82894SKevin Wolf name = '%s_%s_%s' % (case.__name__, media, interface) 372*dfc82894SKevin Wolf globals()[name] = type(name, (case, ), attr) 373adfe2030SMax Reitz 374*dfc82894SKevin Wolfcreate_basic_test_classes() 375adfe2030SMax Reitz 376adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 3771d701e0eSMax Reitz device_name = 'qdev0' 3781d701e0eSMax Reitz 379adfe2030SMax Reitz def setUp(self): 380adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 381adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 382adfe2030SMax Reitz self.vm = iotests.VM() 383adfe2030SMax Reitz 384adfe2030SMax Reitz def tearDown(self): 385adfe2030SMax Reitz self.vm.shutdown() 3864803c5cdSEduardo Habkost os.chmod(old_img, 0o666) 3874803c5cdSEduardo Habkost os.chmod(new_img, 0o666) 388adfe2030SMax Reitz os.remove(old_img) 389adfe2030SMax Reitz os.remove(new_img) 390adfe2030SMax Reitz 391adfe2030SMax Reitz def test_ro_ro_retain(self): 3924803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 3934803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 3941d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 3951d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 396adfe2030SMax Reitz self.vm.launch() 397adfe2030SMax Reitz 398adfe2030SMax Reitz result = self.vm.qmp('query-block') 399adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 400adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 401adfe2030SMax Reitz 4021d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 403adfe2030SMax Reitz filename=new_img, 404adfe2030SMax Reitz format=iotests.imgfmt, 405adfe2030SMax Reitz read_only_mode='retain') 406adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 407adfe2030SMax Reitz 408adfe2030SMax Reitz result = self.vm.qmp('query-block') 409adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 410adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 411adfe2030SMax Reitz 412adfe2030SMax Reitz def test_ro_rw_retain(self): 4134803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4141d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4151d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 416adfe2030SMax Reitz self.vm.launch() 417adfe2030SMax Reitz 418adfe2030SMax Reitz result = self.vm.qmp('query-block') 419adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 420adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 421adfe2030SMax Reitz 4221d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 423adfe2030SMax Reitz filename=new_img, 424adfe2030SMax Reitz format=iotests.imgfmt, 425adfe2030SMax Reitz read_only_mode='retain') 426adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 427adfe2030SMax Reitz 428adfe2030SMax Reitz result = self.vm.qmp('query-block') 429adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 430adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 431adfe2030SMax Reitz 432adfe2030SMax Reitz def test_rw_ro_retain(self): 4334803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4341d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4351d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 436adfe2030SMax Reitz self.vm.launch() 437adfe2030SMax Reitz 438adfe2030SMax Reitz result = self.vm.qmp('query-block') 439adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 440adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 441adfe2030SMax Reitz 4421d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 443adfe2030SMax Reitz filename=new_img, 444adfe2030SMax Reitz format=iotests.imgfmt, 445adfe2030SMax Reitz read_only_mode='retain') 446adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 447adfe2030SMax Reitz 448fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 449adfe2030SMax Reitz 450adfe2030SMax Reitz result = self.vm.qmp('query-block') 451adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 452adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 453adfe2030SMax Reitz 454adfe2030SMax Reitz def test_ro_rw(self): 4554803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4561d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4571d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 458adfe2030SMax Reitz self.vm.launch() 459adfe2030SMax Reitz 460adfe2030SMax Reitz result = self.vm.qmp('query-block') 461adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 462adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 463adfe2030SMax Reitz 464adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4651d701e0eSMax Reitz id=self.device_name, 466adfe2030SMax Reitz filename=new_img, 467adfe2030SMax Reitz format=iotests.imgfmt, 468adfe2030SMax Reitz read_only_mode='read-write') 469adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 470adfe2030SMax Reitz 471adfe2030SMax Reitz result = self.vm.qmp('query-block') 472adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 473adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 474adfe2030SMax Reitz 475adfe2030SMax Reitz def test_rw_ro(self): 4764803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4771d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4781d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 479adfe2030SMax Reitz self.vm.launch() 480adfe2030SMax Reitz 481adfe2030SMax Reitz result = self.vm.qmp('query-block') 482adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 483adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 484adfe2030SMax Reitz 485adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4861d701e0eSMax Reitz id=self.device_name, 487adfe2030SMax Reitz filename=new_img, 488adfe2030SMax Reitz format=iotests.imgfmt, 489adfe2030SMax Reitz read_only_mode='read-only') 490adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 491adfe2030SMax Reitz 492adfe2030SMax Reitz result = self.vm.qmp('query-block') 493adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 494adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 495adfe2030SMax Reitz 496adfe2030SMax Reitz def test_make_rw_ro(self): 4971d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4981d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 499adfe2030SMax Reitz self.vm.launch() 500adfe2030SMax Reitz 501adfe2030SMax Reitz result = self.vm.qmp('query-block') 502adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 503adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 504adfe2030SMax Reitz 505adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5061d701e0eSMax Reitz id=self.device_name, 507adfe2030SMax Reitz filename=new_img, 508adfe2030SMax Reitz format=iotests.imgfmt, 509adfe2030SMax Reitz read_only_mode='read-only') 510adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 511adfe2030SMax Reitz 512adfe2030SMax Reitz result = self.vm.qmp('query-block') 513adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 514adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 515adfe2030SMax Reitz 516adfe2030SMax Reitz def test_make_ro_rw(self): 5174803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5181d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5191d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 520adfe2030SMax Reitz self.vm.launch() 521adfe2030SMax Reitz 522adfe2030SMax Reitz result = self.vm.qmp('query-block') 523adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 524adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 525adfe2030SMax Reitz 526adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5271d701e0eSMax Reitz id=self.device_name, 528adfe2030SMax Reitz filename=new_img, 529adfe2030SMax Reitz format=iotests.imgfmt, 530adfe2030SMax Reitz read_only_mode='read-write') 531adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 532adfe2030SMax Reitz 533adfe2030SMax Reitz result = self.vm.qmp('query-block') 534adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 535adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 536adfe2030SMax Reitz 537adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 5384803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5391d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 5401d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 541adfe2030SMax Reitz self.vm.launch() 542adfe2030SMax Reitz 543adfe2030SMax Reitz result = self.vm.qmp('query-block') 544adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 545adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 546adfe2030SMax Reitz 5471d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 548adfe2030SMax Reitz filename=new_img, 549adfe2030SMax Reitz format=iotests.imgfmt, 550adfe2030SMax Reitz read_only_mode='retain') 551adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 552adfe2030SMax Reitz 553adfe2030SMax Reitz result = self.vm.qmp('query-block') 554adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 555adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 556adfe2030SMax Reitz 557adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 5584803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5591d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', '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', False) 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, 'error/class', 'GenericError') 572adfe2030SMax Reitz 573adfe2030SMax Reitz result = self.vm.qmp('query-block') 574adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 575adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 576adfe2030SMax Reitz 577adfe2030SMax Reitz def test_rw_ro_cycle(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 587adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 5880153d2f5SKevin Wolf node_name='new', 5890153d2f5SKevin Wolf driver=iotests.imgfmt, 5900153d2f5SKevin Wolf read_only=True, 5910153d2f5SKevin Wolf file={'filename': new_img, 5920153d2f5SKevin Wolf 'driver': 'file'}) 593adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 594adfe2030SMax Reitz 595adfe2030SMax Reitz result = self.vm.qmp('query-block') 596adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 597adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 598adfe2030SMax Reitz 59934ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 600adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 601adfe2030SMax Reitz 602adfe2030SMax Reitz result = self.vm.qmp('query-block') 603adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 604adfe2030SMax Reitz 60534ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 606adfe2030SMax Reitz node_name='new') 607adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 608adfe2030SMax Reitz 609adfe2030SMax Reitz result = self.vm.qmp('query-block') 610adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 611adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 612adfe2030SMax Reitz 613adfe2030SMax Reitz result = self.vm.qmp('query-block') 614adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 615adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 616adfe2030SMax Reitz 617adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 618adfe2030SMax ReitzTestInitiallyFilled = None 619adfe2030SMax ReitzTestInitiallyEmpty = None 620adfe2030SMax Reitz 621adfe2030SMax Reitz 622adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 6231d701e0eSMax Reitz device_name = 'qdev0' 6241d701e0eSMax Reitz 625adfe2030SMax Reitz def setUp(self): 6261d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 627adfe2030SMax Reitz 628adfe2030SMax Reitz self.vm = iotests.VM() 629e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6301d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 631adfe2030SMax Reitz self.vm.launch() 632adfe2030SMax Reitz 633adfe2030SMax Reitz result = self.vm.qmp('query-block') 634adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 635adfe2030SMax Reitz 636adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 637adfe2030SMax Reitz # is not necessary 63834ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 639adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 640adfe2030SMax Reitz 641adfe2030SMax Reitz result = self.vm.qmp('query-block') 642adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 643adfe2030SMax Reitz 644adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6450153d2f5SKevin Wolf node_name='node0', 6460153d2f5SKevin Wolf driver=iotests.imgfmt, 6470153d2f5SKevin Wolf file={'filename': old_img, 6480153d2f5SKevin Wolf 'driver': 'file'}) 649adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 650adfe2030SMax Reitz 65134ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 652adfe2030SMax Reitz node_name='node0') 653adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 654adfe2030SMax Reitz 655adfe2030SMax Reitz result = self.vm.qmp('query-block') 656adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 657adfe2030SMax Reitz 658adfe2030SMax Reitz def tearDown(self): 659adfe2030SMax Reitz self.vm.shutdown() 660adfe2030SMax Reitz os.remove(old_img) 661adfe2030SMax Reitz try: 662adfe2030SMax Reitz os.remove(new_img) 663adfe2030SMax Reitz except OSError: 664adfe2030SMax Reitz pass 665adfe2030SMax Reitz 666adfe2030SMax Reitz def test_snapshot_and_commit(self): 667adfe2030SMax Reitz # We need backing file support 668adfe2030SMax Reitz if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 669adfe2030SMax Reitz return 670adfe2030SMax Reitz 671adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 672adfe2030SMax Reitz snapshot_file=new_img, 673adfe2030SMax Reitz format=iotests.imgfmt) 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', new_img) 678adfe2030SMax Reitz self.assert_qmp(result, 679adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 680adfe2030SMax Reitz old_img) 681adfe2030SMax Reitz 682adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 683adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 684adfe2030SMax Reitz 685adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 686adfe2030SMax Reitz 687adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 688adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 689adfe2030SMax Reitz 690adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 691adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 692adfe2030SMax Reitz 693adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 694adfe2030SMax Reitz 695adfe2030SMax Reitz 696adfe2030SMax Reitzif __name__ == '__main__': 697adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 698adfe2030SMax Reitz # We need floppy and IDE CD-ROM 699adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 700adfe2030SMax Reitz iotests.qemu_default_machine) 701cc8c46b7SMax Reitz # Need to support image creation 702cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 703cc8c46b7SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed']) 704