mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-10-15 15:32:51 +00:00
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>
This commit is contained in:
parent
eed875838e
commit
62acae8a9d
|
@ -31,6 +31,7 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
|
iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
|
||||||
self.vm = iotests.VM()
|
self.vm = iotests.VM()
|
||||||
|
self.vm.add_device("virtio-scsi-pci,id=virtio-scsi")
|
||||||
self.vm.launch()
|
self.vm.launch()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@ -39,18 +40,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
if os.path.isfile(new_img):
|
if os.path.isfile(new_img):
|
||||||
os.remove(new_img)
|
os.remove(new_img)
|
||||||
|
|
||||||
# Check whether a BlockBackend exists
|
|
||||||
def checkBlockBackend(self, backend, node, must_exist = True):
|
|
||||||
result = self.vm.qmp('query-block')
|
|
||||||
backends = filter(lambda x: x['device'] == backend, result['return'])
|
|
||||||
self.assertLessEqual(len(backends), 1)
|
|
||||||
self.assertEqual(must_exist, len(backends) == 1)
|
|
||||||
if must_exist:
|
|
||||||
if node:
|
|
||||||
self.assertEqual(backends[0]['inserted']['node-name'], node)
|
|
||||||
else:
|
|
||||||
self.assertFalse(backends[0].has_key('inserted'))
|
|
||||||
|
|
||||||
# Check whether a BlockDriverState exists
|
# Check whether a BlockDriverState exists
|
||||||
def checkBlockDriverState(self, node, must_exist = True):
|
def checkBlockDriverState(self, node, must_exist = True):
|
||||||
result = self.vm.qmp('query-named-block-nodes')
|
result = self.vm.qmp('query-named-block-nodes')
|
||||||
|
@ -58,24 +47,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
self.assertLessEqual(len(nodes), 1)
|
self.assertLessEqual(len(nodes), 1)
|
||||||
self.assertEqual(must_exist, len(nodes) == 1)
|
self.assertEqual(must_exist, len(nodes) == 1)
|
||||||
|
|
||||||
# Add a new BlockBackend (with its attached BlockDriverState)
|
|
||||||
def addBlockBackend(self, backend, node):
|
|
||||||
file_node = '%s_file' % node
|
|
||||||
self.checkBlockBackend(backend, node, False)
|
|
||||||
self.checkBlockDriverState(node, False)
|
|
||||||
self.checkBlockDriverState(file_node, False)
|
|
||||||
opts = {'driver': iotests.imgfmt,
|
|
||||||
'id': backend,
|
|
||||||
'node-name': node,
|
|
||||||
'file': {'driver': 'file',
|
|
||||||
'node-name': file_node,
|
|
||||||
'filename': base_img}}
|
|
||||||
result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
|
|
||||||
self.assert_qmp(result, 'return', {})
|
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
self.checkBlockDriverState(node)
|
|
||||||
self.checkBlockDriverState(file_node)
|
|
||||||
|
|
||||||
# Add a BlockDriverState without a BlockBackend
|
# Add a BlockDriverState without a BlockBackend
|
||||||
def addBlockDriverState(self, node):
|
def addBlockDriverState(self, node):
|
||||||
file_node = '%s_file' % node
|
file_node = '%s_file' % node
|
||||||
|
@ -105,23 +76,6 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
|
|
||||||
# Delete a BlockBackend
|
|
||||||
def delBlockBackend(self, backend, node, expect_error = False,
|
|
||||||
destroys_media = True):
|
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
if node:
|
|
||||||
self.checkBlockDriverState(node)
|
|
||||||
result = self.vm.qmp('x-blockdev-del', id = backend)
|
|
||||||
if expect_error:
|
|
||||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
|
||||||
if node:
|
|
||||||
self.checkBlockDriverState(node)
|
|
||||||
else:
|
|
||||||
self.assert_qmp(result, 'return', {})
|
|
||||||
if node:
|
|
||||||
self.checkBlockDriverState(node, not destroys_media)
|
|
||||||
self.checkBlockBackend(backend, node, must_exist = expect_error)
|
|
||||||
|
|
||||||
# Delete a BlockDriverState
|
# Delete a BlockDriverState
|
||||||
def delBlockDriverState(self, node, expect_error = False):
|
def delBlockDriverState(self, node, expect_error = False):
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
|
@ -133,51 +87,47 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
self.checkBlockDriverState(node, expect_error)
|
self.checkBlockDriverState(node, expect_error)
|
||||||
|
|
||||||
# Add a device model
|
# Add a device model
|
||||||
def addDeviceModel(self, device, backend):
|
def addDeviceModel(self, device, backend, driver = 'virtio-blk-pci'):
|
||||||
result = self.vm.qmp('device_add', id = device,
|
result = self.vm.qmp('device_add', id = device,
|
||||||
driver = 'virtio-blk-pci', drive = backend)
|
driver = driver, drive = backend)
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
# Delete a device model
|
# Delete a device model
|
||||||
def delDeviceModel(self, device):
|
def delDeviceModel(self, device, is_virtio_blk = True):
|
||||||
result = self.vm.qmp('device_del', id = device)
|
result = self.vm.qmp('device_del', id = device)
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
result = self.vm.qmp('system_reset')
|
result = self.vm.qmp('system_reset')
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
device_path = '/machine/peripheral/%s/virtio-backend' % device
|
if is_virtio_blk:
|
||||||
event = self.vm.event_wait(name="DEVICE_DELETED",
|
device_path = '/machine/peripheral/%s/virtio-backend' % device
|
||||||
match={'data': {'path': device_path}})
|
event = self.vm.event_wait(name="DEVICE_DELETED",
|
||||||
self.assertNotEqual(event, None)
|
match={'data': {'path': device_path}})
|
||||||
|
self.assertNotEqual(event, None)
|
||||||
|
|
||||||
event = self.vm.event_wait(name="DEVICE_DELETED",
|
event = self.vm.event_wait(name="DEVICE_DELETED",
|
||||||
match={'data': {'device': device}})
|
match={'data': {'device': device}})
|
||||||
self.assertNotEqual(event, None)
|
self.assertNotEqual(event, None)
|
||||||
|
|
||||||
# Remove a BlockDriverState
|
# Remove a BlockDriverState
|
||||||
def ejectDrive(self, backend, node, expect_error = False,
|
def ejectDrive(self, device, node, expect_error = False,
|
||||||
destroys_media = True):
|
destroys_media = True):
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
result = self.vm.qmp('eject', device = backend)
|
result = self.vm.qmp('eject', id = device)
|
||||||
if expect_error:
|
if expect_error:
|
||||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
self.assert_qmp(result, 'error/class', 'GenericError')
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
else:
|
else:
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.checkBlockDriverState(node, not destroys_media)
|
self.checkBlockDriverState(node, not destroys_media)
|
||||||
self.checkBlockBackend(backend, None)
|
|
||||||
|
|
||||||
# Insert a BlockDriverState
|
# Insert a BlockDriverState
|
||||||
def insertDrive(self, backend, node):
|
def insertDrive(self, device, node):
|
||||||
self.checkBlockBackend(backend, None)
|
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
result = self.vm.qmp('x-blockdev-insert-medium',
|
result = self.vm.qmp('x-blockdev-insert-medium',
|
||||||
device = backend, node_name = node)
|
id = device, node_name = node)
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
self.checkBlockDriverState(node)
|
self.checkBlockDriverState(node)
|
||||||
|
|
||||||
# Create a snapshot using 'blockdev-snapshot-sync'
|
# Create a snapshot using 'blockdev-snapshot-sync'
|
||||||
|
@ -204,26 +154,23 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
self.checkBlockDriverState(overlay)
|
self.checkBlockDriverState(overlay)
|
||||||
|
|
||||||
# Create a mirror
|
# Create a mirror
|
||||||
def createMirror(self, backend, node, new_node):
|
def createMirror(self, node, new_node):
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
self.checkBlockDriverState(new_node, False)
|
self.checkBlockDriverState(new_node, False)
|
||||||
opts = {'device': backend,
|
opts = {'device': node,
|
||||||
|
'job-id': node,
|
||||||
'target': new_img,
|
'target': new_img,
|
||||||
'node-name': new_node,
|
'node-name': new_node,
|
||||||
'sync': 'top',
|
'sync': 'top',
|
||||||
'format': iotests.imgfmt}
|
'format': iotests.imgfmt}
|
||||||
result = self.vm.qmp('drive-mirror', conv_keys=False, **opts)
|
result = self.vm.qmp('drive-mirror', conv_keys=False, **opts)
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.checkBlockBackend(backend, node)
|
|
||||||
self.checkBlockDriverState(new_node)
|
self.checkBlockDriverState(new_node)
|
||||||
|
|
||||||
# Complete an existing block job
|
# Complete an existing block job
|
||||||
def completeBlockJob(self, backend, node_before, node_after):
|
def completeBlockJob(self, id, node_before, node_after):
|
||||||
self.checkBlockBackend(backend, node_before)
|
result = self.vm.qmp('block-job-complete', device=id)
|
||||||
result = self.vm.qmp('block-job-complete', device=backend)
|
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
self.wait_until_completed(backend)
|
self.wait_until_completed(id)
|
||||||
self.checkBlockBackend(backend, node_after)
|
|
||||||
|
|
||||||
# Add a BlkDebug node
|
# Add a BlkDebug node
|
||||||
# Note that the purpose of this is to test the x-blockdev-del
|
# Note that the purpose of this is to test the x-blockdev-del
|
||||||
|
@ -297,89 +244,78 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||||
# The tests start here #
|
# The tests start here #
|
||||||
########################
|
########################
|
||||||
|
|
||||||
def testWrongParameters(self):
|
|
||||||
self.addBlockBackend('drive0', 'node0')
|
|
||||||
result = self.vm.qmp('x-blockdev-del')
|
|
||||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
|
||||||
result = self.vm.qmp('x-blockdev-del', id='drive0', node_name='node0')
|
|
||||||
self.assert_qmp(result, 'error/class', 'GenericError')
|
|
||||||
self.delBlockBackend('drive0', 'node0')
|
|
||||||
|
|
||||||
def testBlockBackend(self):
|
|
||||||
self.addBlockBackend('drive0', 'node0')
|
|
||||||
# You cannot delete a BDS that is attached to a backend
|
|
||||||
self.delBlockDriverState('node0', expect_error = True)
|
|
||||||
self.delBlockBackend('drive0', 'node0')
|
|
||||||
|
|
||||||
def testBlockDriverState(self):
|
def testBlockDriverState(self):
|
||||||
self.addBlockDriverState('node0')
|
self.addBlockDriverState('node0')
|
||||||
# You cannot delete a file BDS directly
|
# You cannot delete a file BDS directly
|
||||||
self.delBlockDriverState('node0_file', expect_error = True)
|
self.delBlockDriverState('node0_file', expect_error = True)
|
||||||
self.delBlockDriverState('node0')
|
self.delBlockDriverState('node0')
|
||||||
|
|
||||||
def testEject(self):
|
|
||||||
self.addBlockBackend('drive0', 'node0')
|
|
||||||
self.ejectDrive('drive0', 'node0')
|
|
||||||
self.delBlockBackend('drive0', None)
|
|
||||||
|
|
||||||
def testDeviceModel(self):
|
def testDeviceModel(self):
|
||||||
self.addBlockBackend('drive0', 'node0')
|
self.addBlockDriverState('node0')
|
||||||
self.addDeviceModel('device0', 'drive0')
|
self.addDeviceModel('device0', 'node0')
|
||||||
self.ejectDrive('drive0', 'node0', expect_error = True)
|
self.ejectDrive('device0', 'node0', expect_error = True)
|
||||||
self.delBlockBackend('drive0', 'node0', expect_error = True)
|
self.delBlockDriverState('node0', expect_error = True)
|
||||||
self.delDeviceModel('device0')
|
self.delDeviceModel('device0')
|
||||||
self.delBlockBackend('drive0', 'node0')
|
self.delBlockDriverState('node0')
|
||||||
|
|
||||||
def testAttachMedia(self):
|
def testAttachMedia(self):
|
||||||
# This creates a BlockBackend and removes its media
|
# This creates a BlockBackend and removes its media
|
||||||
self.addBlockBackend('drive0', 'node0')
|
self.addBlockDriverState('node0')
|
||||||
self.ejectDrive('drive0', 'node0')
|
self.addDeviceModel('device0', 'node0', 'scsi-cd')
|
||||||
# This creates a new BlockDriverState and inserts it into the backend
|
self.ejectDrive('device0', 'node0', destroys_media = False)
|
||||||
|
self.delBlockDriverState('node0')
|
||||||
|
|
||||||
|
# This creates a new BlockDriverState and inserts it into the device
|
||||||
self.addBlockDriverState('node1')
|
self.addBlockDriverState('node1')
|
||||||
self.insertDrive('drive0', 'node1')
|
self.insertDrive('device0', 'node1')
|
||||||
# The backend can't be removed: the new BDS has an extra reference
|
# The node can't be removed: the new device has an extra reference
|
||||||
self.delBlockBackend('drive0', 'node1', expect_error = True)
|
|
||||||
self.delBlockDriverState('node1', expect_error = True)
|
self.delBlockDriverState('node1', expect_error = True)
|
||||||
# The BDS still exists after being ejected, but now it can be removed
|
# The BDS still exists after being ejected, but now it can be removed
|
||||||
self.ejectDrive('drive0', 'node1', destroys_media = False)
|
self.ejectDrive('device0', 'node1', destroys_media = False)
|
||||||
self.delBlockDriverState('node1')
|
self.delBlockDriverState('node1')
|
||||||
self.delBlockBackend('drive0', None)
|
self.delDeviceModel('device0', False)
|
||||||
|
|
||||||
def testSnapshotSync(self):
|
def testSnapshotSync(self):
|
||||||
self.addBlockBackend('drive0', 'node0')
|
self.addBlockDriverState('node0')
|
||||||
|
self.addDeviceModel('device0', 'node0')
|
||||||
self.createSnapshotSync('node0', 'overlay0')
|
self.createSnapshotSync('node0', 'overlay0')
|
||||||
# This fails because node0 is now being used as a backing image
|
# This fails because node0 is now being used as a backing image
|
||||||
self.delBlockDriverState('node0', expect_error = True)
|
self.delBlockDriverState('node0', expect_error = True)
|
||||||
# This succeeds because overlay0 only has the backend reference
|
self.delBlockDriverState('overlay0', expect_error = True)
|
||||||
self.delBlockBackend('drive0', 'overlay0')
|
# This succeeds because device0 only has the backend reference
|
||||||
self.checkBlockDriverState('node0', False)
|
self.delDeviceModel('device0')
|
||||||
|
# FIXME Would still be there if blockdev-snapshot-sync took a ref
|
||||||
|
self.checkBlockDriverState('overlay0', False)
|
||||||
|
self.delBlockDriverState('node0')
|
||||||
|
|
||||||
def testSnapshot(self):
|
def testSnapshot(self):
|
||||||
self.addBlockBackend('drive0', 'node0')
|
self.addBlockDriverState('node0')
|
||||||
|
self.addDeviceModel('device0', 'node0', 'scsi-cd')
|
||||||
self.addBlockDriverStateOverlay('overlay0')
|
self.addBlockDriverStateOverlay('overlay0')
|
||||||
self.createSnapshot('node0', 'overlay0')
|
self.createSnapshot('node0', 'overlay0')
|
||||||
self.delBlockBackend('drive0', 'overlay0', expect_error = True)
|
|
||||||
self.delBlockDriverState('node0', expect_error = True)
|
self.delBlockDriverState('node0', expect_error = True)
|
||||||
self.delBlockDriverState('overlay0', expect_error = True)
|
self.delBlockDriverState('overlay0', expect_error = True)
|
||||||
self.ejectDrive('drive0', 'overlay0', destroys_media = False)
|
self.ejectDrive('device0', 'overlay0', destroys_media = False)
|
||||||
self.delBlockBackend('drive0', None)
|
|
||||||
self.delBlockDriverState('node0', expect_error = True)
|
self.delBlockDriverState('node0', expect_error = True)
|
||||||
self.delBlockDriverState('overlay0')
|
self.delBlockDriverState('overlay0')
|
||||||
self.checkBlockDriverState('node0', False)
|
self.delBlockDriverState('node0')
|
||||||
|
|
||||||
def testMirror(self):
|
def testMirror(self):
|
||||||
self.addBlockBackend('drive0', 'node0')
|
self.addBlockDriverState('node0')
|
||||||
self.createMirror('drive0', 'node0', 'mirror0')
|
self.addDeviceModel('device0', 'node0', 'scsi-cd')
|
||||||
|
self.createMirror('node0', 'mirror0')
|
||||||
# The block job prevents removing the device
|
# The block job prevents removing the device
|
||||||
self.delBlockBackend('drive0', 'node0', expect_error = True)
|
|
||||||
self.delBlockDriverState('node0', expect_error = True)
|
self.delBlockDriverState('node0', expect_error = True)
|
||||||
self.delBlockDriverState('mirror0', expect_error = True)
|
self.delBlockDriverState('mirror0', expect_error = True)
|
||||||
self.wait_ready('drive0')
|
self.wait_ready('node0')
|
||||||
self.completeBlockJob('drive0', 'node0', 'mirror0')
|
self.completeBlockJob('node0', 'node0', 'mirror0')
|
||||||
self.assert_no_active_block_jobs()
|
self.assert_no_active_block_jobs()
|
||||||
self.checkBlockDriverState('node0', False)
|
# This succeeds because the device now points to mirror0
|
||||||
# This succeeds because the backend now points to mirror0
|
self.delBlockDriverState('node0')
|
||||||
self.delBlockBackend('drive0', 'mirror0')
|
self.delBlockDriverState('mirror0', expect_error = True)
|
||||||
|
self.delDeviceModel('device0', False)
|
||||||
|
# FIXME mirror0 disappears, drive-mirror doesn't take a reference
|
||||||
|
#self.delBlockDriverState('mirror0')
|
||||||
|
|
||||||
def testBlkDebug(self):
|
def testBlkDebug(self):
|
||||||
self.addBlkDebug('debug0', 'node0')
|
self.addBlkDebug('debug0', 'node0')
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
............
|
.........
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Ran 12 tests
|
Ran 9 tests
|
||||||
|
|
||||||
OK
|
OK
|
||||||
|
|
Loading…
Reference in a new issue