xref: /openbmc/qemu/tests/qemu-iotests/118 (revision 4803c5cde8afa3f8b8fc1bc639ebf4f4fccddf94)
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
56adfe2030SMax Reitz        timeout = time.clock() + 3
57adfe2030SMax Reitz        while not self.has_opened and time.clock() < timeout:
58adfe2030SMax Reitz            self.process_events()
59adfe2030SMax Reitz        if not self.has_opened:
60adfe2030SMax Reitz            self.fail('Timeout while waiting for the tray to open')
61adfe2030SMax Reitz
62adfe2030SMax Reitz    def wait_for_close(self):
63abb3e55bSMax Reitz        if not self.has_real_tray:
64abb3e55bSMax Reitz            return
65abb3e55bSMax Reitz
66adfe2030SMax Reitz        timeout = time.clock() + 3
67adfe2030SMax Reitz        while not self.has_closed and time.clock() < timeout:
68adfe2030SMax Reitz            self.process_events()
69adfe2030SMax Reitz        if not self.has_opened:
70adfe2030SMax Reitz            self.fail('Timeout while waiting for the tray to close')
71adfe2030SMax Reitz
72adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass):
73486b88bdSKevin Wolf
741d701e0eSMax Reitz    device_name = 'qdev0'
75486b88bdSKevin Wolf
76adfe2030SMax Reitz    def test_change(self):
77adfe2030SMax Reitz        result = self.vm.qmp('change', device='drive0', target=new_img,
78adfe2030SMax Reitz                                       arg=iotests.imgfmt)
79adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
80adfe2030SMax Reitz
81adfe2030SMax Reitz        self.wait_for_open()
82adfe2030SMax Reitz        self.wait_for_close()
83adfe2030SMax Reitz
84adfe2030SMax Reitz        result = self.vm.qmp('query-block')
85abb3e55bSMax Reitz        if self.has_real_tray:
86adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
87adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
88adfe2030SMax Reitz
89adfe2030SMax Reitz    def test_blockdev_change_medium(self):
90486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium',
91486b88bdSKevin Wolf                             id=self.device_name, filename=new_img,
92adfe2030SMax Reitz                             format=iotests.imgfmt)
93486b88bdSKevin Wolf
94adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
95adfe2030SMax Reitz
96adfe2030SMax Reitz        self.wait_for_open()
97adfe2030SMax Reitz        self.wait_for_close()
98adfe2030SMax Reitz
99adfe2030SMax Reitz        result = self.vm.qmp('query-block')
100abb3e55bSMax Reitz        if self.has_real_tray:
101adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
102adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
103adfe2030SMax Reitz
104adfe2030SMax Reitz    def test_eject(self):
105486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
106adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
107adfe2030SMax Reitz
108adfe2030SMax Reitz        self.wait_for_open()
109adfe2030SMax Reitz
110adfe2030SMax Reitz        result = self.vm.qmp('query-block')
111abb3e55bSMax Reitz        if self.has_real_tray:
112adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
113adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
114adfe2030SMax Reitz
115adfe2030SMax Reitz    def test_tray_eject_change(self):
116486b88bdSKevin Wolf        result = self.vm.qmp('eject', id=self.device_name, force=True)
117adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
118adfe2030SMax Reitz
119adfe2030SMax Reitz        self.wait_for_open()
120adfe2030SMax Reitz
121adfe2030SMax Reitz        result = self.vm.qmp('query-block')
122abb3e55bSMax Reitz        if self.has_real_tray:
123adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
124adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
125adfe2030SMax Reitz
126486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
127486b88bdSKevin Wolf                             filename=new_img, format=iotests.imgfmt)
128adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
129adfe2030SMax Reitz
130adfe2030SMax Reitz        self.wait_for_close()
131adfe2030SMax Reitz
132adfe2030SMax Reitz        result = self.vm.qmp('query-block')
133abb3e55bSMax Reitz        if self.has_real_tray:
134adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
135adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
136adfe2030SMax Reitz
137adfe2030SMax Reitz    def test_tray_open_close(self):
138486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
139486b88bdSKevin Wolf                             id=self.device_name, force=True)
140adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
141adfe2030SMax Reitz
142adfe2030SMax Reitz        self.wait_for_open()
143adfe2030SMax Reitz
144adfe2030SMax Reitz        result = self.vm.qmp('query-block')
145abb3e55bSMax Reitz        if self.has_real_tray:
146adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
147adfe2030SMax Reitz        if self.was_empty == True:
148adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
149adfe2030SMax Reitz        else:
150adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
151adfe2030SMax Reitz
152486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
153adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
154adfe2030SMax Reitz
155adfe2030SMax Reitz        if self.has_real_tray or not self.was_empty:
156adfe2030SMax Reitz            self.wait_for_close()
157adfe2030SMax Reitz
158adfe2030SMax Reitz        result = self.vm.qmp('query-block')
159abb3e55bSMax Reitz        if self.has_real_tray:
160adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
161adfe2030SMax Reitz        if self.was_empty == True:
162adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
163adfe2030SMax Reitz        else:
164adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
165adfe2030SMax Reitz
166adfe2030SMax Reitz    def test_tray_eject_close(self):
1671d701e0eSMax Reitz        result = self.vm.qmp('eject', id=self.device_name, force=True)
168adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
169adfe2030SMax Reitz
170adfe2030SMax Reitz        self.wait_for_open()
171adfe2030SMax Reitz
172adfe2030SMax Reitz        result = self.vm.qmp('query-block')
173abb3e55bSMax Reitz        if self.has_real_tray:
174adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
175adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
176adfe2030SMax Reitz
177486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
178adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
179adfe2030SMax Reitz
180adfe2030SMax Reitz        self.wait_for_close()
181adfe2030SMax Reitz
182adfe2030SMax Reitz        result = self.vm.qmp('query-block')
183adfe2030SMax Reitz        if self.has_real_tray:
184adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
185adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
186adfe2030SMax Reitz
187adfe2030SMax Reitz    def test_tray_open_change(self):
1881d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name,
1891d701e0eSMax Reitz                                                   force=True)
190adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
191adfe2030SMax Reitz
192adfe2030SMax Reitz        self.wait_for_open()
193adfe2030SMax Reitz
194adfe2030SMax Reitz        result = self.vm.qmp('query-block')
195abb3e55bSMax Reitz        if self.has_real_tray:
196adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
197adfe2030SMax Reitz        if self.was_empty == True:
198adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
199adfe2030SMax Reitz        else:
200adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
201adfe2030SMax Reitz
2021d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
203adfe2030SMax Reitz                                                       filename=new_img,
204adfe2030SMax Reitz                                                       format=iotests.imgfmt)
205adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
206adfe2030SMax Reitz
207adfe2030SMax Reitz        self.wait_for_close()
208adfe2030SMax Reitz
209adfe2030SMax Reitz        result = self.vm.qmp('query-block')
210abb3e55bSMax Reitz        if self.has_real_tray:
211adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
212adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
213adfe2030SMax Reitz
214adfe2030SMax Reitz    def test_cycle(self):
215adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2160153d2f5SKevin Wolf                             node_name='new',
2170153d2f5SKevin Wolf                             driver=iotests.imgfmt,
2180153d2f5SKevin Wolf                             file={'filename': new_img,
2190153d2f5SKevin Wolf                                    'driver': 'file'})
220adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
221adfe2030SMax Reitz
222486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-open-tray',
223486b88bdSKevin Wolf                             id=self.device_name, force=True)
224adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
225adfe2030SMax Reitz
226adfe2030SMax Reitz        self.wait_for_open()
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        if self.was_empty == True:
232adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
233adfe2030SMax Reitz        else:
234adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
235adfe2030SMax Reitz
23634ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium',
237486b88bdSKevin Wolf                             id=self.device_name)
238adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
239adfe2030SMax Reitz
240adfe2030SMax Reitz        result = self.vm.qmp('query-block')
241abb3e55bSMax Reitz        if self.has_real_tray:
242adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
243adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
244adfe2030SMax Reitz
24534ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium',
246486b88bdSKevin Wolf                             id=self.device_name, node_name='new')
247adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
248adfe2030SMax Reitz
249adfe2030SMax Reitz        result = self.vm.qmp('query-block')
250abb3e55bSMax Reitz        if self.has_real_tray:
251adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
252adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
253adfe2030SMax Reitz
254486b88bdSKevin Wolf        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
255adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
256adfe2030SMax Reitz
257adfe2030SMax Reitz        self.wait_for_close()
258adfe2030SMax Reitz
259adfe2030SMax Reitz        result = self.vm.qmp('query-block')
260abb3e55bSMax Reitz        if self.has_real_tray:
261adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
262adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
263adfe2030SMax Reitz
264adfe2030SMax Reitz    def test_close_on_closed(self):
2651d701e0eSMax Reitz        result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
266adfe2030SMax Reitz        # Should be a no-op
267adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
268adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
269adfe2030SMax Reitz
270adfe2030SMax Reitz    def test_remove_on_closed(self):
271abb3e55bSMax Reitz        if not self.has_real_tray:
272adfe2030SMax Reitz            return
273adfe2030SMax Reitz
27434ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
275adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
276adfe2030SMax Reitz
277adfe2030SMax Reitz    def test_insert_on_closed(self):
278abb3e55bSMax Reitz        if not self.has_real_tray:
279adfe2030SMax Reitz            return
280adfe2030SMax Reitz
281adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
2820153d2f5SKevin Wolf                             node_name='new',
2830153d2f5SKevin Wolf                             driver=iotests.imgfmt,
2840153d2f5SKevin Wolf                             file={'filename': new_img,
2850153d2f5SKevin Wolf                                   'driver': 'file'})
286adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
287adfe2030SMax Reitz
28834ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
289adfe2030SMax Reitz                                                       node_name='new')
290adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
291adfe2030SMax Reitz
292adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass):
293adfe2030SMax Reitz    was_empty = False
294adfe2030SMax Reitz
295adfe2030SMax Reitz    def setUp(self, media, interface):
296adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
297adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
298486b88bdSKevin Wolf        self.vm = iotests.VM()
299486b88bdSKevin Wolf        self.vm.add_drive(old_img, 'media=%s' % media, 'none')
3001d701e0eSMax Reitz        self.vm.add_device('%s,drive=drive0,id=%s' %
3011d701e0eSMax Reitz                           (interface_to_device_name(interface),
3021d701e0eSMax Reitz                            self.device_name))
303adfe2030SMax Reitz        self.vm.launch()
304adfe2030SMax Reitz
305adfe2030SMax Reitz    def tearDown(self):
306adfe2030SMax Reitz        self.vm.shutdown()
307adfe2030SMax Reitz        os.remove(old_img)
308adfe2030SMax Reitz        os.remove(new_img)
309adfe2030SMax Reitz
310adfe2030SMax Reitz    def test_insert_on_filled(self):
311adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
3120153d2f5SKevin Wolf                             node_name='new',
3130153d2f5SKevin Wolf                             driver=iotests.imgfmt,
3140153d2f5SKevin Wolf                             file={'filename': new_img,
3150153d2f5SKevin Wolf                                   'driver': 'file'})
316adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
317adfe2030SMax Reitz
3181d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
319adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
320adfe2030SMax Reitz
321adfe2030SMax Reitz        self.wait_for_open()
322adfe2030SMax Reitz
32334ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
324adfe2030SMax Reitz                                                       node_name='new')
325adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
326adfe2030SMax Reitz
327adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass):
328adfe2030SMax Reitz    was_empty = True
329adfe2030SMax Reitz
330adfe2030SMax Reitz    def setUp(self, media, interface):
331adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
3321d701e0eSMax Reitz        self.vm = iotests.VM().add_drive(None, 'media=%s' % media, 'none')
3331d701e0eSMax Reitz        self.vm.add_device('%s,drive=drive0,id=%s' %
3341d701e0eSMax Reitz                           (interface_to_device_name(interface),
3351d701e0eSMax Reitz                            self.device_name))
336adfe2030SMax Reitz        self.vm.launch()
337adfe2030SMax Reitz
338adfe2030SMax Reitz    def tearDown(self):
339adfe2030SMax Reitz        self.vm.shutdown()
340adfe2030SMax Reitz        os.remove(new_img)
341adfe2030SMax Reitz
342adfe2030SMax Reitz    def test_remove_on_empty(self):
3431d701e0eSMax Reitz        result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
344adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
345adfe2030SMax Reitz
346adfe2030SMax Reitz        self.wait_for_open()
347adfe2030SMax Reitz
34834ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
349adfe2030SMax Reitz        # Should be a no-op
350adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
351adfe2030SMax Reitz
352adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled):
353adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
354adfe2030SMax Reitz    has_real_tray = True
355adfe2030SMax Reitz
356adfe2030SMax Reitz    def setUp(self):
357adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
358adfe2030SMax Reitz
359adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty):
360adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
361adfe2030SMax Reitz    has_real_tray = True
362adfe2030SMax Reitz
363adfe2030SMax Reitz    def setUp(self):
364adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
365adfe2030SMax Reitz
366adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled):
367adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
368adfe2030SMax Reitz    has_real_tray = False
369adfe2030SMax Reitz
370adfe2030SMax Reitz    def setUp(self):
371adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
372adfe2030SMax Reitz
373adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty):
374adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
375adfe2030SMax Reitz    has_real_tray = False
376adfe2030SMax Reitz
377adfe2030SMax Reitz    def setUp(self):
378adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
379adfe2030SMax Reitz        # FDDs not having a real tray and there not being a medium inside the
380adfe2030SMax Reitz        # tray at startup means the tray will be considered open
381adfe2030SMax Reitz        self.has_opened = True
382adfe2030SMax Reitz
383adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass):
3841d701e0eSMax Reitz    device_name = 'qdev0'
3851d701e0eSMax Reitz
386adfe2030SMax Reitz    def setUp(self):
387adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
388adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
389adfe2030SMax Reitz        self.vm = iotests.VM()
390adfe2030SMax Reitz
391adfe2030SMax Reitz    def tearDown(self):
392adfe2030SMax Reitz        self.vm.shutdown()
393*4803c5cdSEduardo Habkost        os.chmod(old_img, 0o666)
394*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o666)
395adfe2030SMax Reitz        os.remove(old_img)
396adfe2030SMax Reitz        os.remove(new_img)
397adfe2030SMax Reitz
398adfe2030SMax Reitz    def test_ro_ro_retain(self):
399*4803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
400*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4011d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4021d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
403adfe2030SMax Reitz        self.vm.launch()
404adfe2030SMax Reitz
405adfe2030SMax Reitz        result = self.vm.qmp('query-block')
406adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
407adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
408adfe2030SMax Reitz
4091d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
410adfe2030SMax Reitz                                                       filename=new_img,
411adfe2030SMax Reitz                                                       format=iotests.imgfmt,
412adfe2030SMax Reitz                                                       read_only_mode='retain')
413adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
414adfe2030SMax Reitz
415adfe2030SMax Reitz        result = self.vm.qmp('query-block')
416adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
417adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
418adfe2030SMax Reitz
419adfe2030SMax Reitz    def test_ro_rw_retain(self):
420*4803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4211d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4221d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
423adfe2030SMax Reitz        self.vm.launch()
424adfe2030SMax Reitz
425adfe2030SMax Reitz        result = self.vm.qmp('query-block')
426adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
427adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
428adfe2030SMax Reitz
4291d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
430adfe2030SMax Reitz                                                       filename=new_img,
431adfe2030SMax Reitz                                                       format=iotests.imgfmt,
432adfe2030SMax Reitz                                                       read_only_mode='retain')
433adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
434adfe2030SMax Reitz
435adfe2030SMax Reitz        result = self.vm.qmp('query-block')
436adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
437adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
438adfe2030SMax Reitz
439adfe2030SMax Reitz    def test_rw_ro_retain(self):
440*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4411d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4421d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
443adfe2030SMax Reitz        self.vm.launch()
444adfe2030SMax Reitz
445adfe2030SMax Reitz        result = self.vm.qmp('query-block')
446adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
447adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
448adfe2030SMax Reitz
4491d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
450adfe2030SMax Reitz                                                       filename=new_img,
451adfe2030SMax Reitz                                                       format=iotests.imgfmt,
452adfe2030SMax Reitz                                                       read_only_mode='retain')
453adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
454adfe2030SMax Reitz
455adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
456adfe2030SMax Reitz
457adfe2030SMax Reitz        result = self.vm.qmp('query-block')
458adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
459adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
460adfe2030SMax Reitz
461adfe2030SMax Reitz    def test_ro_rw(self):
462*4803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
4631d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
4641d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
465adfe2030SMax Reitz        self.vm.launch()
466adfe2030SMax Reitz
467adfe2030SMax Reitz        result = self.vm.qmp('query-block')
468adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
469adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
470adfe2030SMax Reitz
471adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4721d701e0eSMax Reitz                             id=self.device_name,
473adfe2030SMax Reitz                             filename=new_img,
474adfe2030SMax Reitz                             format=iotests.imgfmt,
475adfe2030SMax Reitz                             read_only_mode='read-write')
476adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
477adfe2030SMax Reitz
478adfe2030SMax Reitz        result = self.vm.qmp('query-block')
479adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
480adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
481adfe2030SMax Reitz
482adfe2030SMax Reitz    def test_rw_ro(self):
483*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
4841d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
4851d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
486adfe2030SMax Reitz        self.vm.launch()
487adfe2030SMax Reitz
488adfe2030SMax Reitz        result = self.vm.qmp('query-block')
489adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
490adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
491adfe2030SMax Reitz
492adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
4931d701e0eSMax Reitz                             id=self.device_name,
494adfe2030SMax Reitz                             filename=new_img,
495adfe2030SMax Reitz                             format=iotests.imgfmt,
496adfe2030SMax Reitz                             read_only_mode='read-only')
497adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
498adfe2030SMax Reitz
499adfe2030SMax Reitz        result = self.vm.qmp('query-block')
500adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
501adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
502adfe2030SMax Reitz
503adfe2030SMax Reitz    def test_make_rw_ro(self):
5041d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5051d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
506adfe2030SMax Reitz        self.vm.launch()
507adfe2030SMax Reitz
508adfe2030SMax Reitz        result = self.vm.qmp('query-block')
509adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
510adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
511adfe2030SMax Reitz
512adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5131d701e0eSMax Reitz                             id=self.device_name,
514adfe2030SMax Reitz                             filename=new_img,
515adfe2030SMax Reitz                             format=iotests.imgfmt,
516adfe2030SMax Reitz                             read_only_mode='read-only')
517adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
518adfe2030SMax Reitz
519adfe2030SMax Reitz        result = self.vm.qmp('query-block')
520adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
521adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
522adfe2030SMax Reitz
523adfe2030SMax Reitz    def test_make_ro_rw(self):
524*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5251d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5261d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
527adfe2030SMax Reitz        self.vm.launch()
528adfe2030SMax Reitz
529adfe2030SMax Reitz        result = self.vm.qmp('query-block')
530adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
531adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
532adfe2030SMax Reitz
533adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
5341d701e0eSMax Reitz                             id=self.device_name,
535adfe2030SMax Reitz                             filename=new_img,
536adfe2030SMax Reitz                             format=iotests.imgfmt,
537adfe2030SMax Reitz                             read_only_mode='read-write')
538adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
539adfe2030SMax Reitz
540adfe2030SMax Reitz        result = self.vm.qmp('query-block')
541adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
542adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
543adfe2030SMax Reitz
544adfe2030SMax Reitz    def test_make_rw_ro_by_retain(self):
545*4803c5cdSEduardo Habkost        os.chmod(old_img, 0o444)
5461d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
5471d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
548adfe2030SMax Reitz        self.vm.launch()
549adfe2030SMax Reitz
550adfe2030SMax Reitz        result = self.vm.qmp('query-block')
551adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
552adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
553adfe2030SMax Reitz
5541d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
555adfe2030SMax Reitz                                                       filename=new_img,
556adfe2030SMax Reitz                                                       format=iotests.imgfmt,
557adfe2030SMax Reitz                                                       read_only_mode='retain')
558adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
559adfe2030SMax Reitz
560adfe2030SMax Reitz        result = self.vm.qmp('query-block')
561adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
562adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
563adfe2030SMax Reitz
564adfe2030SMax Reitz    def test_make_ro_rw_by_retain(self):
565*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5661d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5671d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
568adfe2030SMax Reitz        self.vm.launch()
569adfe2030SMax Reitz
570adfe2030SMax Reitz        result = self.vm.qmp('query-block')
571adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
572adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
573adfe2030SMax Reitz
5741d701e0eSMax Reitz        result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
575adfe2030SMax Reitz                                                       filename=new_img,
576adfe2030SMax Reitz                                                       format=iotests.imgfmt,
577adfe2030SMax Reitz                                                       read_only_mode='retain')
578adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
579adfe2030SMax Reitz
580adfe2030SMax Reitz        result = self.vm.qmp('query-block')
581adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
582adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
583adfe2030SMax Reitz
584adfe2030SMax Reitz    def test_rw_ro_cycle(self):
585*4803c5cdSEduardo Habkost        os.chmod(new_img, 0o444)
5861d701e0eSMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'none')
5871d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
588adfe2030SMax Reitz        self.vm.launch()
589adfe2030SMax Reitz
590adfe2030SMax Reitz        result = self.vm.qmp('query-block')
591adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
592adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
593adfe2030SMax Reitz
594adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
5950153d2f5SKevin Wolf                             node_name='new',
5960153d2f5SKevin Wolf                             driver=iotests.imgfmt,
5970153d2f5SKevin Wolf                             read_only=True,
5980153d2f5SKevin Wolf                             file={'filename': new_img,
5990153d2f5SKevin Wolf                                    'driver': 'file'})
600adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
601adfe2030SMax Reitz
602adfe2030SMax Reitz        result = self.vm.qmp('query-block')
603adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
604adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
605adfe2030SMax Reitz
60634ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
607adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
608adfe2030SMax Reitz
609adfe2030SMax Reitz        result = self.vm.qmp('query-block')
610adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
611adfe2030SMax Reitz
61234ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
613adfe2030SMax Reitz                                                       node_name='new')
614adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
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 Reitz        result = self.vm.qmp('query-block')
621adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
622adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
623adfe2030SMax Reitz
624adfe2030SMax ReitzGeneralChangeTestsBaseClass = None
625adfe2030SMax ReitzTestInitiallyFilled = None
626adfe2030SMax ReitzTestInitiallyEmpty = None
627adfe2030SMax Reitz
628adfe2030SMax Reitz
629adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass):
6301d701e0eSMax Reitz    device_name = 'qdev0'
6311d701e0eSMax Reitz
632adfe2030SMax Reitz    def setUp(self):
6331d701e0eSMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K')
634adfe2030SMax Reitz
635adfe2030SMax Reitz        self.vm = iotests.VM()
636e4fd2e9dSKevin Wolf        self.vm.add_drive_raw("id=drive0,driver=null-co,if=none")
6371d701e0eSMax Reitz        self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
638adfe2030SMax Reitz        self.vm.launch()
639adfe2030SMax Reitz
640adfe2030SMax Reitz        result = self.vm.qmp('query-block')
641adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
642adfe2030SMax Reitz
643adfe2030SMax Reitz        # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
644adfe2030SMax Reitz        # is not necessary
64534ce1111SMax Reitz        result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
646adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
647adfe2030SMax Reitz
648adfe2030SMax Reitz        result = self.vm.qmp('query-block')
649adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
650adfe2030SMax Reitz
651adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
6520153d2f5SKevin Wolf                             node_name='node0',
6530153d2f5SKevin Wolf                             driver=iotests.imgfmt,
6540153d2f5SKevin Wolf                             file={'filename': old_img,
6550153d2f5SKevin Wolf                                   'driver': 'file'})
656adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
657adfe2030SMax Reitz
65834ce1111SMax Reitz        result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
659adfe2030SMax Reitz                                                       node_name='node0')
660adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
661adfe2030SMax Reitz
662adfe2030SMax Reitz        result = self.vm.qmp('query-block')
663adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
664adfe2030SMax Reitz
665adfe2030SMax Reitz    def tearDown(self):
666adfe2030SMax Reitz        self.vm.shutdown()
667adfe2030SMax Reitz        os.remove(old_img)
668adfe2030SMax Reitz        try:
669adfe2030SMax Reitz            os.remove(new_img)
670adfe2030SMax Reitz        except OSError:
671adfe2030SMax Reitz            pass
672adfe2030SMax Reitz
673adfe2030SMax Reitz    def test_snapshot_and_commit(self):
674adfe2030SMax Reitz        # We need backing file support
675adfe2030SMax Reitz        if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
676adfe2030SMax Reitz            return
677adfe2030SMax Reitz
678adfe2030SMax Reitz        result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
679adfe2030SMax Reitz                                                       snapshot_file=new_img,
680adfe2030SMax Reitz                                                       format=iotests.imgfmt)
681adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
682adfe2030SMax Reitz
683adfe2030SMax Reitz        result = self.vm.qmp('query-block')
684adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
685adfe2030SMax Reitz        self.assert_qmp(result,
686adfe2030SMax Reitz                        'return[0]/inserted/image/backing-image/filename',
687adfe2030SMax Reitz                        old_img)
688adfe2030SMax Reitz
689adfe2030SMax Reitz        result = self.vm.qmp('block-commit', device='drive0')
690adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
691adfe2030SMax Reitz
692adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_READY')
693adfe2030SMax Reitz
694adfe2030SMax Reitz        result = self.vm.qmp('query-block-jobs')
695adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/device', 'drive0')
696adfe2030SMax Reitz
697adfe2030SMax Reitz        result = self.vm.qmp('block-job-complete', device='drive0')
698adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
699adfe2030SMax Reitz
700adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
701adfe2030SMax Reitz
702adfe2030SMax Reitz
703adfe2030SMax Reitzif __name__ == '__main__':
704adfe2030SMax Reitz    if iotests.qemu_default_machine != 'pc':
705adfe2030SMax Reitz        # We need floppy and IDE CD-ROM
706adfe2030SMax Reitz        iotests.notrun('not suitable for this machine type: %s' %
707adfe2030SMax Reitz                       iotests.qemu_default_machine)
708cc8c46b7SMax Reitz    # Need to support image creation
709cc8c46b7SMax Reitz    iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
710cc8c46b7SMax Reitz                                 'vmdk', 'raw', 'vhdx', 'qed'])
711