xref: /openbmc/qemu/tests/qemu-iotests/118 (revision 014bb4b0e545b70f903adcdf6f118351b7cfaf7b)
1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3
29dd003a9SVladimir Sementsov-Ogievskiy# group: rw
3adfe2030SMax Reitz#
4*014bb4b0SMax Reitz# Test case for media change monitor commands
5adfe2030SMax Reitz#
6adfe2030SMax Reitz# Copyright (C) 2015 Red Hat, Inc.
7adfe2030SMax Reitz#
8adfe2030SMax Reitz# This program is free software; you can redistribute it and/or modify
9adfe2030SMax Reitz# it under the terms of the GNU General Public License as published by
10adfe2030SMax Reitz# the Free Software Foundation; either version 2 of the License, or
11adfe2030SMax Reitz# (at your option) any later version.
12adfe2030SMax Reitz#
13adfe2030SMax Reitz# This program is distributed in the hope that it will be useful,
14adfe2030SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of
15adfe2030SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16adfe2030SMax Reitz# GNU General Public License for more details.
17adfe2030SMax Reitz#
18adfe2030SMax Reitz# You should have received a copy of the GNU General Public License
19adfe2030SMax Reitz# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20adfe2030SMax Reitz#
21adfe2030SMax Reitz
22adfe2030SMax Reitzimport os
23adfe2030SMax Reitzimport stat
24adfe2030SMax Reitzimport time
25adfe2030SMax Reitzimport iotests
26adfe2030SMax Reitzfrom iotests import qemu_img
27adfe2030SMax Reitz
28adfe2030SMax Reitzold_img = os.path.join(iotests.test_dir, 'test0.img')
29adfe2030SMax Reitznew_img = os.path.join(iotests.test_dir, 'test1.img')
30adfe2030SMax Reitz
311d701e0eSMax Reitzdef interface_to_device_name(interface):
321d701e0eSMax Reitz    if interface == 'ide':
331d701e0eSMax Reitz        return 'ide-cd'
341d701e0eSMax Reitz    elif interface == 'floppy':
351d701e0eSMax Reitz        return 'floppy'
36dfa26a11SKevin Wolf    elif interface == 'scsi':
37dfa26a11SKevin Wolf        return 'scsi-cd'
381d701e0eSMax Reitz    else:
391d701e0eSMax Reitz        return None
401d701e0eSMax Reitz
41adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase):
42adfe2030SMax Reitz    has_opened = False
43adfe2030SMax Reitz    has_closed = False
44adfe2030SMax Reitz
4519462c4bSKevin Wolf    device_name = 'qdev0'
4619462c4bSKevin Wolf    use_drive = False
4719462c4bSKevin Wolf
48adfe2030SMax Reitz    def process_events(self):
49adfe2030SMax Reitz        for event in self.vm.get_qmp_events(wait=False):
50adfe2030SMax Reitz            if (event['event'] == 'DEVICE_TRAY_MOVED' and
5119462c4bSKevin Wolf                (event['data']['device'] == 'drive0' or
5219462c4bSKevin Wolf                 event['data']['id'] == self.device_name)):
53adfe2030SMax Reitz                if event['data']['tray-open'] == False:
54adfe2030SMax Reitz                    self.has_closed = True
55adfe2030SMax Reitz                else:
56adfe2030SMax Reitz                    self.has_opened = True
57adfe2030SMax Reitz
58adfe2030SMax Reitz    def wait_for_open(self):
59abb3e55bSMax Reitz        if not self.has_real_tray:
60abb3e55bSMax Reitz            return
61abb3e55bSMax Reitz
62d8336c6bSKevin Wolf        with iotests.Timeout(3, 'Timeout while waiting for the tray to open'):
63d8336c6bSKevin Wolf            while not self.has_opened:
64adfe2030SMax Reitz                self.process_events()
65adfe2030SMax Reitz
66adfe2030SMax Reitz    def wait_for_close(self):
67abb3e55bSMax Reitz        if not self.has_real_tray:
68abb3e55bSMax Reitz            return
69abb3e55bSMax Reitz
70d8336c6bSKevin Wolf        with iotests.Timeout(3, 'Timeout while waiting for the tray to close'):
71d8336c6bSKevin Wolf            while not self.has_closed:
72adfe2030SMax Reitz                self.process_events()
73adfe2030SMax Reitz
74adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass):
75486b88bdSKevin Wolf
76adfe2030SMax Reitz    def test_blockdev_change_medium(self):
77486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium',
78486b88bdSKevin Wolf                             id=self.device_name, filename=new_img,
79adfe2030SMax Reitz                             format=iotests.imgfmt)
80486b88bdSKevin Wolf
81adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
82adfe2030SMax Reitz
83adfe2030SMax Reitz        self.wait_for_open()
84adfe2030SMax Reitz        self.wait_for_close()
85adfe2030SMax Reitz
86adfe2030SMax Reitz        result = self.vm.qmp('query-block')
87abb3e55bSMax Reitz        if self.has_real_tray:
88adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
89adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
90adfe2030SMax Reitz
91adfe2030SMax Reitz    def test_eject(self):
92486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
93adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
94adfe2030SMax Reitz
95adfe2030SMax Reitz        self.wait_for_open()
96adfe2030SMax Reitz
97adfe2030SMax Reitz        result = self.vm.qmp('query-block')
98abb3e55bSMax Reitz        if self.has_real_tray:
99adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
100adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
101adfe2030SMax Reitz
102adfe2030SMax Reitz    def test_tray_eject_change(self):
103486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
104adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
105adfe2030SMax Reitz
106adfe2030SMax Reitz        self.wait_for_open()
107adfe2030SMax Reitz
108adfe2030SMax Reitz        result = self.vm.qmp('query-block')
109abb3e55bSMax Reitz        if self.has_real_tray:
110adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
111adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
112adfe2030SMax Reitz
113486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
114486b88bdSKevin Wolf                             filename=new_img, format=iotests.imgfmt)
115adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
116adfe2030SMax Reitz
117adfe2030SMax Reitz        self.wait_for_close()
118adfe2030SMax Reitz
119adfe2030SMax Reitz        result = self.vm.qmp('query-block')
120abb3e55bSMax Reitz        if self.has_real_tray:
121adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
122adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
123adfe2030SMax Reitz
124adfe2030SMax Reitz    def test_tray_open_close(self):
125486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
126486b88bdSKevin Wolf                             id=self.device_name, force=True)
127adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
128adfe2030SMax Reitz
129adfe2030SMax Reitz        self.wait_for_open()
130adfe2030SMax Reitz
131adfe2030SMax Reitz        result = self.vm.qmp('query-block')
132abb3e55bSMax Reitz        if self.has_real_tray:
133adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
134adfe2030SMax Reitz        if self.was_empty == True:
135adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
136adfe2030SMax Reitz        else:
137adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
138adfe2030SMax Reitz
139486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
140adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
141adfe2030SMax Reitz
142adfe2030SMax Reitz        if self.has_real_tray or not self.was_empty:
143adfe2030SMax Reitz            self.wait_for_close()
144adfe2030SMax Reitz
145adfe2030SMax Reitz        result = self.vm.qmp('query-block')
146abb3e55bSMax Reitz        if self.has_real_tray:
147adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
148adfe2030SMax Reitz        if self.was_empty == True:
149adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
150adfe2030SMax Reitz        else:
151adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
152adfe2030SMax Reitz
153adfe2030SMax Reitz    def test_tray_eject_close(self):
1541d701e0eSMax Reitz        result = self.vm.qmp('eject', id=self.device_name, force=True)
155adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
156adfe2030SMax Reitz
157adfe2030SMax Reitz        self.wait_for_open()
158adfe2030SMax Reitz
159adfe2030SMax Reitz        result = self.vm.qmp('query-block')
160abb3e55bSMax Reitz        if self.has_real_tray:
161adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
162adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
163adfe2030SMax Reitz
164486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
165adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
166adfe2030SMax Reitz
167adfe2030SMax Reitz        self.wait_for_close()
168adfe2030SMax Reitz
169adfe2030SMax Reitz        result = self.vm.qmp('query-block')
170adfe2030SMax Reitz        if self.has_real_tray:
171adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
172adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
173adfe2030SMax Reitz
174adfe2030SMax Reitz    def test_tray_open_change(self):
1751d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name,
1761d701e0eSMax Reitz                                                   force=True)
177adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
178adfe2030SMax Reitz
179adfe2030SMax Reitz        self.wait_for_open()
180adfe2030SMax Reitz
181adfe2030SMax Reitz        result = self.vm.qmp('query-block')
182abb3e55bSMax Reitz        if self.has_real_tray:
183adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
184adfe2030SMax Reitz        if self.was_empty == True:
185adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
186adfe2030SMax Reitz        else:
187adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
188adfe2030SMax Reitz
1891d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
190adfe2030SMax Reitz                                                       filename=new_img,
191adfe2030SMax Reitz                                                       format=iotests.imgfmt)
192adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
193adfe2030SMax Reitz
194adfe2030SMax Reitz        self.wait_for_close()
195adfe2030SMax Reitz
196adfe2030SMax Reitz        result = self.vm.qmp('query-block')
197abb3e55bSMax Reitz        if self.has_real_tray:
198adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
199adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
200adfe2030SMax Reitz
20168174160SKevin Wolf    def test_cycle(self, read_only_node=False):
202adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2030153d2f5SKevin Wolf                             node_name='new',
2040153d2f5SKevin Wolf                             driver=iotests.imgfmt,
20568174160SKevin Wolf                             read_only=read_only_node,
2060153d2f5SKevin Wolf                             file={'filename': new_img,
2070153d2f5SKevin Wolf                                    'driver': 'file'})
208adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
209adfe2030SMax Reitz
210486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
211486b88bdSKevin Wolf                             id=self.device_name, force=True)
212adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
213adfe2030SMax Reitz
214adfe2030SMax Reitz        self.wait_for_open()
215adfe2030SMax Reitz
216adfe2030SMax Reitz        result = self.vm.qmp('query-block')
217abb3e55bSMax Reitz        if self.has_real_tray:
218adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
219adfe2030SMax Reitz        if self.was_empty == True:
220adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
221adfe2030SMax Reitz        else:
222adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
223adfe2030SMax Reitz
22434ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium',
225486b88bdSKevin Wolf                             id=self.device_name)
226adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
227adfe2030SMax Reitz
228adfe2030SMax Reitz        result = self.vm.qmp('query-block')
229abb3e55bSMax Reitz        if self.has_real_tray:
230adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
231adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
232adfe2030SMax Reitz
23334ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium',
234486b88bdSKevin Wolf                             id=self.device_name, node_name='new')
235adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
236adfe2030SMax Reitz
237adfe2030SMax Reitz        result = self.vm.qmp('query-block')
238abb3e55bSMax Reitz        if self.has_real_tray:
239adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
240adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
241adfe2030SMax Reitz
242486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
243adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
244adfe2030SMax Reitz
245adfe2030SMax Reitz        self.wait_for_close()
246adfe2030SMax Reitz
247adfe2030SMax Reitz        result = self.vm.qmp('query-block')
248abb3e55bSMax Reitz        if self.has_real_tray:
249adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
250adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
251adfe2030SMax Reitz
25268174160SKevin Wolf    def test_cycle_read_only_media(self):
25368174160SKevin Wolf        self.test_cycle(True)
25468174160SKevin Wolf
255adfe2030SMax Reitz    def test_close_on_closed(self):
2561d701e0eSMax Reitz        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
257adfe2030SMax Reitz        # Should be a no-op
258adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
259fa1cfb40SKevin Wolf        self.assertEqual(self.vm.get_qmp_events(wait=False), [])
260adfe2030SMax Reitz
261adfe2030SMax Reitz    def test_remove_on_closed(self):
262abb3e55bSMax Reitz        if not self.has_real_tray:
263adfe2030SMax Reitz            return
264adfe2030SMax Reitz
26534ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
266adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
267adfe2030SMax Reitz
268adfe2030SMax Reitz    def test_insert_on_closed(self):
269abb3e55bSMax Reitz        if not self.has_real_tray:
270adfe2030SMax Reitz            return
271adfe2030SMax Reitz
272adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2730153d2f5SKevin Wolf                             node_name='new',
2740153d2f5SKevin Wolf                             driver=iotests.imgfmt,
2750153d2f5SKevin Wolf                             file={'filename': new_img,
2760153d2f5SKevin Wolf                                   'driver': 'file'})
277adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
278adfe2030SMax Reitz
27934ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
280adfe2030SMax Reitz                                                       node_name='new')
281adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
282adfe2030SMax Reitz
283adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass):
284adfe2030SMax Reitz    was_empty = False
285adfe2030SMax Reitz
286dfc82894SKevin Wolf    def setUp(self):
287adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
288adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
289486b88bdSKevin Wolf        self.vm = iotests.VM()
29019462c4bSKevin Wolf        if self.use_drive:
291dfc82894SKevin Wolf            self.vm.add_drive(old_img, 'media=%s' % self.media, 'none')
29219462c4bSKevin Wolf        else:
29319462c4bSKevin Wolf            self.vm.add_blockdev([ 'node-name=drive0',
29419462c4bSKevin Wolf                                   'driver=%s' % iotests.imgfmt,
29519462c4bSKevin Wolf                                   'file.driver=file',
29619462c4bSKevin Wolf                                   'file.filename=%s' % old_img ])
297dfc82894SKevin Wolf        if self.interface == 'scsi':
298dfa26a11SKevin Wolf            self.vm.add_device('virtio-scsi-pci')
2991d701e0eSMax Reitz        self.vm.add_device('%s,drive=drive0,id=%s' %
300dfc82894SKevin Wolf                           (interface_to_device_name(self.interface),
3011d701e0eSMax Reitz                            self.device_name))
302adfe2030SMax Reitz        self.vm.launch()
303adfe2030SMax Reitz
304adfe2030SMax Reitz    def tearDown(self):
305adfe2030SMax Reitz        self.vm.shutdown()
306adfe2030SMax Reitz        os.remove(old_img)
307adfe2030SMax Reitz        os.remove(new_img)
308adfe2030SMax Reitz
309adfe2030SMax Reitz    def test_insert_on_filled(self):
310adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
3110153d2f5SKevin Wolf                             node_name='new',
3120153d2f5SKevin Wolf                             driver=iotests.imgfmt,
3130153d2f5SKevin Wolf                             file={'filename': new_img,
3140153d2f5SKevin Wolf                                   'driver': 'file'})
315adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
316adfe2030SMax Reitz
3171d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
318adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
319adfe2030SMax Reitz
320adfe2030SMax Reitz        self.wait_for_open()
321adfe2030SMax Reitz
32234ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
323adfe2030SMax Reitz                                                       node_name='new')
324adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
325adfe2030SMax Reitz
326adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass):
327adfe2030SMax Reitz    was_empty = True
328adfe2030SMax Reitz
329dfc82894SKevin Wolf    def setUp(self):
330adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
33119462c4bSKevin Wolf        self.vm = iotests.VM()
33219462c4bSKevin Wolf        if self.use_drive:
33319462c4bSKevin Wolf            self.vm.add_drive(None, 'media=%s' % self.media, 'none')
334dfc82894SKevin Wolf        if self.interface == 'scsi':
335dfa26a11SKevin Wolf            self.vm.add_device('virtio-scsi-pci')
33619462c4bSKevin Wolf        self.vm.add_device('%s,%sid=%s' %
337dfc82894SKevin Wolf                           (interface_to_device_name(self.interface),
33819462c4bSKevin Wolf                            'drive=drive0,' if self.use_drive else '',
3391d701e0eSMax Reitz                            self.device_name))
340adfe2030SMax Reitz        self.vm.launch()
341adfe2030SMax Reitz
342adfe2030SMax Reitz    def tearDown(self):
343adfe2030SMax Reitz        self.vm.shutdown()
344adfe2030SMax Reitz        os.remove(new_img)
345adfe2030SMax Reitz
346adfe2030SMax Reitz    def test_remove_on_empty(self):
3471d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
348adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
349adfe2030SMax Reitz
350adfe2030SMax Reitz        self.wait_for_open()
351adfe2030SMax Reitz
35234ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
353adfe2030SMax Reitz        # Should be a no-op
354adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
355adfe2030SMax Reitz
356dfc82894SKevin Wolf# Do this in a function to avoid leaking variables like case into the global
357dfc82894SKevin Wolf# name space (otherwise tests would be run for the abstract base classes)
358dfc82894SKevin Wolfdef create_basic_test_classes():
359dfc82894SKevin Wolf    for (media, interface, has_real_tray) in [ ('cdrom', 'ide', True),
360dfc82894SKevin Wolf                                               ('cdrom', 'scsi', True),
361dfc82894SKevin Wolf                                               ('disk', 'floppy', False) ]:
362adfe2030SMax Reitz
363dfc82894SKevin Wolf        for case in [ TestInitiallyFilled, TestInitiallyEmpty ]:
36419462c4bSKevin Wolf            for use_drive in [ True, False ]:
365dfc82894SKevin Wolf                attr = { 'media': media,
366dfc82894SKevin Wolf                         'interface': interface,
36719462c4bSKevin Wolf                         'has_real_tray': has_real_tray,
36819462c4bSKevin Wolf                         'use_drive': use_drive }
369adfe2030SMax Reitz
37019462c4bSKevin Wolf                name = '%s_%s_%s_%s' % (case.__name__, media, interface,
37119462c4bSKevin Wolf                                        'drive' if use_drive else 'blockdev')
372dfc82894SKevin Wolf                globals()[name] = type(name, (case, ), attr)
373adfe2030SMax Reitz
374dfc82894SKevin Wolfcreate_basic_test_classes()
375adfe2030SMax Reitz
376adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass):
3771d701e0eSMax Reitz    device_name = 'qdev0'
3781d701e0eSMax Reitz
379adfe2030SMax Reitz    def setUp(self):
380adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
381adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
382adfe2030SMax Reitz        self.vm = iotests.VM()
383adfe2030SMax Reitz
384adfe2030SMax Reitz    def tearDown(self):
385adfe2030SMax Reitz        self.vm.shutdown()
3864803c5cdSEduardo Habkost        os.chmod(old_img, 0o666)
3874803c5cdSEduardo Habkost        os.chmod(new_img, 0o666)
388adfe2030SMax Reitz        os.remove(old_img)
389adfe2030SMax Reitz        os.remove(new_img)
390adfe2030SMax Reitz
391adfe2030SMax Reitz    def test_ro_ro_retain(self):
3924803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
3934803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
3941d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
3951d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
396adfe2030SMax Reitz        self.vm.launch()
397adfe2030SMax Reitz
398adfe2030SMax Reitz        result = self.vm.qmp('query-block')
399adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
400adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
401adfe2030SMax Reitz
4021d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
403adfe2030SMax Reitz                                                       filename=new_img,
404adfe2030SMax Reitz                                                       format=iotests.imgfmt,
405adfe2030SMax Reitz                                                       read_only_mode='retain')
406adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
407adfe2030SMax Reitz
408adfe2030SMax Reitz        result = self.vm.qmp('query-block')
409adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
410adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
411adfe2030SMax Reitz
412adfe2030SMax Reitz    def test_ro_rw_retain(self):
4134803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4141d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4151d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
416adfe2030SMax Reitz        self.vm.launch()
417adfe2030SMax Reitz
418adfe2030SMax Reitz        result = self.vm.qmp('query-block')
419adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
420adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
421adfe2030SMax Reitz
4221d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
423adfe2030SMax Reitz                                                       filename=new_img,
424adfe2030SMax Reitz                                                       format=iotests.imgfmt,
425adfe2030SMax Reitz                                                       read_only_mode='retain')
426adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
427adfe2030SMax Reitz
428adfe2030SMax Reitz        result = self.vm.qmp('query-block')
429adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
430adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
431adfe2030SMax Reitz
432d926f4ddSKevin Wolf    @iotests.skip_if_user_is_root
433adfe2030SMax Reitz    def test_rw_ro_retain(self):
4344803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4351d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4361d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
437adfe2030SMax Reitz        self.vm.launch()
438adfe2030SMax Reitz
439adfe2030SMax Reitz        result = self.vm.qmp('query-block')
440adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
441adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
442adfe2030SMax Reitz
4431d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
444adfe2030SMax Reitz                                                       filename=new_img,
445adfe2030SMax Reitz                                                       format=iotests.imgfmt,
446adfe2030SMax Reitz                                                       read_only_mode='retain')
447adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
448adfe2030SMax Reitz
449fa1cfb40SKevin Wolf        self.assertEqual(self.vm.get_qmp_events(wait=False), [])
450adfe2030SMax Reitz
451adfe2030SMax Reitz        result = self.vm.qmp('query-block')
452adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
453adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
454adfe2030SMax Reitz
455adfe2030SMax Reitz    def test_ro_rw(self):
4564803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4571d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4581d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
459adfe2030SMax Reitz        self.vm.launch()
460adfe2030SMax Reitz
461adfe2030SMax Reitz        result = self.vm.qmp('query-block')
462adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
463adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
464adfe2030SMax Reitz
465adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4661d701e0eSMax Reitz                             id=self.device_name,
467adfe2030SMax Reitz                             filename=new_img,
468adfe2030SMax Reitz                             format=iotests.imgfmt,
469adfe2030SMax Reitz                             read_only_mode='read-write')
470adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
471adfe2030SMax Reitz
472adfe2030SMax Reitz        result = self.vm.qmp('query-block')
473adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
474adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
475adfe2030SMax Reitz
476adfe2030SMax Reitz    def test_rw_ro(self):
4774803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4781d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4791d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
480adfe2030SMax Reitz        self.vm.launch()
481adfe2030SMax Reitz
482adfe2030SMax Reitz        result = self.vm.qmp('query-block')
483adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
484adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
485adfe2030SMax Reitz
486adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4871d701e0eSMax Reitz                             id=self.device_name,
488adfe2030SMax Reitz                             filename=new_img,
489adfe2030SMax Reitz                             format=iotests.imgfmt,
490adfe2030SMax Reitz                             read_only_mode='read-only')
491adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
492adfe2030SMax Reitz
493adfe2030SMax Reitz        result = self.vm.qmp('query-block')
494adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
495adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
496adfe2030SMax Reitz
497adfe2030SMax Reitz    def test_make_rw_ro(self):
4981d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4991d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
500adfe2030SMax Reitz        self.vm.launch()
501adfe2030SMax Reitz
502adfe2030SMax Reitz        result = self.vm.qmp('query-block')
503adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
504adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
505adfe2030SMax Reitz
506adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5071d701e0eSMax Reitz                             id=self.device_name,
508adfe2030SMax Reitz                             filename=new_img,
509adfe2030SMax Reitz                             format=iotests.imgfmt,
510adfe2030SMax Reitz                             read_only_mode='read-only')
511adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
512adfe2030SMax Reitz
513adfe2030SMax Reitz        result = self.vm.qmp('query-block')
514adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
515adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
516adfe2030SMax Reitz
517d926f4ddSKevin Wolf    @iotests.skip_if_user_is_root
518adfe2030SMax Reitz    def test_make_ro_rw(self):
5194803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5201d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5211d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
522adfe2030SMax Reitz        self.vm.launch()
523adfe2030SMax Reitz
524adfe2030SMax Reitz        result = self.vm.qmp('query-block')
525adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
526adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
527adfe2030SMax Reitz
528adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5291d701e0eSMax Reitz                             id=self.device_name,
530adfe2030SMax Reitz                             filename=new_img,
531adfe2030SMax Reitz                             format=iotests.imgfmt,
532adfe2030SMax Reitz                             read_only_mode='read-write')
533adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
534adfe2030SMax Reitz
535adfe2030SMax Reitz        result = self.vm.qmp('query-block')
536adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
537adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
538adfe2030SMax Reitz
539adfe2030SMax Reitz    def test_make_rw_ro_by_retain(self):
5404803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
5411d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
5421d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
543adfe2030SMax Reitz        self.vm.launch()
544adfe2030SMax Reitz
545adfe2030SMax Reitz        result = self.vm.qmp('query-block')
546adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
547adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
548adfe2030SMax Reitz
5491d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
550adfe2030SMax Reitz                                                       filename=new_img,
551adfe2030SMax Reitz                                                       format=iotests.imgfmt,
552adfe2030SMax Reitz                                                       read_only_mode='retain')
553adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
554adfe2030SMax Reitz
555adfe2030SMax Reitz        result = self.vm.qmp('query-block')
556adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
557adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
558adfe2030SMax Reitz
559d926f4ddSKevin Wolf    @iotests.skip_if_user_is_root
560adfe2030SMax Reitz    def test_make_ro_rw_by_retain(self):
5614803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5621d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5631d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
564adfe2030SMax Reitz        self.vm.launch()
565adfe2030SMax Reitz
566adfe2030SMax Reitz        result = self.vm.qmp('query-block')
567adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
568adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
569adfe2030SMax Reitz
5701d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
571adfe2030SMax Reitz                                                       filename=new_img,
572adfe2030SMax Reitz                                                       format=iotests.imgfmt,
573adfe2030SMax Reitz                                                       read_only_mode='retain')
574adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
575adfe2030SMax Reitz
576adfe2030SMax Reitz        result = self.vm.qmp('query-block')
577adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
578adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
579adfe2030SMax Reitz
580adfe2030SMax Reitz    def test_rw_ro_cycle(self):
5814803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5821d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5831d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
584adfe2030SMax Reitz        self.vm.launch()
585adfe2030SMax Reitz
586adfe2030SMax Reitz        result = self.vm.qmp('query-block')
587adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
588adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
589adfe2030SMax Reitz
590adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
5910153d2f5SKevin Wolf                             node_name='new',
5920153d2f5SKevin Wolf                             driver=iotests.imgfmt,
5930153d2f5SKevin Wolf                             read_only=True,
5940153d2f5SKevin Wolf                             file={'filename': new_img,
5950153d2f5SKevin Wolf                                    'driver': 'file'})
596adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
597adfe2030SMax Reitz
598adfe2030SMax Reitz        result = self.vm.qmp('query-block')
599adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
600adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
601adfe2030SMax Reitz
60234ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
603adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
604adfe2030SMax Reitz
605adfe2030SMax Reitz        result = self.vm.qmp('query-block')
606adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
607adfe2030SMax Reitz
60834ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
609adfe2030SMax Reitz                                                       node_name='new')
610adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
611adfe2030SMax Reitz
612adfe2030SMax Reitz        result = self.vm.qmp('query-block')
613adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
614adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
615adfe2030SMax Reitz
616adfe2030SMax Reitz        result = self.vm.qmp('query-block')
617adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
618adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
619adfe2030SMax Reitz
620adfe2030SMax ReitzGeneralChangeTestsBaseClass = None
621adfe2030SMax ReitzTestInitiallyFilled = None
622adfe2030SMax ReitzTestInitiallyEmpty = None
623adfe2030SMax Reitz
624adfe2030SMax Reitz
625adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass):
6261d701e0eSMax Reitz    device_name = 'qdev0'
6271d701e0eSMax Reitz
628adfe2030SMax Reitz    def setUp(self):
6291d701e0eSMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K')
630adfe2030SMax Reitz
631adfe2030SMax Reitz        self.vm = iotests.VM()
632e4fd2e9dSKevin Wolf        self.vm.add_drive_raw("id=drive0,driver=null-co,if=none")
6331d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
634adfe2030SMax Reitz        self.vm.launch()
635adfe2030SMax Reitz
636adfe2030SMax Reitz        result = self.vm.qmp('query-block')
637adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
638adfe2030SMax Reitz
639adfe2030SMax Reitz        # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
640adfe2030SMax Reitz        # is not necessary
64134ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
642adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
643adfe2030SMax Reitz
644adfe2030SMax Reitz        result = self.vm.qmp('query-block')
645adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
646adfe2030SMax Reitz
647adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
6480153d2f5SKevin Wolf                             node_name='node0',
6490153d2f5SKevin Wolf                             driver=iotests.imgfmt,
6500153d2f5SKevin Wolf                             file={'filename': old_img,
6510153d2f5SKevin Wolf                                   'driver': 'file'})
652adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
653adfe2030SMax Reitz
65434ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
655adfe2030SMax Reitz                                                       node_name='node0')
656adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
657adfe2030SMax Reitz
658adfe2030SMax Reitz        result = self.vm.qmp('query-block')
659adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
660adfe2030SMax Reitz
661adfe2030SMax Reitz    def tearDown(self):
662adfe2030SMax Reitz        self.vm.shutdown()
663adfe2030SMax Reitz        os.remove(old_img)
664adfe2030SMax Reitz        try:
665adfe2030SMax Reitz            os.remove(new_img)
666adfe2030SMax Reitz        except OSError:
667adfe2030SMax Reitz            pass
668adfe2030SMax Reitz
669adfe2030SMax Reitz    # We need backing file support
670ff3caf5aSMax Reitz    @iotests.skip_for_formats(('vpc', 'parallels', 'qcow', 'vdi', 'vmdk', 'raw',
671ff3caf5aSMax Reitz                               'vhdx'))
672ff3caf5aSMax Reitz    def test_snapshot_and_commit(self):
673adfe2030SMax Reitz        result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
674adfe2030SMax Reitz                                                       snapshot_file=new_img,
675adfe2030SMax Reitz                                                       format=iotests.imgfmt)
676adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
677adfe2030SMax Reitz
678adfe2030SMax Reitz        result = self.vm.qmp('query-block')
679adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
680adfe2030SMax Reitz        self.assert_qmp(result,
681adfe2030SMax Reitz                        'return[0]/inserted/image/backing-image/filename',
682adfe2030SMax Reitz                        old_img)
683adfe2030SMax Reitz
684adfe2030SMax Reitz        result = self.vm.qmp('block-commit', device='drive0')
685adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
686adfe2030SMax Reitz
687adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_READY')
688adfe2030SMax Reitz
689adfe2030SMax Reitz        result = self.vm.qmp('query-block-jobs')
690adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/device', 'drive0')
691adfe2030SMax Reitz
692adfe2030SMax Reitz        result = self.vm.qmp('block-job-complete', device='drive0')
693adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
694adfe2030SMax Reitz
695adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
696adfe2030SMax Reitz
697adfe2030SMax Reitz
698adfe2030SMax Reitzif __name__ == '__main__':
699adfe2030SMax Reitz    if iotests.qemu_default_machine != 'pc':
700adfe2030SMax Reitz        # We need floppy and IDE CD-ROM
701adfe2030SMax Reitz        iotests.notrun('not suitable for this machine type: %s' %
702adfe2030SMax Reitz                       iotests.qemu_default_machine)
703cc8c46b7SMax Reitz    # Need to support image creation
704cc8c46b7SMax Reitz    iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
705103cbc77SMax Reitz                                 'vmdk', 'raw', 'vhdx', 'qed'],
706103cbc77SMax Reitz                 supported_protocols=['file'])
707