1*9b8c59e7SSergio Lopez#!/usr/bin/env python 2*9b8c59e7SSergio Lopez# 3*9b8c59e7SSergio Lopez# Test cases for blockdev + IOThread interactions 4*9b8c59e7SSergio Lopez# 5*9b8c59e7SSergio Lopez# Copyright (C) 2019 Red Hat, Inc. 6*9b8c59e7SSergio Lopez# 7*9b8c59e7SSergio Lopez# This program is free software; you can redistribute it and/or modify 8*9b8c59e7SSergio Lopez# it under the terms of the GNU General Public License as published by 9*9b8c59e7SSergio Lopez# the Free Software Foundation; either version 2 of the License, or 10*9b8c59e7SSergio Lopez# (at your option) any later version. 11*9b8c59e7SSergio Lopez# 12*9b8c59e7SSergio Lopez# This program is distributed in the hope that it will be useful, 13*9b8c59e7SSergio Lopez# but WITHOUT ANY WARRANTY; without even the implied warranty of 14*9b8c59e7SSergio Lopez# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*9b8c59e7SSergio Lopez# GNU General Public License for more details. 16*9b8c59e7SSergio Lopez# 17*9b8c59e7SSergio Lopez# You should have received a copy of the GNU General Public License 18*9b8c59e7SSergio Lopez# along with this program. If not, see <http://www.gnu.org/licenses/>. 19*9b8c59e7SSergio Lopez# 20*9b8c59e7SSergio Lopez 21*9b8c59e7SSergio Lopezimport os 22*9b8c59e7SSergio Lopezimport iotests 23*9b8c59e7SSergio Lopezfrom iotests import qemu_img 24*9b8c59e7SSergio Lopez 25*9b8c59e7SSergio Lopezimage_len = 64 * 1024 * 1024 26*9b8c59e7SSergio Lopez 27*9b8c59e7SSergio Lopez# Test for RHBZ#1782175 28*9b8c59e7SSergio Lopezclass TestDirtyBitmapIOThread(iotests.QMPTestCase): 29*9b8c59e7SSergio Lopez drive0_img = os.path.join(iotests.test_dir, 'drive0.img') 30*9b8c59e7SSergio Lopez images = { 'drive0': drive0_img } 31*9b8c59e7SSergio Lopez 32*9b8c59e7SSergio Lopez def setUp(self): 33*9b8c59e7SSergio Lopez for name in self.images: 34*9b8c59e7SSergio Lopez qemu_img('create', '-f', iotests.imgfmt, 35*9b8c59e7SSergio Lopez self.images[name], str(image_len)) 36*9b8c59e7SSergio Lopez 37*9b8c59e7SSergio Lopez self.vm = iotests.VM() 38*9b8c59e7SSergio Lopez self.vm.add_object('iothread,id=iothread0') 39*9b8c59e7SSergio Lopez 40*9b8c59e7SSergio Lopez for name in self.images: 41*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=file,filename=%s,node-name=file_%s' 42*9b8c59e7SSergio Lopez % (self.images[name], name)) 43*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=qcow2,file=file_%s,node-name=%s' 44*9b8c59e7SSergio Lopez % (name, name)) 45*9b8c59e7SSergio Lopez 46*9b8c59e7SSergio Lopez self.vm.launch() 47*9b8c59e7SSergio Lopez self.vm.qmp('x-blockdev-set-iothread', 48*9b8c59e7SSergio Lopez node_name='drive0', iothread='iothread0', 49*9b8c59e7SSergio Lopez force=True) 50*9b8c59e7SSergio Lopez 51*9b8c59e7SSergio Lopez def tearDown(self): 52*9b8c59e7SSergio Lopez self.vm.shutdown() 53*9b8c59e7SSergio Lopez for name in self.images: 54*9b8c59e7SSergio Lopez os.remove(self.images[name]) 55*9b8c59e7SSergio Lopez 56*9b8c59e7SSergio Lopez def test_add_dirty_bitmap(self): 57*9b8c59e7SSergio Lopez result = self.vm.qmp( 58*9b8c59e7SSergio Lopez 'block-dirty-bitmap-add', 59*9b8c59e7SSergio Lopez node='drive0', 60*9b8c59e7SSergio Lopez name='bitmap1', 61*9b8c59e7SSergio Lopez persistent=True, 62*9b8c59e7SSergio Lopez ) 63*9b8c59e7SSergio Lopez 64*9b8c59e7SSergio Lopez self.assert_qmp(result, 'return', {}) 65*9b8c59e7SSergio Lopez 66*9b8c59e7SSergio Lopez 67*9b8c59e7SSergio Lopez# Test for RHBZ#1746217 & RHBZ#1773517 68*9b8c59e7SSergio Lopezclass TestNBDMirrorIOThread(iotests.QMPTestCase): 69*9b8c59e7SSergio Lopez nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock') 70*9b8c59e7SSergio Lopez drive0_img = os.path.join(iotests.test_dir, 'drive0.img') 71*9b8c59e7SSergio Lopez mirror_img = os.path.join(iotests.test_dir, 'mirror.img') 72*9b8c59e7SSergio Lopez images = { 'drive0': drive0_img, 'mirror': mirror_img } 73*9b8c59e7SSergio Lopez 74*9b8c59e7SSergio Lopez def setUp(self): 75*9b8c59e7SSergio Lopez for name in self.images: 76*9b8c59e7SSergio Lopez qemu_img('create', '-f', iotests.imgfmt, 77*9b8c59e7SSergio Lopez self.images[name], str(image_len)) 78*9b8c59e7SSergio Lopez 79*9b8c59e7SSergio Lopez self.vm_src = iotests.VM(path_suffix='src') 80*9b8c59e7SSergio Lopez self.vm_src.add_object('iothread,id=iothread0') 81*9b8c59e7SSergio Lopez self.vm_src.add_blockdev('driver=file,filename=%s,node-name=file0' 82*9b8c59e7SSergio Lopez % (self.drive0_img)) 83*9b8c59e7SSergio Lopez self.vm_src.add_blockdev('driver=qcow2,file=file0,node-name=drive0') 84*9b8c59e7SSergio Lopez self.vm_src.launch() 85*9b8c59e7SSergio Lopez self.vm_src.qmp('x-blockdev-set-iothread', 86*9b8c59e7SSergio Lopez node_name='drive0', iothread='iothread0', 87*9b8c59e7SSergio Lopez force=True) 88*9b8c59e7SSergio Lopez 89*9b8c59e7SSergio Lopez self.vm_tgt = iotests.VM(path_suffix='tgt') 90*9b8c59e7SSergio Lopez self.vm_tgt.add_object('iothread,id=iothread0') 91*9b8c59e7SSergio Lopez self.vm_tgt.add_blockdev('driver=file,filename=%s,node-name=file0' 92*9b8c59e7SSergio Lopez % (self.mirror_img)) 93*9b8c59e7SSergio Lopez self.vm_tgt.add_blockdev('driver=qcow2,file=file0,node-name=drive0') 94*9b8c59e7SSergio Lopez self.vm_tgt.launch() 95*9b8c59e7SSergio Lopez self.vm_tgt.qmp('x-blockdev-set-iothread', 96*9b8c59e7SSergio Lopez node_name='drive0', iothread='iothread0', 97*9b8c59e7SSergio Lopez force=True) 98*9b8c59e7SSergio Lopez 99*9b8c59e7SSergio Lopez def tearDown(self): 100*9b8c59e7SSergio Lopez self.vm_src.shutdown() 101*9b8c59e7SSergio Lopez self.vm_tgt.shutdown() 102*9b8c59e7SSergio Lopez for name in self.images: 103*9b8c59e7SSergio Lopez os.remove(self.images[name]) 104*9b8c59e7SSergio Lopez 105*9b8c59e7SSergio Lopez def test_nbd_mirror(self): 106*9b8c59e7SSergio Lopez result = self.vm_tgt.qmp( 107*9b8c59e7SSergio Lopez 'nbd-server-start', 108*9b8c59e7SSergio Lopez addr={ 109*9b8c59e7SSergio Lopez 'type': 'unix', 110*9b8c59e7SSergio Lopez 'data': { 'path': self.nbd_sock } 111*9b8c59e7SSergio Lopez } 112*9b8c59e7SSergio Lopez ) 113*9b8c59e7SSergio Lopez self.assert_qmp(result, 'return', {}) 114*9b8c59e7SSergio Lopez 115*9b8c59e7SSergio Lopez result = self.vm_tgt.qmp( 116*9b8c59e7SSergio Lopez 'nbd-server-add', 117*9b8c59e7SSergio Lopez device='drive0', 118*9b8c59e7SSergio Lopez writable=True 119*9b8c59e7SSergio Lopez ) 120*9b8c59e7SSergio Lopez self.assert_qmp(result, 'return', {}) 121*9b8c59e7SSergio Lopez 122*9b8c59e7SSergio Lopez result = self.vm_src.qmp( 123*9b8c59e7SSergio Lopez 'drive-mirror', 124*9b8c59e7SSergio Lopez device='drive0', 125*9b8c59e7SSergio Lopez target='nbd+unix:///drive0?socket=' + self.nbd_sock, 126*9b8c59e7SSergio Lopez sync='full', 127*9b8c59e7SSergio Lopez mode='existing', 128*9b8c59e7SSergio Lopez speed=64*1024*1024, 129*9b8c59e7SSergio Lopez job_id='j1' 130*9b8c59e7SSergio Lopez ) 131*9b8c59e7SSergio Lopez self.assert_qmp(result, 'return', {}) 132*9b8c59e7SSergio Lopez 133*9b8c59e7SSergio Lopez self.vm_src.event_wait(name="BLOCK_JOB_READY") 134*9b8c59e7SSergio Lopez 135*9b8c59e7SSergio Lopez 136*9b8c59e7SSergio Lopez# Test for RHBZ#1779036 137*9b8c59e7SSergio Lopezclass TestExternalSnapshotAbort(iotests.QMPTestCase): 138*9b8c59e7SSergio Lopez drive0_img = os.path.join(iotests.test_dir, 'drive0.img') 139*9b8c59e7SSergio Lopez snapshot_img = os.path.join(iotests.test_dir, 'snapshot.img') 140*9b8c59e7SSergio Lopez images = { 'drive0': drive0_img, 'snapshot': snapshot_img } 141*9b8c59e7SSergio Lopez 142*9b8c59e7SSergio Lopez def setUp(self): 143*9b8c59e7SSergio Lopez for name in self.images: 144*9b8c59e7SSergio Lopez qemu_img('create', '-f', iotests.imgfmt, 145*9b8c59e7SSergio Lopez self.images[name], str(image_len)) 146*9b8c59e7SSergio Lopez 147*9b8c59e7SSergio Lopez self.vm = iotests.VM() 148*9b8c59e7SSergio Lopez self.vm.add_object('iothread,id=iothread0') 149*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=file,filename=%s,node-name=file0' 150*9b8c59e7SSergio Lopez % (self.drive0_img)) 151*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=qcow2,file=file0,node-name=drive0') 152*9b8c59e7SSergio Lopez self.vm.launch() 153*9b8c59e7SSergio Lopez self.vm.qmp('x-blockdev-set-iothread', 154*9b8c59e7SSergio Lopez node_name='drive0', iothread='iothread0', 155*9b8c59e7SSergio Lopez force=True) 156*9b8c59e7SSergio Lopez 157*9b8c59e7SSergio Lopez def tearDown(self): 158*9b8c59e7SSergio Lopez self.vm.shutdown() 159*9b8c59e7SSergio Lopez for name in self.images: 160*9b8c59e7SSergio Lopez os.remove(self.images[name]) 161*9b8c59e7SSergio Lopez 162*9b8c59e7SSergio Lopez def test_external_snapshot_abort(self): 163*9b8c59e7SSergio Lopez # Use a two actions transaction with a bogus values on the second 164*9b8c59e7SSergio Lopez # one to trigger an abort of the transaction. 165*9b8c59e7SSergio Lopez result = self.vm.qmp('transaction', actions=[ 166*9b8c59e7SSergio Lopez { 167*9b8c59e7SSergio Lopez 'type': 'blockdev-snapshot-sync', 168*9b8c59e7SSergio Lopez 'data': { 'node-name': 'drive0', 169*9b8c59e7SSergio Lopez 'snapshot-file': self.snapshot_img, 170*9b8c59e7SSergio Lopez 'snapshot-node-name': 'snap1', 171*9b8c59e7SSergio Lopez 'mode': 'absolute-paths', 172*9b8c59e7SSergio Lopez 'format': 'qcow2' } 173*9b8c59e7SSergio Lopez }, 174*9b8c59e7SSergio Lopez { 175*9b8c59e7SSergio Lopez 'type': 'blockdev-snapshot-sync', 176*9b8c59e7SSergio Lopez 'data': { 'node-name': 'drive0', 177*9b8c59e7SSergio Lopez 'snapshot-file': '/fakesnapshot', 178*9b8c59e7SSergio Lopez 'snapshot-node-name': 'snap2', 179*9b8c59e7SSergio Lopez 'mode': 'absolute-paths', 180*9b8c59e7SSergio Lopez 'format': 'qcow2' } 181*9b8c59e7SSergio Lopez }, 182*9b8c59e7SSergio Lopez ]) 183*9b8c59e7SSergio Lopez 184*9b8c59e7SSergio Lopez # Crashes on failure, we expect this error. 185*9b8c59e7SSergio Lopez self.assert_qmp(result, 'error/class', 'GenericError') 186*9b8c59e7SSergio Lopez 187*9b8c59e7SSergio Lopez 188*9b8c59e7SSergio Lopez# Test for RHBZ#1782111 189*9b8c59e7SSergio Lopezclass TestBlockdevBackupAbort(iotests.QMPTestCase): 190*9b8c59e7SSergio Lopez drive0_img = os.path.join(iotests.test_dir, 'drive0.img') 191*9b8c59e7SSergio Lopez drive1_img = os.path.join(iotests.test_dir, 'drive1.img') 192*9b8c59e7SSergio Lopez snap0_img = os.path.join(iotests.test_dir, 'snap0.img') 193*9b8c59e7SSergio Lopez snap1_img = os.path.join(iotests.test_dir, 'snap1.img') 194*9b8c59e7SSergio Lopez images = { 'drive0': drive0_img, 195*9b8c59e7SSergio Lopez 'drive1': drive1_img, 196*9b8c59e7SSergio Lopez 'snap0': snap0_img, 197*9b8c59e7SSergio Lopez 'snap1': snap1_img } 198*9b8c59e7SSergio Lopez 199*9b8c59e7SSergio Lopez def setUp(self): 200*9b8c59e7SSergio Lopez for name in self.images: 201*9b8c59e7SSergio Lopez qemu_img('create', '-f', iotests.imgfmt, 202*9b8c59e7SSergio Lopez self.images[name], str(image_len)) 203*9b8c59e7SSergio Lopez 204*9b8c59e7SSergio Lopez self.vm = iotests.VM() 205*9b8c59e7SSergio Lopez self.vm.add_object('iothread,id=iothread0') 206*9b8c59e7SSergio Lopez self.vm.add_device('virtio-scsi,iothread=iothread0') 207*9b8c59e7SSergio Lopez 208*9b8c59e7SSergio Lopez for name in self.images: 209*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=file,filename=%s,node-name=file_%s' 210*9b8c59e7SSergio Lopez % (self.images[name], name)) 211*9b8c59e7SSergio Lopez self.vm.add_blockdev('driver=qcow2,file=file_%s,node-name=%s' 212*9b8c59e7SSergio Lopez % (name, name)) 213*9b8c59e7SSergio Lopez 214*9b8c59e7SSergio Lopez self.vm.add_device('scsi-hd,drive=drive0') 215*9b8c59e7SSergio Lopez self.vm.add_device('scsi-hd,drive=drive1') 216*9b8c59e7SSergio Lopez self.vm.launch() 217*9b8c59e7SSergio Lopez 218*9b8c59e7SSergio Lopez def tearDown(self): 219*9b8c59e7SSergio Lopez self.vm.shutdown() 220*9b8c59e7SSergio Lopez for name in self.images: 221*9b8c59e7SSergio Lopez os.remove(self.images[name]) 222*9b8c59e7SSergio Lopez 223*9b8c59e7SSergio Lopez def test_blockdev_backup_abort(self): 224*9b8c59e7SSergio Lopez # Use a two actions transaction with a bogus values on the second 225*9b8c59e7SSergio Lopez # one to trigger an abort of the transaction. 226*9b8c59e7SSergio Lopez result = self.vm.qmp('transaction', actions=[ 227*9b8c59e7SSergio Lopez { 228*9b8c59e7SSergio Lopez 'type': 'blockdev-backup', 229*9b8c59e7SSergio Lopez 'data': { 'device': 'drive0', 230*9b8c59e7SSergio Lopez 'target': 'snap0', 231*9b8c59e7SSergio Lopez 'sync': 'full', 232*9b8c59e7SSergio Lopez 'job-id': 'j1' } 233*9b8c59e7SSergio Lopez }, 234*9b8c59e7SSergio Lopez { 235*9b8c59e7SSergio Lopez 'type': 'blockdev-backup', 236*9b8c59e7SSergio Lopez 'data': { 'device': 'drive1', 237*9b8c59e7SSergio Lopez 'target': 'snap1', 238*9b8c59e7SSergio Lopez 'sync': 'full' } 239*9b8c59e7SSergio Lopez }, 240*9b8c59e7SSergio Lopez ]) 241*9b8c59e7SSergio Lopez 242*9b8c59e7SSergio Lopez # Hangs on failure, we expect this error. 243*9b8c59e7SSergio Lopez self.assert_qmp(result, 'error/class', 'GenericError') 244*9b8c59e7SSergio Lopez 245*9b8c59e7SSergio Lopezif __name__ == '__main__': 246*9b8c59e7SSergio Lopez iotests.main(supported_fmts=['qcow2'], 247*9b8c59e7SSergio Lopez supported_protocols=['file']) 248