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' 361d701e0eSMax Reitz else: 371d701e0eSMax Reitz return None 381d701e0eSMax Reitz 39adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase): 40adfe2030SMax Reitz has_opened = False 41adfe2030SMax Reitz has_closed = False 42adfe2030SMax Reitz 43adfe2030SMax Reitz def process_events(self): 44adfe2030SMax Reitz for event in self.vm.get_qmp_events(wait=False): 45adfe2030SMax Reitz if (event['event'] == 'DEVICE_TRAY_MOVED' and 46adfe2030SMax Reitz event['data']['device'] == 'drive0'): 47adfe2030SMax Reitz if event['data']['tray-open'] == False: 48adfe2030SMax Reitz self.has_closed = True 49adfe2030SMax Reitz else: 50adfe2030SMax Reitz self.has_opened = True 51adfe2030SMax Reitz 52adfe2030SMax Reitz def wait_for_open(self): 53abb3e55bSMax Reitz if not self.has_real_tray: 54abb3e55bSMax Reitz return 55abb3e55bSMax Reitz 56adfe2030SMax Reitz timeout = time.clock() + 3 57adfe2030SMax Reitz while not self.has_opened and time.clock() < timeout: 58adfe2030SMax Reitz self.process_events() 59adfe2030SMax Reitz if not self.has_opened: 60adfe2030SMax Reitz self.fail('Timeout while waiting for the tray to open') 61adfe2030SMax Reitz 62adfe2030SMax Reitz def wait_for_close(self): 63abb3e55bSMax Reitz if not self.has_real_tray: 64abb3e55bSMax Reitz return 65abb3e55bSMax Reitz 66adfe2030SMax Reitz timeout = time.clock() + 3 67adfe2030SMax Reitz while not self.has_closed and time.clock() < timeout: 68adfe2030SMax Reitz self.process_events() 69adfe2030SMax Reitz if not self.has_opened: 70adfe2030SMax Reitz self.fail('Timeout while waiting for the tray to close') 71adfe2030SMax Reitz 72adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass): 73486b88bdSKevin Wolf 741d701e0eSMax Reitz device_name = 'qdev0' 75486b88bdSKevin Wolf 76adfe2030SMax Reitz def test_change(self): 77adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 78adfe2030SMax Reitz arg=iotests.imgfmt) 79adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 80adfe2030SMax Reitz 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_blockdev_change_medium(self): 90486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 91486b88bdSKevin Wolf id=self.device_name, filename=new_img, 92adfe2030SMax Reitz format=iotests.imgfmt) 93486b88bdSKevin Wolf 94adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 95adfe2030SMax Reitz 96adfe2030SMax Reitz self.wait_for_open() 97adfe2030SMax Reitz self.wait_for_close() 98adfe2030SMax Reitz 99adfe2030SMax Reitz result = self.vm.qmp('query-block') 100abb3e55bSMax Reitz if self.has_real_tray: 101adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 102adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 103adfe2030SMax Reitz 104adfe2030SMax Reitz def test_eject(self): 105486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 106adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 107adfe2030SMax Reitz 108adfe2030SMax Reitz self.wait_for_open() 109adfe2030SMax Reitz 110adfe2030SMax Reitz result = self.vm.qmp('query-block') 111abb3e55bSMax Reitz if self.has_real_tray: 112adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 113adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 114adfe2030SMax Reitz 115adfe2030SMax Reitz def test_tray_eject_change(self): 116486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 117adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 118adfe2030SMax Reitz 119adfe2030SMax Reitz self.wait_for_open() 120adfe2030SMax Reitz 121adfe2030SMax Reitz result = self.vm.qmp('query-block') 122abb3e55bSMax Reitz if self.has_real_tray: 123adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 124adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 125adfe2030SMax Reitz 126486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 127486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 128adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 129adfe2030SMax Reitz 130adfe2030SMax Reitz self.wait_for_close() 131adfe2030SMax Reitz 132adfe2030SMax Reitz result = self.vm.qmp('query-block') 133abb3e55bSMax Reitz if self.has_real_tray: 134adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 135adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 136adfe2030SMax Reitz 137adfe2030SMax Reitz def test_tray_open_close(self): 138486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 139486b88bdSKevin Wolf id=self.device_name, force=True) 140adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 141adfe2030SMax Reitz 142adfe2030SMax Reitz self.wait_for_open() 143adfe2030SMax Reitz 144adfe2030SMax Reitz result = self.vm.qmp('query-block') 145abb3e55bSMax Reitz if self.has_real_tray: 146adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 147adfe2030SMax Reitz if self.was_empty == True: 148adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 149adfe2030SMax Reitz else: 150adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 151adfe2030SMax Reitz 152486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 153adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 154adfe2030SMax Reitz 155adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 156adfe2030SMax Reitz self.wait_for_close() 157adfe2030SMax Reitz 158adfe2030SMax Reitz result = self.vm.qmp('query-block') 159abb3e55bSMax Reitz if self.has_real_tray: 160adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 161adfe2030SMax Reitz if self.was_empty == True: 162adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 163adfe2030SMax Reitz else: 164adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 165adfe2030SMax Reitz 166adfe2030SMax Reitz def test_tray_eject_close(self): 1671d701e0eSMax Reitz result = self.vm.qmp('eject', id=self.device_name, force=True) 168adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 169adfe2030SMax Reitz 170adfe2030SMax Reitz self.wait_for_open() 171adfe2030SMax Reitz 172adfe2030SMax Reitz result = self.vm.qmp('query-block') 173abb3e55bSMax Reitz if self.has_real_tray: 174adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 175adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 176adfe2030SMax Reitz 177486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 178adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 179adfe2030SMax Reitz 180adfe2030SMax Reitz self.wait_for_close() 181adfe2030SMax Reitz 182adfe2030SMax Reitz result = self.vm.qmp('query-block') 183adfe2030SMax Reitz if self.has_real_tray: 184adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 185adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 186adfe2030SMax Reitz 187adfe2030SMax Reitz def test_tray_open_change(self): 1881d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name, 1891d701e0eSMax Reitz force=True) 190adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 191adfe2030SMax Reitz 192adfe2030SMax Reitz self.wait_for_open() 193adfe2030SMax Reitz 194adfe2030SMax Reitz result = self.vm.qmp('query-block') 195abb3e55bSMax Reitz if self.has_real_tray: 196adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 197adfe2030SMax Reitz if self.was_empty == True: 198adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 199adfe2030SMax Reitz else: 200adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 201adfe2030SMax Reitz 2021d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 203adfe2030SMax Reitz filename=new_img, 204adfe2030SMax Reitz format=iotests.imgfmt) 205adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 206adfe2030SMax Reitz 207adfe2030SMax Reitz self.wait_for_close() 208adfe2030SMax Reitz 209adfe2030SMax Reitz result = self.vm.qmp('query-block') 210abb3e55bSMax Reitz if self.has_real_tray: 211adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 212adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 213adfe2030SMax Reitz 214adfe2030SMax Reitz def test_cycle(self): 215adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2160153d2f5SKevin Wolf node_name='new', 2170153d2f5SKevin Wolf driver=iotests.imgfmt, 2180153d2f5SKevin Wolf file={'filename': new_img, 2190153d2f5SKevin Wolf 'driver': 'file'}) 220adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 221adfe2030SMax Reitz 222486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 223486b88bdSKevin Wolf id=self.device_name, force=True) 224adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 225adfe2030SMax Reitz 226adfe2030SMax Reitz self.wait_for_open() 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 if self.was_empty == True: 232adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 233adfe2030SMax Reitz else: 234adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 235adfe2030SMax Reitz 23634ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', 237486b88bdSKevin Wolf id=self.device_name) 238adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 239adfe2030SMax Reitz 240adfe2030SMax Reitz result = self.vm.qmp('query-block') 241abb3e55bSMax Reitz if self.has_real_tray: 242adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 243adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 244adfe2030SMax Reitz 24534ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', 246486b88bdSKevin Wolf id=self.device_name, node_name='new') 247adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 248adfe2030SMax Reitz 249adfe2030SMax Reitz result = self.vm.qmp('query-block') 250abb3e55bSMax Reitz if self.has_real_tray: 251adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 252adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 253adfe2030SMax Reitz 254486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 255adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 256adfe2030SMax Reitz 257adfe2030SMax Reitz self.wait_for_close() 258adfe2030SMax Reitz 259adfe2030SMax Reitz result = self.vm.qmp('query-block') 260abb3e55bSMax Reitz if self.has_real_tray: 261adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 262adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 263adfe2030SMax Reitz 264adfe2030SMax Reitz def test_close_on_closed(self): 2651d701e0eSMax Reitz result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 266adfe2030SMax Reitz # Should be a no-op 267adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 268adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 269adfe2030SMax Reitz 270adfe2030SMax Reitz def test_remove_on_closed(self): 271abb3e55bSMax Reitz if not self.has_real_tray: 272adfe2030SMax Reitz return 273adfe2030SMax Reitz 27434ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 275adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 276adfe2030SMax Reitz 277adfe2030SMax Reitz def test_insert_on_closed(self): 278abb3e55bSMax Reitz if not self.has_real_tray: 279adfe2030SMax Reitz return 280adfe2030SMax Reitz 281adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 2820153d2f5SKevin Wolf node_name='new', 2830153d2f5SKevin Wolf driver=iotests.imgfmt, 2840153d2f5SKevin Wolf file={'filename': new_img, 2850153d2f5SKevin Wolf 'driver': 'file'}) 286adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 287adfe2030SMax Reitz 28834ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 289adfe2030SMax Reitz node_name='new') 290adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 291adfe2030SMax Reitz 292adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 293adfe2030SMax Reitz was_empty = False 294adfe2030SMax Reitz 295adfe2030SMax Reitz def setUp(self, media, interface): 296adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 297adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 298486b88bdSKevin Wolf self.vm = iotests.VM() 299486b88bdSKevin Wolf self.vm.add_drive(old_img, 'media=%s' % media, 'none') 3001d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 3011d701e0eSMax Reitz (interface_to_device_name(interface), 3021d701e0eSMax Reitz self.device_name)) 303adfe2030SMax Reitz self.vm.launch() 304adfe2030SMax Reitz 305adfe2030SMax Reitz def tearDown(self): 306adfe2030SMax Reitz self.vm.shutdown() 307adfe2030SMax Reitz os.remove(old_img) 308adfe2030SMax Reitz os.remove(new_img) 309adfe2030SMax Reitz 310adfe2030SMax Reitz def test_insert_on_filled(self): 311adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 3120153d2f5SKevin Wolf node_name='new', 3130153d2f5SKevin Wolf driver=iotests.imgfmt, 3140153d2f5SKevin Wolf file={'filename': new_img, 3150153d2f5SKevin Wolf 'driver': 'file'}) 316adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 317adfe2030SMax Reitz 3181d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 319adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 320adfe2030SMax Reitz 321adfe2030SMax Reitz self.wait_for_open() 322adfe2030SMax Reitz 32334ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 324adfe2030SMax Reitz node_name='new') 325adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 326adfe2030SMax Reitz 327adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 328adfe2030SMax Reitz was_empty = True 329adfe2030SMax Reitz 330adfe2030SMax Reitz def setUp(self, media, interface): 331adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 3321d701e0eSMax Reitz self.vm = iotests.VM().add_drive(None, 'media=%s' % media, 'none') 3331d701e0eSMax Reitz self.vm.add_device('%s,drive=drive0,id=%s' % 3341d701e0eSMax Reitz (interface_to_device_name(interface), 3351d701e0eSMax Reitz self.device_name)) 336adfe2030SMax Reitz self.vm.launch() 337adfe2030SMax Reitz 338adfe2030SMax Reitz def tearDown(self): 339adfe2030SMax Reitz self.vm.shutdown() 340adfe2030SMax Reitz os.remove(new_img) 341adfe2030SMax Reitz 342adfe2030SMax Reitz def test_remove_on_empty(self): 3431d701e0eSMax Reitz result = self.vm.qmp('blockdev-open-tray', id=self.device_name) 344adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 345adfe2030SMax Reitz 346adfe2030SMax Reitz self.wait_for_open() 347adfe2030SMax Reitz 34834ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 349adfe2030SMax Reitz # Should be a no-op 350adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 351adfe2030SMax Reitz 352adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled): 353adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 354adfe2030SMax Reitz has_real_tray = True 355adfe2030SMax Reitz 356adfe2030SMax Reitz def setUp(self): 357adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide') 358adfe2030SMax Reitz 359adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty): 360adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 361adfe2030SMax Reitz has_real_tray = True 362adfe2030SMax Reitz 363adfe2030SMax Reitz def setUp(self): 364adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide') 365adfe2030SMax Reitz 366adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled): 367adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 368adfe2030SMax Reitz has_real_tray = False 369adfe2030SMax Reitz 370adfe2030SMax Reitz def setUp(self): 371adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'disk', 'floppy') 372adfe2030SMax Reitz 373adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty): 374adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 375adfe2030SMax Reitz has_real_tray = False 376adfe2030SMax Reitz 377adfe2030SMax Reitz def setUp(self): 378adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy') 379adfe2030SMax Reitz # FDDs not having a real tray and there not being a medium inside the 380adfe2030SMax Reitz # tray at startup means the tray will be considered open 381adfe2030SMax Reitz self.has_opened = True 382adfe2030SMax Reitz 383adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 3841d701e0eSMax Reitz device_name = 'qdev0' 3851d701e0eSMax Reitz 386adfe2030SMax Reitz def setUp(self): 387adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 388adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 389adfe2030SMax Reitz self.vm = iotests.VM() 390adfe2030SMax Reitz 391adfe2030SMax Reitz def tearDown(self): 392adfe2030SMax Reitz self.vm.shutdown() 393*4803c5cdSEduardo Habkost os.chmod(old_img, 0o666) 394*4803c5cdSEduardo Habkost os.chmod(new_img, 0o666) 395adfe2030SMax Reitz os.remove(old_img) 396adfe2030SMax Reitz os.remove(new_img) 397adfe2030SMax Reitz 398adfe2030SMax Reitz def test_ro_ro_retain(self): 399*4803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 400*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4011d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4021d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 403adfe2030SMax Reitz self.vm.launch() 404adfe2030SMax Reitz 405adfe2030SMax Reitz result = self.vm.qmp('query-block') 406adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 407adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 408adfe2030SMax Reitz 4091d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 410adfe2030SMax Reitz filename=new_img, 411adfe2030SMax Reitz format=iotests.imgfmt, 412adfe2030SMax Reitz read_only_mode='retain') 413adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 414adfe2030SMax Reitz 415adfe2030SMax Reitz result = self.vm.qmp('query-block') 416adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 417adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 418adfe2030SMax Reitz 419adfe2030SMax Reitz def test_ro_rw_retain(self): 420*4803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4211d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4221d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 423adfe2030SMax Reitz self.vm.launch() 424adfe2030SMax Reitz 425adfe2030SMax Reitz result = self.vm.qmp('query-block') 426adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 427adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 428adfe2030SMax Reitz 4291d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 430adfe2030SMax Reitz filename=new_img, 431adfe2030SMax Reitz format=iotests.imgfmt, 432adfe2030SMax Reitz read_only_mode='retain') 433adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 434adfe2030SMax Reitz 435adfe2030SMax Reitz result = self.vm.qmp('query-block') 436adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 437adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 438adfe2030SMax Reitz 439adfe2030SMax Reitz def test_rw_ro_retain(self): 440*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4411d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4421d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 443adfe2030SMax Reitz self.vm.launch() 444adfe2030SMax Reitz 445adfe2030SMax Reitz result = self.vm.qmp('query-block') 446adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 447adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 448adfe2030SMax Reitz 4491d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 450adfe2030SMax Reitz filename=new_img, 451adfe2030SMax Reitz format=iotests.imgfmt, 452adfe2030SMax Reitz read_only_mode='retain') 453adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 454adfe2030SMax Reitz 455adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 456adfe2030SMax Reitz 457adfe2030SMax Reitz result = self.vm.qmp('query-block') 458adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 459adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 460adfe2030SMax Reitz 461adfe2030SMax Reitz def test_ro_rw(self): 462*4803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 4631d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 4641d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 465adfe2030SMax Reitz self.vm.launch() 466adfe2030SMax Reitz 467adfe2030SMax Reitz result = self.vm.qmp('query-block') 468adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 469adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 470adfe2030SMax Reitz 471adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4721d701e0eSMax Reitz id=self.device_name, 473adfe2030SMax Reitz filename=new_img, 474adfe2030SMax Reitz format=iotests.imgfmt, 475adfe2030SMax Reitz read_only_mode='read-write') 476adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 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', new_img) 481adfe2030SMax Reitz 482adfe2030SMax Reitz def test_rw_ro(self): 483*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 4841d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 4851d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 486adfe2030SMax Reitz self.vm.launch() 487adfe2030SMax Reitz 488adfe2030SMax Reitz result = self.vm.qmp('query-block') 489adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 490adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 491adfe2030SMax Reitz 492adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 4931d701e0eSMax Reitz id=self.device_name, 494adfe2030SMax Reitz filename=new_img, 495adfe2030SMax Reitz format=iotests.imgfmt, 496adfe2030SMax Reitz read_only_mode='read-only') 497adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 498adfe2030SMax Reitz 499adfe2030SMax Reitz result = self.vm.qmp('query-block') 500adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 501adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 502adfe2030SMax Reitz 503adfe2030SMax Reitz def test_make_rw_ro(self): 5041d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5051d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 506adfe2030SMax Reitz self.vm.launch() 507adfe2030SMax Reitz 508adfe2030SMax Reitz result = self.vm.qmp('query-block') 509adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 510adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 511adfe2030SMax Reitz 512adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5131d701e0eSMax Reitz id=self.device_name, 514adfe2030SMax Reitz filename=new_img, 515adfe2030SMax Reitz format=iotests.imgfmt, 516adfe2030SMax Reitz read_only_mode='read-only') 517adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 518adfe2030SMax Reitz 519adfe2030SMax Reitz result = self.vm.qmp('query-block') 520adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 521adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 522adfe2030SMax Reitz 523adfe2030SMax Reitz def test_make_ro_rw(self): 524*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5251d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5261d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 527adfe2030SMax Reitz self.vm.launch() 528adfe2030SMax Reitz 529adfe2030SMax Reitz result = self.vm.qmp('query-block') 530adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 531adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 532adfe2030SMax Reitz 533adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 5341d701e0eSMax Reitz id=self.device_name, 535adfe2030SMax Reitz filename=new_img, 536adfe2030SMax Reitz format=iotests.imgfmt, 537adfe2030SMax Reitz read_only_mode='read-write') 538adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 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 544adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 545*4803c5cdSEduardo Habkost os.chmod(old_img, 0o444) 5461d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 5471d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 548adfe2030SMax Reitz self.vm.launch() 549adfe2030SMax Reitz 550adfe2030SMax Reitz result = self.vm.qmp('query-block') 551adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 552adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 553adfe2030SMax Reitz 5541d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 555adfe2030SMax Reitz filename=new_img, 556adfe2030SMax Reitz format=iotests.imgfmt, 557adfe2030SMax Reitz read_only_mode='retain') 558adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 559adfe2030SMax Reitz 560adfe2030SMax Reitz result = self.vm.qmp('query-block') 561adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 562adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 563adfe2030SMax Reitz 564adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 565*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5661d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5671d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 568adfe2030SMax Reitz self.vm.launch() 569adfe2030SMax Reitz 570adfe2030SMax Reitz result = self.vm.qmp('query-block') 571adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 572adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 573adfe2030SMax Reitz 5741d701e0eSMax Reitz result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 575adfe2030SMax Reitz filename=new_img, 576adfe2030SMax Reitz format=iotests.imgfmt, 577adfe2030SMax Reitz read_only_mode='retain') 578adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 579adfe2030SMax Reitz 580adfe2030SMax Reitz result = self.vm.qmp('query-block') 581adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 582adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 583adfe2030SMax Reitz 584adfe2030SMax Reitz def test_rw_ro_cycle(self): 585*4803c5cdSEduardo Habkost os.chmod(new_img, 0o444) 5861d701e0eSMax Reitz self.vm.add_drive(old_img, 'media=disk', 'none') 5871d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 588adfe2030SMax Reitz self.vm.launch() 589adfe2030SMax Reitz 590adfe2030SMax Reitz result = self.vm.qmp('query-block') 591adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 592adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 593adfe2030SMax Reitz 594adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 5950153d2f5SKevin Wolf node_name='new', 5960153d2f5SKevin Wolf driver=iotests.imgfmt, 5970153d2f5SKevin Wolf read_only=True, 5980153d2f5SKevin Wolf file={'filename': new_img, 5990153d2f5SKevin Wolf 'driver': 'file'}) 600adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 601adfe2030SMax Reitz 602adfe2030SMax Reitz result = self.vm.qmp('query-block') 603adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 604adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 605adfe2030SMax Reitz 60634ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 607adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 608adfe2030SMax Reitz 609adfe2030SMax Reitz result = self.vm.qmp('query-block') 610adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 611adfe2030SMax Reitz 61234ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 613adfe2030SMax Reitz node_name='new') 614adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 615adfe2030SMax Reitz 616adfe2030SMax Reitz result = self.vm.qmp('query-block') 617adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 618adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 619adfe2030SMax Reitz 620adfe2030SMax Reitz result = self.vm.qmp('query-block') 621adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 622adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 623adfe2030SMax Reitz 624adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 625adfe2030SMax ReitzTestInitiallyFilled = None 626adfe2030SMax ReitzTestInitiallyEmpty = None 627adfe2030SMax Reitz 628adfe2030SMax Reitz 629adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 6301d701e0eSMax Reitz device_name = 'qdev0' 6311d701e0eSMax Reitz 632adfe2030SMax Reitz def setUp(self): 6331d701e0eSMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 634adfe2030SMax Reitz 635adfe2030SMax Reitz self.vm = iotests.VM() 636e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 6371d701e0eSMax Reitz self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 638adfe2030SMax Reitz self.vm.launch() 639adfe2030SMax Reitz 640adfe2030SMax Reitz result = self.vm.qmp('query-block') 641adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 642adfe2030SMax Reitz 643adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 644adfe2030SMax Reitz # is not necessary 64534ce1111SMax Reitz result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 646adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 647adfe2030SMax Reitz 648adfe2030SMax Reitz result = self.vm.qmp('query-block') 649adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 650adfe2030SMax Reitz 651adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 6520153d2f5SKevin Wolf node_name='node0', 6530153d2f5SKevin Wolf driver=iotests.imgfmt, 6540153d2f5SKevin Wolf file={'filename': old_img, 6550153d2f5SKevin Wolf 'driver': 'file'}) 656adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 657adfe2030SMax Reitz 65834ce1111SMax Reitz result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 659adfe2030SMax Reitz node_name='node0') 660adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 661adfe2030SMax Reitz 662adfe2030SMax Reitz result = self.vm.qmp('query-block') 663adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 664adfe2030SMax Reitz 665adfe2030SMax Reitz def tearDown(self): 666adfe2030SMax Reitz self.vm.shutdown() 667adfe2030SMax Reitz os.remove(old_img) 668adfe2030SMax Reitz try: 669adfe2030SMax Reitz os.remove(new_img) 670adfe2030SMax Reitz except OSError: 671adfe2030SMax Reitz pass 672adfe2030SMax Reitz 673adfe2030SMax Reitz def test_snapshot_and_commit(self): 674adfe2030SMax Reitz # We need backing file support 675adfe2030SMax Reitz if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 676adfe2030SMax Reitz return 677adfe2030SMax Reitz 678adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 679adfe2030SMax Reitz snapshot_file=new_img, 680adfe2030SMax Reitz format=iotests.imgfmt) 681adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 682adfe2030SMax Reitz 683adfe2030SMax Reitz result = self.vm.qmp('query-block') 684adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 685adfe2030SMax Reitz self.assert_qmp(result, 686adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 687adfe2030SMax Reitz old_img) 688adfe2030SMax Reitz 689adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 690adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 691adfe2030SMax Reitz 692adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 693adfe2030SMax Reitz 694adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 695adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 696adfe2030SMax Reitz 697adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 698adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 699adfe2030SMax Reitz 700adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 701adfe2030SMax Reitz 702adfe2030SMax Reitz 703adfe2030SMax Reitzif __name__ == '__main__': 704adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 705adfe2030SMax Reitz # We need floppy and IDE CD-ROM 706adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 707adfe2030SMax Reitz iotests.qemu_default_machine) 708cc8c46b7SMax Reitz # Need to support image creation 709cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 710cc8c46b7SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed']) 711