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