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