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 31adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase): 32adfe2030SMax Reitz has_opened = False 33adfe2030SMax Reitz has_closed = False 34adfe2030SMax Reitz 35adfe2030SMax Reitz def process_events(self): 36adfe2030SMax Reitz for event in self.vm.get_qmp_events(wait=False): 37adfe2030SMax Reitz if (event['event'] == 'DEVICE_TRAY_MOVED' and 38adfe2030SMax Reitz event['data']['device'] == 'drive0'): 39adfe2030SMax Reitz if event['data']['tray-open'] == False: 40adfe2030SMax Reitz self.has_closed = True 41adfe2030SMax Reitz else: 42adfe2030SMax Reitz self.has_opened = True 43adfe2030SMax Reitz 44adfe2030SMax Reitz def wait_for_open(self): 45abb3e55bSMax Reitz if not self.has_real_tray: 46abb3e55bSMax Reitz return 47abb3e55bSMax Reitz 48adfe2030SMax Reitz timeout = time.clock() + 3 49adfe2030SMax Reitz while not self.has_opened and time.clock() < timeout: 50adfe2030SMax Reitz self.process_events() 51adfe2030SMax Reitz if not self.has_opened: 52adfe2030SMax Reitz self.fail('Timeout while waiting for the tray to open') 53adfe2030SMax Reitz 54adfe2030SMax Reitz def wait_for_close(self): 55abb3e55bSMax Reitz if not self.has_real_tray: 56abb3e55bSMax Reitz return 57abb3e55bSMax Reitz 58adfe2030SMax Reitz timeout = time.clock() + 3 59adfe2030SMax Reitz while not self.has_closed and time.clock() < timeout: 60adfe2030SMax Reitz self.process_events() 61adfe2030SMax Reitz if not self.has_opened: 62adfe2030SMax Reitz self.fail('Timeout while waiting for the tray to close') 63adfe2030SMax Reitz 64adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass): 65adfe2030SMax Reitz def test_change(self): 66adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 67adfe2030SMax Reitz arg=iotests.imgfmt) 68adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 69adfe2030SMax Reitz 70adfe2030SMax Reitz self.wait_for_open() 71adfe2030SMax Reitz self.wait_for_close() 72adfe2030SMax Reitz 73adfe2030SMax Reitz result = self.vm.qmp('query-block') 74abb3e55bSMax Reitz if self.has_real_tray: 75adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 76adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 77adfe2030SMax Reitz 78adfe2030SMax Reitz def test_blockdev_change_medium(self): 79adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 80adfe2030SMax Reitz filename=new_img, 81adfe2030SMax Reitz format=iotests.imgfmt) 82adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 83adfe2030SMax Reitz 84adfe2030SMax Reitz self.wait_for_open() 85adfe2030SMax Reitz self.wait_for_close() 86adfe2030SMax Reitz 87adfe2030SMax Reitz result = self.vm.qmp('query-block') 88abb3e55bSMax Reitz if self.has_real_tray: 89adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 90adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 91adfe2030SMax Reitz 92adfe2030SMax Reitz def test_eject(self): 93adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', force=True) 94adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 95adfe2030SMax Reitz 96adfe2030SMax Reitz self.wait_for_open() 97adfe2030SMax Reitz 98adfe2030SMax Reitz result = self.vm.qmp('query-block') 99abb3e55bSMax Reitz if self.has_real_tray: 100adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 101adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 102adfe2030SMax Reitz 103adfe2030SMax Reitz def test_tray_eject_change(self): 104adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', force=True) 105adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 106adfe2030SMax Reitz 107adfe2030SMax Reitz self.wait_for_open() 108adfe2030SMax Reitz 109adfe2030SMax Reitz result = self.vm.qmp('query-block') 110abb3e55bSMax Reitz if self.has_real_tray: 111adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 112adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 113adfe2030SMax Reitz 114adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 115adfe2030SMax Reitz filename=new_img, 116adfe2030SMax Reitz format=iotests.imgfmt) 117adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 118adfe2030SMax Reitz 119adfe2030SMax Reitz self.wait_for_close() 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', False) 124adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 125adfe2030SMax Reitz 126adfe2030SMax Reitz def test_tray_open_close(self): 127adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) 128adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 129adfe2030SMax Reitz 130adfe2030SMax Reitz self.wait_for_open() 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', True) 135adfe2030SMax Reitz if self.was_empty == True: 136adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 137adfe2030SMax Reitz else: 138adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 139adfe2030SMax Reitz 140adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 141adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 142adfe2030SMax Reitz 143adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 144adfe2030SMax Reitz self.wait_for_close() 145adfe2030SMax Reitz 146adfe2030SMax Reitz result = self.vm.qmp('query-block') 147abb3e55bSMax Reitz if self.has_real_tray: 148adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 149adfe2030SMax Reitz if self.was_empty == True: 150adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 151adfe2030SMax Reitz else: 152adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 153adfe2030SMax Reitz 154adfe2030SMax Reitz def test_tray_eject_close(self): 155adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', force=True) 156adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 157adfe2030SMax Reitz 158adfe2030SMax Reitz self.wait_for_open() 159adfe2030SMax Reitz 160adfe2030SMax Reitz result = self.vm.qmp('query-block') 161abb3e55bSMax Reitz if self.has_real_tray: 162adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 163adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 164adfe2030SMax Reitz 165adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 166adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 167adfe2030SMax Reitz 168adfe2030SMax Reitz self.wait_for_close() 169adfe2030SMax Reitz 170adfe2030SMax Reitz result = self.vm.qmp('query-block') 171adfe2030SMax Reitz if self.has_real_tray: 172adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 173adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 174adfe2030SMax Reitz 175adfe2030SMax Reitz def test_tray_open_change(self): 176adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0', 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 189adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 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 201adfe2030SMax Reitz def test_cycle(self): 202adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 203adfe2030SMax Reitz options={'node-name': 'new', 204adfe2030SMax Reitz 'driver': iotests.imgfmt, 205adfe2030SMax Reitz 'file': {'filename': new_img, 206adfe2030SMax Reitz 'driver': 'file'}}) 207adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 208adfe2030SMax Reitz 209adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) 210adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 211adfe2030SMax Reitz 212adfe2030SMax Reitz self.wait_for_open() 213adfe2030SMax Reitz 214adfe2030SMax Reitz result = self.vm.qmp('query-block') 215abb3e55bSMax Reitz if self.has_real_tray: 216adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 217adfe2030SMax Reitz if self.was_empty == True: 218adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 219adfe2030SMax Reitz else: 220adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 221adfe2030SMax Reitz 2226e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 223adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 224adfe2030SMax Reitz 225adfe2030SMax Reitz result = self.vm.qmp('query-block') 226abb3e55bSMax Reitz if self.has_real_tray: 227adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 228adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 229adfe2030SMax Reitz 2306e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 231adfe2030SMax Reitz node_name='new') 232adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 233adfe2030SMax Reitz 234adfe2030SMax Reitz result = self.vm.qmp('query-block') 235abb3e55bSMax Reitz if self.has_real_tray: 236adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 237adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 238adfe2030SMax Reitz 239adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 240adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 241adfe2030SMax Reitz 242adfe2030SMax Reitz self.wait_for_close() 243adfe2030SMax Reitz 244adfe2030SMax Reitz result = self.vm.qmp('query-block') 245abb3e55bSMax Reitz if self.has_real_tray: 246adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 247adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 248adfe2030SMax Reitz 249adfe2030SMax Reitz def test_close_on_closed(self): 250adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 251adfe2030SMax Reitz # Should be a no-op 252adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 253adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 254adfe2030SMax Reitz 255adfe2030SMax Reitz def test_remove_on_closed(self): 256abb3e55bSMax Reitz if not self.has_real_tray: 257adfe2030SMax Reitz return 258adfe2030SMax Reitz 2596e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 260adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 261adfe2030SMax Reitz 262adfe2030SMax Reitz def test_insert_on_closed(self): 263abb3e55bSMax Reitz if not self.has_real_tray: 264adfe2030SMax Reitz return 265adfe2030SMax Reitz 266adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 267adfe2030SMax Reitz options={'node-name': 'new', 268adfe2030SMax Reitz 'driver': iotests.imgfmt, 269adfe2030SMax Reitz 'file': {'filename': new_img, 270adfe2030SMax Reitz 'driver': 'file'}}) 271adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 272adfe2030SMax Reitz 2736e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 274adfe2030SMax Reitz node_name='new') 275adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 276adfe2030SMax Reitz 277adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 278adfe2030SMax Reitz was_empty = False 279adfe2030SMax Reitz 280adfe2030SMax Reitz def setUp(self, media, interface): 281adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 282adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 283adfe2030SMax Reitz self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface) 284adfe2030SMax Reitz self.vm.launch() 285adfe2030SMax Reitz 286adfe2030SMax Reitz def tearDown(self): 287adfe2030SMax Reitz self.vm.shutdown() 288adfe2030SMax Reitz os.remove(old_img) 289adfe2030SMax Reitz os.remove(new_img) 290adfe2030SMax Reitz 291adfe2030SMax Reitz def test_insert_on_filled(self): 292adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 293adfe2030SMax Reitz options={'node-name': 'new', 294adfe2030SMax Reitz 'driver': iotests.imgfmt, 295adfe2030SMax Reitz 'file': {'filename': new_img, 296adfe2030SMax Reitz 'driver': 'file'}}) 297adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 298adfe2030SMax Reitz 299adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0') 300adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 301adfe2030SMax Reitz 302adfe2030SMax Reitz self.wait_for_open() 303adfe2030SMax Reitz 3046e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 305adfe2030SMax Reitz node_name='new') 306adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 307adfe2030SMax Reitz 308adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 309adfe2030SMax Reitz was_empty = True 310adfe2030SMax Reitz 311adfe2030SMax Reitz def setUp(self, media, interface): 312adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 313adfe2030SMax Reitz self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface) 314adfe2030SMax Reitz self.vm.launch() 315adfe2030SMax Reitz 316adfe2030SMax Reitz def tearDown(self): 317adfe2030SMax Reitz self.vm.shutdown() 318adfe2030SMax Reitz os.remove(new_img) 319adfe2030SMax Reitz 320adfe2030SMax Reitz def test_remove_on_empty(self): 321adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0') 322adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 323adfe2030SMax Reitz 324adfe2030SMax Reitz self.wait_for_open() 325adfe2030SMax Reitz 3266e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 327adfe2030SMax Reitz # Should be a no-op 328adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 329adfe2030SMax Reitz 330adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled): 331adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 332adfe2030SMax Reitz has_real_tray = True 333adfe2030SMax Reitz 334adfe2030SMax Reitz def setUp(self): 335adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide') 336adfe2030SMax Reitz 337adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty): 338adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 339adfe2030SMax Reitz has_real_tray = True 340adfe2030SMax Reitz 341adfe2030SMax Reitz def setUp(self): 342adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide') 343adfe2030SMax Reitz 344adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled): 345adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 346adfe2030SMax Reitz has_real_tray = False 347adfe2030SMax Reitz 348adfe2030SMax Reitz def setUp(self): 349adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'disk', 'floppy') 350adfe2030SMax Reitz 351adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty): 352adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 353adfe2030SMax Reitz has_real_tray = False 354adfe2030SMax Reitz 355adfe2030SMax Reitz def setUp(self): 356adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy') 357adfe2030SMax Reitz # FDDs not having a real tray and there not being a medium inside the 358adfe2030SMax Reitz # tray at startup means the tray will be considered open 359adfe2030SMax Reitz self.has_opened = True 360adfe2030SMax Reitz 361adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 362adfe2030SMax Reitz def setUp(self): 363adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 364adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 365adfe2030SMax Reitz self.vm = iotests.VM() 366adfe2030SMax Reitz 367adfe2030SMax Reitz def tearDown(self): 368adfe2030SMax Reitz self.vm.shutdown() 369adfe2030SMax Reitz os.chmod(old_img, 0666) 370adfe2030SMax Reitz os.chmod(new_img, 0666) 371adfe2030SMax Reitz os.remove(old_img) 372adfe2030SMax Reitz os.remove(new_img) 373adfe2030SMax Reitz 374adfe2030SMax Reitz def test_ro_ro_retain(self): 375adfe2030SMax Reitz os.chmod(old_img, 0444) 376adfe2030SMax Reitz os.chmod(new_img, 0444) 377adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 378adfe2030SMax Reitz self.vm.launch() 379adfe2030SMax Reitz 380adfe2030SMax Reitz result = self.vm.qmp('query-block') 381adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 382adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 383adfe2030SMax Reitz 384adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 385adfe2030SMax Reitz filename=new_img, 386adfe2030SMax Reitz format=iotests.imgfmt, 387adfe2030SMax Reitz read_only_mode='retain') 388adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 389adfe2030SMax Reitz 390adfe2030SMax Reitz result = self.vm.qmp('query-block') 391adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 392adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 393adfe2030SMax Reitz 394adfe2030SMax Reitz def test_ro_rw_retain(self): 395adfe2030SMax Reitz os.chmod(old_img, 0444) 396adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 397adfe2030SMax Reitz self.vm.launch() 398adfe2030SMax Reitz 399adfe2030SMax Reitz result = self.vm.qmp('query-block') 400adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 401adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 402adfe2030SMax Reitz 403adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 404adfe2030SMax Reitz filename=new_img, 405adfe2030SMax Reitz format=iotests.imgfmt, 406adfe2030SMax Reitz read_only_mode='retain') 407adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 408adfe2030SMax Reitz 409adfe2030SMax Reitz result = self.vm.qmp('query-block') 410adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 411adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 412adfe2030SMax Reitz 413adfe2030SMax Reitz def test_rw_ro_retain(self): 414adfe2030SMax Reitz os.chmod(new_img, 0444) 415adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 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', False) 420adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 421adfe2030SMax Reitz 422adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 423adfe2030SMax Reitz filename=new_img, 424adfe2030SMax Reitz format=iotests.imgfmt, 425adfe2030SMax Reitz read_only_mode='retain') 426adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 427adfe2030SMax Reitz 428adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 429adfe2030SMax Reitz 430adfe2030SMax Reitz result = self.vm.qmp('query-block') 431adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 432adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 433adfe2030SMax Reitz 434adfe2030SMax Reitz def test_ro_rw(self): 435adfe2030SMax Reitz os.chmod(old_img, 0444) 436adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 437adfe2030SMax Reitz self.vm.launch() 438adfe2030SMax Reitz 439adfe2030SMax Reitz result = self.vm.qmp('query-block') 440adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 441adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 442adfe2030SMax Reitz 443adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 444adfe2030SMax Reitz device='drive0', 445adfe2030SMax Reitz filename=new_img, 446adfe2030SMax Reitz format=iotests.imgfmt, 447adfe2030SMax Reitz read_only_mode='read-write') 448adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 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', new_img) 453adfe2030SMax Reitz 454adfe2030SMax Reitz def test_rw_ro(self): 455adfe2030SMax Reitz os.chmod(new_img, 0444) 456adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 457adfe2030SMax Reitz self.vm.launch() 458adfe2030SMax Reitz 459adfe2030SMax Reitz result = self.vm.qmp('query-block') 460adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 461adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 462adfe2030SMax Reitz 463adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 464adfe2030SMax Reitz device='drive0', 465adfe2030SMax Reitz filename=new_img, 466adfe2030SMax Reitz format=iotests.imgfmt, 467adfe2030SMax Reitz read_only_mode='read-only') 468adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 469adfe2030SMax Reitz 470adfe2030SMax Reitz result = self.vm.qmp('query-block') 471adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 472adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 473adfe2030SMax Reitz 474adfe2030SMax Reitz def test_make_rw_ro(self): 475adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 476adfe2030SMax Reitz self.vm.launch() 477adfe2030SMax Reitz 478adfe2030SMax Reitz result = self.vm.qmp('query-block') 479adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 480adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 481adfe2030SMax Reitz 482adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 483adfe2030SMax Reitz device='drive0', 484adfe2030SMax Reitz filename=new_img, 485adfe2030SMax Reitz format=iotests.imgfmt, 486adfe2030SMax Reitz read_only_mode='read-only') 487adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 488adfe2030SMax Reitz 489adfe2030SMax Reitz result = self.vm.qmp('query-block') 490adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 491adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 492adfe2030SMax Reitz 493adfe2030SMax Reitz def test_make_ro_rw(self): 494adfe2030SMax Reitz os.chmod(new_img, 0444) 495adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 496adfe2030SMax Reitz self.vm.launch() 497adfe2030SMax Reitz 498adfe2030SMax Reitz result = self.vm.qmp('query-block') 499adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 500adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 501adfe2030SMax Reitz 502adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 503adfe2030SMax Reitz device='drive0', 504adfe2030SMax Reitz filename=new_img, 505adfe2030SMax Reitz format=iotests.imgfmt, 506adfe2030SMax Reitz read_only_mode='read-write') 507adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 508adfe2030SMax Reitz 509adfe2030SMax Reitz result = self.vm.qmp('query-block') 510adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 511adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 512adfe2030SMax Reitz 513adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 514adfe2030SMax Reitz os.chmod(old_img, 0444) 515adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 516adfe2030SMax Reitz self.vm.launch() 517adfe2030SMax Reitz 518adfe2030SMax Reitz result = self.vm.qmp('query-block') 519adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 520adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 521adfe2030SMax Reitz 522adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 523adfe2030SMax Reitz filename=new_img, 524adfe2030SMax Reitz format=iotests.imgfmt, 525adfe2030SMax Reitz read_only_mode='retain') 526adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 527adfe2030SMax Reitz 528adfe2030SMax Reitz result = self.vm.qmp('query-block') 529adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 530adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 531adfe2030SMax Reitz 532adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 533adfe2030SMax Reitz os.chmod(new_img, 0444) 534adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 535adfe2030SMax Reitz self.vm.launch() 536adfe2030SMax Reitz 537adfe2030SMax Reitz result = self.vm.qmp('query-block') 538adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 539adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 540adfe2030SMax Reitz 541adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 542adfe2030SMax Reitz filename=new_img, 543adfe2030SMax Reitz format=iotests.imgfmt, 544adfe2030SMax Reitz read_only_mode='retain') 545adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 546adfe2030SMax Reitz 547adfe2030SMax Reitz result = self.vm.qmp('query-block') 548adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 549adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 550adfe2030SMax Reitz 551adfe2030SMax Reitz def test_rw_ro_cycle(self): 552adfe2030SMax Reitz os.chmod(new_img, 0444) 553adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 554adfe2030SMax Reitz self.vm.launch() 555adfe2030SMax Reitz 556adfe2030SMax Reitz result = self.vm.qmp('query-block') 557adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 558adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 559adfe2030SMax Reitz 560adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 561adfe2030SMax Reitz options={'node-name': 'new', 562adfe2030SMax Reitz 'driver': iotests.imgfmt, 563adfe2030SMax Reitz 'read-only': True, 564adfe2030SMax Reitz 'file': {'filename': new_img, 565adfe2030SMax Reitz 'driver': 'file'}}) 566adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 567adfe2030SMax Reitz 568adfe2030SMax Reitz result = self.vm.qmp('query-block') 569adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 570adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 571adfe2030SMax Reitz 5726e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 573adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 574adfe2030SMax Reitz 575adfe2030SMax Reitz result = self.vm.qmp('query-block') 576adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 577adfe2030SMax Reitz 5786e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 579adfe2030SMax Reitz node_name='new') 580adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 581adfe2030SMax Reitz 582adfe2030SMax Reitz result = self.vm.qmp('query-block') 583adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 584adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 585adfe2030SMax Reitz 586adfe2030SMax Reitz result = self.vm.qmp('query-block') 587adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 588adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 589adfe2030SMax Reitz 590adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 591adfe2030SMax ReitzTestInitiallyFilled = None 592adfe2030SMax ReitzTestInitiallyEmpty = None 593adfe2030SMax Reitz 594adfe2030SMax Reitz 595adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 596adfe2030SMax Reitz def setUp(self): 597adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1M') 598adfe2030SMax Reitz 599adfe2030SMax Reitz self.vm = iotests.VM() 600adfe2030SMax Reitz self.vm.launch() 601adfe2030SMax Reitz 602adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 603adfe2030SMax Reitz options={'id': 'drive0', 604adfe2030SMax Reitz 'driver': 'null-co'}) 605adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 606adfe2030SMax Reitz 607adfe2030SMax Reitz result = self.vm.qmp('query-block') 608adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 609adfe2030SMax Reitz 610adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 611adfe2030SMax Reitz # is not necessary 6126e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 613adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 614adfe2030SMax Reitz 615adfe2030SMax Reitz result = self.vm.qmp('query-block') 616adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 617adfe2030SMax Reitz 618adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 619adfe2030SMax Reitz options={'node-name': 'node0', 620adfe2030SMax Reitz 'driver': iotests.imgfmt, 621adfe2030SMax Reitz 'file': {'filename': old_img, 622adfe2030SMax Reitz 'driver': 'file'}}) 623adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 624adfe2030SMax Reitz 6256e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 626adfe2030SMax Reitz node_name='node0') 627adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 628adfe2030SMax Reitz 629adfe2030SMax Reitz result = self.vm.qmp('query-block') 630adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 631adfe2030SMax Reitz 632adfe2030SMax Reitz def tearDown(self): 633adfe2030SMax Reitz self.vm.shutdown() 634adfe2030SMax Reitz os.remove(old_img) 635adfe2030SMax Reitz try: 636adfe2030SMax Reitz os.remove(new_img) 637adfe2030SMax Reitz except OSError: 638adfe2030SMax Reitz pass 639adfe2030SMax Reitz 640adfe2030SMax Reitz def test_snapshot_and_commit(self): 641adfe2030SMax Reitz # We need backing file support 642adfe2030SMax Reitz if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 643adfe2030SMax Reitz return 644adfe2030SMax Reitz 645adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 646adfe2030SMax Reitz snapshot_file=new_img, 647adfe2030SMax Reitz format=iotests.imgfmt) 648adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 649adfe2030SMax Reitz 650adfe2030SMax Reitz result = self.vm.qmp('query-block') 651adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 652adfe2030SMax Reitz self.assert_qmp(result, 653adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 654adfe2030SMax Reitz old_img) 655adfe2030SMax Reitz 656adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 657adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 658adfe2030SMax Reitz 659adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 660adfe2030SMax Reitz 661adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 662adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 663adfe2030SMax Reitz 664adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 665adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 666adfe2030SMax Reitz 667adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 668adfe2030SMax Reitz 669adfe2030SMax Reitz 670adfe2030SMax Reitzif __name__ == '__main__': 671adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 672adfe2030SMax Reitz # We need floppy and IDE CD-ROM 673adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 674adfe2030SMax Reitz iotests.qemu_default_machine) 675*cc8c46b7SMax Reitz # Need to support image creation 676*cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 677*cc8c46b7SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed']) 678