1#!/usr/bin/env python3 2# group: rw quick 3# 4# Copyright (C) Red Hat, Inc. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18# 19# Creator/Owner: Kevin Wolf <kwolf@redhat.com> 20 21import iotests 22 23from iotests import filter_qemu_io, filter_qtest 24 25iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], 26 supported_protocols=['file'], 27 supported_platforms=['linux']) 28 29with iotests.FilePath('disk.img') as path, \ 30 iotests.FilePath('nbd-src.sock', base_dir=iotests.sock_dir) as nbd_src, \ 31 iotests.FilePath('nbd-dst.sock', base_dir=iotests.sock_dir) as nbd_dst, \ 32 iotests.FilePath('migrate.sock', base_dir=iotests.sock_dir) as mig_sock, \ 33 iotests.VM(path_suffix="-src") as vm_src, \ 34 iotests.VM(path_suffix="-dst") as vm_dst: 35 36 img_size = '10M' 37 38 iotests.log('Preparing disk...') 39 iotests.qemu_img_create('-f', iotests.imgfmt, path, img_size) 40 41 iotests.log('Launching source QSD...') 42 qsd_src = iotests.QemuStorageDaemon( 43 '--blockdev', f'file,node-name=disk-file,filename={path}', 44 '--blockdev', f'{iotests.imgfmt},file=disk-file,node-name=disk-fmt', 45 '--nbd-server', f'addr.type=unix,addr.path={nbd_src}', 46 '--export', 'nbd,id=exp0,node-name=disk-fmt,writable=true,' 47 'allow-inactive=true', 48 qmp=True, 49 ) 50 51 iotests.log('Launching source VM...') 52 vm_src.add_args('-blockdev', f'nbd,node-name=disk,server.type=unix,' 53 f'server.path={nbd_src},export=disk-fmt') 54 vm_src.add_args('-device', 'virtio-blk,drive=disk,id=virtio0') 55 vm_src.launch() 56 57 iotests.log('Launching destination QSD...') 58 qsd_dst = iotests.QemuStorageDaemon( 59 '--blockdev', f'file,node-name=disk-file,filename={path},active=off', 60 '--blockdev', f'{iotests.imgfmt},file=disk-file,node-name=disk-fmt,' 61 f'active=off', 62 '--nbd-server', f'addr.type=unix,addr.path={nbd_dst}', 63 '--export', 'nbd,id=exp0,node-name=disk-fmt,writable=true,' 64 'allow-inactive=true', 65 qmp=True, 66 instance_id='b', 67 ) 68 69 iotests.log('Launching destination VM...') 70 vm_dst.add_args('-blockdev', f'nbd,node-name=disk,server.type=unix,' 71 f'server.path={nbd_dst},export=disk-fmt') 72 vm_dst.add_args('-device', 'virtio-blk,drive=disk,id=virtio0') 73 vm_dst.add_args('-incoming', f'unix:{mig_sock}') 74 vm_dst.launch() 75 76 iotests.log('\nTest I/O on the source') 77 vm_src.hmp_qemu_io('virtio0/virtio-backend', 'write -P 0x11 0 4k', 78 use_log=True, qdev=True) 79 vm_src.hmp_qemu_io('virtio0/virtio-backend', 'read -P 0x11 0 4k', 80 use_log=True, qdev=True) 81 82 iotests.log('\nStarting migration...') 83 84 mig_caps = [ 85 {'capability': 'events', 'state': True}, 86 {'capability': 'pause-before-switchover', 'state': True}, 87 ] 88 vm_src.qmp_log('migrate-set-capabilities', capabilities=mig_caps) 89 vm_dst.qmp_log('migrate-set-capabilities', capabilities=mig_caps) 90 vm_src.qmp_log('migrate', uri=f'unix:{mig_sock}', 91 filters=[iotests.filter_qmp_testfiles]) 92 93 vm_src.event_wait('MIGRATION', 94 match={'data': {'status': 'pre-switchover'}}) 95 96 iotests.log('\nPre-switchover: Reconfigure QSD instances') 97 98 iotests.log(qsd_src.qmp('blockdev-set-active', {'active': False})) 99 100 # Reading is okay from both sides while the image is inactive. Note that 101 # the destination may have stale data until it activates the image, though. 102 vm_src.hmp_qemu_io('virtio0/virtio-backend', 'read -P 0x11 0 4k', 103 use_log=True, qdev=True) 104 vm_dst.hmp_qemu_io('virtio0/virtio-backend', 'read 0 4k', 105 use_log=True, qdev=True) 106 107 iotests.log(qsd_dst.qmp('blockdev-set-active', {'active': True})) 108 109 iotests.log('\nCompleting migration...') 110 111 vm_src.qmp_log('migrate-continue', state='pre-switchover') 112 vm_dst.event_wait('MIGRATION', match={'data': {'status': 'completed'}}) 113 114 iotests.log('\nTest I/O on the destination') 115 116 # Now the destination must see what the source wrote 117 vm_dst.hmp_qemu_io('virtio0/virtio-backend', 'read -P 0x11 0 4k', 118 use_log=True, qdev=True) 119 120 # And be able to overwrite it 121 vm_dst.hmp_qemu_io('virtio0/virtio-backend', 'write -P 0x22 0 4k', 122 use_log=True, qdev=True) 123 vm_dst.hmp_qemu_io('virtio0/virtio-backend', 'read -P 0x22 0 4k', 124 use_log=True, qdev=True) 125 126 iotests.log('\nDone') 127 128 vm_src.shutdown() 129 iotests.log('\n--- vm_src log ---') 130 log = vm_src.get_log() 131 if log: 132 iotests.log(log, [filter_qtest, filter_qemu_io]) 133 qsd_src.stop() 134 135 vm_dst.shutdown() 136 iotests.log('\n--- vm_dst log ---') 137 log = vm_dst.get_log() 138 if log: 139 iotests.log(log, [filter_qtest, filter_qemu_io]) 140 qsd_dst.stop() 141