1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3 2e5ca8fddSStefan Hajnoczi# 37c6a4ab8SFam Zheng# Tests for drive-backup and blockdev-backup 4e5ca8fddSStefan Hajnoczi# 57c6a4ab8SFam Zheng# Copyright (C) 2013, 2014 Red Hat, Inc. 6e5ca8fddSStefan Hajnoczi# 7e5ca8fddSStefan Hajnoczi# Based on 041. 8e5ca8fddSStefan Hajnoczi# 9e5ca8fddSStefan Hajnoczi# This program is free software; you can redistribute it and/or modify 10e5ca8fddSStefan Hajnoczi# it under the terms of the GNU General Public License as published by 11e5ca8fddSStefan Hajnoczi# the Free Software Foundation; either version 2 of the License, or 12e5ca8fddSStefan Hajnoczi# (at your option) any later version. 13e5ca8fddSStefan Hajnoczi# 14e5ca8fddSStefan Hajnoczi# This program is distributed in the hope that it will be useful, 15e5ca8fddSStefan Hajnoczi# but WITHOUT ANY WARRANTY; without even the implied warranty of 16e5ca8fddSStefan Hajnoczi# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17e5ca8fddSStefan Hajnoczi# GNU General Public License for more details. 18e5ca8fddSStefan Hajnoczi# 19e5ca8fddSStefan Hajnoczi# You should have received a copy of the GNU General Public License 20e5ca8fddSStefan Hajnoczi# along with this program. If not, see <http://www.gnu.org/licenses/>. 21e5ca8fddSStefan Hajnoczi# 22e5ca8fddSStefan Hajnoczi 23e5ca8fddSStefan Hajnocziimport time 24e5ca8fddSStefan Hajnocziimport os 25e5ca8fddSStefan Hajnocziimport iotests 26e5ca8fddSStefan Hajnoczifrom iotests import qemu_img, qemu_io 27e5ca8fddSStefan Hajnoczi 28e5ca8fddSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img') 29e5ca8fddSStefan Hajnoczitarget_img = os.path.join(iotests.test_dir, 'target.img') 307c6a4ab8SFam Zhengblockdev_target_img = os.path.join(iotests.test_dir, 'blockdev-target.img') 31e5ca8fddSStefan Hajnoczi 32e5ca8fddSStefan Hajnocziimage_len = 64 * 1024 * 1024 # MB 33e5ca8fddSStefan Hajnoczi 34819cec01SVladimir Sementsov-Ogievskiydef setUpModule(): 35819cec01SVladimir Sementsov-Ogievskiy qemu_img('create', '-f', iotests.imgfmt, test_img, str(image_len)) 36819cec01SVladimir Sementsov-Ogievskiy qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x11 0 64k', test_img) 37819cec01SVladimir Sementsov-Ogievskiy qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x00 64k 128k', test_img) 38819cec01SVladimir Sementsov-Ogievskiy qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x22 162k 32k', test_img) 3990c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) 4090c9b167SKevin Wolf qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) 41819cec01SVladimir Sementsov-Ogievskiy qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x33 67043328 64k', test_img) 42819cec01SVladimir Sementsov-Ogievskiy 43819cec01SVladimir Sementsov-Ogievskiydef tearDownModule(): 44819cec01SVladimir Sementsov-Ogievskiy os.remove(test_img) 45819cec01SVladimir Sementsov-Ogievskiy 46819cec01SVladimir Sementsov-Ogievskiy 47819cec01SVladimir Sementsov-Ogievskiyclass TestSingleDrive(iotests.QMPTestCase): 48819cec01SVladimir Sementsov-Ogievskiy def setUp(self): 49819cec01SVladimir Sementsov-Ogievskiy qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) 50e5ca8fddSStefan Hajnoczi 510a82a927SKevin Wolf self.vm = iotests.VM() 520a82a927SKevin Wolf self.vm.add_drive('blkdebug::' + test_img, 'node-name=source') 530a82a927SKevin Wolf self.vm.add_drive(blockdev_target_img, 'node-name=target', 540a82a927SKevin Wolf interface="none") 550ed82f7aSMax Reitz if iotests.qemu_default_machine == 'pc': 560ed82f7aSMax Reitz self.vm.add_drive(None, 'media=cdrom', 'ide') 57e5ca8fddSStefan Hajnoczi self.vm.launch() 58e5ca8fddSStefan Hajnoczi 59e5ca8fddSStefan Hajnoczi def tearDown(self): 60e5ca8fddSStefan Hajnoczi self.vm.shutdown() 617c6a4ab8SFam Zheng os.remove(blockdev_target_img) 62e5ca8fddSStefan Hajnoczi try: 63e5ca8fddSStefan Hajnoczi os.remove(target_img) 64e5ca8fddSStefan Hajnoczi except OSError: 65e5ca8fddSStefan Hajnoczi pass 66e5ca8fddSStefan Hajnoczi 677c6a4ab8SFam Zheng def do_test_cancel(self, cmd, target): 68e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 69e5ca8fddSStefan Hajnoczi 70bc11aee2SMax Reitz self.vm.pause_drive('drive0') 717c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') 72e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 73e5ca8fddSStefan Hajnoczi 74bc11aee2SMax Reitz event = self.cancel_and_wait(resume=True) 75e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 76e5ca8fddSStefan Hajnoczi 777c6a4ab8SFam Zheng def test_cancel_drive_backup(self): 787c6a4ab8SFam Zheng self.do_test_cancel('drive-backup', target_img) 797c6a4ab8SFam Zheng 807c6a4ab8SFam Zheng def test_cancel_blockdev_backup(self): 817c6a4ab8SFam Zheng self.do_test_cancel('blockdev-backup', 'drive1') 827c6a4ab8SFam Zheng 837c6a4ab8SFam Zheng def do_test_pause(self, cmd, target, image): 84e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 85e5ca8fddSStefan Hajnoczi 86b59b3d57SFam Zheng self.vm.pause_drive('drive0') 877c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', 887c6a4ab8SFam Zheng target=target, sync='full') 89e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 90e5ca8fddSStefan Hajnoczi 91f03d9d24SJohn Snow self.pause_job('drive0', wait=False) 92b59b3d57SFam Zheng self.vm.resume_drive('drive0') 93f03d9d24SJohn Snow self.pause_wait('drive0') 942c93c5cbSKevin Wolf 95e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 96e5ca8fddSStefan Hajnoczi offset = self.dictpath(result, 'return[0]/offset') 97e5ca8fddSStefan Hajnoczi 982c93c5cbSKevin Wolf time.sleep(0.5) 99e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 100e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/offset', offset) 101e5ca8fddSStefan Hajnoczi 102e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-resume', device='drive0') 103e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 104e5ca8fddSStefan Hajnoczi 105e5ca8fddSStefan Hajnoczi self.wait_until_completed() 106e5ca8fddSStefan Hajnoczi 107e5ca8fddSStefan Hajnoczi self.vm.shutdown() 1087c6a4ab8SFam Zheng self.assertTrue(iotests.compare_images(test_img, image), 109e5ca8fddSStefan Hajnoczi 'target image does not match source after backup') 110e5ca8fddSStefan Hajnoczi 1117c6a4ab8SFam Zheng def test_pause_drive_backup(self): 1127c6a4ab8SFam Zheng self.do_test_pause('drive-backup', target_img, target_img) 1137c6a4ab8SFam Zheng 1147c6a4ab8SFam Zheng def test_pause_blockdev_backup(self): 1157c6a4ab8SFam Zheng self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) 1167c6a4ab8SFam Zheng 1170a82a927SKevin Wolf def do_test_resize_blockdev_backup(self, device, node): 1180a82a927SKevin Wolf def pre_finalize(): 1190a82a927SKevin Wolf result = self.vm.qmp('block_resize', device=device, size=65536) 1200a82a927SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 1210a82a927SKevin Wolf 1220a82a927SKevin Wolf result = self.vm.qmp('block_resize', node_name=node, size=65536) 1230a82a927SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 1240a82a927SKevin Wolf 1250a82a927SKevin Wolf result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', 1260a82a927SKevin Wolf target='drive1', sync='full', auto_finalize=False, 1270a82a927SKevin Wolf auto_dismiss=False) 1280a82a927SKevin Wolf self.assert_qmp(result, 'return', {}) 1290a82a927SKevin Wolf 1300a82a927SKevin Wolf self.vm.run_job('job0', auto_finalize=False, pre_finalize=pre_finalize) 1310a82a927SKevin Wolf 1320a82a927SKevin Wolf def test_source_resize_blockdev_backup(self): 1330a82a927SKevin Wolf self.do_test_resize_blockdev_backup('drive0', 'source') 1340a82a927SKevin Wolf 1350a82a927SKevin Wolf def test_target_resize_blockdev_backup(self): 1360a82a927SKevin Wolf self.do_test_resize_blockdev_backup('drive1', 'target') 1370a82a927SKevin Wolf 1380a82a927SKevin Wolf def do_test_target_size(self, size): 1390a82a927SKevin Wolf result = self.vm.qmp('block_resize', device='drive1', size=size) 1400a82a927SKevin Wolf self.assert_qmp(result, 'return', {}) 1410a82a927SKevin Wolf 1420a82a927SKevin Wolf result = self.vm.qmp('blockdev-backup', job_id='job0', device='drive0', 1430a82a927SKevin Wolf target='drive1', sync='full') 1440a82a927SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 1450a82a927SKevin Wolf 1460a82a927SKevin Wolf def test_small_target(self): 1470a82a927SKevin Wolf self.do_test_target_size(image_len // 2) 1480a82a927SKevin Wolf 1490a82a927SKevin Wolf def test_large_target(self): 1500a82a927SKevin Wolf self.do_test_target_size(image_len * 2) 1510a82a927SKevin Wolf 152e5ca8fddSStefan Hajnoczi def test_medium_not_found(self): 153d8683155SBo Tu if iotests.qemu_default_machine != 'pc': 154d8683155SBo Tu return 155d8683155SBo Tu 1560ed82f7aSMax Reitz result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM 157b53169eaSStefan Hajnoczi target=target_img, sync='full') 158e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 159e5ca8fddSStefan Hajnoczi 1607c6a4ab8SFam Zheng def test_medium_not_found_blockdev_backup(self): 161d8683155SBo Tu if iotests.qemu_default_machine != 'pc': 162d8683155SBo Tu return 163d8683155SBo Tu 1640ed82f7aSMax Reitz result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM 1657c6a4ab8SFam Zheng target='drive1', sync='full') 1667c6a4ab8SFam Zheng self.assert_qmp(result, 'error/class', 'GenericError') 1677c6a4ab8SFam Zheng 168e5ca8fddSStefan Hajnoczi def test_image_not_found(self): 169e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 170b53169eaSStefan Hajnoczi target=target_img, sync='full', mode='existing') 171e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 172e5ca8fddSStefan Hajnoczi 173e3409362SIan Main def test_invalid_format(self): 174e3409362SIan Main result = self.vm.qmp('drive-backup', device='drive0', 175e3409362SIan Main target=target_img, sync='full', 176e3409362SIan Main format='spaghetti-noodles') 177e3409362SIan Main self.assert_qmp(result, 'error/class', 'GenericError') 178e3409362SIan Main 1797c6a4ab8SFam Zheng def do_test_device_not_found(self, cmd, **args): 1807c6a4ab8SFam Zheng result = self.vm.qmp(cmd, **args) 1815b347c54SMarkus Armbruster self.assert_qmp(result, 'error/class', 'GenericError') 182e5ca8fddSStefan Hajnoczi 1837c6a4ab8SFam Zheng def test_device_not_found(self): 1847c6a4ab8SFam Zheng self.do_test_device_not_found('drive-backup', device='nonexistent', 1857c6a4ab8SFam Zheng target=target_img, sync='full') 1867c6a4ab8SFam Zheng 1877c6a4ab8SFam Zheng self.do_test_device_not_found('blockdev-backup', device='nonexistent', 1887c6a4ab8SFam Zheng target='drive0', sync='full') 1897c6a4ab8SFam Zheng 1907c6a4ab8SFam Zheng self.do_test_device_not_found('blockdev-backup', device='drive0', 1917c6a4ab8SFam Zheng target='nonexistent', sync='full') 1927c6a4ab8SFam Zheng 1937c6a4ab8SFam Zheng self.do_test_device_not_found('blockdev-backup', device='nonexistent', 1947c6a4ab8SFam Zheng target='nonexistent', sync='full') 1957c6a4ab8SFam Zheng 1967c6a4ab8SFam Zheng def test_target_is_source(self): 1977c6a4ab8SFam Zheng result = self.vm.qmp('blockdev-backup', device='drive0', 1987c6a4ab8SFam Zheng target='drive0', sync='full') 1997c6a4ab8SFam Zheng self.assert_qmp(result, 'error/class', 'GenericError') 2007c6a4ab8SFam Zheng 201e5ca8fddSStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase): 202e5ca8fddSStefan Hajnoczi def setUp(self): 203819cec01SVladimir Sementsov-Ogievskiy qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) 2047c6a4ab8SFam Zheng 205bc11aee2SMax Reitz self.vm = iotests.VM().add_drive('blkdebug::' + test_img) 2064e9e4323SKevin Wolf self.vm.add_drive(blockdev_target_img, interface="none") 207e5ca8fddSStefan Hajnoczi self.vm.launch() 208e5ca8fddSStefan Hajnoczi 209e5ca8fddSStefan Hajnoczi def tearDown(self): 210e5ca8fddSStefan Hajnoczi self.vm.shutdown() 2117c6a4ab8SFam Zheng os.remove(blockdev_target_img) 2127c6a4ab8SFam Zheng try: 213e5ca8fddSStefan Hajnoczi os.remove(target_img) 2147c6a4ab8SFam Zheng except OSError: 2157c6a4ab8SFam Zheng pass 216e5ca8fddSStefan Hajnoczi 2177c6a4ab8SFam Zheng def do_test_set_speed(self, cmd, target): 218e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 219e5ca8fddSStefan Hajnoczi 220b59b3d57SFam Zheng self.vm.pause_drive('drive0') 2217c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') 222e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 223e5ca8fddSStefan Hajnoczi 224e5ca8fddSStefan Hajnoczi # Default speed is 0 225e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 226e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 227e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 228e5ca8fddSStefan Hajnoczi 229e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 230e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 231e5ca8fddSStefan Hajnoczi 232e5ca8fddSStefan Hajnoczi # Ensure the speed we set was accepted 233e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 234e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 235e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 236e5ca8fddSStefan Hajnoczi 237b59b3d57SFam Zheng event = self.cancel_and_wait(resume=True) 238e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 239e5ca8fddSStefan Hajnoczi 2407c6a4ab8SFam Zheng # Check setting speed option works 241b59b3d57SFam Zheng self.vm.pause_drive('drive0') 2427c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', 2437c6a4ab8SFam Zheng target=target, sync='full', speed=4*1024*1024) 244e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 245e5ca8fddSStefan Hajnoczi 246e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 247e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 248e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) 249e5ca8fddSStefan Hajnoczi 250b59b3d57SFam Zheng event = self.cancel_and_wait(resume=True) 251e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 252e5ca8fddSStefan Hajnoczi 2537c6a4ab8SFam Zheng def test_set_speed_drive_backup(self): 2547c6a4ab8SFam Zheng self.do_test_set_speed('drive-backup', target_img) 2557c6a4ab8SFam Zheng 2567c6a4ab8SFam Zheng def test_set_speed_blockdev_backup(self): 2577c6a4ab8SFam Zheng self.do_test_set_speed('blockdev-backup', 'drive1') 2587c6a4ab8SFam Zheng 2597c6a4ab8SFam Zheng def do_test_set_speed_invalid(self, cmd, target): 260e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 261e5ca8fddSStefan Hajnoczi 2627c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', 2637c6a4ab8SFam Zheng target=target, sync='full', speed=-1) 264e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 265e5ca8fddSStefan Hajnoczi 266e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 267e5ca8fddSStefan Hajnoczi 268b59b3d57SFam Zheng self.vm.pause_drive('drive0') 2697c6a4ab8SFam Zheng result = self.vm.qmp(cmd, device='drive0', 2707c6a4ab8SFam Zheng target=target, sync='full') 271e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 272e5ca8fddSStefan Hajnoczi 273e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 274e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 275e5ca8fddSStefan Hajnoczi 276b59b3d57SFam Zheng event = self.cancel_and_wait(resume=True) 277e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 278e5ca8fddSStefan Hajnoczi 2797c6a4ab8SFam Zheng def test_set_speed_invalid_drive_backup(self): 2807c6a4ab8SFam Zheng self.do_test_set_speed_invalid('drive-backup', target_img) 2817c6a4ab8SFam Zheng 2827c6a4ab8SFam Zheng def test_set_speed_invalid_blockdev_backup(self): 2837c6a4ab8SFam Zheng self.do_test_set_speed_invalid('blockdev-backup', 'drive1') 2847c6a4ab8SFam Zheng 285bc11aee2SMax Reitz# Note: We cannot use pause_drive() here, or the transaction command 286bc11aee2SMax Reitz# would stall. Instead, we limit the block job speed here. 287e5ca8fddSStefan Hajnocziclass TestSingleTransaction(iotests.QMPTestCase): 288e5ca8fddSStefan Hajnoczi def setUp(self): 289819cec01SVladimir Sementsov-Ogievskiy qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) 290e5ca8fddSStefan Hajnoczi 2914e9e4323SKevin Wolf self.vm = iotests.VM().add_drive(test_img) 2924e9e4323SKevin Wolf self.vm.add_drive(blockdev_target_img, interface="none") 2930ed82f7aSMax Reitz if iotests.qemu_default_machine == 'pc': 2940ed82f7aSMax Reitz self.vm.add_drive(None, 'media=cdrom', 'ide') 295e5ca8fddSStefan Hajnoczi self.vm.launch() 296e5ca8fddSStefan Hajnoczi 297e5ca8fddSStefan Hajnoczi def tearDown(self): 298e5ca8fddSStefan Hajnoczi self.vm.shutdown() 2997c6a4ab8SFam Zheng os.remove(blockdev_target_img) 300e5ca8fddSStefan Hajnoczi try: 301e5ca8fddSStefan Hajnoczi os.remove(target_img) 302e5ca8fddSStefan Hajnoczi except OSError: 303e5ca8fddSStefan Hajnoczi pass 304e5ca8fddSStefan Hajnoczi 3057c6a4ab8SFam Zheng def do_test_cancel(self, cmd, target): 306e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 307e5ca8fddSStefan Hajnoczi 308e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 3097c6a4ab8SFam Zheng 'type': cmd, 310e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 3117c6a4ab8SFam Zheng 'target': target, 312bc11aee2SMax Reitz 'sync': 'full', 313bc11aee2SMax Reitz 'speed': 64 * 1024 }, 314e5ca8fddSStefan Hajnoczi } 315e5ca8fddSStefan Hajnoczi ]) 3167c6a4ab8SFam Zheng 317e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 318e5ca8fddSStefan Hajnoczi 319e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 320e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 321e5ca8fddSStefan Hajnoczi 3227c6a4ab8SFam Zheng def test_cancel_drive_backup(self): 3237c6a4ab8SFam Zheng self.do_test_cancel('drive-backup', target_img) 3247c6a4ab8SFam Zheng 3257c6a4ab8SFam Zheng def test_cancel_blockdev_backup(self): 3267c6a4ab8SFam Zheng self.do_test_cancel('blockdev-backup', 'drive1') 3277c6a4ab8SFam Zheng 3287c6a4ab8SFam Zheng def do_test_pause(self, cmd, target, image): 329e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 330e5ca8fddSStefan Hajnoczi 331e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 3327c6a4ab8SFam Zheng 'type': cmd, 333e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 3347c6a4ab8SFam Zheng 'target': target, 335bc11aee2SMax Reitz 'sync': 'full', 336bc11aee2SMax Reitz 'speed': 64 * 1024 }, 337e5ca8fddSStefan Hajnoczi } 338e5ca8fddSStefan Hajnoczi ]) 339e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 340e5ca8fddSStefan Hajnoczi 341f03d9d24SJohn Snow self.pause_job('drive0', wait=False) 342e5ca8fddSStefan Hajnoczi 343bc11aee2SMax Reitz result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0) 344bc11aee2SMax Reitz self.assert_qmp(result, 'return', {}) 345bc11aee2SMax Reitz 346f03d9d24SJohn Snow self.pause_wait('drive0') 3472c93c5cbSKevin Wolf 348e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 349e5ca8fddSStefan Hajnoczi offset = self.dictpath(result, 'return[0]/offset') 350e5ca8fddSStefan Hajnoczi 3512c93c5cbSKevin Wolf time.sleep(0.5) 352e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 353e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/offset', offset) 354e5ca8fddSStefan Hajnoczi 355e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-resume', device='drive0') 356e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 357e5ca8fddSStefan Hajnoczi 358e5ca8fddSStefan Hajnoczi self.wait_until_completed() 359e5ca8fddSStefan Hajnoczi 360e5ca8fddSStefan Hajnoczi self.vm.shutdown() 3617c6a4ab8SFam Zheng self.assertTrue(iotests.compare_images(test_img, image), 362e5ca8fddSStefan Hajnoczi 'target image does not match source after backup') 363e5ca8fddSStefan Hajnoczi 3647c6a4ab8SFam Zheng def test_pause_drive_backup(self): 3657c6a4ab8SFam Zheng self.do_test_pause('drive-backup', target_img, target_img) 3667c6a4ab8SFam Zheng 3677c6a4ab8SFam Zheng def test_pause_blockdev_backup(self): 3687c6a4ab8SFam Zheng self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img) 3697c6a4ab8SFam Zheng 3707c6a4ab8SFam Zheng def do_test_medium_not_found(self, cmd, target): 371d8683155SBo Tu if iotests.qemu_default_machine != 'pc': 372d8683155SBo Tu return 373d8683155SBo Tu 374e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 3757c6a4ab8SFam Zheng 'type': cmd, 3760ed82f7aSMax Reitz 'data': { 'device': 'drive2', # CD-ROM 3777c6a4ab8SFam Zheng 'target': target, 378b53169eaSStefan Hajnoczi 'sync': 'full' }, 379e5ca8fddSStefan Hajnoczi } 380e5ca8fddSStefan Hajnoczi ]) 381e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 382e5ca8fddSStefan Hajnoczi 3837c6a4ab8SFam Zheng def test_medium_not_found_drive_backup(self): 3847c6a4ab8SFam Zheng self.do_test_medium_not_found('drive-backup', target_img) 3857c6a4ab8SFam Zheng 3867c6a4ab8SFam Zheng def test_medium_not_found_blockdev_backup(self): 3877c6a4ab8SFam Zheng self.do_test_medium_not_found('blockdev-backup', 'drive1') 3887c6a4ab8SFam Zheng 389e5ca8fddSStefan Hajnoczi def test_image_not_found(self): 390e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 391e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 392e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 393e5ca8fddSStefan Hajnoczi 'mode': 'existing', 394b53169eaSStefan Hajnoczi 'target': target_img, 395b53169eaSStefan Hajnoczi 'sync': 'full' }, 396e5ca8fddSStefan Hajnoczi } 397e5ca8fddSStefan Hajnoczi ]) 398e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 399e5ca8fddSStefan Hajnoczi 400e5ca8fddSStefan Hajnoczi def test_device_not_found(self): 401e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 402e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 403e5ca8fddSStefan Hajnoczi 'data': { 'device': 'nonexistent', 404e5ca8fddSStefan Hajnoczi 'mode': 'existing', 405b53169eaSStefan Hajnoczi 'target': target_img, 406b53169eaSStefan Hajnoczi 'sync': 'full' }, 407e5ca8fddSStefan Hajnoczi } 408e5ca8fddSStefan Hajnoczi ]) 409b7e4fa22SKevin Wolf self.assert_qmp(result, 'error/class', 'GenericError') 410e5ca8fddSStefan Hajnoczi 4117c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4127c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4137c6a4ab8SFam Zheng 'data': { 'device': 'nonexistent', 4147c6a4ab8SFam Zheng 'target': 'drive1', 4157c6a4ab8SFam Zheng 'sync': 'full' }, 4167c6a4ab8SFam Zheng } 4177c6a4ab8SFam Zheng ]) 4185b347c54SMarkus Armbruster self.assert_qmp(result, 'error/class', 'GenericError') 4197c6a4ab8SFam Zheng 4207c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4217c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4227c6a4ab8SFam Zheng 'data': { 'device': 'drive0', 4237c6a4ab8SFam Zheng 'target': 'nonexistent', 4247c6a4ab8SFam Zheng 'sync': 'full' }, 4257c6a4ab8SFam Zheng } 4267c6a4ab8SFam Zheng ]) 4275b347c54SMarkus Armbruster self.assert_qmp(result, 'error/class', 'GenericError') 4287c6a4ab8SFam Zheng 4297c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4307c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4317c6a4ab8SFam Zheng 'data': { 'device': 'nonexistent', 4327c6a4ab8SFam Zheng 'target': 'nonexistent', 4337c6a4ab8SFam Zheng 'sync': 'full' }, 4347c6a4ab8SFam Zheng } 4357c6a4ab8SFam Zheng ]) 4365b347c54SMarkus Armbruster self.assert_qmp(result, 'error/class', 'GenericError') 4377c6a4ab8SFam Zheng 4387c6a4ab8SFam Zheng def test_target_is_source(self): 4397c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4407c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4417c6a4ab8SFam Zheng 'data': { 'device': 'drive0', 4427c6a4ab8SFam Zheng 'target': 'drive0', 4437c6a4ab8SFam Zheng 'sync': 'full' }, 4447c6a4ab8SFam Zheng } 4457c6a4ab8SFam Zheng ]) 4467c6a4ab8SFam Zheng self.assert_qmp(result, 'error/class', 'GenericError') 4477c6a4ab8SFam Zheng 448e5ca8fddSStefan Hajnoczi def test_abort(self): 449e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 450e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 451e5ca8fddSStefan Hajnoczi 'data': { 'device': 'nonexistent', 452e5ca8fddSStefan Hajnoczi 'mode': 'existing', 453b53169eaSStefan Hajnoczi 'target': target_img, 454b53169eaSStefan Hajnoczi 'sync': 'full' }, 455e5ca8fddSStefan Hajnoczi }, { 456e5ca8fddSStefan Hajnoczi 'type': 'Abort', 457e5ca8fddSStefan Hajnoczi 'data': {}, 458e5ca8fddSStefan Hajnoczi } 459e5ca8fddSStefan Hajnoczi ]) 460e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 461e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 462e5ca8fddSStefan Hajnoczi 4637c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4647c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4657c6a4ab8SFam Zheng 'data': { 'device': 'nonexistent', 4667c6a4ab8SFam Zheng 'target': 'drive1', 4677c6a4ab8SFam Zheng 'sync': 'full' }, 4687c6a4ab8SFam Zheng }, { 4697c6a4ab8SFam Zheng 'type': 'Abort', 4707c6a4ab8SFam Zheng 'data': {}, 4717c6a4ab8SFam Zheng } 4727c6a4ab8SFam Zheng ]) 4737c6a4ab8SFam Zheng self.assert_qmp(result, 'error/class', 'GenericError') 4747c6a4ab8SFam Zheng self.assert_no_active_block_jobs() 4757c6a4ab8SFam Zheng 4767c6a4ab8SFam Zheng result = self.vm.qmp('transaction', actions=[{ 4777c6a4ab8SFam Zheng 'type': 'blockdev-backup', 4787c6a4ab8SFam Zheng 'data': { 'device': 'drive0', 4797c6a4ab8SFam Zheng 'target': 'nonexistent', 4807c6a4ab8SFam Zheng 'sync': 'full' }, 4817c6a4ab8SFam Zheng }, { 4827c6a4ab8SFam Zheng 'type': 'Abort', 4837c6a4ab8SFam Zheng 'data': {}, 4847c6a4ab8SFam Zheng } 4857c6a4ab8SFam Zheng ]) 4867c6a4ab8SFam Zheng self.assert_qmp(result, 'error/class', 'GenericError') 4877c6a4ab8SFam Zheng self.assert_no_active_block_jobs() 4887c6a4ab8SFam Zheng 489e1b5c51fSPavel Butsykin 4908e837294SVladimir Sementsov-Ogievskiyclass TestCompressedToQcow2(iotests.QMPTestCase): 491e1b5c51fSPavel Butsykin image_len = 64 * 1024 * 1024 # MB 492*6a9d73bdSKevin Wolf target_fmt = {'type': 'qcow2', 'args': (), 'drive-opts': ''} 493e1b5c51fSPavel Butsykin 494e1b5c51fSPavel Butsykin def tearDown(self): 495e1b5c51fSPavel Butsykin self.vm.shutdown() 496e1b5c51fSPavel Butsykin os.remove(blockdev_target_img) 497e1b5c51fSPavel Butsykin try: 498e1b5c51fSPavel Butsykin os.remove(target_img) 499e1b5c51fSPavel Butsykin except OSError: 500e1b5c51fSPavel Butsykin pass 501e1b5c51fSPavel Butsykin 5028e837294SVladimir Sementsov-Ogievskiy def do_prepare_drives(self, attach_target): 503*6a9d73bdSKevin Wolf self.vm = iotests.VM().add_drive('blkdebug::' + test_img, 504*6a9d73bdSKevin Wolf opts=self.target_fmt['drive-opts']) 50500198eccSPavel Butsykin 5068e837294SVladimir Sementsov-Ogievskiy qemu_img('create', '-f', self.target_fmt['type'], blockdev_target_img, 5078e837294SVladimir Sementsov-Ogievskiy str(self.image_len), *self.target_fmt['args']) 5084797aeabSFam Zheng if attach_target: 5091d3d4b63SJohn Snow self.vm.add_drive(blockdev_target_img, 5108e837294SVladimir Sementsov-Ogievskiy img_format=self.target_fmt['type'], 511*6a9d73bdSKevin Wolf interface="none", 512*6a9d73bdSKevin Wolf opts=self.target_fmt['drive-opts']) 51300198eccSPavel Butsykin 51400198eccSPavel Butsykin self.vm.launch() 51500198eccSPavel Butsykin 5168e837294SVladimir Sementsov-Ogievskiy def do_test_compress_complete(self, cmd, attach_target, **args): 5178e837294SVladimir Sementsov-Ogievskiy self.do_prepare_drives(attach_target) 51800198eccSPavel Butsykin 519e1b5c51fSPavel Butsykin self.assert_no_active_block_jobs() 520e1b5c51fSPavel Butsykin 521e1b5c51fSPavel Butsykin result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) 522e1b5c51fSPavel Butsykin self.assert_qmp(result, 'return', {}) 523e1b5c51fSPavel Butsykin 524e1b5c51fSPavel Butsykin self.wait_until_completed() 525e1b5c51fSPavel Butsykin 526e1b5c51fSPavel Butsykin self.vm.shutdown() 527e1b5c51fSPavel Butsykin self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, 5288e837294SVladimir Sementsov-Ogievskiy iotests.imgfmt, 5298e837294SVladimir Sementsov-Ogievskiy self.target_fmt['type']), 530e1b5c51fSPavel Butsykin 'target image does not match source after backup') 531e1b5c51fSPavel Butsykin 532e1b5c51fSPavel Butsykin def test_complete_compress_drive_backup(self): 5338e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_complete('drive-backup', False, 5348e837294SVladimir Sementsov-Ogievskiy target=blockdev_target_img, 5358e837294SVladimir Sementsov-Ogievskiy mode='existing') 536e1b5c51fSPavel Butsykin 537e1b5c51fSPavel Butsykin def test_complete_compress_blockdev_backup(self): 5388e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_complete('blockdev-backup', 5398e837294SVladimir Sementsov-Ogievskiy True, target='drive1') 540e1b5c51fSPavel Butsykin 5418e837294SVladimir Sementsov-Ogievskiy def do_test_compress_cancel(self, cmd, attach_target, **args): 5428e837294SVladimir Sementsov-Ogievskiy self.do_prepare_drives(attach_target) 54300198eccSPavel Butsykin 544e1b5c51fSPavel Butsykin self.assert_no_active_block_jobs() 545e1b5c51fSPavel Butsykin 546bc11aee2SMax Reitz self.vm.pause_drive('drive0') 547e1b5c51fSPavel Butsykin result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) 548e1b5c51fSPavel Butsykin self.assert_qmp(result, 'return', {}) 549e1b5c51fSPavel Butsykin 550bc11aee2SMax Reitz event = self.cancel_and_wait(resume=True) 551e1b5c51fSPavel Butsykin self.assert_qmp(event, 'data/type', 'backup') 552e1b5c51fSPavel Butsykin 55300198eccSPavel Butsykin self.vm.shutdown() 55400198eccSPavel Butsykin 555e1b5c51fSPavel Butsykin def test_compress_cancel_drive_backup(self): 5568e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_cancel('drive-backup', False, 5578e837294SVladimir Sementsov-Ogievskiy target=blockdev_target_img, 5588e837294SVladimir Sementsov-Ogievskiy mode='existing') 559e1b5c51fSPavel Butsykin 560e1b5c51fSPavel Butsykin def test_compress_cancel_blockdev_backup(self): 5618e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_cancel('blockdev-backup', True, 5624797aeabSFam Zheng target='drive1') 563e1b5c51fSPavel Butsykin 5648e837294SVladimir Sementsov-Ogievskiy def do_test_compress_pause(self, cmd, attach_target, **args): 5658e837294SVladimir Sementsov-Ogievskiy self.do_prepare_drives(attach_target) 56600198eccSPavel Butsykin 567e1b5c51fSPavel Butsykin self.assert_no_active_block_jobs() 568e1b5c51fSPavel Butsykin 569e1b5c51fSPavel Butsykin self.vm.pause_drive('drive0') 570e1b5c51fSPavel Butsykin result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) 571e1b5c51fSPavel Butsykin self.assert_qmp(result, 'return', {}) 572e1b5c51fSPavel Butsykin 573f03d9d24SJohn Snow self.pause_job('drive0', wait=False) 574e1b5c51fSPavel Butsykin self.vm.resume_drive('drive0') 575f03d9d24SJohn Snow self.pause_wait('drive0') 5762c93c5cbSKevin Wolf 577e1b5c51fSPavel Butsykin result = self.vm.qmp('query-block-jobs') 578e1b5c51fSPavel Butsykin offset = self.dictpath(result, 'return[0]/offset') 579e1b5c51fSPavel Butsykin 5802c93c5cbSKevin Wolf time.sleep(0.5) 581e1b5c51fSPavel Butsykin result = self.vm.qmp('query-block-jobs') 582e1b5c51fSPavel Butsykin self.assert_qmp(result, 'return[0]/offset', offset) 583e1b5c51fSPavel Butsykin 584e1b5c51fSPavel Butsykin result = self.vm.qmp('block-job-resume', device='drive0') 585e1b5c51fSPavel Butsykin self.assert_qmp(result, 'return', {}) 586e1b5c51fSPavel Butsykin 587e1b5c51fSPavel Butsykin self.wait_until_completed() 588e1b5c51fSPavel Butsykin 589e1b5c51fSPavel Butsykin self.vm.shutdown() 590e1b5c51fSPavel Butsykin self.assertTrue(iotests.compare_images(test_img, blockdev_target_img, 5918e837294SVladimir Sementsov-Ogievskiy iotests.imgfmt, 5928e837294SVladimir Sementsov-Ogievskiy self.target_fmt['type']), 593e1b5c51fSPavel Butsykin 'target image does not match source after backup') 594e1b5c51fSPavel Butsykin 595e1b5c51fSPavel Butsykin def test_compress_pause_drive_backup(self): 5968e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_pause('drive-backup', False, 5978e837294SVladimir Sementsov-Ogievskiy target=blockdev_target_img, 5988e837294SVladimir Sementsov-Ogievskiy mode='existing') 599e1b5c51fSPavel Butsykin 600e1b5c51fSPavel Butsykin def test_compress_pause_blockdev_backup(self): 6018e837294SVladimir Sementsov-Ogievskiy self.do_test_compress_pause('blockdev-backup', True, 6024797aeabSFam Zheng target='drive1') 603e1b5c51fSPavel Butsykin 6048e837294SVladimir Sementsov-Ogievskiy 6058e837294SVladimir Sementsov-Ogievskiyclass TestCompressedToVmdk(TestCompressedToQcow2): 606*6a9d73bdSKevin Wolf target_fmt = {'type': 'vmdk', 'args': ('-o', 'subformat=streamOptimized'), 607*6a9d73bdSKevin Wolf 'drive-opts': 'cache.no-flush=on'} 6088e837294SVladimir Sementsov-Ogievskiy 609761cd2e7SVladimir Sementsov-Ogievskiy @iotests.skip_if_unsupported(['vmdk']) 610761cd2e7SVladimir Sementsov-Ogievskiy def setUp(self): 611761cd2e7SVladimir Sementsov-Ogievskiy pass 612761cd2e7SVladimir Sementsov-Ogievskiy 6138e837294SVladimir Sementsov-Ogievskiy 614e5ca8fddSStefan Hajnocziif __name__ == '__main__': 615103cbc77SMax Reitz iotests.main(supported_fmts=['raw', 'qcow2'], 616103cbc77SMax Reitz supported_protocols=['file']) 617