]>
Commit | Line | Data |
---|---|---|
adfe2030 HR |
1 | #!/usr/bin/env python |
2 | # | |
3 | # Test case for the QMP 'change' command and all other associated | |
4 | # commands | |
5 | # | |
6 | # Copyright (C) 2015 Red Hat, Inc. | |
7 | # | |
8 | # This program is free software; you can redistribute it and/or modify | |
9 | # it under the terms of the GNU General Public License as published by | |
10 | # the Free Software Foundation; either version 2 of the License, or | |
11 | # (at your option) any later version. | |
12 | # | |
13 | # This program is distributed in the hope that it will be useful, | |
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | # GNU General Public License for more details. | |
17 | # | |
18 | # You should have received a copy of the GNU General Public License | |
19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 | # | |
21 | ||
22 | import os | |
23 | import stat | |
24 | import time | |
25 | import iotests | |
26 | from iotests import qemu_img | |
27 | ||
28 | old_img = os.path.join(iotests.test_dir, 'test0.img') | |
29 | new_img = os.path.join(iotests.test_dir, 'test1.img') | |
30 | ||
31 | class ChangeBaseClass(iotests.QMPTestCase): | |
32 | has_opened = False | |
33 | has_closed = False | |
34 | ||
35 | def process_events(self): | |
36 | for event in self.vm.get_qmp_events(wait=False): | |
37 | if (event['event'] == 'DEVICE_TRAY_MOVED' and | |
38 | event['data']['device'] == 'drive0'): | |
39 | if event['data']['tray-open'] == False: | |
40 | self.has_closed = True | |
41 | else: | |
42 | self.has_opened = True | |
43 | ||
44 | def wait_for_open(self): | |
abb3e55b HR |
45 | if not self.has_real_tray: |
46 | return | |
47 | ||
adfe2030 HR |
48 | timeout = time.clock() + 3 |
49 | while not self.has_opened and time.clock() < timeout: | |
50 | self.process_events() | |
51 | if not self.has_opened: | |
52 | self.fail('Timeout while waiting for the tray to open') | |
53 | ||
54 | def wait_for_close(self): | |
abb3e55b HR |
55 | if not self.has_real_tray: |
56 | return | |
57 | ||
adfe2030 HR |
58 | timeout = time.clock() + 3 |
59 | while not self.has_closed and time.clock() < timeout: | |
60 | self.process_events() | |
61 | if not self.has_opened: | |
62 | self.fail('Timeout while waiting for the tray to close') | |
63 | ||
64 | class GeneralChangeTestsBaseClass(ChangeBaseClass): | |
65 | def test_change(self): | |
66 | result = self.vm.qmp('change', device='drive0', target=new_img, | |
67 | arg=iotests.imgfmt) | |
68 | self.assert_qmp(result, 'return', {}) | |
69 | ||
70 | self.wait_for_open() | |
71 | self.wait_for_close() | |
72 | ||
73 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
74 | if self.has_real_tray: |
75 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
76 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
77 | ||
78 | def test_blockdev_change_medium(self): | |
79 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
80 | filename=new_img, | |
81 | format=iotests.imgfmt) | |
82 | self.assert_qmp(result, 'return', {}) | |
83 | ||
84 | self.wait_for_open() | |
85 | self.wait_for_close() | |
86 | ||
87 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
88 | if self.has_real_tray: |
89 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
90 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
91 | ||
92 | def test_eject(self): | |
93 | result = self.vm.qmp('eject', device='drive0', force=True) | |
94 | self.assert_qmp(result, 'return', {}) | |
95 | ||
96 | self.wait_for_open() | |
97 | ||
98 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
99 | if self.has_real_tray: |
100 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
101 | self.assert_qmp_absent(result, 'return[0]/inserted') |
102 | ||
103 | def test_tray_eject_change(self): | |
104 | result = self.vm.qmp('eject', device='drive0', force=True) | |
105 | self.assert_qmp(result, 'return', {}) | |
106 | ||
107 | self.wait_for_open() | |
108 | ||
109 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
110 | if self.has_real_tray: |
111 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
112 | self.assert_qmp_absent(result, 'return[0]/inserted') |
113 | ||
114 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
115 | filename=new_img, | |
116 | format=iotests.imgfmt) | |
117 | self.assert_qmp(result, 'return', {}) | |
118 | ||
119 | self.wait_for_close() | |
120 | ||
121 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
122 | if self.has_real_tray: |
123 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
124 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
125 | ||
126 | def test_tray_open_close(self): | |
127 | result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) | |
128 | self.assert_qmp(result, 'return', {}) | |
129 | ||
130 | self.wait_for_open() | |
131 | ||
132 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
133 | if self.has_real_tray: |
134 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
135 | if self.was_empty == True: |
136 | self.assert_qmp_absent(result, 'return[0]/inserted') | |
137 | else: | |
138 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
139 | ||
140 | result = self.vm.qmp('blockdev-close-tray', device='drive0') | |
141 | self.assert_qmp(result, 'return', {}) | |
142 | ||
143 | if self.has_real_tray or not self.was_empty: | |
144 | self.wait_for_close() | |
145 | ||
146 | result = self.vm.qmp('query-block') | |
abb3e55b | 147 | if self.has_real_tray: |
adfe2030 | 148 | self.assert_qmp(result, 'return[0]/tray_open', False) |
adfe2030 HR |
149 | if self.was_empty == True: |
150 | self.assert_qmp_absent(result, 'return[0]/inserted') | |
151 | else: | |
152 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
153 | ||
154 | def test_tray_eject_close(self): | |
155 | result = self.vm.qmp('eject', device='drive0', force=True) | |
156 | self.assert_qmp(result, 'return', {}) | |
157 | ||
158 | self.wait_for_open() | |
159 | ||
160 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
161 | if self.has_real_tray: |
162 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
163 | self.assert_qmp_absent(result, 'return[0]/inserted') |
164 | ||
165 | result = self.vm.qmp('blockdev-close-tray', device='drive0') | |
166 | self.assert_qmp(result, 'return', {}) | |
167 | ||
abb3e55b | 168 | self.wait_for_close() |
adfe2030 HR |
169 | |
170 | result = self.vm.qmp('query-block') | |
171 | if self.has_real_tray: | |
172 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
173 | self.assert_qmp_absent(result, 'return[0]/inserted') |
174 | ||
175 | def test_tray_open_change(self): | |
176 | result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) | |
177 | self.assert_qmp(result, 'return', {}) | |
178 | ||
179 | self.wait_for_open() | |
180 | ||
181 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
182 | if self.has_real_tray: |
183 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
184 | if self.was_empty == True: |
185 | self.assert_qmp_absent(result, 'return[0]/inserted') | |
186 | else: | |
187 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
188 | ||
189 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
190 | filename=new_img, | |
191 | format=iotests.imgfmt) | |
192 | self.assert_qmp(result, 'return', {}) | |
193 | ||
194 | self.wait_for_close() | |
195 | ||
196 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
197 | if self.has_real_tray: |
198 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
199 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
200 | ||
201 | def test_cycle(self): | |
202 | result = self.vm.qmp('blockdev-add', | |
203 | options={'node-name': 'new', | |
204 | 'driver': iotests.imgfmt, | |
205 | 'file': {'filename': new_img, | |
206 | 'driver': 'file'}}) | |
207 | self.assert_qmp(result, 'return', {}) | |
208 | ||
209 | result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True) | |
210 | self.assert_qmp(result, 'return', {}) | |
211 | ||
212 | self.wait_for_open() | |
213 | ||
214 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
215 | if self.has_real_tray: |
216 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
217 | if self.was_empty == True: |
218 | self.assert_qmp_absent(result, 'return[0]/inserted') | |
219 | else: | |
220 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
221 | ||
6e0abc25 | 222 | result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') |
adfe2030 HR |
223 | self.assert_qmp(result, 'return', {}) |
224 | ||
225 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
226 | if self.has_real_tray: |
227 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
228 | self.assert_qmp_absent(result, 'return[0]/inserted') |
229 | ||
6e0abc25 | 230 | result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', |
adfe2030 HR |
231 | node_name='new') |
232 | self.assert_qmp(result, 'return', {}) | |
233 | ||
234 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
235 | if self.has_real_tray: |
236 | self.assert_qmp(result, 'return[0]/tray_open', True) | |
adfe2030 HR |
237 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
238 | ||
239 | result = self.vm.qmp('blockdev-close-tray', device='drive0') | |
240 | self.assert_qmp(result, 'return', {}) | |
241 | ||
242 | self.wait_for_close() | |
243 | ||
244 | result = self.vm.qmp('query-block') | |
abb3e55b HR |
245 | if self.has_real_tray: |
246 | self.assert_qmp(result, 'return[0]/tray_open', False) | |
adfe2030 HR |
247 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) |
248 | ||
249 | def test_close_on_closed(self): | |
250 | result = self.vm.qmp('blockdev-close-tray', device='drive0') | |
251 | # Should be a no-op | |
252 | self.assert_qmp(result, 'return', {}) | |
253 | self.assertEquals(self.vm.get_qmp_events(wait=False), []) | |
254 | ||
255 | def test_remove_on_closed(self): | |
abb3e55b | 256 | if not self.has_real_tray: |
adfe2030 HR |
257 | return |
258 | ||
6e0abc25 | 259 | result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') |
adfe2030 HR |
260 | self.assert_qmp(result, 'error/class', 'GenericError') |
261 | ||
262 | def test_insert_on_closed(self): | |
abb3e55b | 263 | if not self.has_real_tray: |
adfe2030 HR |
264 | return |
265 | ||
266 | result = self.vm.qmp('blockdev-add', | |
267 | options={'node-name': 'new', | |
268 | 'driver': iotests.imgfmt, | |
269 | 'file': {'filename': new_img, | |
270 | 'driver': 'file'}}) | |
271 | self.assert_qmp(result, 'return', {}) | |
272 | ||
6e0abc25 | 273 | result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', |
adfe2030 HR |
274 | node_name='new') |
275 | self.assert_qmp(result, 'error/class', 'GenericError') | |
276 | ||
277 | class TestInitiallyFilled(GeneralChangeTestsBaseClass): | |
278 | was_empty = False | |
279 | ||
280 | def setUp(self, media, interface): | |
281 | qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') | |
282 | qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') | |
283 | self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface) | |
284 | self.vm.launch() | |
285 | ||
286 | def tearDown(self): | |
287 | self.vm.shutdown() | |
288 | os.remove(old_img) | |
289 | os.remove(new_img) | |
290 | ||
291 | def test_insert_on_filled(self): | |
292 | result = self.vm.qmp('blockdev-add', | |
293 | options={'node-name': 'new', | |
294 | 'driver': iotests.imgfmt, | |
295 | 'file': {'filename': new_img, | |
296 | 'driver': 'file'}}) | |
297 | self.assert_qmp(result, 'return', {}) | |
298 | ||
299 | result = self.vm.qmp('blockdev-open-tray', device='drive0') | |
300 | self.assert_qmp(result, 'return', {}) | |
301 | ||
302 | self.wait_for_open() | |
303 | ||
6e0abc25 | 304 | result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', |
adfe2030 HR |
305 | node_name='new') |
306 | self.assert_qmp(result, 'error/class', 'GenericError') | |
307 | ||
308 | class TestInitiallyEmpty(GeneralChangeTestsBaseClass): | |
309 | was_empty = True | |
310 | ||
311 | def setUp(self, media, interface): | |
312 | qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') | |
313 | self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface) | |
314 | self.vm.launch() | |
315 | ||
316 | def tearDown(self): | |
317 | self.vm.shutdown() | |
318 | os.remove(new_img) | |
319 | ||
320 | def test_remove_on_empty(self): | |
321 | result = self.vm.qmp('blockdev-open-tray', device='drive0') | |
322 | self.assert_qmp(result, 'return', {}) | |
323 | ||
324 | self.wait_for_open() | |
325 | ||
6e0abc25 | 326 | result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') |
adfe2030 HR |
327 | # Should be a no-op |
328 | self.assert_qmp(result, 'return', {}) | |
329 | ||
330 | class TestCDInitiallyFilled(TestInitiallyFilled): | |
331 | TestInitiallyFilled = TestInitiallyFilled | |
332 | has_real_tray = True | |
333 | ||
334 | def setUp(self): | |
335 | self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide') | |
336 | ||
337 | class TestCDInitiallyEmpty(TestInitiallyEmpty): | |
338 | TestInitiallyEmpty = TestInitiallyEmpty | |
339 | has_real_tray = True | |
340 | ||
341 | def setUp(self): | |
342 | self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide') | |
343 | ||
344 | class TestFloppyInitiallyFilled(TestInitiallyFilled): | |
345 | TestInitiallyFilled = TestInitiallyFilled | |
346 | has_real_tray = False | |
347 | ||
348 | def setUp(self): | |
349 | self.TestInitiallyFilled.setUp(self, 'disk', 'floppy') | |
350 | ||
351 | class TestFloppyInitiallyEmpty(TestInitiallyEmpty): | |
352 | TestInitiallyEmpty = TestInitiallyEmpty | |
353 | has_real_tray = False | |
354 | ||
355 | def setUp(self): | |
356 | self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy') | |
357 | # FDDs not having a real tray and there not being a medium inside the | |
358 | # tray at startup means the tray will be considered open | |
359 | self.has_opened = True | |
360 | ||
361 | class TestChangeReadOnly(ChangeBaseClass): | |
362 | def setUp(self): | |
363 | qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k') | |
364 | qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k') | |
365 | self.vm = iotests.VM() | |
366 | ||
367 | def tearDown(self): | |
368 | self.vm.shutdown() | |
369 | os.chmod(old_img, 0666) | |
370 | os.chmod(new_img, 0666) | |
371 | os.remove(old_img) | |
372 | os.remove(new_img) | |
373 | ||
374 | def test_ro_ro_retain(self): | |
375 | os.chmod(old_img, 0444) | |
376 | os.chmod(new_img, 0444) | |
377 | self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') | |
378 | self.vm.launch() | |
379 | ||
380 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
381 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
382 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
383 | ||
384 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
385 | filename=new_img, | |
386 | format=iotests.imgfmt, | |
387 | read_only_mode='retain') | |
388 | self.assert_qmp(result, 'return', {}) | |
389 | ||
adfe2030 | 390 | result = self.vm.qmp('query-block') |
adfe2030 HR |
391 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
392 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
393 | ||
394 | def test_ro_rw_retain(self): | |
395 | os.chmod(old_img, 0444) | |
396 | self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') | |
397 | self.vm.launch() | |
398 | ||
399 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
400 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
401 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
402 | ||
403 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
404 | filename=new_img, | |
405 | format=iotests.imgfmt, | |
406 | read_only_mode='retain') | |
407 | self.assert_qmp(result, 'return', {}) | |
408 | ||
adfe2030 | 409 | result = self.vm.qmp('query-block') |
adfe2030 HR |
410 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
411 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
412 | ||
413 | def test_rw_ro_retain(self): | |
414 | os.chmod(new_img, 0444) | |
415 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
416 | self.vm.launch() | |
417 | ||
418 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
419 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
420 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
421 | ||
422 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
423 | filename=new_img, | |
424 | format=iotests.imgfmt, | |
425 | read_only_mode='retain') | |
426 | self.assert_qmp(result, 'error/class', 'GenericError') | |
427 | ||
428 | self.assertEquals(self.vm.get_qmp_events(wait=False), []) | |
429 | ||
430 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
431 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
432 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
433 | ||
434 | def test_ro_rw(self): | |
435 | os.chmod(old_img, 0444) | |
436 | self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') | |
437 | self.vm.launch() | |
438 | ||
439 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
440 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
441 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
442 | ||
443 | result = self.vm.qmp('blockdev-change-medium', | |
444 | device='drive0', | |
445 | filename=new_img, | |
446 | format=iotests.imgfmt, | |
447 | read_only_mode='read-write') | |
448 | self.assert_qmp(result, 'return', {}) | |
449 | ||
adfe2030 | 450 | result = self.vm.qmp('query-block') |
adfe2030 HR |
451 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
452 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
453 | ||
454 | def test_rw_ro(self): | |
455 | os.chmod(new_img, 0444) | |
456 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
457 | self.vm.launch() | |
458 | ||
459 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
460 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
461 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
462 | ||
463 | result = self.vm.qmp('blockdev-change-medium', | |
464 | device='drive0', | |
465 | filename=new_img, | |
466 | format=iotests.imgfmt, | |
467 | read_only_mode='read-only') | |
468 | self.assert_qmp(result, 'return', {}) | |
469 | ||
adfe2030 | 470 | result = self.vm.qmp('query-block') |
adfe2030 HR |
471 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
472 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
473 | ||
474 | def test_make_rw_ro(self): | |
475 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
476 | self.vm.launch() | |
477 | ||
478 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
479 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
480 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
481 | ||
482 | result = self.vm.qmp('blockdev-change-medium', | |
483 | device='drive0', | |
484 | filename=new_img, | |
485 | format=iotests.imgfmt, | |
486 | read_only_mode='read-only') | |
487 | self.assert_qmp(result, 'return', {}) | |
488 | ||
adfe2030 | 489 | result = self.vm.qmp('query-block') |
adfe2030 HR |
490 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
491 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
492 | ||
493 | def test_make_ro_rw(self): | |
494 | os.chmod(new_img, 0444) | |
495 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
496 | self.vm.launch() | |
497 | ||
498 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
499 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
500 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
501 | ||
502 | result = self.vm.qmp('blockdev-change-medium', | |
503 | device='drive0', | |
504 | filename=new_img, | |
505 | format=iotests.imgfmt, | |
506 | read_only_mode='read-write') | |
507 | self.assert_qmp(result, 'error/class', 'GenericError') | |
508 | ||
adfe2030 | 509 | result = self.vm.qmp('query-block') |
adfe2030 HR |
510 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
511 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
512 | ||
513 | def test_make_rw_ro_by_retain(self): | |
514 | os.chmod(old_img, 0444) | |
515 | self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy') | |
516 | self.vm.launch() | |
517 | ||
518 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
519 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
520 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
521 | ||
522 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
523 | filename=new_img, | |
524 | format=iotests.imgfmt, | |
525 | read_only_mode='retain') | |
526 | self.assert_qmp(result, 'return', {}) | |
527 | ||
adfe2030 | 528 | result = self.vm.qmp('query-block') |
adfe2030 HR |
529 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
530 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
531 | ||
532 | def test_make_ro_rw_by_retain(self): | |
533 | os.chmod(new_img, 0444) | |
534 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
535 | self.vm.launch() | |
536 | ||
537 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
538 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
539 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
540 | ||
541 | result = self.vm.qmp('blockdev-change-medium', device='drive0', | |
542 | filename=new_img, | |
543 | format=iotests.imgfmt, | |
544 | read_only_mode='retain') | |
545 | self.assert_qmp(result, 'error/class', 'GenericError') | |
546 | ||
adfe2030 | 547 | result = self.vm.qmp('query-block') |
adfe2030 HR |
548 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
549 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
550 | ||
551 | def test_rw_ro_cycle(self): | |
552 | os.chmod(new_img, 0444) | |
553 | self.vm.add_drive(old_img, 'media=disk', 'floppy') | |
554 | self.vm.launch() | |
555 | ||
556 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
557 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
558 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
559 | ||
560 | result = self.vm.qmp('blockdev-add', | |
561 | options={'node-name': 'new', | |
562 | 'driver': iotests.imgfmt, | |
563 | 'read-only': True, | |
564 | 'file': {'filename': new_img, | |
565 | 'driver': 'file'}}) | |
566 | self.assert_qmp(result, 'return', {}) | |
567 | ||
adfe2030 | 568 | result = self.vm.qmp('query-block') |
adfe2030 HR |
569 | self.assert_qmp(result, 'return[0]/inserted/ro', False) |
570 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) | |
571 | ||
6e0abc25 | 572 | result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') |
adfe2030 HR |
573 | self.assert_qmp(result, 'return', {}) |
574 | ||
575 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
576 | self.assert_qmp_absent(result, 'return[0]/inserted') |
577 | ||
6e0abc25 | 578 | result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', |
adfe2030 HR |
579 | node_name='new') |
580 | self.assert_qmp(result, 'return', {}) | |
581 | ||
582 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
583 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
584 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
585 | ||
adfe2030 | 586 | result = self.vm.qmp('query-block') |
adfe2030 HR |
587 | self.assert_qmp(result, 'return[0]/inserted/ro', True) |
588 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
589 | ||
590 | GeneralChangeTestsBaseClass = None | |
591 | TestInitiallyFilled = None | |
592 | TestInitiallyEmpty = None | |
593 | ||
594 | ||
595 | class TestBlockJobsAfterCycle(ChangeBaseClass): | |
596 | def setUp(self): | |
597 | qemu_img('create', '-f', iotests.imgfmt, old_img, '1M') | |
598 | ||
599 | self.vm = iotests.VM() | |
600 | self.vm.launch() | |
601 | ||
602 | result = self.vm.qmp('blockdev-add', | |
603 | options={'id': 'drive0', | |
604 | 'driver': 'null-co'}) | |
605 | self.assert_qmp(result, 'return', {}) | |
606 | ||
607 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
608 | self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') |
609 | ||
610 | # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray | |
611 | # is not necessary | |
6e0abc25 | 612 | result = self.vm.qmp('x-blockdev-remove-medium', device='drive0') |
adfe2030 HR |
613 | self.assert_qmp(result, 'return', {}) |
614 | ||
615 | result = self.vm.qmp('query-block') | |
616 | self.assert_qmp_absent(result, 'return[0]/inserted') | |
617 | ||
618 | result = self.vm.qmp('blockdev-add', | |
619 | options={'node-name': 'node0', | |
620 | 'driver': iotests.imgfmt, | |
621 | 'file': {'filename': old_img, | |
622 | 'driver': 'file'}}) | |
623 | self.assert_qmp(result, 'return', {}) | |
624 | ||
6e0abc25 | 625 | result = self.vm.qmp('x-blockdev-insert-medium', device='drive0', |
adfe2030 HR |
626 | node_name='node0') |
627 | self.assert_qmp(result, 'return', {}) | |
628 | ||
629 | result = self.vm.qmp('query-block') | |
adfe2030 HR |
630 | self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) |
631 | ||
632 | def tearDown(self): | |
633 | self.vm.shutdown() | |
634 | os.remove(old_img) | |
635 | try: | |
636 | os.remove(new_img) | |
637 | except OSError: | |
638 | pass | |
639 | ||
640 | def test_snapshot_and_commit(self): | |
641 | # We need backing file support | |
642 | if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': | |
643 | return | |
644 | ||
645 | result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', | |
646 | snapshot_file=new_img, | |
647 | format=iotests.imgfmt) | |
648 | self.assert_qmp(result, 'return', {}) | |
649 | ||
650 | result = self.vm.qmp('query-block') | |
651 | self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) | |
652 | self.assert_qmp(result, | |
653 | 'return[0]/inserted/image/backing-image/filename', | |
654 | old_img) | |
655 | ||
656 | result = self.vm.qmp('block-commit', device='drive0') | |
657 | self.assert_qmp(result, 'return', {}) | |
658 | ||
659 | self.vm.event_wait(name='BLOCK_JOB_READY') | |
660 | ||
661 | result = self.vm.qmp('query-block-jobs') | |
662 | self.assert_qmp(result, 'return[0]/device', 'drive0') | |
663 | ||
664 | result = self.vm.qmp('block-job-complete', device='drive0') | |
665 | self.assert_qmp(result, 'return', {}) | |
666 | ||
667 | self.vm.event_wait(name='BLOCK_JOB_COMPLETED') | |
668 | ||
669 | ||
670 | if __name__ == '__main__': | |
671 | if iotests.qemu_default_machine != 'pc': | |
672 | # We need floppy and IDE CD-ROM | |
673 | iotests.notrun('not suitable for this machine type: %s' % | |
674 | iotests.qemu_default_machine) | |
675 | iotests.main() |