]> git.proxmox.com Git - mirror_qemu.git/blame - tests/qemu-iotests/139
build: Remove --enable-gprof
[mirror_qemu.git] / tests / qemu-iotests / 139
CommitLineData
903cb1bf 1#!/usr/bin/env python3
9dd003a9 2# group: rw quick
342075fd 3#
79b7a77e 4# Test cases for the QMP 'blockdev-del' command
342075fd
AG
5#
6# Copyright (C) 2015 Igalia, S.L.
7# Author: Alberto Garcia <berto@igalia.com>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21#
22
23import os
24import iotests
25import time
26
27base_img = os.path.join(iotests.test_dir, 'base.img')
28new_img = os.path.join(iotests.test_dir, 'new.img')
29
30class TestBlockdevDel(iotests.QMPTestCase):
31
32 def setUp(self):
33 iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
34 self.vm = iotests.VM()
22329f0d 35 self.vm.add_device("{},id=virtio-scsi".format('virtio-scsi'))
342075fd
AG
36 self.vm.launch()
37
38 def tearDown(self):
39 self.vm.shutdown()
40 os.remove(base_img)
41 if os.path.isfile(new_img):
42 os.remove(new_img)
43
342075fd
AG
44 # Check whether a BlockDriverState exists
45 def checkBlockDriverState(self, node, must_exist = True):
46 result = self.vm.qmp('query-named-block-nodes')
68474776 47 nodes = [x for x in result['return'] if x['node-name'] == node]
342075fd
AG
48 self.assertLessEqual(len(nodes), 1)
49 self.assertEqual(must_exist, len(nodes) == 1)
50
342075fd
AG
51 # Add a BlockDriverState without a BlockBackend
52 def addBlockDriverState(self, node):
53 file_node = '%s_file' % node
54 self.checkBlockDriverState(node, False)
55 self.checkBlockDriverState(file_node, False)
56 opts = {'driver': iotests.imgfmt,
57 'node-name': node,
58 'file': {'driver': 'file',
59 'node-name': file_node,
60 'filename': base_img}}
0153d2f5 61 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
342075fd
AG
62 self.assert_qmp(result, 'return', {})
63 self.checkBlockDriverState(node)
64 self.checkBlockDriverState(file_node)
65
66 # Add a BlockDriverState that will be used as overlay for the base_img BDS
67 def addBlockDriverStateOverlay(self, node):
68 self.checkBlockDriverState(node, False)
6e6e55f5 69 iotests.qemu_img('create', '-u', '-f', iotests.imgfmt,
b66ff2c2 70 '-b', base_img, '-F', iotests.imgfmt, new_img, '1M')
342075fd
AG
71 opts = {'driver': iotests.imgfmt,
72 'node-name': node,
c42e8742 73 'backing': None,
342075fd
AG
74 'file': {'driver': 'file',
75 'filename': new_img}}
0153d2f5 76 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
342075fd
AG
77 self.assert_qmp(result, 'return', {})
78 self.checkBlockDriverState(node)
79
342075fd
AG
80 # Delete a BlockDriverState
81 def delBlockDriverState(self, node, expect_error = False):
82 self.checkBlockDriverState(node)
79b7a77e 83 result = self.vm.qmp('blockdev-del', node_name = node)
342075fd
AG
84 if expect_error:
85 self.assert_qmp(result, 'error/class', 'GenericError')
86 else:
87 self.assert_qmp(result, 'return', {})
88 self.checkBlockDriverState(node, expect_error)
89
90 # Add a device model
22329f0d 91 def addDeviceModel(self, device, backend, driver = 'virtio-blk'):
342075fd 92 result = self.vm.qmp('device_add', id = device,
62acae8a 93 driver = driver, drive = backend)
342075fd
AG
94 self.assert_qmp(result, 'return', {})
95
96 # Delete a device model
62acae8a 97 def delDeviceModel(self, device, is_virtio_blk = True):
342075fd
AG
98 result = self.vm.qmp('device_del', id = device)
99 self.assert_qmp(result, 'return', {})
100
101 result = self.vm.qmp('system_reset')
102 self.assert_qmp(result, 'return', {})
103
62acae8a
KW
104 if is_virtio_blk:
105 device_path = '/machine/peripheral/%s/virtio-backend' % device
106 event = self.vm.event_wait(name="DEVICE_DELETED",
107 match={'data': {'path': device_path}})
108 self.assertNotEqual(event, None)
342075fd
AG
109
110 event = self.vm.event_wait(name="DEVICE_DELETED",
111 match={'data': {'device': device}})
112 self.assertNotEqual(event, None)
113
114 # Remove a BlockDriverState
62acae8a 115 def ejectDrive(self, device, node, expect_error = False,
342075fd 116 destroys_media = True):
342075fd 117 self.checkBlockDriverState(node)
62acae8a 118 result = self.vm.qmp('eject', id = device)
342075fd
AG
119 if expect_error:
120 self.assert_qmp(result, 'error/class', 'GenericError')
121 self.checkBlockDriverState(node)
342075fd
AG
122 else:
123 self.assert_qmp(result, 'return', {})
124 self.checkBlockDriverState(node, not destroys_media)
342075fd
AG
125
126 # Insert a BlockDriverState
62acae8a 127 def insertDrive(self, device, node):
342075fd 128 self.checkBlockDriverState(node)
34ce1111 129 result = self.vm.qmp('blockdev-insert-medium',
62acae8a 130 id = device, node_name = node)
342075fd 131 self.assert_qmp(result, 'return', {})
342075fd
AG
132 self.checkBlockDriverState(node)
133
134 # Create a snapshot using 'blockdev-snapshot-sync'
135 def createSnapshotSync(self, node, overlay):
136 self.checkBlockDriverState(node)
137 self.checkBlockDriverState(overlay, False)
138 opts = {'node-name': node,
139 'snapshot-file': new_img,
140 'snapshot-node-name': overlay,
141 'format': iotests.imgfmt}
142 result = self.vm.qmp('blockdev-snapshot-sync', conv_keys=False, **opts)
143 self.assert_qmp(result, 'return', {})
144 self.checkBlockDriverState(node)
145 self.checkBlockDriverState(overlay)
146
147 # Create a snapshot using 'blockdev-snapshot'
148 def createSnapshot(self, node, overlay):
149 self.checkBlockDriverState(node)
150 self.checkBlockDriverState(overlay)
151 result = self.vm.qmp('blockdev-snapshot',
152 node = node, overlay = overlay)
153 self.assert_qmp(result, 'return', {})
154 self.checkBlockDriverState(node)
155 self.checkBlockDriverState(overlay)
156
157 # Create a mirror
62acae8a 158 def createMirror(self, node, new_node):
342075fd 159 self.checkBlockDriverState(new_node, False)
62acae8a
KW
160 opts = {'device': node,
161 'job-id': node,
342075fd
AG
162 'target': new_img,
163 'node-name': new_node,
164 'sync': 'top',
165 'format': iotests.imgfmt}
166 result = self.vm.qmp('drive-mirror', conv_keys=False, **opts)
167 self.assert_qmp(result, 'return', {})
342075fd
AG
168 self.checkBlockDriverState(new_node)
169
170 # Complete an existing block job
62acae8a
KW
171 def completeBlockJob(self, id, node_before, node_after):
172 result = self.vm.qmp('block-job-complete', device=id)
342075fd 173 self.assert_qmp(result, 'return', {})
62acae8a 174 self.wait_until_completed(id)
342075fd
AG
175
176 # Add a BlkDebug node
79b7a77e 177 # Note that the purpose of this is to test the blockdev-del
342075fd
AG
178 # sanity checks, not to create a usable blkdebug drive
179 def addBlkDebug(self, debug, node):
180 self.checkBlockDriverState(node, False)
181 self.checkBlockDriverState(debug, False)
182 image = {'driver': iotests.imgfmt,
183 'node-name': node,
184 'file': {'driver': 'file',
185 'filename': base_img}}
186 opts = {'driver': 'blkdebug',
187 'node-name': debug,
188 'image': image}
0153d2f5 189 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
342075fd
AG
190 self.assert_qmp(result, 'return', {})
191 self.checkBlockDriverState(node)
192 self.checkBlockDriverState(debug)
193
194 # Add a BlkVerify node
79b7a77e 195 # Note that the purpose of this is to test the blockdev-del
342075fd
AG
196 # sanity checks, not to create a usable blkverify drive
197 def addBlkVerify(self, blkverify, test, raw):
198 self.checkBlockDriverState(test, False)
199 self.checkBlockDriverState(raw, False)
200 self.checkBlockDriverState(blkverify, False)
201 iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M')
202 node_0 = {'driver': iotests.imgfmt,
203 'node-name': test,
204 'file': {'driver': 'file',
205 'filename': base_img}}
206 node_1 = {'driver': iotests.imgfmt,
207 'node-name': raw,
208 'file': {'driver': 'file',
209 'filename': new_img}}
210 opts = {'driver': 'blkverify',
211 'node-name': blkverify,
212 'test': node_0,
213 'raw': node_1}
0153d2f5 214 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
342075fd
AG
215 self.assert_qmp(result, 'return', {})
216 self.checkBlockDriverState(test)
217 self.checkBlockDriverState(raw)
218 self.checkBlockDriverState(blkverify)
219
220 # Add a Quorum node
221 def addQuorum(self, quorum, child0, child1):
222 self.checkBlockDriverState(child0, False)
223 self.checkBlockDriverState(child1, False)
224 self.checkBlockDriverState(quorum, False)
225 iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M')
226 child_0 = {'driver': iotests.imgfmt,
227 'node-name': child0,
228 'file': {'driver': 'file',
229 'filename': base_img}}
230 child_1 = {'driver': iotests.imgfmt,
231 'node-name': child1,
232 'file': {'driver': 'file',
233 'filename': new_img}}
234 opts = {'driver': 'quorum',
235 'node-name': quorum,
236 'vote-threshold': 1,
237 'children': [ child_0, child_1 ]}
0153d2f5 238 result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
342075fd
AG
239 self.assert_qmp(result, 'return', {})
240 self.checkBlockDriverState(child0)
241 self.checkBlockDriverState(child1)
242 self.checkBlockDriverState(quorum)
243
244 ########################
245 # The tests start here #
246 ########################
247
342075fd
AG
248 def testBlockDriverState(self):
249 self.addBlockDriverState('node0')
250 # You cannot delete a file BDS directly
251 self.delBlockDriverState('node0_file', expect_error = True)
252 self.delBlockDriverState('node0')
253
342075fd 254 def testDeviceModel(self):
62acae8a
KW
255 self.addBlockDriverState('node0')
256 self.addDeviceModel('device0', 'node0')
257 self.ejectDrive('device0', 'node0', expect_error = True)
258 self.delBlockDriverState('node0', expect_error = True)
342075fd 259 self.delDeviceModel('device0')
62acae8a 260 self.delBlockDriverState('node0')
342075fd
AG
261
262 def testAttachMedia(self):
263 # This creates a BlockBackend and removes its media
62acae8a
KW
264 self.addBlockDriverState('node0')
265 self.addDeviceModel('device0', 'node0', 'scsi-cd')
266 self.ejectDrive('device0', 'node0', destroys_media = False)
267 self.delBlockDriverState('node0')
268
269 # This creates a new BlockDriverState and inserts it into the device
342075fd 270 self.addBlockDriverState('node1')
62acae8a
KW
271 self.insertDrive('device0', 'node1')
272 # The node can't be removed: the new device has an extra reference
342075fd
AG
273 self.delBlockDriverState('node1', expect_error = True)
274 # The BDS still exists after being ejected, but now it can be removed
62acae8a 275 self.ejectDrive('device0', 'node1', destroys_media = False)
342075fd 276 self.delBlockDriverState('node1')
62acae8a 277 self.delDeviceModel('device0', False)
342075fd
AG
278
279 def testSnapshotSync(self):
62acae8a
KW
280 self.addBlockDriverState('node0')
281 self.addDeviceModel('device0', 'node0')
342075fd
AG
282 self.createSnapshotSync('node0', 'overlay0')
283 # This fails because node0 is now being used as a backing image
284 self.delBlockDriverState('node0', expect_error = True)
62acae8a
KW
285 self.delBlockDriverState('overlay0', expect_error = True)
286 # This succeeds because device0 only has the backend reference
287 self.delDeviceModel('device0')
288 # FIXME Would still be there if blockdev-snapshot-sync took a ref
289 self.checkBlockDriverState('overlay0', False)
290 self.delBlockDriverState('node0')
342075fd
AG
291
292 def testSnapshot(self):
62acae8a
KW
293 self.addBlockDriverState('node0')
294 self.addDeviceModel('device0', 'node0', 'scsi-cd')
342075fd
AG
295 self.addBlockDriverStateOverlay('overlay0')
296 self.createSnapshot('node0', 'overlay0')
342075fd
AG
297 self.delBlockDriverState('node0', expect_error = True)
298 self.delBlockDriverState('overlay0', expect_error = True)
62acae8a 299 self.ejectDrive('device0', 'overlay0', destroys_media = False)
342075fd
AG
300 self.delBlockDriverState('node0', expect_error = True)
301 self.delBlockDriverState('overlay0')
62acae8a 302 self.delBlockDriverState('node0')
342075fd
AG
303
304 def testMirror(self):
62acae8a
KW
305 self.addBlockDriverState('node0')
306 self.addDeviceModel('device0', 'node0', 'scsi-cd')
307 self.createMirror('node0', 'mirror0')
342075fd 308 # The block job prevents removing the device
342075fd
AG
309 self.delBlockDriverState('node0', expect_error = True)
310 self.delBlockDriverState('mirror0', expect_error = True)
62acae8a
KW
311 self.wait_ready('node0')
312 self.completeBlockJob('node0', 'node0', 'mirror0')
342075fd 313 self.assert_no_active_block_jobs()
62acae8a
KW
314 # This succeeds because the device now points to mirror0
315 self.delBlockDriverState('node0')
316 self.delBlockDriverState('mirror0', expect_error = True)
317 self.delDeviceModel('device0', False)
318 # FIXME mirror0 disappears, drive-mirror doesn't take a reference
319 #self.delBlockDriverState('mirror0')
342075fd 320
d9df28e7 321 @iotests.skip_if_unsupported(['blkdebug'])
342075fd
AG
322 def testBlkDebug(self):
323 self.addBlkDebug('debug0', 'node0')
324 # 'node0' is used by the blkdebug node
325 self.delBlockDriverState('node0', expect_error = True)
326 # But we can remove the blkdebug node directly
327 self.delBlockDriverState('debug0')
328 self.checkBlockDriverState('node0', False)
329
d9df28e7 330 @iotests.skip_if_unsupported(['blkverify'])
342075fd
AG
331 def testBlkVerify(self):
332 self.addBlkVerify('verify0', 'node0', 'node1')
333 # We cannot remove the children of a blkverify device
334 self.delBlockDriverState('node0', expect_error = True)
335 self.delBlockDriverState('node1', expect_error = True)
336 # But we can remove the blkverify node directly
337 self.delBlockDriverState('verify0')
338 self.checkBlockDriverState('node0', False)
339 self.checkBlockDriverState('node1', False)
340
d9df28e7 341 @iotests.skip_if_unsupported(['quorum'])
342075fd
AG
342 def testQuorum(self):
343 self.addQuorum('quorum0', 'node0', 'node1')
344 # We cannot remove the children of a Quorum device
345 self.delBlockDriverState('node0', expect_error = True)
346 self.delBlockDriverState('node1', expect_error = True)
347 # But we can remove the Quorum node directly
348 self.delBlockDriverState('quorum0')
349 self.checkBlockDriverState('node0', False)
350 self.checkBlockDriverState('node1', False)
351
352
353if __name__ == '__main__':
103cbc77
HR
354 iotests.main(supported_fmts=["qcow2"],
355 supported_protocols=["file"])