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