xref: /openbmc/qemu/tests/qemu-iotests/tests/qsd-migrate (revision 0462a32b4f63b2448b4a196381138afd50719dc4)
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