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 def test_rw_ro_retain(self): 450 os.chmod(new_img, 0o444) 451 self.vm.add_drive(old_img, 'media=disk', 'none') 452 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 453 self.vm.launch() 454 455 result = self.vm.qmp('query-block') 456 self.assert_qmp(result, 'return[0]/inserted/ro', False) 457 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 458 459 result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 460 filename=new_img, 461 format=iotests.imgfmt, 462 read_only_mode='retain') 463 self.assert_qmp(result, 'error/class', 'GenericError') 464 465 self.assertEqual(self.vm.get_qmp_events(wait=False), []) 466 467 result = self.vm.qmp('query-block') 468 self.assert_qmp(result, 'return[0]/inserted/ro', False) 469 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 470 471 def test_ro_rw(self): 472 os.chmod(old_img, 0o444) 473 self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 474 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 475 self.vm.launch() 476 477 result = self.vm.qmp('query-block') 478 self.assert_qmp(result, 'return[0]/inserted/ro', True) 479 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 480 481 result = self.vm.qmp('blockdev-change-medium', 482 id=self.device_name, 483 filename=new_img, 484 format=iotests.imgfmt, 485 read_only_mode='read-write') 486 self.assert_qmp(result, 'return', {}) 487 488 result = self.vm.qmp('query-block') 489 self.assert_qmp(result, 'return[0]/inserted/ro', False) 490 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 491 492 def test_rw_ro(self): 493 os.chmod(new_img, 0o444) 494 self.vm.add_drive(old_img, 'media=disk', 'none') 495 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 496 self.vm.launch() 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', old_img) 501 502 result = self.vm.qmp('blockdev-change-medium', 503 id=self.device_name, 504 filename=new_img, 505 format=iotests.imgfmt, 506 read_only_mode='read-only') 507 self.assert_qmp(result, 'return', {}) 508 509 result = self.vm.qmp('query-block') 510 self.assert_qmp(result, 'return[0]/inserted/ro', True) 511 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 512 513 def test_make_rw_ro(self): 514 self.vm.add_drive(old_img, 'media=disk', 'none') 515 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 516 self.vm.launch() 517 518 result = self.vm.qmp('query-block') 519 self.assert_qmp(result, 'return[0]/inserted/ro', False) 520 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 521 522 result = self.vm.qmp('blockdev-change-medium', 523 id=self.device_name, 524 filename=new_img, 525 format=iotests.imgfmt, 526 read_only_mode='read-only') 527 self.assert_qmp(result, 'return', {}) 528 529 result = self.vm.qmp('query-block') 530 self.assert_qmp(result, 'return[0]/inserted/ro', True) 531 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 532 533 def test_make_ro_rw(self): 534 os.chmod(new_img, 0o444) 535 self.vm.add_drive(old_img, 'media=disk', 'none') 536 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 537 self.vm.launch() 538 539 result = self.vm.qmp('query-block') 540 self.assert_qmp(result, 'return[0]/inserted/ro', False) 541 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 542 543 result = self.vm.qmp('blockdev-change-medium', 544 id=self.device_name, 545 filename=new_img, 546 format=iotests.imgfmt, 547 read_only_mode='read-write') 548 self.assert_qmp(result, 'error/class', 'GenericError') 549 550 result = self.vm.qmp('query-block') 551 self.assert_qmp(result, 'return[0]/inserted/ro', False) 552 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 553 554 def test_make_rw_ro_by_retain(self): 555 os.chmod(old_img, 0o444) 556 self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none') 557 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 558 self.vm.launch() 559 560 result = self.vm.qmp('query-block') 561 self.assert_qmp(result, 'return[0]/inserted/ro', True) 562 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 563 564 result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 565 filename=new_img, 566 format=iotests.imgfmt, 567 read_only_mode='retain') 568 self.assert_qmp(result, 'return', {}) 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', new_img) 573 574 def test_make_ro_rw_by_retain(self): 575 os.chmod(new_img, 0o444) 576 self.vm.add_drive(old_img, 'media=disk', 'none') 577 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 578 self.vm.launch() 579 580 result = self.vm.qmp('query-block') 581 self.assert_qmp(result, 'return[0]/inserted/ro', False) 582 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 583 584 result = self.vm.qmp('blockdev-change-medium', id=self.device_name, 585 filename=new_img, 586 format=iotests.imgfmt, 587 read_only_mode='retain') 588 self.assert_qmp(result, 'error/class', 'GenericError') 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 def test_rw_ro_cycle(self): 595 os.chmod(new_img, 0o444) 596 self.vm.add_drive(old_img, 'media=disk', 'none') 597 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 598 self.vm.launch() 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 result = self.vm.qmp('blockdev-add', 605 node_name='new', 606 driver=iotests.imgfmt, 607 read_only=True, 608 file={'filename': new_img, 609 'driver': 'file'}) 610 self.assert_qmp(result, 'return', {}) 611 612 result = self.vm.qmp('query-block') 613 self.assert_qmp(result, 'return[0]/inserted/ro', False) 614 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 615 616 result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 617 self.assert_qmp(result, 'return', {}) 618 619 result = self.vm.qmp('query-block') 620 self.assert_qmp_absent(result, 'return[0]/inserted') 621 622 result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 623 node_name='new') 624 self.assert_qmp(result, 'return', {}) 625 626 result = self.vm.qmp('query-block') 627 self.assert_qmp(result, 'return[0]/inserted/ro', True) 628 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 629 630 result = self.vm.qmp('query-block') 631 self.assert_qmp(result, 'return[0]/inserted/ro', True) 632 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 633 634GeneralChangeTestsBaseClass = None 635TestInitiallyFilled = None 636TestInitiallyEmpty = None 637 638 639class TestBlockJobsAfterCycle(ChangeBaseClass): 640 device_name = 'qdev0' 641 642 def setUp(self): 643 qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K') 644 645 self.vm = iotests.VM() 646 self.vm.add_drive_raw("id=drive0,driver=null-co,if=none") 647 self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name) 648 self.vm.launch() 649 650 result = self.vm.qmp('query-block') 651 self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co') 652 653 # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray 654 # is not necessary 655 result = self.vm.qmp('blockdev-remove-medium', id=self.device_name) 656 self.assert_qmp(result, 'return', {}) 657 658 result = self.vm.qmp('query-block') 659 self.assert_qmp_absent(result, 'return[0]/inserted') 660 661 result = self.vm.qmp('blockdev-add', 662 node_name='node0', 663 driver=iotests.imgfmt, 664 file={'filename': old_img, 665 'driver': 'file'}) 666 self.assert_qmp(result, 'return', {}) 667 668 result = self.vm.qmp('blockdev-insert-medium', id=self.device_name, 669 node_name='node0') 670 self.assert_qmp(result, 'return', {}) 671 672 result = self.vm.qmp('query-block') 673 self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img) 674 675 def tearDown(self): 676 self.vm.shutdown() 677 os.remove(old_img) 678 try: 679 os.remove(new_img) 680 except OSError: 681 pass 682 683 def test_snapshot_and_commit(self): 684 # We need backing file support 685 if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed': 686 return 687 688 result = self.vm.qmp('blockdev-snapshot-sync', device='drive0', 689 snapshot_file=new_img, 690 format=iotests.imgfmt) 691 self.assert_qmp(result, 'return', {}) 692 693 result = self.vm.qmp('query-block') 694 self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img) 695 self.assert_qmp(result, 696 'return[0]/inserted/image/backing-image/filename', 697 old_img) 698 699 result = self.vm.qmp('block-commit', device='drive0') 700 self.assert_qmp(result, 'return', {}) 701 702 self.vm.event_wait(name='BLOCK_JOB_READY') 703 704 result = self.vm.qmp('query-block-jobs') 705 self.assert_qmp(result, 'return[0]/device', 'drive0') 706 707 result = self.vm.qmp('block-job-complete', device='drive0') 708 self.assert_qmp(result, 'return', {}) 709 710 self.vm.event_wait(name='BLOCK_JOB_COMPLETED') 711 712 713if __name__ == '__main__': 714 if iotests.qemu_default_machine != 'pc': 715 # We need floppy and IDE CD-ROM 716 iotests.notrun('not suitable for this machine type: %s' % 717 iotests.qemu_default_machine) 718 # Need to support image creation 719 iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2', 720 'vmdk', 'raw', 'vhdx', 'qed'], 721 supported_protocols=['file']) 722