1342075fdSAlberto Garcia#!/usr/bin/env python 2342075fdSAlberto Garcia# 3342075fdSAlberto Garcia# Test cases for the QMP 'x-blockdev-del' command 4342075fdSAlberto Garcia# 5342075fdSAlberto Garcia# Copyright (C) 2015 Igalia, S.L. 6342075fdSAlberto Garcia# Author: Alberto Garcia <berto@igalia.com> 7342075fdSAlberto Garcia# 8342075fdSAlberto Garcia# This program is free software; you can redistribute it and/or modify 9342075fdSAlberto Garcia# it under the terms of the GNU General Public License as published by 10342075fdSAlberto Garcia# the Free Software Foundation; either version 2 of the License, or 11342075fdSAlberto Garcia# (at your option) any later version. 12342075fdSAlberto Garcia# 13342075fdSAlberto Garcia# This program is distributed in the hope that it will be useful, 14342075fdSAlberto Garcia# but WITHOUT ANY WARRANTY; without even the implied warranty of 15342075fdSAlberto Garcia# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16342075fdSAlberto Garcia# GNU General Public License for more details. 17342075fdSAlberto Garcia# 18342075fdSAlberto Garcia# You should have received a copy of the GNU General Public License 19342075fdSAlberto Garcia# along with this program. If not, see <http://www.gnu.org/licenses/>. 20342075fdSAlberto Garcia# 21342075fdSAlberto Garcia 22342075fdSAlberto Garciaimport os 23342075fdSAlberto Garciaimport iotests 24342075fdSAlberto Garciaimport time 25342075fdSAlberto Garcia 26342075fdSAlberto Garciabase_img = os.path.join(iotests.test_dir, 'base.img') 27342075fdSAlberto Garcianew_img = os.path.join(iotests.test_dir, 'new.img') 28342075fdSAlberto Garcia 29342075fdSAlberto Garciaclass TestBlockdevDel(iotests.QMPTestCase): 30342075fdSAlberto Garcia 31342075fdSAlberto Garcia def setUp(self): 32342075fdSAlberto Garcia iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M') 33342075fdSAlberto Garcia self.vm = iotests.VM() 34342075fdSAlberto Garcia self.vm.launch() 35342075fdSAlberto Garcia 36342075fdSAlberto Garcia def tearDown(self): 37342075fdSAlberto Garcia self.vm.shutdown() 38342075fdSAlberto Garcia os.remove(base_img) 39342075fdSAlberto Garcia if os.path.isfile(new_img): 40342075fdSAlberto Garcia os.remove(new_img) 41342075fdSAlberto Garcia 42342075fdSAlberto Garcia # Check whether a BlockBackend exists 43342075fdSAlberto Garcia def checkBlockBackend(self, backend, node, must_exist = True): 44342075fdSAlberto Garcia result = self.vm.qmp('query-block') 45342075fdSAlberto Garcia backends = filter(lambda x: x['device'] == backend, result['return']) 46342075fdSAlberto Garcia self.assertLessEqual(len(backends), 1) 47342075fdSAlberto Garcia self.assertEqual(must_exist, len(backends) == 1) 48342075fdSAlberto Garcia if must_exist: 49342075fdSAlberto Garcia if node: 50342075fdSAlberto Garcia self.assertEqual(backends[0]['inserted']['node-name'], node) 51342075fdSAlberto Garcia else: 52342075fdSAlberto Garcia self.assertFalse(backends[0].has_key('inserted')) 53342075fdSAlberto Garcia 54342075fdSAlberto Garcia # Check whether a BlockDriverState exists 55342075fdSAlberto Garcia def checkBlockDriverState(self, node, must_exist = True): 56342075fdSAlberto Garcia result = self.vm.qmp('query-named-block-nodes') 57342075fdSAlberto Garcia nodes = filter(lambda x: x['node-name'] == node, result['return']) 58342075fdSAlberto Garcia self.assertLessEqual(len(nodes), 1) 59342075fdSAlberto Garcia self.assertEqual(must_exist, len(nodes) == 1) 60342075fdSAlberto Garcia 61342075fdSAlberto Garcia # Add a new BlockBackend (with its attached BlockDriverState) 62342075fdSAlberto Garcia def addBlockBackend(self, backend, node): 63342075fdSAlberto Garcia file_node = '%s_file' % node 64342075fdSAlberto Garcia self.checkBlockBackend(backend, node, False) 65342075fdSAlberto Garcia self.checkBlockDriverState(node, False) 66342075fdSAlberto Garcia self.checkBlockDriverState(file_node, False) 67342075fdSAlberto Garcia opts = {'driver': iotests.imgfmt, 68342075fdSAlberto Garcia 'id': backend, 69342075fdSAlberto Garcia 'node-name': node, 70342075fdSAlberto Garcia 'file': {'driver': 'file', 71342075fdSAlberto Garcia 'node-name': file_node, 72342075fdSAlberto Garcia 'filename': base_img}} 73342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 74342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 75342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 76342075fdSAlberto Garcia self.checkBlockDriverState(node) 77342075fdSAlberto Garcia self.checkBlockDriverState(file_node) 78342075fdSAlberto Garcia 79342075fdSAlberto Garcia # Add a BlockDriverState without a BlockBackend 80342075fdSAlberto Garcia def addBlockDriverState(self, node): 81342075fdSAlberto Garcia file_node = '%s_file' % node 82342075fdSAlberto Garcia self.checkBlockDriverState(node, False) 83342075fdSAlberto Garcia self.checkBlockDriverState(file_node, False) 84342075fdSAlberto Garcia opts = {'driver': iotests.imgfmt, 85342075fdSAlberto Garcia 'node-name': node, 86342075fdSAlberto Garcia 'file': {'driver': 'file', 87342075fdSAlberto Garcia 'node-name': file_node, 88342075fdSAlberto Garcia 'filename': base_img}} 89342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 90342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 91342075fdSAlberto Garcia self.checkBlockDriverState(node) 92342075fdSAlberto Garcia self.checkBlockDriverState(file_node) 93342075fdSAlberto Garcia 94342075fdSAlberto Garcia # Add a BlockDriverState that will be used as overlay for the base_img BDS 95342075fdSAlberto Garcia def addBlockDriverStateOverlay(self, node): 96342075fdSAlberto Garcia self.checkBlockDriverState(node, False) 97342075fdSAlberto Garcia iotests.qemu_img('create', '-f', iotests.imgfmt, 98342075fdSAlberto Garcia '-b', base_img, new_img, '1M') 99342075fdSAlberto Garcia opts = {'driver': iotests.imgfmt, 100342075fdSAlberto Garcia 'node-name': node, 101342075fdSAlberto Garcia 'backing': '', 102342075fdSAlberto Garcia 'file': {'driver': 'file', 103342075fdSAlberto Garcia 'filename': new_img}} 104342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 105342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 106342075fdSAlberto Garcia self.checkBlockDriverState(node) 107342075fdSAlberto Garcia 108342075fdSAlberto Garcia # Delete a BlockBackend 109342075fdSAlberto Garcia def delBlockBackend(self, backend, node, expect_error = False, 110342075fdSAlberto Garcia destroys_media = True): 111342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 112342075fdSAlberto Garcia if node: 113342075fdSAlberto Garcia self.checkBlockDriverState(node) 114342075fdSAlberto Garcia result = self.vm.qmp('x-blockdev-del', id = backend) 115342075fdSAlberto Garcia if expect_error: 116342075fdSAlberto Garcia self.assert_qmp(result, 'error/class', 'GenericError') 117342075fdSAlberto Garcia if node: 118342075fdSAlberto Garcia self.checkBlockDriverState(node) 119342075fdSAlberto Garcia else: 120342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 121342075fdSAlberto Garcia if node: 122342075fdSAlberto Garcia self.checkBlockDriverState(node, not destroys_media) 123342075fdSAlberto Garcia self.checkBlockBackend(backend, node, must_exist = expect_error) 124342075fdSAlberto Garcia 125342075fdSAlberto Garcia # Delete a BlockDriverState 126342075fdSAlberto Garcia def delBlockDriverState(self, node, expect_error = False): 127342075fdSAlberto Garcia self.checkBlockDriverState(node) 128342075fdSAlberto Garcia result = self.vm.qmp('x-blockdev-del', node_name = node) 129342075fdSAlberto Garcia if expect_error: 130342075fdSAlberto Garcia self.assert_qmp(result, 'error/class', 'GenericError') 131342075fdSAlberto Garcia else: 132342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 133342075fdSAlberto Garcia self.checkBlockDriverState(node, expect_error) 134342075fdSAlberto Garcia 135342075fdSAlberto Garcia # Add a device model 136342075fdSAlberto Garcia def addDeviceModel(self, device, backend): 137342075fdSAlberto Garcia result = self.vm.qmp('device_add', id = device, 138342075fdSAlberto Garcia driver = 'virtio-blk-pci', drive = backend) 139342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 140342075fdSAlberto Garcia 141342075fdSAlberto Garcia # Delete a device model 142342075fdSAlberto Garcia def delDeviceModel(self, device): 143342075fdSAlberto Garcia result = self.vm.qmp('device_del', id = device) 144342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 145342075fdSAlberto Garcia 146342075fdSAlberto Garcia result = self.vm.qmp('system_reset') 147342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 148342075fdSAlberto Garcia 149342075fdSAlberto Garcia device_path = '/machine/peripheral/%s/virtio-backend' % device 150342075fdSAlberto Garcia event = self.vm.event_wait(name="DEVICE_DELETED", 151342075fdSAlberto Garcia match={'data': {'path': device_path}}) 152342075fdSAlberto Garcia self.assertNotEqual(event, None) 153342075fdSAlberto Garcia 154342075fdSAlberto Garcia event = self.vm.event_wait(name="DEVICE_DELETED", 155342075fdSAlberto Garcia match={'data': {'device': device}}) 156342075fdSAlberto Garcia self.assertNotEqual(event, None) 157342075fdSAlberto Garcia 158342075fdSAlberto Garcia # Remove a BlockDriverState 159342075fdSAlberto Garcia def ejectDrive(self, backend, node, expect_error = False, 160342075fdSAlberto Garcia destroys_media = True): 161342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 162342075fdSAlberto Garcia self.checkBlockDriverState(node) 163342075fdSAlberto Garcia result = self.vm.qmp('eject', device = backend) 164342075fdSAlberto Garcia if expect_error: 165342075fdSAlberto Garcia self.assert_qmp(result, 'error/class', 'GenericError') 166342075fdSAlberto Garcia self.checkBlockDriverState(node) 167342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 168342075fdSAlberto Garcia else: 169342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 170342075fdSAlberto Garcia self.checkBlockDriverState(node, not destroys_media) 171342075fdSAlberto Garcia self.checkBlockBackend(backend, None) 172342075fdSAlberto Garcia 173342075fdSAlberto Garcia # Insert a BlockDriverState 174342075fdSAlberto Garcia def insertDrive(self, backend, node): 175342075fdSAlberto Garcia self.checkBlockBackend(backend, None) 176342075fdSAlberto Garcia self.checkBlockDriverState(node) 177342075fdSAlberto Garcia result = self.vm.qmp('blockdev-insert-medium', 178342075fdSAlberto Garcia device = backend, node_name = node) 179342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 180342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 181342075fdSAlberto Garcia self.checkBlockDriverState(node) 182342075fdSAlberto Garcia 183342075fdSAlberto Garcia # Create a snapshot using 'blockdev-snapshot-sync' 184342075fdSAlberto Garcia def createSnapshotSync(self, node, overlay): 185342075fdSAlberto Garcia self.checkBlockDriverState(node) 186342075fdSAlberto Garcia self.checkBlockDriverState(overlay, False) 187342075fdSAlberto Garcia opts = {'node-name': node, 188342075fdSAlberto Garcia 'snapshot-file': new_img, 189342075fdSAlberto Garcia 'snapshot-node-name': overlay, 190342075fdSAlberto Garcia 'format': iotests.imgfmt} 191342075fdSAlberto Garcia result = self.vm.qmp('blockdev-snapshot-sync', conv_keys=False, **opts) 192342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 193342075fdSAlberto Garcia self.checkBlockDriverState(node) 194342075fdSAlberto Garcia self.checkBlockDriverState(overlay) 195342075fdSAlberto Garcia 196342075fdSAlberto Garcia # Create a snapshot using 'blockdev-snapshot' 197342075fdSAlberto Garcia def createSnapshot(self, node, overlay): 198342075fdSAlberto Garcia self.checkBlockDriverState(node) 199342075fdSAlberto Garcia self.checkBlockDriverState(overlay) 200342075fdSAlberto Garcia result = self.vm.qmp('blockdev-snapshot', 201342075fdSAlberto Garcia node = node, overlay = overlay) 202342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 203342075fdSAlberto Garcia self.checkBlockDriverState(node) 204342075fdSAlberto Garcia self.checkBlockDriverState(overlay) 205342075fdSAlberto Garcia 206342075fdSAlberto Garcia # Create a mirror 207342075fdSAlberto Garcia def createMirror(self, backend, node, new_node): 208342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 209342075fdSAlberto Garcia self.checkBlockDriverState(new_node, False) 210342075fdSAlberto Garcia opts = {'device': backend, 211342075fdSAlberto Garcia 'target': new_img, 212342075fdSAlberto Garcia 'node-name': new_node, 213342075fdSAlberto Garcia 'sync': 'top', 214342075fdSAlberto Garcia 'format': iotests.imgfmt} 215342075fdSAlberto Garcia result = self.vm.qmp('drive-mirror', conv_keys=False, **opts) 216342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 217342075fdSAlberto Garcia self.checkBlockBackend(backend, node) 218342075fdSAlberto Garcia self.checkBlockDriverState(new_node) 219342075fdSAlberto Garcia 220342075fdSAlberto Garcia # Complete an existing block job 221342075fdSAlberto Garcia def completeBlockJob(self, backend, node_before, node_after): 222342075fdSAlberto Garcia self.checkBlockBackend(backend, node_before) 223342075fdSAlberto Garcia result = self.vm.qmp('block-job-complete', device=backend) 224342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 225342075fdSAlberto Garcia self.wait_until_completed(backend) 226342075fdSAlberto Garcia self.checkBlockBackend(backend, node_after) 227342075fdSAlberto Garcia 228342075fdSAlberto Garcia # Add a BlkDebug node 229342075fdSAlberto Garcia # Note that the purpose of this is to test the x-blockdev-del 230342075fdSAlberto Garcia # sanity checks, not to create a usable blkdebug drive 231342075fdSAlberto Garcia def addBlkDebug(self, debug, node): 232342075fdSAlberto Garcia self.checkBlockDriverState(node, False) 233342075fdSAlberto Garcia self.checkBlockDriverState(debug, False) 234342075fdSAlberto Garcia image = {'driver': iotests.imgfmt, 235342075fdSAlberto Garcia 'node-name': node, 236342075fdSAlberto Garcia 'file': {'driver': 'file', 237342075fdSAlberto Garcia 'filename': base_img}} 238342075fdSAlberto Garcia opts = {'driver': 'blkdebug', 239342075fdSAlberto Garcia 'node-name': debug, 240342075fdSAlberto Garcia 'image': image} 241342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 242342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 243342075fdSAlberto Garcia self.checkBlockDriverState(node) 244342075fdSAlberto Garcia self.checkBlockDriverState(debug) 245342075fdSAlberto Garcia 246342075fdSAlberto Garcia # Add a BlkVerify node 247342075fdSAlberto Garcia # Note that the purpose of this is to test the x-blockdev-del 248342075fdSAlberto Garcia # sanity checks, not to create a usable blkverify drive 249342075fdSAlberto Garcia def addBlkVerify(self, blkverify, test, raw): 250342075fdSAlberto Garcia self.checkBlockDriverState(test, False) 251342075fdSAlberto Garcia self.checkBlockDriverState(raw, False) 252342075fdSAlberto Garcia self.checkBlockDriverState(blkverify, False) 253342075fdSAlberto Garcia iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M') 254342075fdSAlberto Garcia node_0 = {'driver': iotests.imgfmt, 255342075fdSAlberto Garcia 'node-name': test, 256342075fdSAlberto Garcia 'file': {'driver': 'file', 257342075fdSAlberto Garcia 'filename': base_img}} 258342075fdSAlberto Garcia node_1 = {'driver': iotests.imgfmt, 259342075fdSAlberto Garcia 'node-name': raw, 260342075fdSAlberto Garcia 'file': {'driver': 'file', 261342075fdSAlberto Garcia 'filename': new_img}} 262342075fdSAlberto Garcia opts = {'driver': 'blkverify', 263342075fdSAlberto Garcia 'node-name': blkverify, 264342075fdSAlberto Garcia 'test': node_0, 265342075fdSAlberto Garcia 'raw': node_1} 266342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 267342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 268342075fdSAlberto Garcia self.checkBlockDriverState(test) 269342075fdSAlberto Garcia self.checkBlockDriverState(raw) 270342075fdSAlberto Garcia self.checkBlockDriverState(blkverify) 271342075fdSAlberto Garcia 272342075fdSAlberto Garcia # Add a Quorum node 273342075fdSAlberto Garcia def addQuorum(self, quorum, child0, child1): 274342075fdSAlberto Garcia self.checkBlockDriverState(child0, False) 275342075fdSAlberto Garcia self.checkBlockDriverState(child1, False) 276342075fdSAlberto Garcia self.checkBlockDriverState(quorum, False) 277342075fdSAlberto Garcia iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M') 278342075fdSAlberto Garcia child_0 = {'driver': iotests.imgfmt, 279342075fdSAlberto Garcia 'node-name': child0, 280342075fdSAlberto Garcia 'file': {'driver': 'file', 281342075fdSAlberto Garcia 'filename': base_img}} 282342075fdSAlberto Garcia child_1 = {'driver': iotests.imgfmt, 283342075fdSAlberto Garcia 'node-name': child1, 284342075fdSAlberto Garcia 'file': {'driver': 'file', 285342075fdSAlberto Garcia 'filename': new_img}} 286342075fdSAlberto Garcia opts = {'driver': 'quorum', 287342075fdSAlberto Garcia 'node-name': quorum, 288342075fdSAlberto Garcia 'vote-threshold': 1, 289342075fdSAlberto Garcia 'children': [ child_0, child_1 ]} 290342075fdSAlberto Garcia result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 291342075fdSAlberto Garcia self.assert_qmp(result, 'return', {}) 292342075fdSAlberto Garcia self.checkBlockDriverState(child0) 293342075fdSAlberto Garcia self.checkBlockDriverState(child1) 294342075fdSAlberto Garcia self.checkBlockDriverState(quorum) 295342075fdSAlberto Garcia 296342075fdSAlberto Garcia ######################## 297342075fdSAlberto Garcia # The tests start here # 298342075fdSAlberto Garcia ######################## 299342075fdSAlberto Garcia 300342075fdSAlberto Garcia def testWrongParameters(self): 301342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 302342075fdSAlberto Garcia result = self.vm.qmp('x-blockdev-del') 303342075fdSAlberto Garcia self.assert_qmp(result, 'error/class', 'GenericError') 304342075fdSAlberto Garcia result = self.vm.qmp('x-blockdev-del', id='drive0', node_name='node0') 305342075fdSAlberto Garcia self.assert_qmp(result, 'error/class', 'GenericError') 306342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node0') 307342075fdSAlberto Garcia 308342075fdSAlberto Garcia def testBlockBackend(self): 309342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 310342075fdSAlberto Garcia # You cannot delete a BDS that is attached to a backend 311342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 312342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node0') 313342075fdSAlberto Garcia 314342075fdSAlberto Garcia def testBlockDriverState(self): 315342075fdSAlberto Garcia self.addBlockDriverState('node0') 316342075fdSAlberto Garcia # You cannot delete a file BDS directly 317342075fdSAlberto Garcia self.delBlockDriverState('node0_file', expect_error = True) 318342075fdSAlberto Garcia self.delBlockDriverState('node0') 319342075fdSAlberto Garcia 320342075fdSAlberto Garcia def testEject(self): 321342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 322342075fdSAlberto Garcia self.ejectDrive('drive0', 'node0') 323342075fdSAlberto Garcia self.delBlockBackend('drive0', None) 324342075fdSAlberto Garcia 325342075fdSAlberto Garcia def testDeviceModel(self): 326342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 327342075fdSAlberto Garcia self.addDeviceModel('device0', 'drive0') 328342075fdSAlberto Garcia self.ejectDrive('drive0', 'node0', expect_error = True) 329342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node0', expect_error = True) 330342075fdSAlberto Garcia self.delDeviceModel('device0') 331342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node0') 332342075fdSAlberto Garcia 333342075fdSAlberto Garcia def testAttachMedia(self): 334342075fdSAlberto Garcia # This creates a BlockBackend and removes its media 335342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 336342075fdSAlberto Garcia self.ejectDrive('drive0', 'node0') 337342075fdSAlberto Garcia # This creates a new BlockDriverState and inserts it into the backend 338342075fdSAlberto Garcia self.addBlockDriverState('node1') 339342075fdSAlberto Garcia self.insertDrive('drive0', 'node1') 340342075fdSAlberto Garcia # The backend can't be removed: the new BDS has an extra reference 341342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node1', expect_error = True) 342342075fdSAlberto Garcia self.delBlockDriverState('node1', expect_error = True) 343342075fdSAlberto Garcia # The BDS still exists after being ejected, but now it can be removed 344342075fdSAlberto Garcia self.ejectDrive('drive0', 'node1', destroys_media = False) 345342075fdSAlberto Garcia self.delBlockDriverState('node1') 346342075fdSAlberto Garcia self.delBlockBackend('drive0', None) 347342075fdSAlberto Garcia 348342075fdSAlberto Garcia def testSnapshotSync(self): 349342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 350342075fdSAlberto Garcia self.createSnapshotSync('node0', 'overlay0') 351342075fdSAlberto Garcia # This fails because node0 is now being used as a backing image 352342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 353342075fdSAlberto Garcia # This succeeds because overlay0 only has the backend reference 354342075fdSAlberto Garcia self.delBlockBackend('drive0', 'overlay0') 355342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 356342075fdSAlberto Garcia 357342075fdSAlberto Garcia def testSnapshot(self): 358342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 359342075fdSAlberto Garcia self.addBlockDriverStateOverlay('overlay0') 360342075fdSAlberto Garcia self.createSnapshot('node0', 'overlay0') 361342075fdSAlberto Garcia self.delBlockBackend('drive0', 'overlay0', expect_error = True) 362342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 363342075fdSAlberto Garcia self.delBlockDriverState('overlay0', expect_error = True) 364342075fdSAlberto Garcia self.ejectDrive('drive0', 'overlay0', destroys_media = False) 365342075fdSAlberto Garcia self.delBlockBackend('drive0', None) 366342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 367342075fdSAlberto Garcia self.delBlockDriverState('overlay0') 368342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 369342075fdSAlberto Garcia 370342075fdSAlberto Garcia def testMirror(self): 371342075fdSAlberto Garcia self.addBlockBackend('drive0', 'node0') 372342075fdSAlberto Garcia self.createMirror('drive0', 'node0', 'mirror0') 373342075fdSAlberto Garcia # The block job prevents removing the device 374342075fdSAlberto Garcia self.delBlockBackend('drive0', 'node0', expect_error = True) 375342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 376342075fdSAlberto Garcia self.delBlockDriverState('mirror0', expect_error = True) 377342075fdSAlberto Garcia self.wait_ready('drive0') 378342075fdSAlberto Garcia self.completeBlockJob('drive0', 'node0', 'mirror0') 379342075fdSAlberto Garcia self.assert_no_active_block_jobs() 380342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 381342075fdSAlberto Garcia # This succeeds because the backend now points to mirror0 382342075fdSAlberto Garcia self.delBlockBackend('drive0', 'mirror0') 383342075fdSAlberto Garcia 384342075fdSAlberto Garcia def testBlkDebug(self): 385342075fdSAlberto Garcia self.addBlkDebug('debug0', 'node0') 386342075fdSAlberto Garcia # 'node0' is used by the blkdebug node 387342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 388342075fdSAlberto Garcia # But we can remove the blkdebug node directly 389342075fdSAlberto Garcia self.delBlockDriverState('debug0') 390342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 391342075fdSAlberto Garcia 392342075fdSAlberto Garcia def testBlkVerify(self): 393342075fdSAlberto Garcia self.addBlkVerify('verify0', 'node0', 'node1') 394342075fdSAlberto Garcia # We cannot remove the children of a blkverify device 395342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 396342075fdSAlberto Garcia self.delBlockDriverState('node1', expect_error = True) 397342075fdSAlberto Garcia # But we can remove the blkverify node directly 398342075fdSAlberto Garcia self.delBlockDriverState('verify0') 399342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 400342075fdSAlberto Garcia self.checkBlockDriverState('node1', False) 401342075fdSAlberto Garcia 402342075fdSAlberto Garcia def testQuorum(self): 403*92e68987SAlberto Garcia if not 'quorum' in iotests.qemu_img_pipe('--help'): 404*92e68987SAlberto Garcia return 405342075fdSAlberto Garcia self.addQuorum('quorum0', 'node0', 'node1') 406342075fdSAlberto Garcia # We cannot remove the children of a Quorum device 407342075fdSAlberto Garcia self.delBlockDriverState('node0', expect_error = True) 408342075fdSAlberto Garcia self.delBlockDriverState('node1', expect_error = True) 409342075fdSAlberto Garcia # But we can remove the Quorum node directly 410342075fdSAlberto Garcia self.delBlockDriverState('quorum0') 411342075fdSAlberto Garcia self.checkBlockDriverState('node0', False) 412342075fdSAlberto Garcia self.checkBlockDriverState('node1', False) 413342075fdSAlberto Garcia 414342075fdSAlberto Garcia 415342075fdSAlberto Garciaif __name__ == '__main__': 416342075fdSAlberto Garcia iotests.main(supported_fmts=["qcow2"]) 417