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