xref: /qemu/tests/qemu-iotests/118 (revision cc8c46b7c5fffd6b6ca099799be0af224c589603)
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
31adfe2030SMax Reitzclass ChangeBaseClass(iotests.QMPTestCase):
32adfe2030SMax Reitz    has_opened = False
33adfe2030SMax Reitz    has_closed = False
34adfe2030SMax Reitz
35adfe2030SMax Reitz    def process_events(self):
36adfe2030SMax Reitz        for event in self.vm.get_qmp_events(wait=False):
37adfe2030SMax Reitz            if (event['event'] == 'DEVICE_TRAY_MOVED' and
38adfe2030SMax Reitz                event['data']['device'] == 'drive0'):
39adfe2030SMax Reitz                if event['data']['tray-open'] == False:
40adfe2030SMax Reitz                    self.has_closed = True
41adfe2030SMax Reitz                else:
42adfe2030SMax Reitz                    self.has_opened = True
43adfe2030SMax Reitz
44adfe2030SMax Reitz    def wait_for_open(self):
45abb3e55bSMax Reitz        if not self.has_real_tray:
46abb3e55bSMax Reitz            return
47abb3e55bSMax Reitz
48adfe2030SMax Reitz        timeout = time.clock() + 3
49adfe2030SMax Reitz        while not self.has_opened and time.clock() < timeout:
50adfe2030SMax Reitz            self.process_events()
51adfe2030SMax Reitz        if not self.has_opened:
52adfe2030SMax Reitz            self.fail('Timeout while waiting for the tray to open')
53adfe2030SMax Reitz
54adfe2030SMax Reitz    def wait_for_close(self):
55abb3e55bSMax Reitz        if not self.has_real_tray:
56abb3e55bSMax Reitz            return
57abb3e55bSMax Reitz
58adfe2030SMax Reitz        timeout = time.clock() + 3
59adfe2030SMax Reitz        while not self.has_closed and time.clock() < timeout:
60adfe2030SMax Reitz            self.process_events()
61adfe2030SMax Reitz        if not self.has_opened:
62adfe2030SMax Reitz            self.fail('Timeout while waiting for the tray to close')
63adfe2030SMax Reitz
64adfe2030SMax Reitzclass GeneralChangeTestsBaseClass(ChangeBaseClass):
65adfe2030SMax Reitz    def test_change(self):
66adfe2030SMax Reitz        result = self.vm.qmp('change', device='drive0', target=new_img,
67adfe2030SMax Reitz                                       arg=iotests.imgfmt)
68adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
69adfe2030SMax Reitz
70adfe2030SMax Reitz        self.wait_for_open()
71adfe2030SMax Reitz        self.wait_for_close()
72adfe2030SMax Reitz
73adfe2030SMax Reitz        result = self.vm.qmp('query-block')
74abb3e55bSMax Reitz        if self.has_real_tray:
75adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
76adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
77adfe2030SMax Reitz
78adfe2030SMax Reitz    def test_blockdev_change_medium(self):
79adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
80adfe2030SMax Reitz                                                       filename=new_img,
81adfe2030SMax Reitz                                                       format=iotests.imgfmt)
82adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
83adfe2030SMax Reitz
84adfe2030SMax Reitz        self.wait_for_open()
85adfe2030SMax Reitz        self.wait_for_close()
86adfe2030SMax Reitz
87adfe2030SMax Reitz        result = self.vm.qmp('query-block')
88abb3e55bSMax Reitz        if self.has_real_tray:
89adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
90adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
91adfe2030SMax Reitz
92adfe2030SMax Reitz    def test_eject(self):
93adfe2030SMax Reitz        result = self.vm.qmp('eject', device='drive0', force=True)
94adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
95adfe2030SMax Reitz
96adfe2030SMax Reitz        self.wait_for_open()
97adfe2030SMax Reitz
98adfe2030SMax Reitz        result = self.vm.qmp('query-block')
99abb3e55bSMax Reitz        if self.has_real_tray:
100adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
101adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
102adfe2030SMax Reitz
103adfe2030SMax Reitz    def test_tray_eject_change(self):
104adfe2030SMax Reitz        result = self.vm.qmp('eject', device='drive0', force=True)
105adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
106adfe2030SMax Reitz
107adfe2030SMax Reitz        self.wait_for_open()
108adfe2030SMax Reitz
109adfe2030SMax Reitz        result = self.vm.qmp('query-block')
110abb3e55bSMax Reitz        if self.has_real_tray:
111adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
112adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
113adfe2030SMax Reitz
114adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
115adfe2030SMax Reitz                                                       filename=new_img,
116adfe2030SMax Reitz                                                       format=iotests.imgfmt)
117adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
118adfe2030SMax Reitz
119adfe2030SMax Reitz        self.wait_for_close()
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', False)
124adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
125adfe2030SMax Reitz
126adfe2030SMax Reitz    def test_tray_open_close(self):
127adfe2030SMax Reitz        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
128adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
129adfe2030SMax Reitz
130adfe2030SMax Reitz        self.wait_for_open()
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', True)
135adfe2030SMax Reitz        if self.was_empty == True:
136adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
137adfe2030SMax Reitz        else:
138adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
139adfe2030SMax Reitz
140adfe2030SMax Reitz        result = self.vm.qmp('blockdev-close-tray', device='drive0')
141adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
142adfe2030SMax Reitz
143adfe2030SMax Reitz        if self.has_real_tray or not self.was_empty:
144adfe2030SMax Reitz            self.wait_for_close()
145adfe2030SMax Reitz
146adfe2030SMax Reitz        result = self.vm.qmp('query-block')
147abb3e55bSMax Reitz        if self.has_real_tray:
148adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
149adfe2030SMax Reitz        if self.was_empty == True:
150adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
151adfe2030SMax Reitz        else:
152adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
153adfe2030SMax Reitz
154adfe2030SMax Reitz    def test_tray_eject_close(self):
155adfe2030SMax Reitz        result = self.vm.qmp('eject', device='drive0', force=True)
156adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
157adfe2030SMax Reitz
158adfe2030SMax Reitz        self.wait_for_open()
159adfe2030SMax Reitz
160adfe2030SMax Reitz        result = self.vm.qmp('query-block')
161abb3e55bSMax Reitz        if self.has_real_tray:
162adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
163adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
164adfe2030SMax Reitz
165adfe2030SMax Reitz        result = self.vm.qmp('blockdev-close-tray', device='drive0')
166adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
167adfe2030SMax Reitz
168adfe2030SMax Reitz        self.wait_for_close()
169adfe2030SMax Reitz
170adfe2030SMax Reitz        result = self.vm.qmp('query-block')
171adfe2030SMax Reitz        if self.has_real_tray:
172adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
173adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
174adfe2030SMax Reitz
175adfe2030SMax Reitz    def test_tray_open_change(self):
176adfe2030SMax Reitz        result = self.vm.qmp('blockdev-open-tray', device='drive0', 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
189adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
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
201adfe2030SMax Reitz    def test_cycle(self):
202adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
203adfe2030SMax Reitz                             options={'node-name': 'new',
204adfe2030SMax Reitz                                      'driver': iotests.imgfmt,
205adfe2030SMax Reitz                                      'file': {'filename': new_img,
206adfe2030SMax Reitz                                               'driver': 'file'}})
207adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
208adfe2030SMax Reitz
209adfe2030SMax Reitz        result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
210adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
211adfe2030SMax Reitz
212adfe2030SMax Reitz        self.wait_for_open()
213adfe2030SMax Reitz
214adfe2030SMax Reitz        result = self.vm.qmp('query-block')
215abb3e55bSMax Reitz        if self.has_real_tray:
216adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
217adfe2030SMax Reitz        if self.was_empty == True:
218adfe2030SMax Reitz            self.assert_qmp_absent(result, 'return[0]/inserted')
219adfe2030SMax Reitz        else:
220adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
221adfe2030SMax Reitz
2226e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
223adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
224adfe2030SMax Reitz
225adfe2030SMax Reitz        result = self.vm.qmp('query-block')
226abb3e55bSMax Reitz        if self.has_real_tray:
227adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
228adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
229adfe2030SMax Reitz
2306e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
231adfe2030SMax Reitz                                                       node_name='new')
232adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
233adfe2030SMax Reitz
234adfe2030SMax Reitz        result = self.vm.qmp('query-block')
235abb3e55bSMax Reitz        if self.has_real_tray:
236adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', True)
237adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
238adfe2030SMax Reitz
239adfe2030SMax Reitz        result = self.vm.qmp('blockdev-close-tray', device='drive0')
240adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
241adfe2030SMax Reitz
242adfe2030SMax Reitz        self.wait_for_close()
243adfe2030SMax Reitz
244adfe2030SMax Reitz        result = self.vm.qmp('query-block')
245abb3e55bSMax Reitz        if self.has_real_tray:
246adfe2030SMax Reitz            self.assert_qmp(result, 'return[0]/tray_open', False)
247adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
248adfe2030SMax Reitz
249adfe2030SMax Reitz    def test_close_on_closed(self):
250adfe2030SMax Reitz        result = self.vm.qmp('blockdev-close-tray', device='drive0')
251adfe2030SMax Reitz        # Should be a no-op
252adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
253adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
254adfe2030SMax Reitz
255adfe2030SMax Reitz    def test_remove_on_closed(self):
256abb3e55bSMax Reitz        if not self.has_real_tray:
257adfe2030SMax Reitz            return
258adfe2030SMax Reitz
2596e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
260adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
261adfe2030SMax Reitz
262adfe2030SMax Reitz    def test_insert_on_closed(self):
263abb3e55bSMax Reitz        if not self.has_real_tray:
264adfe2030SMax Reitz            return
265adfe2030SMax Reitz
266adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
267adfe2030SMax Reitz                             options={'node-name': 'new',
268adfe2030SMax Reitz                                      'driver': iotests.imgfmt,
269adfe2030SMax Reitz                                      'file': {'filename': new_img,
270adfe2030SMax Reitz                                               'driver': 'file'}})
271adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
272adfe2030SMax Reitz
2736e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
274adfe2030SMax Reitz                                                       node_name='new')
275adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
276adfe2030SMax Reitz
277adfe2030SMax Reitzclass TestInitiallyFilled(GeneralChangeTestsBaseClass):
278adfe2030SMax Reitz    was_empty = False
279adfe2030SMax Reitz
280adfe2030SMax Reitz    def setUp(self, media, interface):
281adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
282adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
283adfe2030SMax Reitz        self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface)
284adfe2030SMax Reitz        self.vm.launch()
285adfe2030SMax Reitz
286adfe2030SMax Reitz    def tearDown(self):
287adfe2030SMax Reitz        self.vm.shutdown()
288adfe2030SMax Reitz        os.remove(old_img)
289adfe2030SMax Reitz        os.remove(new_img)
290adfe2030SMax Reitz
291adfe2030SMax Reitz    def test_insert_on_filled(self):
292adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
293adfe2030SMax Reitz                             options={'node-name': 'new',
294adfe2030SMax Reitz                                      'driver': iotests.imgfmt,
295adfe2030SMax Reitz                                      'file': {'filename': new_img,
296adfe2030SMax Reitz                                               'driver': 'file'}})
297adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
298adfe2030SMax Reitz
299adfe2030SMax Reitz        result = self.vm.qmp('blockdev-open-tray', device='drive0')
300adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
301adfe2030SMax Reitz
302adfe2030SMax Reitz        self.wait_for_open()
303adfe2030SMax Reitz
3046e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
305adfe2030SMax Reitz                                                       node_name='new')
306adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
307adfe2030SMax Reitz
308adfe2030SMax Reitzclass TestInitiallyEmpty(GeneralChangeTestsBaseClass):
309adfe2030SMax Reitz    was_empty = True
310adfe2030SMax Reitz
311adfe2030SMax Reitz    def setUp(self, media, interface):
312adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
313adfe2030SMax Reitz        self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
314adfe2030SMax Reitz        self.vm.launch()
315adfe2030SMax Reitz
316adfe2030SMax Reitz    def tearDown(self):
317adfe2030SMax Reitz        self.vm.shutdown()
318adfe2030SMax Reitz        os.remove(new_img)
319adfe2030SMax Reitz
320adfe2030SMax Reitz    def test_remove_on_empty(self):
321adfe2030SMax Reitz        result = self.vm.qmp('blockdev-open-tray', device='drive0')
322adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
323adfe2030SMax Reitz
324adfe2030SMax Reitz        self.wait_for_open()
325adfe2030SMax Reitz
3266e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
327adfe2030SMax Reitz        # Should be a no-op
328adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
329adfe2030SMax Reitz
330adfe2030SMax Reitzclass TestCDInitiallyFilled(TestInitiallyFilled):
331adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
332adfe2030SMax Reitz    has_real_tray = True
333adfe2030SMax Reitz
334adfe2030SMax Reitz    def setUp(self):
335adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
336adfe2030SMax Reitz
337adfe2030SMax Reitzclass TestCDInitiallyEmpty(TestInitiallyEmpty):
338adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
339adfe2030SMax Reitz    has_real_tray = True
340adfe2030SMax Reitz
341adfe2030SMax Reitz    def setUp(self):
342adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
343adfe2030SMax Reitz
344adfe2030SMax Reitzclass TestFloppyInitiallyFilled(TestInitiallyFilled):
345adfe2030SMax Reitz    TestInitiallyFilled = TestInitiallyFilled
346adfe2030SMax Reitz    has_real_tray = False
347adfe2030SMax Reitz
348adfe2030SMax Reitz    def setUp(self):
349adfe2030SMax Reitz        self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
350adfe2030SMax Reitz
351adfe2030SMax Reitzclass TestFloppyInitiallyEmpty(TestInitiallyEmpty):
352adfe2030SMax Reitz    TestInitiallyEmpty = TestInitiallyEmpty
353adfe2030SMax Reitz    has_real_tray = False
354adfe2030SMax Reitz
355adfe2030SMax Reitz    def setUp(self):
356adfe2030SMax Reitz        self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
357adfe2030SMax Reitz        # FDDs not having a real tray and there not being a medium inside the
358adfe2030SMax Reitz        # tray at startup means the tray will be considered open
359adfe2030SMax Reitz        self.has_opened = True
360adfe2030SMax Reitz
361adfe2030SMax Reitzclass TestChangeReadOnly(ChangeBaseClass):
362adfe2030SMax Reitz    def setUp(self):
363adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
364adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
365adfe2030SMax Reitz        self.vm = iotests.VM()
366adfe2030SMax Reitz
367adfe2030SMax Reitz    def tearDown(self):
368adfe2030SMax Reitz        self.vm.shutdown()
369adfe2030SMax Reitz        os.chmod(old_img, 0666)
370adfe2030SMax Reitz        os.chmod(new_img, 0666)
371adfe2030SMax Reitz        os.remove(old_img)
372adfe2030SMax Reitz        os.remove(new_img)
373adfe2030SMax Reitz
374adfe2030SMax Reitz    def test_ro_ro_retain(self):
375adfe2030SMax Reitz        os.chmod(old_img, 0444)
376adfe2030SMax Reitz        os.chmod(new_img, 0444)
377adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
378adfe2030SMax Reitz        self.vm.launch()
379adfe2030SMax Reitz
380adfe2030SMax Reitz        result = self.vm.qmp('query-block')
381adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
382adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
383adfe2030SMax Reitz
384adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
385adfe2030SMax Reitz                                                       filename=new_img,
386adfe2030SMax Reitz                                                       format=iotests.imgfmt,
387adfe2030SMax Reitz                                                       read_only_mode='retain')
388adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
389adfe2030SMax Reitz
390adfe2030SMax Reitz        result = self.vm.qmp('query-block')
391adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
392adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
393adfe2030SMax Reitz
394adfe2030SMax Reitz    def test_ro_rw_retain(self):
395adfe2030SMax Reitz        os.chmod(old_img, 0444)
396adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
397adfe2030SMax Reitz        self.vm.launch()
398adfe2030SMax Reitz
399adfe2030SMax Reitz        result = self.vm.qmp('query-block')
400adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
401adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
402adfe2030SMax Reitz
403adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
404adfe2030SMax Reitz                                                       filename=new_img,
405adfe2030SMax Reitz                                                       format=iotests.imgfmt,
406adfe2030SMax Reitz                                                       read_only_mode='retain')
407adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
408adfe2030SMax Reitz
409adfe2030SMax Reitz        result = self.vm.qmp('query-block')
410adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
411adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
412adfe2030SMax Reitz
413adfe2030SMax Reitz    def test_rw_ro_retain(self):
414adfe2030SMax Reitz        os.chmod(new_img, 0444)
415adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
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', False)
420adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
421adfe2030SMax Reitz
422adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
423adfe2030SMax Reitz                                                       filename=new_img,
424adfe2030SMax Reitz                                                       format=iotests.imgfmt,
425adfe2030SMax Reitz                                                       read_only_mode='retain')
426adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
427adfe2030SMax Reitz
428adfe2030SMax Reitz        self.assertEquals(self.vm.get_qmp_events(wait=False), [])
429adfe2030SMax Reitz
430adfe2030SMax Reitz        result = self.vm.qmp('query-block')
431adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
432adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
433adfe2030SMax Reitz
434adfe2030SMax Reitz    def test_ro_rw(self):
435adfe2030SMax Reitz        os.chmod(old_img, 0444)
436adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
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', True)
441adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
442adfe2030SMax Reitz
443adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
444adfe2030SMax Reitz                             device='drive0',
445adfe2030SMax Reitz                             filename=new_img,
446adfe2030SMax Reitz                             format=iotests.imgfmt,
447adfe2030SMax Reitz                             read_only_mode='read-write')
448adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
449adfe2030SMax Reitz
450adfe2030SMax Reitz        result = self.vm.qmp('query-block')
451adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
452adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
453adfe2030SMax Reitz
454adfe2030SMax Reitz    def test_rw_ro(self):
455adfe2030SMax Reitz        os.chmod(new_img, 0444)
456adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
457adfe2030SMax Reitz        self.vm.launch()
458adfe2030SMax Reitz
459adfe2030SMax Reitz        result = self.vm.qmp('query-block')
460adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
461adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
462adfe2030SMax Reitz
463adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
464adfe2030SMax Reitz                             device='drive0',
465adfe2030SMax Reitz                             filename=new_img,
466adfe2030SMax Reitz                             format=iotests.imgfmt,
467adfe2030SMax Reitz                             read_only_mode='read-only')
468adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
469adfe2030SMax Reitz
470adfe2030SMax Reitz        result = self.vm.qmp('query-block')
471adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
472adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
473adfe2030SMax Reitz
474adfe2030SMax Reitz    def test_make_rw_ro(self):
475adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
476adfe2030SMax Reitz        self.vm.launch()
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', old_img)
481adfe2030SMax Reitz
482adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
483adfe2030SMax Reitz                             device='drive0',
484adfe2030SMax Reitz                             filename=new_img,
485adfe2030SMax Reitz                             format=iotests.imgfmt,
486adfe2030SMax Reitz                             read_only_mode='read-only')
487adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
488adfe2030SMax Reitz
489adfe2030SMax Reitz        result = self.vm.qmp('query-block')
490adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
491adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
492adfe2030SMax Reitz
493adfe2030SMax Reitz    def test_make_ro_rw(self):
494adfe2030SMax Reitz        os.chmod(new_img, 0444)
495adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
496adfe2030SMax Reitz        self.vm.launch()
497adfe2030SMax Reitz
498adfe2030SMax Reitz        result = self.vm.qmp('query-block')
499adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
500adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
501adfe2030SMax Reitz
502adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium',
503adfe2030SMax Reitz                             device='drive0',
504adfe2030SMax Reitz                             filename=new_img,
505adfe2030SMax Reitz                             format=iotests.imgfmt,
506adfe2030SMax Reitz                             read_only_mode='read-write')
507adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
508adfe2030SMax Reitz
509adfe2030SMax Reitz        result = self.vm.qmp('query-block')
510adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
511adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
512adfe2030SMax Reitz
513adfe2030SMax Reitz    def test_make_rw_ro_by_retain(self):
514adfe2030SMax Reitz        os.chmod(old_img, 0444)
515adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
516adfe2030SMax Reitz        self.vm.launch()
517adfe2030SMax Reitz
518adfe2030SMax Reitz        result = self.vm.qmp('query-block')
519adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
520adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
521adfe2030SMax Reitz
522adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
523adfe2030SMax Reitz                                                       filename=new_img,
524adfe2030SMax Reitz                                                       format=iotests.imgfmt,
525adfe2030SMax Reitz                                                       read_only_mode='retain')
526adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
527adfe2030SMax Reitz
528adfe2030SMax Reitz        result = self.vm.qmp('query-block')
529adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
530adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
531adfe2030SMax Reitz
532adfe2030SMax Reitz    def test_make_ro_rw_by_retain(self):
533adfe2030SMax Reitz        os.chmod(new_img, 0444)
534adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
535adfe2030SMax Reitz        self.vm.launch()
536adfe2030SMax Reitz
537adfe2030SMax Reitz        result = self.vm.qmp('query-block')
538adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
539adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
540adfe2030SMax Reitz
541adfe2030SMax Reitz        result = self.vm.qmp('blockdev-change-medium', device='drive0',
542adfe2030SMax Reitz                                                       filename=new_img,
543adfe2030SMax Reitz                                                       format=iotests.imgfmt,
544adfe2030SMax Reitz                                                       read_only_mode='retain')
545adfe2030SMax Reitz        self.assert_qmp(result, 'error/class', 'GenericError')
546adfe2030SMax Reitz
547adfe2030SMax Reitz        result = self.vm.qmp('query-block')
548adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
549adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
550adfe2030SMax Reitz
551adfe2030SMax Reitz    def test_rw_ro_cycle(self):
552adfe2030SMax Reitz        os.chmod(new_img, 0444)
553adfe2030SMax Reitz        self.vm.add_drive(old_img, 'media=disk', 'floppy')
554adfe2030SMax Reitz        self.vm.launch()
555adfe2030SMax Reitz
556adfe2030SMax Reitz        result = self.vm.qmp('query-block')
557adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
558adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
559adfe2030SMax Reitz
560adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
561adfe2030SMax Reitz                             options={'node-name': 'new',
562adfe2030SMax Reitz                                      'driver': iotests.imgfmt,
563adfe2030SMax Reitz                                      'read-only': True,
564adfe2030SMax Reitz                                      'file': {'filename': new_img,
565adfe2030SMax Reitz                                               'driver': 'file'}})
566adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
567adfe2030SMax Reitz
568adfe2030SMax Reitz        result = self.vm.qmp('query-block')
569adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', False)
570adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
571adfe2030SMax Reitz
5726e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
573adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
574adfe2030SMax Reitz
575adfe2030SMax Reitz        result = self.vm.qmp('query-block')
576adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
577adfe2030SMax Reitz
5786e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
579adfe2030SMax Reitz                                                       node_name='new')
580adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
581adfe2030SMax Reitz
582adfe2030SMax Reitz        result = self.vm.qmp('query-block')
583adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
584adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
585adfe2030SMax Reitz
586adfe2030SMax Reitz        result = self.vm.qmp('query-block')
587adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/ro', True)
588adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
589adfe2030SMax Reitz
590adfe2030SMax ReitzGeneralChangeTestsBaseClass = None
591adfe2030SMax ReitzTestInitiallyFilled = None
592adfe2030SMax ReitzTestInitiallyEmpty = None
593adfe2030SMax Reitz
594adfe2030SMax Reitz
595adfe2030SMax Reitzclass TestBlockJobsAfterCycle(ChangeBaseClass):
596adfe2030SMax Reitz    def setUp(self):
597adfe2030SMax Reitz        qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
598adfe2030SMax Reitz
599adfe2030SMax Reitz        self.vm = iotests.VM()
600adfe2030SMax Reitz        self.vm.launch()
601adfe2030SMax Reitz
602adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
603adfe2030SMax Reitz                             options={'id': 'drive0',
604adfe2030SMax Reitz                                      'driver': 'null-co'})
605adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
606adfe2030SMax Reitz
607adfe2030SMax Reitz        result = self.vm.qmp('query-block')
608adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
609adfe2030SMax Reitz
610adfe2030SMax Reitz        # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
611adfe2030SMax Reitz        # is not necessary
6126e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
613adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
614adfe2030SMax Reitz
615adfe2030SMax Reitz        result = self.vm.qmp('query-block')
616adfe2030SMax Reitz        self.assert_qmp_absent(result, 'return[0]/inserted')
617adfe2030SMax Reitz
618adfe2030SMax Reitz        result = self.vm.qmp('blockdev-add',
619adfe2030SMax Reitz                             options={'node-name': 'node0',
620adfe2030SMax Reitz                                      'driver': iotests.imgfmt,
621adfe2030SMax Reitz                                      'file': {'filename': old_img,
622adfe2030SMax Reitz                                               'driver': 'file'}})
623adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
624adfe2030SMax Reitz
6256e0abc25SMax Reitz        result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
626adfe2030SMax Reitz                                                       node_name='node0')
627adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
628adfe2030SMax Reitz
629adfe2030SMax Reitz        result = self.vm.qmp('query-block')
630adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
631adfe2030SMax Reitz
632adfe2030SMax Reitz    def tearDown(self):
633adfe2030SMax Reitz        self.vm.shutdown()
634adfe2030SMax Reitz        os.remove(old_img)
635adfe2030SMax Reitz        try:
636adfe2030SMax Reitz            os.remove(new_img)
637adfe2030SMax Reitz        except OSError:
638adfe2030SMax Reitz            pass
639adfe2030SMax Reitz
640adfe2030SMax Reitz    def test_snapshot_and_commit(self):
641adfe2030SMax Reitz        # We need backing file support
642adfe2030SMax Reitz        if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
643adfe2030SMax Reitz            return
644adfe2030SMax Reitz
645adfe2030SMax Reitz        result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
646adfe2030SMax Reitz                                                       snapshot_file=new_img,
647adfe2030SMax Reitz                                                       format=iotests.imgfmt)
648adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
649adfe2030SMax Reitz
650adfe2030SMax Reitz        result = self.vm.qmp('query-block')
651adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
652adfe2030SMax Reitz        self.assert_qmp(result,
653adfe2030SMax Reitz                        'return[0]/inserted/image/backing-image/filename',
654adfe2030SMax Reitz                        old_img)
655adfe2030SMax Reitz
656adfe2030SMax Reitz        result = self.vm.qmp('block-commit', device='drive0')
657adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
658adfe2030SMax Reitz
659adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_READY')
660adfe2030SMax Reitz
661adfe2030SMax Reitz        result = self.vm.qmp('query-block-jobs')
662adfe2030SMax Reitz        self.assert_qmp(result, 'return[0]/device', 'drive0')
663adfe2030SMax Reitz
664adfe2030SMax Reitz        result = self.vm.qmp('block-job-complete', device='drive0')
665adfe2030SMax Reitz        self.assert_qmp(result, 'return', {})
666adfe2030SMax Reitz
667adfe2030SMax Reitz        self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
668adfe2030SMax Reitz
669adfe2030SMax Reitz
670adfe2030SMax Reitzif __name__ == '__main__':
671adfe2030SMax Reitz    if iotests.qemu_default_machine != 'pc':
672adfe2030SMax Reitz        # We need floppy and IDE CD-ROM
673adfe2030SMax Reitz        iotests.notrun('not suitable for this machine type: %s' %
674adfe2030SMax Reitz                       iotests.qemu_default_machine)
675*cc8c46b7SMax Reitz    # Need to support image creation
676*cc8c46b7SMax Reitz    iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
677*cc8c46b7SMax Reitz                                 'vmdk', 'raw', 'vhdx', 'qed'])
678