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): 65486b88bdSKevin Wolf 66486b88bdSKevin Wolf device_name = None 67486b88bdSKevin Wolf 68adfe2030SMax Reitz def test_change(self): 69adfe2030SMax Reitz result = self.vm.qmp('change', device='drive0', target=new_img, 70adfe2030SMax Reitz arg=iotests.imgfmt) 71adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 72adfe2030SMax Reitz 73adfe2030SMax Reitz self.wait_for_open() 74adfe2030SMax Reitz self.wait_for_close() 75adfe2030SMax Reitz 76adfe2030SMax Reitz result = self.vm.qmp('query-block') 77abb3e55bSMax Reitz if self.has_real_tray: 78adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 79adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 80adfe2030SMax Reitz 81adfe2030SMax Reitz def test_blockdev_change_medium(self): 82486b88bdSKevin Wolf if self.device_name is not None: 83486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 84486b88bdSKevin Wolf id=self.device_name, filename=new_img, 85adfe2030SMax Reitz format=iotests.imgfmt) 86486b88bdSKevin Wolf else: 87486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', 88486b88bdSKevin Wolf device='drive0', filename=new_img, 89486b88bdSKevin Wolf format=iotests.imgfmt) 90486b88bdSKevin Wolf 91adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 92adfe2030SMax Reitz 93adfe2030SMax Reitz self.wait_for_open() 94adfe2030SMax Reitz self.wait_for_close() 95adfe2030SMax Reitz 96adfe2030SMax Reitz result = self.vm.qmp('query-block') 97abb3e55bSMax Reitz if self.has_real_tray: 98adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 99adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 100adfe2030SMax Reitz 101adfe2030SMax Reitz def test_eject(self): 102486b88bdSKevin Wolf if self.device_name is not None: 103486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 104486b88bdSKevin Wolf else: 105adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', 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 if self.device_name is not None: 117486b88bdSKevin Wolf result = self.vm.qmp('eject', id=self.device_name, force=True) 118486b88bdSKevin Wolf else: 119adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', force=True) 120adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 121adfe2030SMax Reitz 122adfe2030SMax Reitz self.wait_for_open() 123adfe2030SMax Reitz 124adfe2030SMax Reitz result = self.vm.qmp('query-block') 125abb3e55bSMax Reitz if self.has_real_tray: 126adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 127adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 128adfe2030SMax Reitz 129486b88bdSKevin Wolf if self.device_name is not None: 130486b88bdSKevin Wolf result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 131486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 132486b88bdSKevin Wolf else: 133adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 134486b88bdSKevin Wolf filename=new_img, format=iotests.imgfmt) 135adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 136adfe2030SMax Reitz 137adfe2030SMax Reitz self.wait_for_close() 138adfe2030SMax Reitz 139adfe2030SMax Reitz result = self.vm.qmp('query-block') 140abb3e55bSMax Reitz if self.has_real_tray: 141adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 142adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 143adfe2030SMax Reitz 144adfe2030SMax Reitz def test_tray_open_close(self): 145486b88bdSKevin Wolf if self.device_name is not None: 146486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 147486b88bdSKevin Wolf id=self.device_name, force=True) 148486b88bdSKevin Wolf else: 149486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 150486b88bdSKevin Wolf device='drive0', force=True) 151adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 152adfe2030SMax Reitz 153adfe2030SMax Reitz self.wait_for_open() 154adfe2030SMax Reitz 155adfe2030SMax Reitz result = self.vm.qmp('query-block') 156abb3e55bSMax Reitz if self.has_real_tray: 157adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 158adfe2030SMax Reitz if self.was_empty == True: 159adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 160adfe2030SMax Reitz else: 161adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 162adfe2030SMax Reitz 163486b88bdSKevin Wolf if self.device_name is not None: 164486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 165486b88bdSKevin Wolf else: 166adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 167adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 168adfe2030SMax Reitz 169adfe2030SMax Reitz if self.has_real_tray or not self.was_empty: 170adfe2030SMax Reitz self.wait_for_close() 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', False) 175adfe2030SMax Reitz if self.was_empty == True: 176adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 177adfe2030SMax Reitz else: 178adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 179adfe2030SMax Reitz 180adfe2030SMax Reitz def test_tray_eject_close(self): 181adfe2030SMax Reitz result = self.vm.qmp('eject', device='drive0', force=True) 182adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 183adfe2030SMax Reitz 184adfe2030SMax Reitz self.wait_for_open() 185adfe2030SMax Reitz 186adfe2030SMax Reitz result = self.vm.qmp('query-block') 187abb3e55bSMax Reitz if self.has_real_tray: 188adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 189adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 190adfe2030SMax Reitz 191486b88bdSKevin Wolf if self.device_name is not None: 192486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 193486b88bdSKevin Wolf else: 194adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 195adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 196adfe2030SMax Reitz 197adfe2030SMax Reitz self.wait_for_close() 198adfe2030SMax Reitz 199adfe2030SMax Reitz result = self.vm.qmp('query-block') 200adfe2030SMax Reitz if self.has_real_tray: 201adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 202adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 203adfe2030SMax Reitz 204adfe2030SMax Reitz def test_tray_open_change(self): 205adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) 206adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 207adfe2030SMax Reitz 208adfe2030SMax Reitz self.wait_for_open() 209adfe2030SMax Reitz 210adfe2030SMax Reitz result = self.vm.qmp('query-block') 211abb3e55bSMax Reitz if self.has_real_tray: 212adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 213adfe2030SMax Reitz if self.was_empty == True: 214adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 215adfe2030SMax Reitz else: 216adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 217adfe2030SMax Reitz 218adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 219adfe2030SMax Reitz filename=new_img, 220adfe2030SMax Reitz format=iotests.imgfmt) 221adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 222adfe2030SMax Reitz 223adfe2030SMax Reitz self.wait_for_close() 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', False) 228adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 229adfe2030SMax Reitz 230adfe2030SMax Reitz def test_cycle(self): 231adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 232adfe2030SMax Reitz options={'node-name': 'new', 233adfe2030SMax Reitz 'driver': iotests.imgfmt, 234adfe2030SMax Reitz 'file': {'filename': new_img, 235adfe2030SMax Reitz 'driver': 'file'}}) 236adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 237adfe2030SMax Reitz 238486b88bdSKevin Wolf if self.device_name is not None: 239486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 240486b88bdSKevin Wolf id=self.device_name, force=True) 241486b88bdSKevin Wolf else: 242486b88bdSKevin Wolf result = self.vm.qmp('blockdev-open-tray', 243486b88bdSKevin Wolf device='drive0', force=True) 244adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 245adfe2030SMax Reitz 246adfe2030SMax Reitz self.wait_for_open() 247adfe2030SMax Reitz 248adfe2030SMax Reitz result = self.vm.qmp('query-block') 249abb3e55bSMax Reitz if self.has_real_tray: 250adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 251adfe2030SMax Reitz if self.was_empty == True: 252adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 253adfe2030SMax Reitz else: 254adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 255adfe2030SMax Reitz 256486b88bdSKevin Wolf if self.device_name is not None: 257486b88bdSKevin Wolf result = self.vm.qmp('x-blockdev-remove-medium', 258486b88bdSKevin Wolf id=self.device_name) 259486b88bdSKevin Wolf else: 2606e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 261adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 262adfe2030SMax Reitz 263adfe2030SMax Reitz result = self.vm.qmp('query-block') 264abb3e55bSMax Reitz if self.has_real_tray: 265adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 266adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 267adfe2030SMax Reitz 268486b88bdSKevin Wolf if self.device_name is not None: 269486b88bdSKevin Wolf result = self.vm.qmp('x-blockdev-insert-medium', 270486b88bdSKevin Wolf id=self.device_name, node_name='new') 271486b88bdSKevin Wolf else: 272486b88bdSKevin Wolf result = self.vm.qmp('x-blockdev-insert-medium', 273486b88bdSKevin Wolf device='drive0', node_name='new') 274adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 275adfe2030SMax Reitz 276adfe2030SMax Reitz result = self.vm.qmp('query-block') 277abb3e55bSMax Reitz if self.has_real_tray: 278adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', True) 279adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 280adfe2030SMax Reitz 281486b88bdSKevin Wolf if self.device_name is not None: 282486b88bdSKevin Wolf result = self.vm.qmp('blockdev-close-tray', id=self.device_name) 283486b88bdSKevin Wolf else: 284adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 285adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 286adfe2030SMax Reitz 287adfe2030SMax Reitz self.wait_for_close() 288adfe2030SMax Reitz 289adfe2030SMax Reitz result = self.vm.qmp('query-block') 290abb3e55bSMax Reitz if self.has_real_tray: 291adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/tray_open', False) 292adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 293adfe2030SMax Reitz 294adfe2030SMax Reitz def test_close_on_closed(self): 295adfe2030SMax Reitz result = self.vm.qmp('blockdev-close-tray', device='drive0') 296adfe2030SMax Reitz # Should be a no-op 297adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 298adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 299adfe2030SMax Reitz 300adfe2030SMax Reitz def test_remove_on_closed(self): 301abb3e55bSMax Reitz if not self.has_real_tray: 302adfe2030SMax Reitz return 303adfe2030SMax Reitz 3046e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 305adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 306adfe2030SMax Reitz 307adfe2030SMax Reitz def test_insert_on_closed(self): 308abb3e55bSMax Reitz if not self.has_real_tray: 309adfe2030SMax Reitz return 310adfe2030SMax Reitz 311adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 312adfe2030SMax Reitz options={'node-name': 'new', 313adfe2030SMax Reitz 'driver': iotests.imgfmt, 314adfe2030SMax Reitz 'file': {'filename': new_img, 315adfe2030SMax Reitz 'driver': 'file'}}) 316adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 317adfe2030SMax Reitz 3186e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 319adfe2030SMax Reitz node_name='new') 320adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 321adfe2030SMax Reitz 322adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass): 323adfe2030SMax Reitz was_empty = False 324adfe2030SMax Reitz 325adfe2030SMax Reitz def setUp(self, media, interface): 326adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 327adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 328486b88bdSKevin Wolf self.vm = iotests.VM() 329486b88bdSKevin Wolf if interface == 'ide': 330486b88bdSKevin Wolf self.device_name = 'qdev0' 331486b88bdSKevin Wolf self.vm.add_drive(old_img, 'media=%s' % media, 'none') 332486b88bdSKevin Wolf self.vm.add_device('ide-cd,drive=drive0,id=%s' % self.device_name) 333486b88bdSKevin Wolf else: 334486b88bdSKevin Wolf self.vm.add_drive(old_img, 'media=%s' % media, interface) 335adfe2030SMax Reitz self.vm.launch() 336adfe2030SMax Reitz 337adfe2030SMax Reitz def tearDown(self): 338adfe2030SMax Reitz self.vm.shutdown() 339adfe2030SMax Reitz os.remove(old_img) 340adfe2030SMax Reitz os.remove(new_img) 341adfe2030SMax Reitz 342adfe2030SMax Reitz def test_insert_on_filled(self): 343adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 344adfe2030SMax Reitz options={'node-name': 'new', 345adfe2030SMax Reitz 'driver': iotests.imgfmt, 346adfe2030SMax Reitz 'file': {'filename': new_img, 347adfe2030SMax Reitz 'driver': 'file'}}) 348adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 349adfe2030SMax Reitz 350adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0') 351adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 352adfe2030SMax Reitz 353adfe2030SMax Reitz self.wait_for_open() 354adfe2030SMax Reitz 3556e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 356adfe2030SMax Reitz node_name='new') 357adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 358adfe2030SMax Reitz 359adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass): 360adfe2030SMax Reitz was_empty = True 361adfe2030SMax Reitz 362adfe2030SMax Reitz def setUp(self, media, interface): 363adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 364adfe2030SMax Reitz self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface) 365adfe2030SMax Reitz self.vm.launch() 366adfe2030SMax Reitz 367adfe2030SMax Reitz def tearDown(self): 368adfe2030SMax Reitz self.vm.shutdown() 369adfe2030SMax Reitz os.remove(new_img) 370adfe2030SMax Reitz 371adfe2030SMax Reitz def test_remove_on_empty(self): 372adfe2030SMax Reitz result = self.vm.qmp('blockdev-open-tray', device='drive0') 373adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 374adfe2030SMax Reitz 375adfe2030SMax Reitz self.wait_for_open() 376adfe2030SMax Reitz 3776e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 378adfe2030SMax Reitz # Should be a no-op 379adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 380adfe2030SMax Reitz 381adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled): 382adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 383adfe2030SMax Reitz has_real_tray = True 384adfe2030SMax Reitz 385adfe2030SMax Reitz def setUp(self): 386adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide') 387adfe2030SMax Reitz 388adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty): 389adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 390adfe2030SMax Reitz has_real_tray = True 391adfe2030SMax Reitz 392adfe2030SMax Reitz def setUp(self): 393adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide') 394adfe2030SMax Reitz 395adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled): 396adfe2030SMax Reitz TestInitiallyFilled = TestInitiallyFilled 397adfe2030SMax Reitz has_real_tray = False 398adfe2030SMax Reitz 399adfe2030SMax Reitz def setUp(self): 400adfe2030SMax Reitz self.TestInitiallyFilled.setUp(self, 'disk', 'floppy') 401adfe2030SMax Reitz 402adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty): 403adfe2030SMax Reitz TestInitiallyEmpty = TestInitiallyEmpty 404adfe2030SMax Reitz has_real_tray = False 405adfe2030SMax Reitz 406adfe2030SMax Reitz def setUp(self): 407adfe2030SMax Reitz self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy') 408adfe2030SMax Reitz # FDDs not having a real tray and there not being a medium inside the 409adfe2030SMax Reitz # tray at startup means the tray will be considered open 410adfe2030SMax Reitz self.has_opened = True 411adfe2030SMax Reitz 412adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass): 413adfe2030SMax Reitz def setUp(self): 414adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') 415adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') 416adfe2030SMax Reitz self.vm = iotests.VM() 417adfe2030SMax Reitz 418adfe2030SMax Reitz def tearDown(self): 419adfe2030SMax Reitz self.vm.shutdown() 420adfe2030SMax Reitz os.chmod(old_img, 0666) 421adfe2030SMax Reitz os.chmod(new_img, 0666) 422adfe2030SMax Reitz os.remove(old_img) 423adfe2030SMax Reitz os.remove(new_img) 424adfe2030SMax Reitz 425adfe2030SMax Reitz def test_ro_ro_retain(self): 426adfe2030SMax Reitz os.chmod(old_img, 0444) 427adfe2030SMax Reitz os.chmod(new_img, 0444) 428adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 429adfe2030SMax Reitz self.vm.launch() 430adfe2030SMax Reitz 431adfe2030SMax Reitz result = self.vm.qmp('query-block') 432adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 433adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 434adfe2030SMax Reitz 435adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 436adfe2030SMax Reitz filename=new_img, 437adfe2030SMax Reitz format=iotests.imgfmt, 438adfe2030SMax Reitz read_only_mode='retain') 439adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 440adfe2030SMax Reitz 441adfe2030SMax Reitz result = self.vm.qmp('query-block') 442adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 443adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 444adfe2030SMax Reitz 445adfe2030SMax Reitz def test_ro_rw_retain(self): 446adfe2030SMax Reitz os.chmod(old_img, 0444) 447adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 448adfe2030SMax Reitz self.vm.launch() 449adfe2030SMax Reitz 450adfe2030SMax Reitz result = self.vm.qmp('query-block') 451adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 452adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 453adfe2030SMax Reitz 454adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 455adfe2030SMax Reitz filename=new_img, 456adfe2030SMax Reitz format=iotests.imgfmt, 457adfe2030SMax Reitz read_only_mode='retain') 458adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 459adfe2030SMax Reitz 460adfe2030SMax Reitz result = self.vm.qmp('query-block') 461adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 462adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 463adfe2030SMax Reitz 464adfe2030SMax Reitz def test_rw_ro_retain(self): 465adfe2030SMax Reitz os.chmod(new_img, 0444) 466adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 467adfe2030SMax Reitz self.vm.launch() 468adfe2030SMax Reitz 469adfe2030SMax Reitz result = self.vm.qmp('query-block') 470adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 471adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 472adfe2030SMax Reitz 473adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 474adfe2030SMax Reitz filename=new_img, 475adfe2030SMax Reitz format=iotests.imgfmt, 476adfe2030SMax Reitz read_only_mode='retain') 477adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 478adfe2030SMax Reitz 479adfe2030SMax Reitz self.assertEquals(self.vm.get_qmp_events(wait=False), []) 480adfe2030SMax Reitz 481adfe2030SMax Reitz result = self.vm.qmp('query-block') 482adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 483adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 484adfe2030SMax Reitz 485adfe2030SMax Reitz def test_ro_rw(self): 486adfe2030SMax Reitz os.chmod(old_img, 0444) 487adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 488adfe2030SMax Reitz self.vm.launch() 489adfe2030SMax Reitz 490adfe2030SMax Reitz result = self.vm.qmp('query-block') 491adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 492adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 493adfe2030SMax Reitz 494adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 495adfe2030SMax Reitz device='drive0', 496adfe2030SMax Reitz filename=new_img, 497adfe2030SMax Reitz format=iotests.imgfmt, 498adfe2030SMax Reitz read_only_mode='read-write') 499adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 500adfe2030SMax Reitz 501adfe2030SMax Reitz result = self.vm.qmp('query-block') 502adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 503adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 504adfe2030SMax Reitz 505adfe2030SMax Reitz def test_rw_ro(self): 506adfe2030SMax Reitz os.chmod(new_img, 0444) 507adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 508adfe2030SMax Reitz self.vm.launch() 509adfe2030SMax Reitz 510adfe2030SMax Reitz result = self.vm.qmp('query-block') 511adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 512adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 513adfe2030SMax Reitz 514adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 515adfe2030SMax Reitz device='drive0', 516adfe2030SMax Reitz filename=new_img, 517adfe2030SMax Reitz format=iotests.imgfmt, 518adfe2030SMax Reitz read_only_mode='read-only') 519adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 520adfe2030SMax Reitz 521adfe2030SMax Reitz result = self.vm.qmp('query-block') 522adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 523adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 524adfe2030SMax Reitz 525adfe2030SMax Reitz def test_make_rw_ro(self): 526adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 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', 534adfe2030SMax Reitz device='drive0', 535adfe2030SMax Reitz filename=new_img, 536adfe2030SMax Reitz format=iotests.imgfmt, 537adfe2030SMax Reitz read_only_mode='read-only') 538adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 539adfe2030SMax Reitz 540adfe2030SMax Reitz result = self.vm.qmp('query-block') 541adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 542adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 543adfe2030SMax Reitz 544adfe2030SMax Reitz def test_make_ro_rw(self): 545adfe2030SMax Reitz os.chmod(new_img, 0444) 546adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 547adfe2030SMax Reitz self.vm.launch() 548adfe2030SMax Reitz 549adfe2030SMax Reitz result = self.vm.qmp('query-block') 550adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 551adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 552adfe2030SMax Reitz 553adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', 554adfe2030SMax Reitz device='drive0', 555adfe2030SMax Reitz filename=new_img, 556adfe2030SMax Reitz format=iotests.imgfmt, 557adfe2030SMax Reitz read_only_mode='read-write') 558adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 559adfe2030SMax Reitz 560adfe2030SMax Reitz result = self.vm.qmp('query-block') 561adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 562adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 563adfe2030SMax Reitz 564adfe2030SMax Reitz def test_make_rw_ro_by_retain(self): 565adfe2030SMax Reitz os.chmod(old_img, 0444) 566adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') 567adfe2030SMax Reitz self.vm.launch() 568adfe2030SMax Reitz 569adfe2030SMax Reitz result = self.vm.qmp('query-block') 570adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 571adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 572adfe2030SMax Reitz 573adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 574adfe2030SMax Reitz filename=new_img, 575adfe2030SMax Reitz format=iotests.imgfmt, 576adfe2030SMax Reitz read_only_mode='retain') 577adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 578adfe2030SMax Reitz 579adfe2030SMax Reitz result = self.vm.qmp('query-block') 580adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 581adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 582adfe2030SMax Reitz 583adfe2030SMax Reitz def test_make_ro_rw_by_retain(self): 584adfe2030SMax Reitz os.chmod(new_img, 0444) 585adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 586adfe2030SMax Reitz self.vm.launch() 587adfe2030SMax Reitz 588adfe2030SMax Reitz result = self.vm.qmp('query-block') 589adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 590adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 591adfe2030SMax Reitz 592adfe2030SMax Reitz result = self.vm.qmp('blockdev-change-medium', device='drive0', 593adfe2030SMax Reitz filename=new_img, 594adfe2030SMax Reitz format=iotests.imgfmt, 595adfe2030SMax Reitz read_only_mode='retain') 596adfe2030SMax Reitz self.assert_qmp(result, 'error/class', 'GenericError') 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 602adfe2030SMax Reitz def test_rw_ro_cycle(self): 603adfe2030SMax Reitz os.chmod(new_img, 0444) 604adfe2030SMax Reitz self.vm.add_drive(old_img, 'media=disk', 'floppy') 605adfe2030SMax Reitz self.vm.launch() 606adfe2030SMax Reitz 607adfe2030SMax Reitz result = self.vm.qmp('query-block') 608adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 609adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 610adfe2030SMax Reitz 611adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 612adfe2030SMax Reitz options={'node-name': 'new', 613adfe2030SMax Reitz 'driver': iotests.imgfmt, 614adfe2030SMax Reitz 'read-only': True, 615adfe2030SMax Reitz 'file': {'filename': new_img, 616adfe2030SMax Reitz 'driver': 'file'}}) 617adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 618adfe2030SMax Reitz 619adfe2030SMax Reitz result = self.vm.qmp('query-block') 620adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', False) 621adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 622adfe2030SMax Reitz 6236e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 624adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 625adfe2030SMax Reitz 626adfe2030SMax Reitz result = self.vm.qmp('query-block') 627adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 628adfe2030SMax Reitz 6296e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 630adfe2030SMax Reitz node_name='new') 631adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 632adfe2030SMax Reitz 633adfe2030SMax Reitz result = self.vm.qmp('query-block') 634adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 635adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 636adfe2030SMax Reitz 637adfe2030SMax Reitz result = self.vm.qmp('query-block') 638adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/ro', True) 639adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 640adfe2030SMax Reitz 641adfe2030SMax ReitzGeneralChangeTestsBaseClass = None 642adfe2030SMax ReitzTestInitiallyFilled = None 643adfe2030SMax ReitzTestInitiallyEmpty = None 644adfe2030SMax Reitz 645adfe2030SMax Reitz 646adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass): 647adfe2030SMax Reitz def setUp(self): 648adfe2030SMax Reitz qemu_img('create', '-f', iotests.imgfmt, old_img, '1M') 649adfe2030SMax Reitz 650adfe2030SMax Reitz self.vm = iotests.VM() 651*e4fd2e9dSKevin Wolf self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 652adfe2030SMax Reitz self.vm.launch() 653adfe2030SMax Reitz 654adfe2030SMax Reitz result = self.vm.qmp('query-block') 655adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 656adfe2030SMax Reitz 657adfe2030SMax Reitz # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 658adfe2030SMax Reitz # is not necessary 6596e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') 660adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 661adfe2030SMax Reitz 662adfe2030SMax Reitz result = self.vm.qmp('query-block') 663adfe2030SMax Reitz self.assert_qmp_absent(result, 'return[0]/inserted') 664adfe2030SMax Reitz 665adfe2030SMax Reitz result = self.vm.qmp('blockdev-add', 666adfe2030SMax Reitz options={'node-name': 'node0', 667adfe2030SMax Reitz 'driver': iotests.imgfmt, 668adfe2030SMax Reitz 'file': {'filename': old_img, 669adfe2030SMax Reitz 'driver': 'file'}}) 670adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 671adfe2030SMax Reitz 6726e0abc25SMax Reitz result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', 673adfe2030SMax Reitz node_name='node0') 674adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 675adfe2030SMax Reitz 676adfe2030SMax Reitz result = self.vm.qmp('query-block') 677adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 678adfe2030SMax Reitz 679adfe2030SMax Reitz def tearDown(self): 680adfe2030SMax Reitz self.vm.shutdown() 681adfe2030SMax Reitz os.remove(old_img) 682adfe2030SMax Reitz try: 683adfe2030SMax Reitz os.remove(new_img) 684adfe2030SMax Reitz except OSError: 685adfe2030SMax Reitz pass 686adfe2030SMax Reitz 687adfe2030SMax Reitz def test_snapshot_and_commit(self): 688adfe2030SMax Reitz # We need backing file support 689adfe2030SMax Reitz if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 690adfe2030SMax Reitz return 691adfe2030SMax Reitz 692adfe2030SMax Reitz result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 693adfe2030SMax Reitz snapshot_file=new_img, 694adfe2030SMax Reitz format=iotests.imgfmt) 695adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 696adfe2030SMax Reitz 697adfe2030SMax Reitz result = self.vm.qmp('query-block') 698adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 699adfe2030SMax Reitz self.assert_qmp(result, 700adfe2030SMax Reitz 'return[0]/inserted/image/backing-image/filename', 701adfe2030SMax Reitz old_img) 702adfe2030SMax Reitz 703adfe2030SMax Reitz result = self.vm.qmp('block-commit', device='drive0') 704adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 705adfe2030SMax Reitz 706adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_READY') 707adfe2030SMax Reitz 708adfe2030SMax Reitz result = self.vm.qmp('query-block-jobs') 709adfe2030SMax Reitz self.assert_qmp(result, 'return[0]/device', 'drive0') 710adfe2030SMax Reitz 711adfe2030SMax Reitz result = self.vm.qmp('block-job-complete', device='drive0') 712adfe2030SMax Reitz self.assert_qmp(result, 'return', {}) 713adfe2030SMax Reitz 714adfe2030SMax Reitz self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 715adfe2030SMax Reitz 716adfe2030SMax Reitz 717adfe2030SMax Reitzif __name__ == '__main__': 718adfe2030SMax Reitz if iotests.qemu_default_machine != 'pc': 719adfe2030SMax Reitz # We need floppy and IDE CD-ROM 720adfe2030SMax Reitz iotests.notrun('not suitable for this machine type: %s' % 721adfe2030SMax Reitz iotests.qemu_default_machine) 722cc8c46b7SMax Reitz # Need to support image creation 723cc8c46b7SMax Reitz iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 724cc8c46b7SMax Reitz 'vmdk', 'raw', 'vhdx', 'qed']) 725