1*e5ca8fddSStefan Hajnoczi#!/usr/bin/env python 2*e5ca8fddSStefan Hajnoczi# 3*e5ca8fddSStefan Hajnoczi# Tests for drive-backup 4*e5ca8fddSStefan Hajnoczi# 5*e5ca8fddSStefan Hajnoczi# Copyright (C) 2013 Red Hat, Inc. 6*e5ca8fddSStefan Hajnoczi# 7*e5ca8fddSStefan Hajnoczi# Based on 041. 8*e5ca8fddSStefan Hajnoczi# 9*e5ca8fddSStefan Hajnoczi# This program is free software; you can redistribute it and/or modify 10*e5ca8fddSStefan Hajnoczi# it under the terms of the GNU General Public License as published by 11*e5ca8fddSStefan Hajnoczi# the Free Software Foundation; either version 2 of the License, or 12*e5ca8fddSStefan Hajnoczi# (at your option) any later version. 13*e5ca8fddSStefan Hajnoczi# 14*e5ca8fddSStefan Hajnoczi# This program is distributed in the hope that it will be useful, 15*e5ca8fddSStefan Hajnoczi# but WITHOUT ANY WARRANTY; without even the implied warranty of 16*e5ca8fddSStefan Hajnoczi# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*e5ca8fddSStefan Hajnoczi# GNU General Public License for more details. 18*e5ca8fddSStefan Hajnoczi# 19*e5ca8fddSStefan Hajnoczi# You should have received a copy of the GNU General Public License 20*e5ca8fddSStefan Hajnoczi# along with this program. If not, see <http://www.gnu.org/licenses/>. 21*e5ca8fddSStefan Hajnoczi# 22*e5ca8fddSStefan Hajnoczi 23*e5ca8fddSStefan Hajnocziimport time 24*e5ca8fddSStefan Hajnocziimport os 25*e5ca8fddSStefan Hajnocziimport iotests 26*e5ca8fddSStefan Hajnoczifrom iotests import qemu_img, qemu_io 27*e5ca8fddSStefan Hajnoczi 28*e5ca8fddSStefan Hajnoczitest_img = os.path.join(iotests.test_dir, 'test.img') 29*e5ca8fddSStefan Hajnoczitarget_img = os.path.join(iotests.test_dir, 'target.img') 30*e5ca8fddSStefan Hajnoczi 31*e5ca8fddSStefan Hajnocziclass TestSingleDrive(iotests.QMPTestCase): 32*e5ca8fddSStefan Hajnoczi image_len = 64 * 1024 * 1024 # MB 33*e5ca8fddSStefan Hajnoczi 34*e5ca8fddSStefan Hajnoczi def setUp(self): 35*e5ca8fddSStefan Hajnoczi # Write data to the image so we can compare later 36*e5ca8fddSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len)) 37*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0x5d 0 64k', test_img) 38*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xd5 1M 32k', test_img) 39*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xdc 32M 124k', test_img) 40*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) 41*e5ca8fddSStefan Hajnoczi 42*e5ca8fddSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 43*e5ca8fddSStefan Hajnoczi self.vm.launch() 44*e5ca8fddSStefan Hajnoczi 45*e5ca8fddSStefan Hajnoczi def tearDown(self): 46*e5ca8fddSStefan Hajnoczi self.vm.shutdown() 47*e5ca8fddSStefan Hajnoczi os.remove(test_img) 48*e5ca8fddSStefan Hajnoczi try: 49*e5ca8fddSStefan Hajnoczi os.remove(target_img) 50*e5ca8fddSStefan Hajnoczi except OSError: 51*e5ca8fddSStefan Hajnoczi pass 52*e5ca8fddSStefan Hajnoczi 53*e5ca8fddSStefan Hajnoczi def test_cancel(self): 54*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 55*e5ca8fddSStefan Hajnoczi 56*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 57*e5ca8fddSStefan Hajnoczi target=target_img) 58*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 59*e5ca8fddSStefan Hajnoczi 60*e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 61*e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 62*e5ca8fddSStefan Hajnoczi 63*e5ca8fddSStefan Hajnoczi def test_pause(self): 64*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 65*e5ca8fddSStefan Hajnoczi 66*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 67*e5ca8fddSStefan Hajnoczi target=target_img) 68*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 69*e5ca8fddSStefan Hajnoczi 70*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-pause', device='drive0') 71*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 72*e5ca8fddSStefan Hajnoczi 73*e5ca8fddSStefan Hajnoczi time.sleep(1) 74*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 75*e5ca8fddSStefan Hajnoczi offset = self.dictpath(result, 'return[0]/offset') 76*e5ca8fddSStefan Hajnoczi 77*e5ca8fddSStefan Hajnoczi time.sleep(1) 78*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 79*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/offset', offset) 80*e5ca8fddSStefan Hajnoczi 81*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-resume', device='drive0') 82*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 83*e5ca8fddSStefan Hajnoczi 84*e5ca8fddSStefan Hajnoczi self.wait_until_completed() 85*e5ca8fddSStefan Hajnoczi 86*e5ca8fddSStefan Hajnoczi self.vm.shutdown() 87*e5ca8fddSStefan Hajnoczi self.assertTrue(iotests.compare_images(test_img, target_img), 88*e5ca8fddSStefan Hajnoczi 'target image does not match source after backup') 89*e5ca8fddSStefan Hajnoczi 90*e5ca8fddSStefan Hajnoczi def test_medium_not_found(self): 91*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='ide1-cd0', 92*e5ca8fddSStefan Hajnoczi target=target_img) 93*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 94*e5ca8fddSStefan Hajnoczi 95*e5ca8fddSStefan Hajnoczi def test_image_not_found(self): 96*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 97*e5ca8fddSStefan Hajnoczi mode='existing', target=target_img) 98*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 99*e5ca8fddSStefan Hajnoczi 100*e5ca8fddSStefan Hajnoczi def test_device_not_found(self): 101*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='nonexistent', 102*e5ca8fddSStefan Hajnoczi target=target_img) 103*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'DeviceNotFound') 104*e5ca8fddSStefan Hajnoczi 105*e5ca8fddSStefan Hajnocziclass TestSetSpeed(iotests.QMPTestCase): 106*e5ca8fddSStefan Hajnoczi image_len = 80 * 1024 * 1024 # MB 107*e5ca8fddSStefan Hajnoczi 108*e5ca8fddSStefan Hajnoczi def setUp(self): 109*e5ca8fddSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len)) 110*e5ca8fddSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 111*e5ca8fddSStefan Hajnoczi self.vm.launch() 112*e5ca8fddSStefan Hajnoczi 113*e5ca8fddSStefan Hajnoczi def tearDown(self): 114*e5ca8fddSStefan Hajnoczi self.vm.shutdown() 115*e5ca8fddSStefan Hajnoczi os.remove(test_img) 116*e5ca8fddSStefan Hajnoczi os.remove(target_img) 117*e5ca8fddSStefan Hajnoczi 118*e5ca8fddSStefan Hajnoczi def test_set_speed(self): 119*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 120*e5ca8fddSStefan Hajnoczi 121*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 122*e5ca8fddSStefan Hajnoczi target=target_img) 123*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 124*e5ca8fddSStefan Hajnoczi 125*e5ca8fddSStefan Hajnoczi # Default speed is 0 126*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 127*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 128*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 0) 129*e5ca8fddSStefan Hajnoczi 130*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024) 131*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 132*e5ca8fddSStefan Hajnoczi 133*e5ca8fddSStefan Hajnoczi # Ensure the speed we set was accepted 134*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 135*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 136*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024) 137*e5ca8fddSStefan Hajnoczi 138*e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 139*e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 140*e5ca8fddSStefan Hajnoczi 141*e5ca8fddSStefan Hajnoczi # Check setting speed in drive-backup works 142*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 143*e5ca8fddSStefan Hajnoczi target=target_img, speed=4*1024*1024) 144*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 145*e5ca8fddSStefan Hajnoczi 146*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 147*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/device', 'drive0') 148*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024) 149*e5ca8fddSStefan Hajnoczi 150*e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 151*e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 152*e5ca8fddSStefan Hajnoczi 153*e5ca8fddSStefan Hajnoczi def test_set_speed_invalid(self): 154*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 155*e5ca8fddSStefan Hajnoczi 156*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 157*e5ca8fddSStefan Hajnoczi target=target_img, speed=-1) 158*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 159*e5ca8fddSStefan Hajnoczi 160*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 161*e5ca8fddSStefan Hajnoczi 162*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('drive-backup', device='drive0', 163*e5ca8fddSStefan Hajnoczi target=target_img) 164*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 165*e5ca8fddSStefan Hajnoczi 166*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) 167*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 168*e5ca8fddSStefan Hajnoczi 169*e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 170*e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 171*e5ca8fddSStefan Hajnoczi 172*e5ca8fddSStefan Hajnocziclass TestSingleTransaction(iotests.QMPTestCase): 173*e5ca8fddSStefan Hajnoczi image_len = 64 * 1024 * 1024 # MB 174*e5ca8fddSStefan Hajnoczi 175*e5ca8fddSStefan Hajnoczi def setUp(self): 176*e5ca8fddSStefan Hajnoczi qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len)) 177*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0x5d 0 64k', test_img) 178*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xd5 1M 32k', test_img) 179*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xdc 32M 124k', test_img) 180*e5ca8fddSStefan Hajnoczi qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) 181*e5ca8fddSStefan Hajnoczi 182*e5ca8fddSStefan Hajnoczi self.vm = iotests.VM().add_drive(test_img) 183*e5ca8fddSStefan Hajnoczi self.vm.launch() 184*e5ca8fddSStefan Hajnoczi 185*e5ca8fddSStefan Hajnoczi def tearDown(self): 186*e5ca8fddSStefan Hajnoczi self.vm.shutdown() 187*e5ca8fddSStefan Hajnoczi os.remove(test_img) 188*e5ca8fddSStefan Hajnoczi try: 189*e5ca8fddSStefan Hajnoczi os.remove(target_img) 190*e5ca8fddSStefan Hajnoczi except OSError: 191*e5ca8fddSStefan Hajnoczi pass 192*e5ca8fddSStefan Hajnoczi 193*e5ca8fddSStefan Hajnoczi def test_cancel(self): 194*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 195*e5ca8fddSStefan Hajnoczi 196*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 197*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 198*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 199*e5ca8fddSStefan Hajnoczi 'target': target_img }, 200*e5ca8fddSStefan Hajnoczi } 201*e5ca8fddSStefan Hajnoczi ]) 202*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 203*e5ca8fddSStefan Hajnoczi 204*e5ca8fddSStefan Hajnoczi event = self.cancel_and_wait() 205*e5ca8fddSStefan Hajnoczi self.assert_qmp(event, 'data/type', 'backup') 206*e5ca8fddSStefan Hajnoczi 207*e5ca8fddSStefan Hajnoczi def test_pause(self): 208*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 209*e5ca8fddSStefan Hajnoczi 210*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 211*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 212*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 213*e5ca8fddSStefan Hajnoczi 'target': target_img }, 214*e5ca8fddSStefan Hajnoczi } 215*e5ca8fddSStefan Hajnoczi ]) 216*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 217*e5ca8fddSStefan Hajnoczi 218*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-pause', device='drive0') 219*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 220*e5ca8fddSStefan Hajnoczi 221*e5ca8fddSStefan Hajnoczi time.sleep(1) 222*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 223*e5ca8fddSStefan Hajnoczi offset = self.dictpath(result, 'return[0]/offset') 224*e5ca8fddSStefan Hajnoczi 225*e5ca8fddSStefan Hajnoczi time.sleep(1) 226*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('query-block-jobs') 227*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return[0]/offset', offset) 228*e5ca8fddSStefan Hajnoczi 229*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('block-job-resume', device='drive0') 230*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'return', {}) 231*e5ca8fddSStefan Hajnoczi 232*e5ca8fddSStefan Hajnoczi self.wait_until_completed() 233*e5ca8fddSStefan Hajnoczi 234*e5ca8fddSStefan Hajnoczi self.vm.shutdown() 235*e5ca8fddSStefan Hajnoczi self.assertTrue(iotests.compare_images(test_img, target_img), 236*e5ca8fddSStefan Hajnoczi 'target image does not match source after backup') 237*e5ca8fddSStefan Hajnoczi 238*e5ca8fddSStefan Hajnoczi def test_medium_not_found(self): 239*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 240*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 241*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'ide1-cd0', 242*e5ca8fddSStefan Hajnoczi 'target': target_img }, 243*e5ca8fddSStefan Hajnoczi } 244*e5ca8fddSStefan Hajnoczi ]) 245*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 246*e5ca8fddSStefan Hajnoczi 247*e5ca8fddSStefan Hajnoczi def test_image_not_found(self): 248*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 249*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 250*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'drive0', 251*e5ca8fddSStefan Hajnoczi 'mode': 'existing', 252*e5ca8fddSStefan Hajnoczi 'target': target_img }, 253*e5ca8fddSStefan Hajnoczi } 254*e5ca8fddSStefan Hajnoczi ]) 255*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 256*e5ca8fddSStefan Hajnoczi 257*e5ca8fddSStefan Hajnoczi def test_device_not_found(self): 258*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 259*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 260*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'nonexistent', 261*e5ca8fddSStefan Hajnoczi 'mode': 'existing', 262*e5ca8fddSStefan Hajnoczi 'target': target_img }, 263*e5ca8fddSStefan Hajnoczi } 264*e5ca8fddSStefan Hajnoczi ]) 265*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'DeviceNotFound') 266*e5ca8fddSStefan Hajnoczi 267*e5ca8fddSStefan Hajnoczi def test_abort(self): 268*e5ca8fddSStefan Hajnoczi result = self.vm.qmp('transaction', actions=[{ 269*e5ca8fddSStefan Hajnoczi 'type': 'drive-backup', 270*e5ca8fddSStefan Hajnoczi 'data': { 'device': 'nonexistent', 271*e5ca8fddSStefan Hajnoczi 'mode': 'existing', 272*e5ca8fddSStefan Hajnoczi 'target': target_img }, 273*e5ca8fddSStefan Hajnoczi }, { 274*e5ca8fddSStefan Hajnoczi 'type': 'Abort', 275*e5ca8fddSStefan Hajnoczi 'data': {}, 276*e5ca8fddSStefan Hajnoczi } 277*e5ca8fddSStefan Hajnoczi ]) 278*e5ca8fddSStefan Hajnoczi self.assert_qmp(result, 'error/class', 'GenericError') 279*e5ca8fddSStefan Hajnoczi self.assert_no_active_block_jobs() 280*e5ca8fddSStefan Hajnoczi 281*e5ca8fddSStefan Hajnocziif __name__ == '__main__': 282*e5ca8fddSStefan Hajnoczi iotests.main(supported_fmts=['raw', 'qcow2']) 283