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