1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 29dd003a9SVladimir Sementsov-Ogievskiy# group: rw 3adfe2030SMax Reitz# 4*014bb4b0SMax 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): 77486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 78486b88bdSKevin Wolf id=self.device_name, filename=new_img, 79adfe2030SMax Reitz format=iotests.imgfmt) 80486b88bdSKevin Wolf 81adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 82adfe2030SMax Reitz 83adfe2030SMax Reitz self.wait_for_open() 84adfe2030SMax Reitz self.wait_for_close() 85adfe2030SMax Reitz 86adfe2030SMax Reitz result = self.vm.qmp('query-block') 87abb3e55bSMax Reitz if self.has_real_tray: 88adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 89adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 90adfe2030SMax Reitz 91adfe2030SMax Reitz def test_eject(self): 92486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 93adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 94adfe2030SMax Reitz 95adfe2030SMax Reitz self.wait_for_open() 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', True) 100adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 101adfe2030SMax Reitz 102adfe2030SMax Reitz def test_tray_eject_change(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 113486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 114486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 115adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 116adfe2030SMax Reitz 117adfe2030SMax Reitz self.wait_for_close() 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', False) 122adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 123adfe2030SMax Reitz 124adfe2030SMax Reitz def test_tray_open_close(self): 125486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 126486b88bdSKevin Wolf id=self.device_name, force=True) 127adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 128adfe2030SMax Reitz 129adfe2030SMax Reitz self.wait_for_open() 130adfe2030SMax Reitz 131adfe2030SMax Reitz result = self.vm.qmp('query-block') 132abb3e55bSMax Reitz if self.has_real_tray: 133adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 134adfe2030SMax Reitz if self.was_empty == True: 135adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 136adfe2030SMax Reitz else: 137adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 138adfe2030SMax Reitz 139486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 140adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 141adfe2030SMax Reitz 142adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 143adfe2030SMax Reitz self.wait_for_close() 144adfe2030SMax Reitz 145adfe2030SMax Reitz result = self.vm.qmp('query-block') 146abb3e55bSMax Reitz if self.has_real_tray: 147adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 148adfe2030SMax Reitz if self.was_empty == True: 149adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 150adfe2030SMax Reitz else: 151adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 152adfe2030SMax Reitz 153adfe2030SMax Reitz def test_tray_eject_close(self): 1541d701e0eSMax Reitz result = self.vm.qmp('eject', id=self.device_name, force=True) 155adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 156adfe2030SMax Reitz 157adfe2030SMax Reitz self.wait_for_open() 158adfe2030SMax Reitz 159adfe2030SMax Reitz result = self.vm.qmp('query-block') 160abb3e55bSMax Reitz if self.has_real_tray: 161adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 162adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 163adfe2030SMax Reitz 164486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 165adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 166adfe2030SMax Reitz 167adfe2030SMax Reitz self.wait_for_close() 168adfe2030SMax Reitz 169adfe2030SMax Reitz result = self.vm.qmp('query-block') 170adfe2030SMax Reitz if self.has_real_tray: 171adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 172adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 173adfe2030SMax Reitz 174adfe2030SMax Reitz def test_tray_open_change(self): 1751d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name, 1761d701e0eSMax Reitz force=True) 177adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 178adfe2030SMax Reitz 179adfe2030SMax Reitz self.wait_for_open() 180adfe2030SMax Reitz 181adfe2030SMax Reitz result = self.vm.qmp('query-block') 182abb3e55bSMax Reitz if self.has_real_tray: 183adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 184adfe2030SMax Reitz if self.was_empty == True: 185adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 186adfe2030SMax Reitz else: 187adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 188adfe2030SMax Reitz 1891d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 190adfe2030SMax Reitz filename=new_img, 191adfe2030SMax Reitz format=iotests.imgfmt) 192adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 193adfe2030SMax Reitz 194adfe2030SMax Reitz self.wait_for_close() 195adfe2030SMax Reitz 196adfe2030SMax Reitz result = self.vm.qmp('query-block') 197abb3e55bSMax Reitz if self.has_real_tray: 198adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 199adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 200adfe2030SMax Reitz 20168174160SKevin Wolf def test_cycle(self, read_only_node=False): 202adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2030153d2f5SKevin Wolf node_name='new', 2040153d2f5SKevin Wolf driver=iotests.imgfmt, 20568174160SKevin Wolf read_only=read_only_node, 2060153d2f5SKevin Wolf file={'filename': new_img, 2070153d2f5SKevin Wolf 'driver': 'file'}) 208adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 209adfe2030SMax Reitz 210486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 211486b88bdSKevin Wolf id=self.device_name, force=True) 212adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 213adfe2030SMax Reitz 214adfe2030SMax Reitz self.wait_for_open() 215adfe2030SMax Reitz 216adfe2030SMax Reitz result = self.vm.qmp('query-block') 217abb3e55bSMax Reitz if self.has_real_tray: 218adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 219adfe2030SMax Reitz if self.was_empty == True: 220adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 221adfe2030SMax Reitz else: 222adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 223adfe2030SMax Reitz 22434ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', 225486b88bdSKevin Wolf id=self.device_name) 226adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 227adfe2030SMax Reitz 228adfe2030SMax Reitz result = self.vm.qmp('query-block') 229abb3e55bSMax Reitz if self.has_real_tray: 230adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 231adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 232adfe2030SMax Reitz 23334ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', 234486b88bdSKevin Wolf id=self.device_name, node_name='new') 235adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 236adfe2030SMax Reitz 237adfe2030SMax Reitz result = self.vm.qmp('query-block') 238abb3e55bSMax Reitz if self.has_real_tray: 239adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 240adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 241adfe2030SMax Reitz 242486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 243adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 244adfe2030SMax Reitz 245adfe2030SMax Reitz self.wait_for_close() 246adfe2030SMax Reitz 247adfe2030SMax Reitz result = self.vm.qmp('query-block') 248abb3e55bSMax Reitz if self.has_real_tray: 249adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 250adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 251adfe2030SMax Reitz 25268174160SKevin Wolf def test_cycle_read_only_media(self): 25368174160SKevin Wolf self.test_cycle(True) 25468174160SKevin Wolf 255adfe2030SMax Reitz def test_close_on_closed(self): 2561d701e0eSMax Reitz result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 257adfe2030SMax Reitz # Should be a no-op 258adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 259fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 260adfe2030SMax Reitz 261adfe2030SMax Reitz def test_remove_on_closed(self): 262abb3e55bSMax Reitz if not self.has_real_tray: 263adfe2030SMax Reitz return 264adfe2030SMax Reitz 26534ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 266adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 267adfe2030SMax Reitz 268adfe2030SMax Reitz def test_insert_on_closed(self): 269abb3e55bSMax Reitz if not self.has_real_tray: 270adfe2030SMax Reitz return 271adfe2030SMax Reitz 272adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2730153d2f5SKevin Wolf node_name='new', 2740153d2f5SKevin Wolf driver=iotests.imgfmt, 2750153d2f5SKevin Wolf file={'filename': new_img, 2760153d2f5SKevin Wolf 'driver': 'file'}) 277adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 278adfe2030SMax Reitz 27934ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 280adfe2030SMax Reitz node_name='new') 281adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 282adfe2030SMax Reitz 283adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 284adfe2030SMax Reitz was_empty = False 285adfe2030SMax Reitz 286dfc82894SKevin Wolf def setUp(self): 287adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 288adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 289486b88bdSKevin Wolf self.vm = iotests.VM() 29019462c4bSKevin Wolf if self.use_drive: 291dfc82894SKevin Wolf self.vm.add_drive(old_img, 'media=%s' % self.media, 'none') 29219462c4bSKevin Wolf else: 29319462c4bSKevin Wolf self.vm.add_blockdev([ 'node-name=drive0', 29419462c4bSKevin Wolf 'driver=%s' % iotests.imgfmt, 29519462c4bSKevin Wolf 'file.driver=file', 29619462c4bSKevin Wolf 'file.filename=%s' % old_img ]) 297dfc82894SKevin Wolf if self.interface == 'scsi': 298dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 2991d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 300dfc82894SKevin Wolf (interface_to_device_name(self.interface), 3011d701e0eSMax Reitz self.device_name)) 302adfe2030SMax Reitz self.vm.launch() 303adfe2030SMax Reitz 304adfe2030SMax Reitz def tearDown(self): 305adfe2030SMax Reitz self.vm.shutdown() 306adfe2030SMax Reitz os.remove(old_img) 307adfe2030SMax Reitz os.remove(new_img) 308adfe2030SMax Reitz 309adfe2030SMax Reitz def test_insert_on_filled(self): 310adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 3110153d2f5SKevin Wolf node_name='new', 3120153d2f5SKevin Wolf driver=iotests.imgfmt, 3130153d2f5SKevin Wolf file={'filename': new_img, 3140153d2f5SKevin Wolf 'driver': 'file'}) 315adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 316adfe2030SMax Reitz 3171d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 318adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 319adfe2030SMax Reitz 320adfe2030SMax Reitz self.wait_for_open() 321adfe2030SMax Reitz 32234ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 323adfe2030SMax Reitz node_name='new') 324adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 325adfe2030SMax Reitz 326adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 327adfe2030SMax Reitz was_empty = True 328adfe2030SMax Reitz 329dfc82894SKevin Wolf def setUp(self): 330adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 33119462c4bSKevin Wolf self.vm = iotests.VM() 33219462c4bSKevin Wolf if self.use_drive: 33319462c4bSKevin Wolf self.vm.add_drive(None, 'media=%s' % self.media, 'none') 334dfc82894SKevin Wolf if self.interface == 'scsi': 335dfa26a11SKevin Wolf self.vm.add_device('virtio-scsi-pci') 33619462c4bSKevin Wolf self.vm.add_device('%s,%sid=%s' % 337dfc82894SKevin Wolf (interface_to_device_name(self.interface), 33819462c4bSKevin Wolf 'drive=drive0,' if self.use_drive else '', 3391d701e0eSMax Reitz self.device_name)) 340adfe2030SMax Reitz self.vm.launch() 341adfe2030SMax Reitz 342adfe2030SMax Reitz def tearDown(self): 343adfe2030SMax Reitz self.vm.shutdown() 344adfe2030SMax Reitz os.remove(new_img) 345adfe2030SMax Reitz 346adfe2030SMax Reitz def test_remove_on_empty(self): 3471d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 348adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 349adfe2030SMax Reitz 350adfe2030SMax Reitz self.wait_for_open() 351adfe2030SMax Reitz 35234ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 353adfe2030SMax Reitz # Should be a no-op 354adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 355adfe2030SMax Reitz 356dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global 357dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes) 358dfc82894SKevin Wolfdef create_basic_test_classes(): 359dfc82894SKevin Wolf for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True), 360dfc82894SKevin Wolf ('cdrom', 'scsi', True), 361dfc82894SKevin Wolf ('disk', 'floppy', False) ]: 362adfe2030SMax Reitz 363dfc82894SKevin Wolf for case in [ TestInitiallyFilled, TestInitiallyEmpty ]: 36419462c4bSKevin Wolf for use_drive in [ True, False ]: 365dfc82894SKevin Wolf attr = { 'media': media, 366dfc82894SKevin Wolf 'interface': interface, 36719462c4bSKevin Wolf 'has_real_tray': has_real_tray, 36819462c4bSKevin Wolf 'use_drive': use_drive } 369adfe2030SMax Reitz 37019462c4bSKevin Wolf name = '%s_%s_%s_%s' % (case.__name__, media, interface, 37119462c4bSKevin Wolf 'drive' if use_drive else 'blockdev') 372dfc82894SKevin Wolf globals()[name] = type(name, (case, ), attr) 373adfe2030SMax Reitz 374dfc82894SKevin 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 432d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 433adfe2030SMax Reitz def test_rw_ro_retain(self): 4344803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4351d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', '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', False) 441adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 442adfe2030SMax Reitz 4431d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 444adfe2030SMax Reitz filename=new_img, 445adfe2030SMax Reitz format=iotests.imgfmt, 446adfe2030SMax Reitz read_only_mode='retain') 447adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 448adfe2030SMax Reitz 449fa1cfb40SKevin Wolf self.assertEqual(self.vm.get_qmp_events(wait=False), []) 450adfe2030SMax Reitz 451adfe2030SMax Reitz result = self.vm.qmp('query-block') 452adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 453adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 454adfe2030SMax Reitz 455adfe2030SMax Reitz def test_ro_rw(self): 4564803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4571d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4581d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 459adfe2030SMax Reitz self.vm.launch() 460adfe2030SMax Reitz 461adfe2030SMax Reitz result = self.vm.qmp('query-block') 462adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 463adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 464adfe2030SMax Reitz 465adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4661d701e0eSMax Reitz id=self.device_name, 467adfe2030SMax Reitz filename=new_img, 468adfe2030SMax Reitz format=iotests.imgfmt, 469adfe2030SMax Reitz read_only_mode='read-write') 470adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 471adfe2030SMax Reitz 472adfe2030SMax Reitz result = self.vm.qmp('query-block') 473adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 474adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 475adfe2030SMax Reitz 476adfe2030SMax Reitz def test_rw_ro(self): 4774803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4781d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4791d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 480adfe2030SMax Reitz self.vm.launch() 481adfe2030SMax Reitz 482adfe2030SMax Reitz result = self.vm.qmp('query-block') 483adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 484adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 485adfe2030SMax Reitz 486adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4871d701e0eSMax Reitz id=self.device_name, 488adfe2030SMax Reitz filename=new_img, 489adfe2030SMax Reitz format=iotests.imgfmt, 490adfe2030SMax Reitz read_only_mode='read-only') 491adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 492adfe2030SMax Reitz 493adfe2030SMax Reitz result = self.vm.qmp('query-block') 494adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 495adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 496adfe2030SMax Reitz 497adfe2030SMax Reitz def test_make_rw_ro(self): 4981d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4991d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 500adfe2030SMax Reitz self.vm.launch() 501adfe2030SMax Reitz 502adfe2030SMax Reitz result = self.vm.qmp('query-block') 503adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 504adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 505adfe2030SMax Reitz 506adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5071d701e0eSMax Reitz id=self.device_name, 508adfe2030SMax Reitz filename=new_img, 509adfe2030SMax Reitz format=iotests.imgfmt, 510adfe2030SMax Reitz read_only_mode='read-only') 511adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 512adfe2030SMax Reitz 513adfe2030SMax Reitz result = self.vm.qmp('query-block') 514adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 515adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 516adfe2030SMax Reitz 517d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 518adfe2030SMax Reitz def test_make_ro_rw(self): 5194803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5201d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5211d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 522adfe2030SMax Reitz self.vm.launch() 523adfe2030SMax Reitz 524adfe2030SMax Reitz result = self.vm.qmp('query-block') 525adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 526adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 527adfe2030SMax Reitz 528adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5291d701e0eSMax Reitz id=self.device_name, 530adfe2030SMax Reitz filename=new_img, 531adfe2030SMax Reitz format=iotests.imgfmt, 532adfe2030SMax Reitz read_only_mode='read-write') 533adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 534adfe2030SMax Reitz 535adfe2030SMax Reitz result = self.vm.qmp('query-block') 536adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 537adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 538adfe2030SMax Reitz 539adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 5404803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5411d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 5421d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 543adfe2030SMax Reitz self.vm.launch() 544adfe2030SMax Reitz 545adfe2030SMax Reitz result = self.vm.qmp('query-block') 546adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 547adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 548adfe2030SMax Reitz 5491d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 550adfe2030SMax Reitz filename=new_img, 551adfe2030SMax Reitz format=iotests.imgfmt, 552adfe2030SMax Reitz read_only_mode='retain') 553adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 554adfe2030SMax Reitz 555adfe2030SMax Reitz result = self.vm.qmp('query-block') 556adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 557adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 558adfe2030SMax Reitz 559d926f4ddSKevin Wolf @iotests.skip_if_user_is_root 560adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 5614803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5621d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5631d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 564adfe2030SMax Reitz self.vm.launch() 565adfe2030SMax Reitz 566adfe2030SMax Reitz result = self.vm.qmp('query-block') 567adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 568adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 569adfe2030SMax Reitz 5701d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 571adfe2030SMax Reitz filename=new_img, 572adfe2030SMax Reitz format=iotests.imgfmt, 573adfe2030SMax Reitz read_only_mode='retain') 574adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 575adfe2030SMax Reitz 576adfe2030SMax Reitz result = self.vm.qmp('query-block') 577adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 578adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 579adfe2030SMax Reitz 580adfe2030SMax Reitz def test_rw_ro_cycle(self): 5814803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5821d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5831d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 584adfe2030SMax Reitz self.vm.launch() 585adfe2030SMax Reitz 586adfe2030SMax Reitz result = self.vm.qmp('query-block') 587adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 588adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 589adfe2030SMax Reitz 590adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 5910153d2f5SKevin Wolf node_name='new', 5920153d2f5SKevin Wolf driver=iotests.imgfmt, 5930153d2f5SKevin Wolf read_only=True, 5940153d2f5SKevin Wolf file={'filename': new_img, 5950153d2f5SKevin Wolf 'driver': 'file'}) 596adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 597adfe2030SMax Reitz 598adfe2030SMax Reitz result = self.vm.qmp('query-block') 599adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 600adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 601adfe2030SMax Reitz 60234ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 603adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 604adfe2030SMax Reitz 605adfe2030SMax Reitz result = self.vm.qmp('query-block') 606adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 607adfe2030SMax Reitz 60834ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 609adfe2030SMax Reitz node_name='new') 610adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 611adfe2030SMax Reitz 612adfe2030SMax Reitz result = self.vm.qmp('query-block') 613adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 614adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 615adfe2030SMax Reitz 616adfe2030SMax Reitz result = self.vm.qmp('query-block') 617adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 618adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 619adfe2030SMax Reitz 620adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 621adfe2030SMax ReitzTestInitiallyFilled = None 622adfe2030SMax ReitzTestInitiallyEmpty = None 623adfe2030SMax Reitz 624adfe2030SMax Reitz 625adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 6261d701e0eSMax Reitz device_name = 'qdev0' 6271d701e0eSMax Reitz 628adfe2030SMax Reitz def setUp(self): 6291d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 630adfe2030SMax Reitz 631adfe2030SMax Reitz self.vm = iotests.VM() 632e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6331d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 634adfe2030SMax Reitz self.vm.launch() 635adfe2030SMax Reitz 636adfe2030SMax Reitz result = self.vm.qmp('query-block') 637adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 638adfe2030SMax Reitz 639adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 640adfe2030SMax Reitz # is not necessary 64134ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 642adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 643adfe2030SMax Reitz 644adfe2030SMax Reitz result = self.vm.qmp('query-block') 645adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 646adfe2030SMax Reitz 647adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6480153d2f5SKevin Wolf node_name='node0', 6490153d2f5SKevin Wolf driver=iotests.imgfmt, 6500153d2f5SKevin Wolf file={'filename': old_img, 6510153d2f5SKevin Wolf 'driver': 'file'}) 652adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 653adfe2030SMax Reitz 65434ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 655adfe2030SMax Reitz node_name='node0') 656adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 657adfe2030SMax Reitz 658adfe2030SMax Reitz result = self.vm.qmp('query-block') 659adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 660adfe2030SMax Reitz 661adfe2030SMax Reitz def tearDown(self): 662adfe2030SMax Reitz self.vm.shutdown() 663adfe2030SMax Reitz os.remove(old_img) 664adfe2030SMax Reitz try: 665adfe2030SMax Reitz os.remove(new_img) 666adfe2030SMax Reitz except OSError: 667adfe2030SMax Reitz pass 668adfe2030SMax Reitz 669adfe2030SMax Reitz # We need backing file support 670ff3caf5aSMax Reitz @iotests.skip_for_formats(('vpc', 'parallels', 'qcow', 'vdi', 'vmdk', 'raw', 671ff3caf5aSMax Reitz 'vhdx')) 672ff3caf5aSMax Reitz def test_snapshot_and_commit(self): 673adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 674adfe2030SMax Reitz snapshot_file=new_img, 675adfe2030SMax Reitz format=iotests.imgfmt) 676adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 677adfe2030SMax Reitz 678adfe2030SMax Reitz result = self.vm.qmp('query-block') 679adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 680adfe2030SMax Reitz self.assert_qmp(result, 681adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 682adfe2030SMax Reitz old_img) 683adfe2030SMax Reitz 684adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 685adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 686adfe2030SMax Reitz 687adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 688adfe2030SMax Reitz 689adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 690adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 691adfe2030SMax Reitz 692adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 693adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 694adfe2030SMax Reitz 695adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 696adfe2030SMax Reitz 697adfe2030SMax Reitz 698adfe2030SMax Reitzif __name__ == '__main__': 699adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 700adfe2030SMax Reitz # We need floppy and IDE CD-ROM 701adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 702adfe2030SMax Reitz iotests.qemu_default_machine) 703cc8c46b7SMax Reitz # Need to support image creation 704cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 705103cbc77SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed'], 706103cbc77SMax Reitz supported_protocols=['file']) 707