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