qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qemu-iotests/139: Avoid blockdev-add with id

We want to remove the 'id' option for blockdev-add. This removes one
user of the option and makes it use only node names.

Some test cases that used to work with an unattached BlockBackend are
removed, either because they don't make sense with an attached device or
because the equivalent test case with an attached device already exists.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>

+59 -123
+57 -121
tests/qemu-iotests/139
··· 31 31 def setUp(self): 32 32 iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M') 33 33 self.vm = iotests.VM() 34 + self.vm.add_device("virtio-scsi-pci,id=virtio-scsi") 34 35 self.vm.launch() 35 36 36 37 def tearDown(self): ··· 39 40 if os.path.isfile(new_img): 40 41 os.remove(new_img) 41 42 42 - # Check whether a BlockBackend exists 43 - def checkBlockBackend(self, backend, node, must_exist = True): 44 - result = self.vm.qmp('query-block') 45 - backends = filter(lambda x: x['device'] == backend, result['return']) 46 - self.assertLessEqual(len(backends), 1) 47 - self.assertEqual(must_exist, len(backends) == 1) 48 - if must_exist: 49 - if node: 50 - self.assertEqual(backends[0]['inserted']['node-name'], node) 51 - else: 52 - self.assertFalse(backends[0].has_key('inserted')) 53 - 54 43 # Check whether a BlockDriverState exists 55 44 def checkBlockDriverState(self, node, must_exist = True): 56 45 result = self.vm.qmp('query-named-block-nodes') ··· 58 47 self.assertLessEqual(len(nodes), 1) 59 48 self.assertEqual(must_exist, len(nodes) == 1) 60 49 61 - # Add a new BlockBackend (with its attached BlockDriverState) 62 - def addBlockBackend(self, backend, node): 63 - file_node = '%s_file' % node 64 - self.checkBlockBackend(backend, node, False) 65 - self.checkBlockDriverState(node, False) 66 - self.checkBlockDriverState(file_node, False) 67 - opts = {'driver': iotests.imgfmt, 68 - 'id': backend, 69 - 'node-name': node, 70 - 'file': {'driver': 'file', 71 - 'node-name': file_node, 72 - 'filename': base_img}} 73 - result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts) 74 - self.assert_qmp(result, 'return', {}) 75 - self.checkBlockBackend(backend, node) 76 - self.checkBlockDriverState(node) 77 - self.checkBlockDriverState(file_node) 78 - 79 50 # Add a BlockDriverState without a BlockBackend 80 51 def addBlockDriverState(self, node): 81 52 file_node = '%s_file' % node ··· 105 76 self.assert_qmp(result, 'return', {}) 106 77 self.checkBlockDriverState(node) 107 78 108 - # Delete a BlockBackend 109 - def delBlockBackend(self, backend, node, expect_error = False, 110 - destroys_media = True): 111 - self.checkBlockBackend(backend, node) 112 - if node: 113 - self.checkBlockDriverState(node) 114 - result = self.vm.qmp('x-blockdev-del', id = backend) 115 - if expect_error: 116 - self.assert_qmp(result, 'error/class', 'GenericError') 117 - if node: 118 - self.checkBlockDriverState(node) 119 - else: 120 - self.assert_qmp(result, 'return', {}) 121 - if node: 122 - self.checkBlockDriverState(node, not destroys_media) 123 - self.checkBlockBackend(backend, node, must_exist = expect_error) 124 - 125 79 # Delete a BlockDriverState 126 80 def delBlockDriverState(self, node, expect_error = False): 127 81 self.checkBlockDriverState(node) ··· 133 87 self.checkBlockDriverState(node, expect_error) 134 88 135 89 # Add a device model 136 - def addDeviceModel(self, device, backend): 90 + def addDeviceModel(self, device, backend, driver = 'virtio-blk-pci'): 137 91 result = self.vm.qmp('device_add', id = device, 138 - driver = 'virtio-blk-pci', drive = backend) 92 + driver = driver, drive = backend) 139 93 self.assert_qmp(result, 'return', {}) 140 94 141 95 # Delete a device model 142 - def delDeviceModel(self, device): 96 + def delDeviceModel(self, device, is_virtio_blk = True): 143 97 result = self.vm.qmp('device_del', id = device) 144 98 self.assert_qmp(result, 'return', {}) 145 99 146 100 result = self.vm.qmp('system_reset') 147 101 self.assert_qmp(result, 'return', {}) 148 102 149 - device_path = '/machine/peripheral/%s/virtio-backend' % device 150 - event = self.vm.event_wait(name="DEVICE_DELETED", 151 - match={'data': {'path': device_path}}) 152 - self.assertNotEqual(event, None) 103 + if is_virtio_blk: 104 + device_path = '/machine/peripheral/%s/virtio-backend' % device 105 + event = self.vm.event_wait(name="DEVICE_DELETED", 106 + match={'data': {'path': device_path}}) 107 + self.assertNotEqual(event, None) 153 108 154 109 event = self.vm.event_wait(name="DEVICE_DELETED", 155 110 match={'data': {'device': device}}) 156 111 self.assertNotEqual(event, None) 157 112 158 113 # Remove a BlockDriverState 159 - def ejectDrive(self, backend, node, expect_error = False, 114 + def ejectDrive(self, device, node, expect_error = False, 160 115 destroys_media = True): 161 - self.checkBlockBackend(backend, node) 162 116 self.checkBlockDriverState(node) 163 - result = self.vm.qmp('eject', device = backend) 117 + result = self.vm.qmp('eject', id = device) 164 118 if expect_error: 165 119 self.assert_qmp(result, 'error/class', 'GenericError') 166 120 self.checkBlockDriverState(node) 167 - self.checkBlockBackend(backend, node) 168 121 else: 169 122 self.assert_qmp(result, 'return', {}) 170 123 self.checkBlockDriverState(node, not destroys_media) 171 - self.checkBlockBackend(backend, None) 172 124 173 125 # Insert a BlockDriverState 174 - def insertDrive(self, backend, node): 175 - self.checkBlockBackend(backend, None) 126 + def insertDrive(self, device, node): 176 127 self.checkBlockDriverState(node) 177 128 result = self.vm.qmp('x-blockdev-insert-medium', 178 - device = backend, node_name = node) 129 + id = device, node_name = node) 179 130 self.assert_qmp(result, 'return', {}) 180 - self.checkBlockBackend(backend, node) 181 131 self.checkBlockDriverState(node) 182 132 183 133 # Create a snapshot using 'blockdev-snapshot-sync' ··· 204 154 self.checkBlockDriverState(overlay) 205 155 206 156 # Create a mirror 207 - def createMirror(self, backend, node, new_node): 208 - self.checkBlockBackend(backend, node) 157 + def createMirror(self, node, new_node): 209 158 self.checkBlockDriverState(new_node, False) 210 - opts = {'device': backend, 159 + opts = {'device': node, 160 + 'job-id': node, 211 161 'target': new_img, 212 162 'node-name': new_node, 213 163 'sync': 'top', 214 164 'format': iotests.imgfmt} 215 165 result = self.vm.qmp('drive-mirror', conv_keys=False, **opts) 216 166 self.assert_qmp(result, 'return', {}) 217 - self.checkBlockBackend(backend, node) 218 167 self.checkBlockDriverState(new_node) 219 168 220 169 # Complete an existing block job 221 - def completeBlockJob(self, backend, node_before, node_after): 222 - self.checkBlockBackend(backend, node_before) 223 - result = self.vm.qmp('block-job-complete', device=backend) 170 + def completeBlockJob(self, id, node_before, node_after): 171 + result = self.vm.qmp('block-job-complete', device=id) 224 172 self.assert_qmp(result, 'return', {}) 225 - self.wait_until_completed(backend) 226 - self.checkBlockBackend(backend, node_after) 173 + self.wait_until_completed(id) 227 174 228 175 # Add a BlkDebug node 229 176 # Note that the purpose of this is to test the x-blockdev-del ··· 297 244 # The tests start here # 298 245 ######################## 299 246 300 - def testWrongParameters(self): 301 - self.addBlockBackend('drive0', 'node0') 302 - result = self.vm.qmp('x-blockdev-del') 303 - self.assert_qmp(result, 'error/class', 'GenericError') 304 - result = self.vm.qmp('x-blockdev-del', id='drive0', node_name='node0') 305 - self.assert_qmp(result, 'error/class', 'GenericError') 306 - self.delBlockBackend('drive0', 'node0') 307 - 308 - def testBlockBackend(self): 309 - self.addBlockBackend('drive0', 'node0') 310 - # You cannot delete a BDS that is attached to a backend 311 - self.delBlockDriverState('node0', expect_error = True) 312 - self.delBlockBackend('drive0', 'node0') 313 - 314 247 def testBlockDriverState(self): 315 248 self.addBlockDriverState('node0') 316 249 # You cannot delete a file BDS directly 317 250 self.delBlockDriverState('node0_file', expect_error = True) 318 251 self.delBlockDriverState('node0') 319 252 320 - def testEject(self): 321 - self.addBlockBackend('drive0', 'node0') 322 - self.ejectDrive('drive0', 'node0') 323 - self.delBlockBackend('drive0', None) 324 - 325 253 def testDeviceModel(self): 326 - self.addBlockBackend('drive0', 'node0') 327 - self.addDeviceModel('device0', 'drive0') 328 - self.ejectDrive('drive0', 'node0', expect_error = True) 329 - self.delBlockBackend('drive0', 'node0', expect_error = True) 254 + self.addBlockDriverState('node0') 255 + self.addDeviceModel('device0', 'node0') 256 + self.ejectDrive('device0', 'node0', expect_error = True) 257 + self.delBlockDriverState('node0', expect_error = True) 330 258 self.delDeviceModel('device0') 331 - self.delBlockBackend('drive0', 'node0') 259 + self.delBlockDriverState('node0') 332 260 333 261 def testAttachMedia(self): 334 262 # This creates a BlockBackend and removes its media 335 - self.addBlockBackend('drive0', 'node0') 336 - self.ejectDrive('drive0', 'node0') 337 - # This creates a new BlockDriverState and inserts it into the backend 263 + self.addBlockDriverState('node0') 264 + self.addDeviceModel('device0', 'node0', 'scsi-cd') 265 + self.ejectDrive('device0', 'node0', destroys_media = False) 266 + self.delBlockDriverState('node0') 267 + 268 + # This creates a new BlockDriverState and inserts it into the device 338 269 self.addBlockDriverState('node1') 339 - self.insertDrive('drive0', 'node1') 340 - # The backend can't be removed: the new BDS has an extra reference 341 - self.delBlockBackend('drive0', 'node1', expect_error = True) 270 + self.insertDrive('device0', 'node1') 271 + # The node can't be removed: the new device has an extra reference 342 272 self.delBlockDriverState('node1', expect_error = True) 343 273 # The BDS still exists after being ejected, but now it can be removed 344 - self.ejectDrive('drive0', 'node1', destroys_media = False) 274 + self.ejectDrive('device0', 'node1', destroys_media = False) 345 275 self.delBlockDriverState('node1') 346 - self.delBlockBackend('drive0', None) 276 + self.delDeviceModel('device0', False) 347 277 348 278 def testSnapshotSync(self): 349 - self.addBlockBackend('drive0', 'node0') 279 + self.addBlockDriverState('node0') 280 + self.addDeviceModel('device0', 'node0') 350 281 self.createSnapshotSync('node0', 'overlay0') 351 282 # This fails because node0 is now being used as a backing image 352 283 self.delBlockDriverState('node0', expect_error = True) 353 - # This succeeds because overlay0 only has the backend reference 354 - self.delBlockBackend('drive0', 'overlay0') 355 - self.checkBlockDriverState('node0', False) 284 + self.delBlockDriverState('overlay0', expect_error = True) 285 + # This succeeds because device0 only has the backend reference 286 + self.delDeviceModel('device0') 287 + # FIXME Would still be there if blockdev-snapshot-sync took a ref 288 + self.checkBlockDriverState('overlay0', False) 289 + self.delBlockDriverState('node0') 356 290 357 291 def testSnapshot(self): 358 - self.addBlockBackend('drive0', 'node0') 292 + self.addBlockDriverState('node0') 293 + self.addDeviceModel('device0', 'node0', 'scsi-cd') 359 294 self.addBlockDriverStateOverlay('overlay0') 360 295 self.createSnapshot('node0', 'overlay0') 361 - self.delBlockBackend('drive0', 'overlay0', expect_error = True) 362 296 self.delBlockDriverState('node0', expect_error = True) 363 297 self.delBlockDriverState('overlay0', expect_error = True) 364 - self.ejectDrive('drive0', 'overlay0', destroys_media = False) 365 - self.delBlockBackend('drive0', None) 298 + self.ejectDrive('device0', 'overlay0', destroys_media = False) 366 299 self.delBlockDriverState('node0', expect_error = True) 367 300 self.delBlockDriverState('overlay0') 368 - self.checkBlockDriverState('node0', False) 301 + self.delBlockDriverState('node0') 369 302 370 303 def testMirror(self): 371 - self.addBlockBackend('drive0', 'node0') 372 - self.createMirror('drive0', 'node0', 'mirror0') 304 + self.addBlockDriverState('node0') 305 + self.addDeviceModel('device0', 'node0', 'scsi-cd') 306 + self.createMirror('node0', 'mirror0') 373 307 # The block job prevents removing the device 374 - self.delBlockBackend('drive0', 'node0', expect_error = True) 375 308 self.delBlockDriverState('node0', expect_error = True) 376 309 self.delBlockDriverState('mirror0', expect_error = True) 377 - self.wait_ready('drive0') 378 - self.completeBlockJob('drive0', 'node0', 'mirror0') 310 + self.wait_ready('node0') 311 + self.completeBlockJob('node0', 'node0', 'mirror0') 379 312 self.assert_no_active_block_jobs() 380 - self.checkBlockDriverState('node0', False) 381 - # This succeeds because the backend now points to mirror0 382 - self.delBlockBackend('drive0', 'mirror0') 313 + # This succeeds because the device now points to mirror0 314 + self.delBlockDriverState('node0') 315 + self.delBlockDriverState('mirror0', expect_error = True) 316 + self.delDeviceModel('device0', False) 317 + # FIXME mirror0 disappears, drive-mirror doesn't take a reference 318 + #self.delBlockDriverState('mirror0') 383 319 384 320 def testBlkDebug(self): 385 321 self.addBlkDebug('debug0', 'node0')
+2 -2
tests/qemu-iotests/139.out
··· 1 - ............ 1 + ......... 2 2 ---------------------------------------------------------------------- 3 - Ran 12 tests 3 + Ran 9 tests 4 4 5 5 OK