xref: /openbmc/qemu/tests/qemu-iotests/118 (revision d8336c6b286d9715bfe29a0e0b415dfd7891f671)
1adfe2030SMax Reitz#!/usr/bin/env python
2adfe2030SMax Reitz#
3adfe2030SMax Reitz# Test case for the QMP 'change' command and all other associated
4adfe2030SMax Reitz# 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'
361d701e0eSMax Reitz    else:
371d701e0eSMax Reitz        return None
381d701e0eSMax Reitz
39adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase):
40adfe2030SMax Reitz    has_opened = False
41adfe2030SMax Reitz    has_closed = False
42adfe2030SMax Reitz
43adfe2030SMax Reitz    def process_events(self):
44adfe2030SMax Reitz        for event in self.vm.get_qmp_events(wait=False):
45adfe2030SMax Reitz            if (event['event'] == 'DEVICE_TRAY_MOVED' and
46adfe2030SMax Reitz                event['data']['device'] == 'drive0'):
47adfe2030SMax Reitz                if event['data']['tray-open'] == False:
48adfe2030SMax Reitz                    self.has_closed = True
49adfe2030SMax Reitz                else:
50adfe2030SMax Reitz                    self.has_opened = True
51adfe2030SMax Reitz
52adfe2030SMax Reitz    def wait_for_open(self):
53abb3e55bSMax Reitz        if not self.has_real_tray:
54abb3e55bSMax Reitz            return
55abb3e55bSMax Reitz
56*d8336c6bSKevin Wolf        with iotests.Timeout(3, 'Timeout while waiting for the tray to open'):
57*d8336c6bSKevin Wolf            while not self.has_opened:
58adfe2030SMax Reitz                self.process_events()
59adfe2030SMax Reitz
60adfe2030SMax Reitz    def wait_for_close(self):
61abb3e55bSMax Reitz        if not self.has_real_tray:
62abb3e55bSMax Reitz            return
63abb3e55bSMax Reitz
64*d8336c6bSKevin Wolf        with iotests.Timeout(3, 'Timeout while waiting for the tray to close'):
65*d8336c6bSKevin Wolf            while not self.has_closed:
66adfe2030SMax Reitz                self.process_events()
67adfe2030SMax Reitz
68adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass):
69486b88bdSKevin Wolf
701d701e0eSMax Reitz    device_name = 'qdev0'
71486b88bdSKevin Wolf
72adfe2030SMax Reitz    def test_change(self):
73adfe2030SMax Reitz        result = self.vm.qmp('change', device='drive0', target=new_img,
74adfe2030SMax Reitz                                       arg=iotests.imgfmt)
75adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
76adfe2030SMax Reitz
77adfe2030SMax Reitz        self.wait_for_open()
78adfe2030SMax Reitz        self.wait_for_close()
79adfe2030SMax Reitz
80adfe2030SMax Reitz        result = self.vm.qmp('query-block')
81abb3e55bSMax Reitz        if self.has_real_tray:
82adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
83adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
84adfe2030SMax Reitz
85adfe2030SMax Reitz    def test_blockdev_change_medium(self):
86486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium',
87486b88bdSKevin Wolf                             id=self.device_name, filename=new_img,
88adfe2030SMax Reitz                             format=iotests.imgfmt)
89486b88bdSKevin Wolf
90adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
91adfe2030SMax Reitz
92adfe2030SMax Reitz        self.wait_for_open()
93adfe2030SMax Reitz        self.wait_for_close()
94adfe2030SMax Reitz
95adfe2030SMax Reitz        result = self.vm.qmp('query-block')
96abb3e55bSMax Reitz        if self.has_real_tray:
97adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
98adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
99adfe2030SMax Reitz
100adfe2030SMax Reitz    def test_eject(self):
101486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
102adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
103adfe2030SMax Reitz
104adfe2030SMax Reitz        self.wait_for_open()
105adfe2030SMax Reitz
106adfe2030SMax Reitz        result = self.vm.qmp('query-block')
107abb3e55bSMax Reitz        if self.has_real_tray:
108adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
109adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
110adfe2030SMax Reitz
111adfe2030SMax Reitz    def test_tray_eject_change(self):
112486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
113adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
114adfe2030SMax Reitz
115adfe2030SMax Reitz        self.wait_for_open()
116adfe2030SMax Reitz
117adfe2030SMax Reitz        result = self.vm.qmp('query-block')
118abb3e55bSMax Reitz        if self.has_real_tray:
119adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
120adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
121adfe2030SMax Reitz
122486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
123486b88bdSKevin Wolf                             filename=new_img, format=iotests.imgfmt)
124adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
125adfe2030SMax Reitz
126adfe2030SMax Reitz        self.wait_for_close()
127adfe2030SMax Reitz
128adfe2030SMax Reitz        result = self.vm.qmp('query-block')
129abb3e55bSMax Reitz        if self.has_real_tray:
130adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
131adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
132adfe2030SMax Reitz
133adfe2030SMax Reitz    def test_tray_open_close(self):
134486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
135486b88bdSKevin Wolf                             id=self.device_name, force=True)
136adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
137adfe2030SMax Reitz
138adfe2030SMax Reitz        self.wait_for_open()
139adfe2030SMax Reitz
140adfe2030SMax Reitz        result = self.vm.qmp('query-block')
141abb3e55bSMax Reitz        if self.has_real_tray:
142adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
143adfe2030SMax Reitz        if self.was_empty == True:
144adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
145adfe2030SMax Reitz        else:
146adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
147adfe2030SMax Reitz
148486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
149adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
150adfe2030SMax Reitz
151adfe2030SMax Reitz        if self.has_real_tray or not self.was_empty:
152adfe2030SMax Reitz            self.wait_for_close()
153adfe2030SMax Reitz
154adfe2030SMax Reitz        result = self.vm.qmp('query-block')
155abb3e55bSMax Reitz        if self.has_real_tray:
156adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
157adfe2030SMax Reitz        if self.was_empty == True:
158adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
159adfe2030SMax Reitz        else:
160adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
161adfe2030SMax Reitz
162adfe2030SMax Reitz    def test_tray_eject_close(self):
1631d701e0eSMax Reitz        result = self.vm.qmp('eject', id=self.device_name, force=True)
164adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
165adfe2030SMax Reitz
166adfe2030SMax Reitz        self.wait_for_open()
167adfe2030SMax Reitz
168adfe2030SMax Reitz        result = self.vm.qmp('query-block')
169abb3e55bSMax Reitz        if self.has_real_tray:
170adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
171adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
172adfe2030SMax Reitz
173486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
174adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
175adfe2030SMax Reitz
176adfe2030SMax Reitz        self.wait_for_close()
177adfe2030SMax Reitz
178adfe2030SMax Reitz        result = self.vm.qmp('query-block')
179adfe2030SMax Reitz        if self.has_real_tray:
180adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
181adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
182adfe2030SMax Reitz
183adfe2030SMax Reitz    def test_tray_open_change(self):
1841d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name,
1851d701e0eSMax Reitz                                                   force=True)
186adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
187adfe2030SMax Reitz
188adfe2030SMax Reitz        self.wait_for_open()
189adfe2030SMax Reitz
190adfe2030SMax Reitz        result = self.vm.qmp('query-block')
191abb3e55bSMax Reitz        if self.has_real_tray:
192adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
193adfe2030SMax Reitz        if self.was_empty == True:
194adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
195adfe2030SMax Reitz        else:
196adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
197adfe2030SMax Reitz
1981d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
199adfe2030SMax Reitz                                                       filename=new_img,
200adfe2030SMax Reitz                                                       format=iotests.imgfmt)
201adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
202adfe2030SMax Reitz
203adfe2030SMax Reitz        self.wait_for_close()
204adfe2030SMax Reitz
205adfe2030SMax Reitz        result = self.vm.qmp('query-block')
206abb3e55bSMax Reitz        if self.has_real_tray:
207adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
208adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
209adfe2030SMax Reitz
210adfe2030SMax Reitz    def test_cycle(self):
211adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2120153d2f5SKevin Wolf                             node_name='new',
2130153d2f5SKevin Wolf                             driver=iotests.imgfmt,
2140153d2f5SKevin Wolf                             file={'filename': new_img,
2150153d2f5SKevin Wolf                                    'driver': 'file'})
216adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
217adfe2030SMax Reitz
218486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
219486b88bdSKevin Wolf                             id=self.device_name, force=True)
220adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
221adfe2030SMax Reitz
222adfe2030SMax Reitz        self.wait_for_open()
223adfe2030SMax Reitz
224adfe2030SMax Reitz        result = self.vm.qmp('query-block')
225abb3e55bSMax Reitz        if self.has_real_tray:
226adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
227adfe2030SMax Reitz        if self.was_empty == True:
228adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
229adfe2030SMax Reitz        else:
230adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
231adfe2030SMax Reitz
23234ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium',
233486b88bdSKevin Wolf                             id=self.device_name)
234adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
235adfe2030SMax Reitz
236adfe2030SMax Reitz        result = self.vm.qmp('query-block')
237abb3e55bSMax Reitz        if self.has_real_tray:
238adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
239adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
240adfe2030SMax Reitz
24134ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium',
242486b88bdSKevin Wolf                             id=self.device_name, node_name='new')
243adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
244adfe2030SMax Reitz
245adfe2030SMax Reitz        result = self.vm.qmp('query-block')
246abb3e55bSMax Reitz        if self.has_real_tray:
247adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
248adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
249adfe2030SMax Reitz
250486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
251adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
252adfe2030SMax Reitz
253adfe2030SMax Reitz        self.wait_for_close()
254adfe2030SMax Reitz
255adfe2030SMax Reitz        result = self.vm.qmp('query-block')
256abb3e55bSMax Reitz        if self.has_real_tray:
257adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
258adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
259adfe2030SMax Reitz
260adfe2030SMax Reitz    def test_close_on_closed(self):
2611d701e0eSMax Reitz        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
262adfe2030SMax Reitz        # Should be a no-op
263adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
264adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
265adfe2030SMax Reitz
266adfe2030SMax Reitz    def test_remove_on_closed(self):
267abb3e55bSMax Reitz        if not self.has_real_tray:
268adfe2030SMax Reitz            return
269adfe2030SMax Reitz
27034ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
271adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
272adfe2030SMax Reitz
273adfe2030SMax Reitz    def test_insert_on_closed(self):
274abb3e55bSMax Reitz        if not self.has_real_tray:
275adfe2030SMax Reitz            return
276adfe2030SMax Reitz
277adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2780153d2f5SKevin Wolf                             node_name='new',
2790153d2f5SKevin Wolf                             driver=iotests.imgfmt,
2800153d2f5SKevin Wolf                             file={'filename': new_img,
2810153d2f5SKevin Wolf                                   'driver': 'file'})
282adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
283adfe2030SMax Reitz
28434ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
285adfe2030SMax Reitz                                                       node_name='new')
286adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
287adfe2030SMax Reitz
288adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass):
289adfe2030SMax Reitz    was_empty = False
290adfe2030SMax Reitz
291adfe2030SMax Reitz    def setUp(self, media, interface):
292adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
293adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
294486b88bdSKevin Wolf        self.vm = iotests.VM()
295486b88bdSKevin Wolf        self.vm.add_drive(old_img, 'media=%s' % media, 'none')
2961d701e0eSMax Reitz        self.vm.add_device('%s,drive=drive0,id=%s' %
2971d701e0eSMax Reitz                           (interface_to_device_name(interface),
2981d701e0eSMax Reitz                            self.device_name))
299adfe2030SMax Reitz        self.vm.launch()
300adfe2030SMax Reitz
301adfe2030SMax Reitz    def tearDown(self):
302adfe2030SMax Reitz        self.vm.shutdown()
303adfe2030SMax Reitz        os.remove(old_img)
304adfe2030SMax Reitz        os.remove(new_img)
305adfe2030SMax Reitz
306adfe2030SMax Reitz    def test_insert_on_filled(self):
307adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
3080153d2f5SKevin Wolf                             node_name='new',
3090153d2f5SKevin Wolf                             driver=iotests.imgfmt,
3100153d2f5SKevin Wolf                             file={'filename': new_img,
3110153d2f5SKevin Wolf                                   'driver': 'file'})
312adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
313adfe2030SMax Reitz
3141d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
315adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
316adfe2030SMax Reitz
317adfe2030SMax Reitz        self.wait_for_open()
318adfe2030SMax Reitz
31934ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
320adfe2030SMax Reitz                                                       node_name='new')
321adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
322adfe2030SMax Reitz
323adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass):
324adfe2030SMax Reitz    was_empty = True
325adfe2030SMax Reitz
326adfe2030SMax Reitz    def setUp(self, media, interface):
327adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
3281d701e0eSMax Reitz        self.vm = iotests.VM().add_drive(None, 'media=%s' % media, 'none')
3291d701e0eSMax Reitz        self.vm.add_device('%s,drive=drive0,id=%s' %
3301d701e0eSMax Reitz                           (interface_to_device_name(interface),
3311d701e0eSMax Reitz                            self.device_name))
332adfe2030SMax Reitz        self.vm.launch()
333adfe2030SMax Reitz
334adfe2030SMax Reitz    def tearDown(self):
335adfe2030SMax Reitz        self.vm.shutdown()
336adfe2030SMax Reitz        os.remove(new_img)
337adfe2030SMax Reitz
338adfe2030SMax Reitz    def test_remove_on_empty(self):
3391d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
340adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
341adfe2030SMax Reitz
342adfe2030SMax Reitz        self.wait_for_open()
343adfe2030SMax Reitz
34434ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
345adfe2030SMax Reitz        # Should be a no-op
346adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
347adfe2030SMax Reitz
348adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled):
349adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
350adfe2030SMax Reitz    has_real_tray = True
351adfe2030SMax Reitz
352adfe2030SMax Reitz    def setUp(self):
353adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
354adfe2030SMax Reitz
355adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty):
356adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
357adfe2030SMax Reitz    has_real_tray = True
358adfe2030SMax Reitz
359adfe2030SMax Reitz    def setUp(self):
360adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
361adfe2030SMax Reitz
362adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled):
363adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
364adfe2030SMax Reitz    has_real_tray = False
365adfe2030SMax Reitz
366adfe2030SMax Reitz    def setUp(self):
367adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
368adfe2030SMax Reitz
369adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty):
370adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
371adfe2030SMax Reitz    has_real_tray = False
372adfe2030SMax Reitz
373adfe2030SMax Reitz    def setUp(self):
374adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
375adfe2030SMax Reitz        # FDDs not having a real tray and there not being a medium inside the
376adfe2030SMax Reitz        # tray at startup means the tray will be considered open
377adfe2030SMax Reitz        self.has_opened = True
378adfe2030SMax Reitz
379adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass):
3801d701e0eSMax Reitz    device_name = 'qdev0'
3811d701e0eSMax Reitz
382adfe2030SMax Reitz    def setUp(self):
383adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
384adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
385adfe2030SMax Reitz        self.vm = iotests.VM()
386adfe2030SMax Reitz
387adfe2030SMax Reitz    def tearDown(self):
388adfe2030SMax Reitz        self.vm.shutdown()
3894803c5cdSEduardo Habkost        os.chmod(old_img, 0o666)
3904803c5cdSEduardo Habkost        os.chmod(new_img, 0o666)
391adfe2030SMax Reitz        os.remove(old_img)
392adfe2030SMax Reitz        os.remove(new_img)
393adfe2030SMax Reitz
394adfe2030SMax Reitz    def test_ro_ro_retain(self):
3954803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
3964803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
3971d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
3981d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
399adfe2030SMax Reitz        self.vm.launch()
400adfe2030SMax Reitz
401adfe2030SMax Reitz        result = self.vm.qmp('query-block')
402adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
403adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
404adfe2030SMax Reitz
4051d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
406adfe2030SMax Reitz                                                       filename=new_img,
407adfe2030SMax Reitz                                                       format=iotests.imgfmt,
408adfe2030SMax Reitz                                                       read_only_mode='retain')
409adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
410adfe2030SMax Reitz
411adfe2030SMax Reitz        result = self.vm.qmp('query-block')
412adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
413adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
414adfe2030SMax Reitz
415adfe2030SMax Reitz    def test_ro_rw_retain(self):
4164803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4171d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4181d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
419adfe2030SMax Reitz        self.vm.launch()
420adfe2030SMax Reitz
421adfe2030SMax Reitz        result = self.vm.qmp('query-block')
422adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
423adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
424adfe2030SMax Reitz
4251d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
426adfe2030SMax Reitz                                                       filename=new_img,
427adfe2030SMax Reitz                                                       format=iotests.imgfmt,
428adfe2030SMax Reitz                                                       read_only_mode='retain')
429adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
430adfe2030SMax Reitz
431adfe2030SMax Reitz        result = self.vm.qmp('query-block')
432adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
433adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
434adfe2030SMax Reitz
435adfe2030SMax Reitz    def test_rw_ro_retain(self):
4364803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4371d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4381d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
439adfe2030SMax Reitz        self.vm.launch()
440adfe2030SMax Reitz
441adfe2030SMax Reitz        result = self.vm.qmp('query-block')
442adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
443adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
444adfe2030SMax Reitz
4451d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
446adfe2030SMax Reitz                                                       filename=new_img,
447adfe2030SMax Reitz                                                       format=iotests.imgfmt,
448adfe2030SMax Reitz                                                       read_only_mode='retain')
449adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
450adfe2030SMax Reitz
451adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
452adfe2030SMax Reitz
453adfe2030SMax Reitz        result = self.vm.qmp('query-block')
454adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
455adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
456adfe2030SMax Reitz
457adfe2030SMax Reitz    def test_ro_rw(self):
4584803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4591d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4601d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
461adfe2030SMax Reitz        self.vm.launch()
462adfe2030SMax Reitz
463adfe2030SMax Reitz        result = self.vm.qmp('query-block')
464adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
465adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
466adfe2030SMax Reitz
467adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4681d701e0eSMax Reitz                             id=self.device_name,
469adfe2030SMax Reitz                             filename=new_img,
470adfe2030SMax Reitz                             format=iotests.imgfmt,
471adfe2030SMax Reitz                             read_only_mode='read-write')
472adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
473adfe2030SMax Reitz
474adfe2030SMax Reitz        result = self.vm.qmp('query-block')
475adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
476adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
477adfe2030SMax Reitz
478adfe2030SMax Reitz    def test_rw_ro(self):
4794803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4801d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4811d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
482adfe2030SMax Reitz        self.vm.launch()
483adfe2030SMax Reitz
484adfe2030SMax Reitz        result = self.vm.qmp('query-block')
485adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
486adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
487adfe2030SMax Reitz
488adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4891d701e0eSMax Reitz                             id=self.device_name,
490adfe2030SMax Reitz                             filename=new_img,
491adfe2030SMax Reitz                             format=iotests.imgfmt,
492adfe2030SMax Reitz                             read_only_mode='read-only')
493adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
494adfe2030SMax Reitz
495adfe2030SMax Reitz        result = self.vm.qmp('query-block')
496adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
497adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
498adfe2030SMax Reitz
499adfe2030SMax Reitz    def test_make_rw_ro(self):
5001d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5011d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
502adfe2030SMax Reitz        self.vm.launch()
503adfe2030SMax Reitz
504adfe2030SMax Reitz        result = self.vm.qmp('query-block')
505adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
506adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
507adfe2030SMax Reitz
508adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5091d701e0eSMax Reitz                             id=self.device_name,
510adfe2030SMax Reitz                             filename=new_img,
511adfe2030SMax Reitz                             format=iotests.imgfmt,
512adfe2030SMax Reitz                             read_only_mode='read-only')
513adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
514adfe2030SMax Reitz
515adfe2030SMax Reitz        result = self.vm.qmp('query-block')
516adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
517adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
518adfe2030SMax Reitz
519adfe2030SMax Reitz    def test_make_ro_rw(self):
5204803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5211d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5221d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
523adfe2030SMax Reitz        self.vm.launch()
524adfe2030SMax Reitz
525adfe2030SMax Reitz        result = self.vm.qmp('query-block')
526adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
527adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
528adfe2030SMax Reitz
529adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5301d701e0eSMax Reitz                             id=self.device_name,
531adfe2030SMax Reitz                             filename=new_img,
532adfe2030SMax Reitz                             format=iotests.imgfmt,
533adfe2030SMax Reitz                             read_only_mode='read-write')
534adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
535adfe2030SMax Reitz
536adfe2030SMax Reitz        result = self.vm.qmp('query-block')
537adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
538adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
539adfe2030SMax Reitz
540adfe2030SMax Reitz    def test_make_rw_ro_by_retain(self):
5414803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
5421d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
5431d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
544adfe2030SMax Reitz        self.vm.launch()
545adfe2030SMax Reitz
546adfe2030SMax Reitz        result = self.vm.qmp('query-block')
547adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
548adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
549adfe2030SMax Reitz
5501d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
551adfe2030SMax Reitz                                                       filename=new_img,
552adfe2030SMax Reitz                                                       format=iotests.imgfmt,
553adfe2030SMax Reitz                                                       read_only_mode='retain')
554adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
555adfe2030SMax Reitz
556adfe2030SMax Reitz        result = self.vm.qmp('query-block')
557adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
558adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
559adfe2030SMax Reitz
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    def test_snapshot_and_commit(self):
670adfe2030SMax Reitz        # We need backing file support
671adfe2030SMax Reitz        if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
672adfe2030SMax Reitz            return
673adfe2030SMax Reitz
674adfe2030SMax Reitz        result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
675adfe2030SMax Reitz                                                       snapshot_file=new_img,
676adfe2030SMax Reitz                                                       format=iotests.imgfmt)
677adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
678adfe2030SMax Reitz
679adfe2030SMax Reitz        result = self.vm.qmp('query-block')
680adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
681adfe2030SMax Reitz        self.assert_qmp(result,
682adfe2030SMax Reitz                        'return[0]/inserted/image/backing-image/filename',
683adfe2030SMax Reitz                        old_img)
684adfe2030SMax Reitz
685adfe2030SMax Reitz        result = self.vm.qmp('block-commit', device='drive0')
686adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
687adfe2030SMax Reitz
688adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_READY')
689adfe2030SMax Reitz
690adfe2030SMax Reitz        result = self.vm.qmp('query-block-jobs')
691adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/device', 'drive0')
692adfe2030SMax Reitz
693adfe2030SMax Reitz        result = self.vm.qmp('block-job-complete', device='drive0')
694adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
695adfe2030SMax Reitz
696adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
697adfe2030SMax Reitz
698adfe2030SMax Reitz
699adfe2030SMax Reitzif __name__ == '__main__':
700adfe2030SMax Reitz    if iotests.qemu_default_machine != 'pc':
701adfe2030SMax Reitz        # We need floppy and IDE CD-ROM
702adfe2030SMax Reitz        iotests.notrun('not suitable for this machine type: %s' %
703adfe2030SMax Reitz                       iotests.qemu_default_machine)
704cc8c46b7SMax Reitz    # Need to support image creation
705cc8c46b7SMax Reitz    iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
706cc8c46b7SMax Reitz                                 'vmdk', 'raw', 'vhdx', 'qed'])
707