xref: /openbmc/qemu/tests/qemu-iotests/tests/migrate-bitmaps-test (revision b30b8077243ea5dc93a540eedfecee3c74b19fa2)
1a44be033SVladimir Sementsov-Ogievskiy#!/usr/bin/env python3
2a44be033SVladimir Sementsov-Ogievskiy# group: rw migration
3a44be033SVladimir Sementsov-Ogievskiy#
4a44be033SVladimir Sementsov-Ogievskiy# Tests for dirty bitmaps migration.
5a44be033SVladimir Sementsov-Ogievskiy#
6a44be033SVladimir Sementsov-Ogievskiy# Copyright (c) 2016-2017 Virtuozzo International GmbH. All rights reserved.
7a44be033SVladimir Sementsov-Ogievskiy#
8a44be033SVladimir Sementsov-Ogievskiy# This program is free software; you can redistribute it and/or modify
9a44be033SVladimir Sementsov-Ogievskiy# it under the terms of the GNU General Public License as published by
10a44be033SVladimir Sementsov-Ogievskiy# the Free Software Foundation; either version 2 of the License, or
11a44be033SVladimir Sementsov-Ogievskiy# (at your option) any later version.
12a44be033SVladimir Sementsov-Ogievskiy#
13a44be033SVladimir Sementsov-Ogievskiy# This program is distributed in the hope that it will be useful,
14a44be033SVladimir Sementsov-Ogievskiy# but WITHOUT ANY WARRANTY; without even the implied warranty of
15a44be033SVladimir Sementsov-Ogievskiy# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16a44be033SVladimir Sementsov-Ogievskiy# GNU General Public License for more details.
17a44be033SVladimir Sementsov-Ogievskiy#
18a44be033SVladimir Sementsov-Ogievskiy# You should have received a copy of the GNU General Public License
19a44be033SVladimir Sementsov-Ogievskiy# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20a44be033SVladimir Sementsov-Ogievskiy#
21a44be033SVladimir Sementsov-Ogievskiy
22a44be033SVladimir Sementsov-Ogievskiyimport itertools
23a44be033SVladimir Sementsov-Ogievskiyimport operator
2422968996SJohn Snowimport os
25a44be033SVladimir Sementsov-Ogievskiyimport re
2622968996SJohn Snow
27d8c2e47dSHanna Reitzimport iotests
28a44be033SVladimir Sementsov-Ogievskiyfrom iotests import qemu_img, qemu_img_create, Timeout
29a44be033SVladimir Sementsov-Ogievskiy
30a44be033SVladimir Sementsov-Ogievskiy
31a44be033SVladimir Sementsov-Ogievskiydisk_a = os.path.join(iotests.test_dir, 'disk_a')
32a44be033SVladimir Sementsov-Ogievskiydisk_b = os.path.join(iotests.test_dir, 'disk_b')
33a44be033SVladimir Sementsov-Ogievskiybase_a = os.path.join(iotests.test_dir, 'base_a')
34a44be033SVladimir Sementsov-Ogievskiysize = '1M'
35a44be033SVladimir Sementsov-Ogievskiymig_file = os.path.join(iotests.test_dir, 'mig_file')
36a44be033SVladimir Sementsov-Ogievskiymig_cmd = 'exec: cat > ' + mig_file
37a44be033SVladimir Sementsov-Ogievskiyincoming_cmd = 'exec: cat ' + mig_file
38a44be033SVladimir Sementsov-Ogievskiy
39a44be033SVladimir Sementsov-Ogievskiy
40d8c2e47dSHanna Reitzdef get_bitmap_hash(vm):
41d8c2e47dSHanna Reitz    result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
42d8c2e47dSHanna Reitz                    node='drive0', name='bitmap0')
43d8c2e47dSHanna Reitz    return result['return']['sha256']
44d8c2e47dSHanna Reitz
45d8c2e47dSHanna Reitz
46a44be033SVladimir Sementsov-Ogievskiyclass TestDirtyBitmapMigration(iotests.QMPTestCase):
47a44be033SVladimir Sementsov-Ogievskiy    def tearDown(self):
48a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.shutdown()
49a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.shutdown()
50a44be033SVladimir Sementsov-Ogievskiy        os.remove(disk_a)
51a44be033SVladimir Sementsov-Ogievskiy        os.remove(disk_b)
52a44be033SVladimir Sementsov-Ogievskiy        os.remove(mig_file)
53a44be033SVladimir Sementsov-Ogievskiy
54a44be033SVladimir Sementsov-Ogievskiy    def setUp(self):
55a44be033SVladimir Sementsov-Ogievskiy        qemu_img('create', '-f', iotests.imgfmt, disk_a, size)
56a44be033SVladimir Sementsov-Ogievskiy        qemu_img('create', '-f', iotests.imgfmt, disk_b, size)
57a44be033SVladimir Sementsov-Ogievskiy
58a44be033SVladimir Sementsov-Ogievskiy        self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a)
59a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.launch()
60a44be033SVladimir Sementsov-Ogievskiy
61a44be033SVladimir Sementsov-Ogievskiy        self.vm_b = iotests.VM(path_suffix='b')
62a44be033SVladimir Sementsov-Ogievskiy
63a44be033SVladimir Sementsov-Ogievskiy    def add_bitmap(self, vm, granularity, persistent):
64a44be033SVladimir Sementsov-Ogievskiy        params = {'node': 'drive0',
65a44be033SVladimir Sementsov-Ogievskiy                  'name': 'bitmap0',
66a44be033SVladimir Sementsov-Ogievskiy                  'granularity': granularity}
67a44be033SVladimir Sementsov-Ogievskiy        if persistent:
68a44be033SVladimir Sementsov-Ogievskiy            params['persistent'] = True
69a44be033SVladimir Sementsov-Ogievskiy
70a44be033SVladimir Sementsov-Ogievskiy        result = vm.qmp('block-dirty-bitmap-add', **params)
71d8c2e47dSHanna Reitz        self.assert_qmp(result, 'return', {})
72a44be033SVladimir Sementsov-Ogievskiy
73a44be033SVladimir Sementsov-Ogievskiy    def check_bitmap(self, vm, sha256):
74a44be033SVladimir Sementsov-Ogievskiy        result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
75a44be033SVladimir Sementsov-Ogievskiy                        node='drive0', name='bitmap0')
76a44be033SVladimir Sementsov-Ogievskiy        if sha256:
77d8c2e47dSHanna Reitz            self.assert_qmp(result, 'return/sha256', sha256)
78a44be033SVladimir Sementsov-Ogievskiy        else:
79a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'error/desc',
80d8c2e47dSHanna Reitz                            "Dirty bitmap 'bitmap0' not found")
81a44be033SVladimir Sementsov-Ogievskiy
82a44be033SVladimir Sementsov-Ogievskiy    def do_test_migration_resume_source(self, persistent, migrate_bitmaps):
83a44be033SVladimir Sementsov-Ogievskiy        granularity = 512
84a44be033SVladimir Sementsov-Ogievskiy
85a44be033SVladimir Sementsov-Ogievskiy        # regions = ((start, count), ...)
86a44be033SVladimir Sementsov-Ogievskiy        regions = ((0, 0x10000),
87a44be033SVladimir Sementsov-Ogievskiy                   (0xf0000, 0x10000),
88a44be033SVladimir Sementsov-Ogievskiy                   (0xa0201, 0x1000))
89a44be033SVladimir Sementsov-Ogievskiy
90a44be033SVladimir Sementsov-Ogievskiy        mig_caps = [{'capability': 'events', 'state': True}]
91a44be033SVladimir Sementsov-Ogievskiy        if migrate_bitmaps:
92a44be033SVladimir Sementsov-Ogievskiy            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})
93a44be033SVladimir Sementsov-Ogievskiy
94a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate-set-capabilities',
95a44be033SVladimir Sementsov-Ogievskiy                               capabilities=mig_caps)
96a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
97a44be033SVladimir Sementsov-Ogievskiy
98a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
99a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
100a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
101d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
102a44be033SVladimir Sementsov-Ogievskiy
103a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate', uri=mig_cmd)
104a44be033SVladimir Sementsov-Ogievskiy        while True:
105a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
106a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
107a44be033SVladimir Sementsov-Ogievskiy                break
108a44be033SVladimir Sementsov-Ogievskiy        while True:
109a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_a.qmp('query-status')
110d8c2e47dSHanna Reitz            if result['return']['status'] == 'postmigrate':
111a44be033SVladimir Sementsov-Ogievskiy                break
112a44be033SVladimir Sementsov-Ogievskiy
113a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here
114a44be033SVladimir Sementsov-Ogievskiy        removed = (not migrate_bitmaps) and persistent
115a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, False if removed else sha256)
116a44be033SVladimir Sementsov-Ogievskiy
117a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('cont')
118a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
119a44be033SVladimir Sementsov-Ogievskiy
120a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here after invalidation
121a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256)
122a44be033SVladimir Sementsov-Ogievskiy
123a44be033SVladimir Sementsov-Ogievskiy        # shutdown and check that invalidation didn't fail
124a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.shutdown()
125a44be033SVladimir Sementsov-Ogievskiy
126a44be033SVladimir Sementsov-Ogievskiy        # catch 'Could not reopen qcow2 layer: Bitmap already exists'
127a44be033SVladimir Sementsov-Ogievskiy        # possible error
128a44be033SVladimir Sementsov-Ogievskiy        log = self.vm_a.get_log()
129a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
130a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^(wrote .* bytes at offset .*\n.*KiB.*ops.*sec.*\n){3}',
131a44be033SVladimir Sementsov-Ogievskiy                     '', log)
132a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
133a44be033SVladimir Sementsov-Ogievskiy        self.assertEqual(log, '')
134a44be033SVladimir Sementsov-Ogievskiy
135a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still persistent
136a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.launch()
137a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256 if persistent else False)
138a44be033SVladimir Sementsov-Ogievskiy
139a44be033SVladimir Sementsov-Ogievskiy    def do_test_migration(self, persistent, migrate_bitmaps, online,
140a44be033SVladimir Sementsov-Ogievskiy                          shared_storage, pre_shutdown):
141a44be033SVladimir Sementsov-Ogievskiy        granularity = 512
142a44be033SVladimir Sementsov-Ogievskiy
143a44be033SVladimir Sementsov-Ogievskiy        # regions = ((start, count), ...)
144a44be033SVladimir Sementsov-Ogievskiy        regions = ((0, 0x10000),
145a44be033SVladimir Sementsov-Ogievskiy                   (0xf0000, 0x10000),
146a44be033SVladimir Sementsov-Ogievskiy                   (0xa0201, 0x1000))
147a44be033SVladimir Sementsov-Ogievskiy
148a44be033SVladimir Sementsov-Ogievskiy        should_migrate = \
149a44be033SVladimir Sementsov-Ogievskiy            (migrate_bitmaps and (persistent or not pre_shutdown)) or \
150a44be033SVladimir Sementsov-Ogievskiy            (persistent and shared_storage)
151a44be033SVladimir Sementsov-Ogievskiy        mig_caps = [{'capability': 'events', 'state': True}]
152a44be033SVladimir Sementsov-Ogievskiy        if migrate_bitmaps:
153a44be033SVladimir Sementsov-Ogievskiy            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})
154a44be033SVladimir Sementsov-Ogievskiy
155a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_incoming(incoming_cmd if online else "defer")
156a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_drive(disk_a if shared_storage else disk_b)
157a44be033SVladimir Sementsov-Ogievskiy
158a44be033SVladimir Sementsov-Ogievskiy        if online:
159a44be033SVladimir Sementsov-Ogievskiy            os.mkfifo(mig_file)
160a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
161a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-set-capabilities',
162a44be033SVladimir Sementsov-Ogievskiy                                   capabilities=mig_caps)
163a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
164a44be033SVladimir Sementsov-Ogievskiy
165a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
166a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
167a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
168d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
169a44be033SVladimir Sementsov-Ogievskiy
170a44be033SVladimir Sementsov-Ogievskiy        if pre_shutdown:
171a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
172a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.launch()
173a44be033SVladimir Sementsov-Ogievskiy
174a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate-set-capabilities',
175a44be033SVladimir Sementsov-Ogievskiy                               capabilities=mig_caps)
176a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
177a44be033SVladimir Sementsov-Ogievskiy
178a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate', uri=mig_cmd)
179a44be033SVladimir Sementsov-Ogievskiy        while True:
180a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
181a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
182a44be033SVladimir Sementsov-Ogievskiy                break
183a44be033SVladimir Sementsov-Ogievskiy
184a44be033SVladimir Sementsov-Ogievskiy        if not online:
185a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
186a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
187a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-set-capabilities',
188a44be033SVladimir Sementsov-Ogievskiy                                   capabilities=mig_caps)
189a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
190a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-incoming', uri=incoming_cmd)
191a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
192a44be033SVladimir Sementsov-Ogievskiy
193a44be033SVladimir Sementsov-Ogievskiy        while True:
194a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_b.event_wait('MIGRATION')
195a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
196a44be033SVladimir Sementsov-Ogievskiy                break
197a44be033SVladimir Sementsov-Ogievskiy
198a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_b, sha256 if should_migrate else False)
199a44be033SVladimir Sementsov-Ogievskiy
200a44be033SVladimir Sementsov-Ogievskiy        if should_migrate:
201a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.shutdown()
202a44be033SVladimir Sementsov-Ogievskiy
203a44be033SVladimir Sementsov-Ogievskiy            # catch 'Could not reopen qcow2 layer: Bitmap already exists'
204a44be033SVladimir Sementsov-Ogievskiy            # possible error
205a44be033SVladimir Sementsov-Ogievskiy            log = self.vm_b.get_log()
206a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
207a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
208a44be033SVladimir Sementsov-Ogievskiy            self.assertEqual(log, '')
209a44be033SVladimir Sementsov-Ogievskiy
210a44be033SVladimir Sementsov-Ogievskiy            # recreate vm_b, as we don't want -incoming option (this will lead
211a44be033SVladimir Sementsov-Ogievskiy            # to "cat" process left alive after test finish)
212a44be033SVladimir Sementsov-Ogievskiy            self.vm_b = iotests.VM(path_suffix='b')
213a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.add_drive(disk_a if shared_storage else disk_b)
214a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
215a44be033SVladimir Sementsov-Ogievskiy            self.check_bitmap(self.vm_b, sha256 if persistent else False)
216a44be033SVladimir Sementsov-Ogievskiy
217a44be033SVladimir Sementsov-Ogievskiy
218d8c2e47dSHanna Reitzdef inject_test_case(klass, suffix, method, *args, **kwargs):
219a44be033SVladimir Sementsov-Ogievskiy    mc = operator.methodcaller(method, *args, **kwargs)
220d8c2e47dSHanna Reitz    # We want to add a function attribute to `klass`, so that it is
221d8c2e47dSHanna Reitz    # correctly converted to a method on instantiation.  The
222d8c2e47dSHanna Reitz    # methodcaller object `mc` is a callable, not a function, so we
223d8c2e47dSHanna Reitz    # need the lambda to turn it into a function.
224d8c2e47dSHanna Reitz    # pylint: disable=unnecessary-lambda
225d8c2e47dSHanna Reitz    setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
226d8c2e47dSHanna Reitz
227a44be033SVladimir Sementsov-Ogievskiy
228a44be033SVladimir Sementsov-Ogievskiyclass TestDirtyBitmapBackingMigration(iotests.QMPTestCase):
229a44be033SVladimir Sementsov-Ogievskiy    def setUp(self):
230a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, base_a, size)
231a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
232a44be033SVladimir Sementsov-Ogievskiy                        '-b', base_a, disk_a, size)
233a44be033SVladimir Sementsov-Ogievskiy
234a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
235a44be033SVladimir Sementsov-Ogievskiy            qemu_img('bitmap', '--add', f, 'bmap0')
236a44be033SVladimir Sementsov-Ogievskiy
237a44be033SVladimir Sementsov-Ogievskiy        blockdev = {
238a44be033SVladimir Sementsov-Ogievskiy            'node-name': 'node0',
239a44be033SVladimir Sementsov-Ogievskiy            'driver': iotests.imgfmt,
240a44be033SVladimir Sementsov-Ogievskiy            'file': {
241a44be033SVladimir Sementsov-Ogievskiy                'driver': 'file',
242a44be033SVladimir Sementsov-Ogievskiy                'filename': disk_a
243a44be033SVladimir Sementsov-Ogievskiy            },
244a44be033SVladimir Sementsov-Ogievskiy            'backing': {
245a44be033SVladimir Sementsov-Ogievskiy                'node-name': 'node0-base',
246a44be033SVladimir Sementsov-Ogievskiy                'driver': iotests.imgfmt,
247a44be033SVladimir Sementsov-Ogievskiy                'file': {
248a44be033SVladimir Sementsov-Ogievskiy                    'driver': 'file',
249a44be033SVladimir Sementsov-Ogievskiy                    'filename': base_a
250a44be033SVladimir Sementsov-Ogievskiy                }
251a44be033SVladimir Sementsov-Ogievskiy            }
252a44be033SVladimir Sementsov-Ogievskiy        }
253a44be033SVladimir Sementsov-Ogievskiy
254a44be033SVladimir Sementsov-Ogievskiy        self.vm = iotests.VM()
255a44be033SVladimir Sementsov-Ogievskiy        self.vm.launch()
256a44be033SVladimir Sementsov-Ogievskiy
257a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('blockdev-add', **blockdev)
258a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
259a44be033SVladimir Sementsov-Ogievskiy
260a44be033SVladimir Sementsov-Ogievskiy        # Check that the bitmaps are there
261d8c2e47dSHanna Reitz        nodes = self.vm.qmp('query-named-block-nodes', flat=True)['return']
262d8c2e47dSHanna Reitz        for node in nodes:
263a44be033SVladimir Sementsov-Ogievskiy            if 'node0' in node['node-name']:
264a44be033SVladimir Sementsov-Ogievskiy                self.assert_qmp(node, 'dirty-bitmaps[0]/name', 'bmap0')
265a44be033SVladimir Sementsov-Ogievskiy
266a44be033SVladimir Sementsov-Ogievskiy        caps = [{'capability': 'events', 'state': True}]
267a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('migrate-set-capabilities', capabilities=caps)
268a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
269a44be033SVladimir Sementsov-Ogievskiy
270a44be033SVladimir Sementsov-Ogievskiy    def tearDown(self):
271a44be033SVladimir Sementsov-Ogievskiy        self.vm.shutdown()
272a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
273a44be033SVladimir Sementsov-Ogievskiy            os.remove(f)
274a44be033SVladimir Sementsov-Ogievskiy
275a44be033SVladimir Sementsov-Ogievskiy    def test_cont_on_source(self):
276a44be033SVladimir Sementsov-Ogievskiy        """
277a44be033SVladimir Sementsov-Ogievskiy        Continue the source after migration.
278a44be033SVladimir Sementsov-Ogievskiy        """
279d8c2e47dSHanna Reitz        result = self.vm.qmp('migrate', uri='exec: cat > /dev/null')
280a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
281a44be033SVladimir Sementsov-Ogievskiy
282a44be033SVladimir Sementsov-Ogievskiy        with Timeout(10, 'Migration timeout'):
283a44be033SVladimir Sementsov-Ogievskiy            self.vm.wait_migration('postmigrate')
284a44be033SVladimir Sementsov-Ogievskiy
285a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('cont')
286a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
287a44be033SVladimir Sementsov-Ogievskiy
288a44be033SVladimir Sementsov-Ogievskiy
28922968996SJohn Snowdef main() -> None:
29022968996SJohn Snow    for cmb in list(itertools.product((True, False), repeat=5)):
29122968996SJohn Snow        name = ('_' if cmb[0] else '_not_') + 'persistent_'
29222968996SJohn Snow        name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
29322968996SJohn Snow        name += '_online' if cmb[2] else '_offline'
29422968996SJohn Snow        name += '_shared' if cmb[3] else '_nonshared'
29522968996SJohn Snow        if cmb[4]:
29622968996SJohn Snow            name += '__pre_shutdown'
29722968996SJohn Snow
29822968996SJohn Snow        inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
29922968996SJohn Snow                         *list(cmb))
30022968996SJohn Snow
30122968996SJohn Snow    for cmb in list(itertools.product((True, False), repeat=2)):
30222968996SJohn Snow        name = ('_' if cmb[0] else '_not_') + 'persistent_'
30322968996SJohn Snow        name += ('_' if cmb[1] else '_not_') + 'migbitmap'
30422968996SJohn Snow
30522968996SJohn Snow        inject_test_case(TestDirtyBitmapMigration, name,
30622968996SJohn Snow                         'do_test_migration_resume_source', *list(cmb))
30722968996SJohn Snow
30822968996SJohn Snow    iotests.main(
30922968996SJohn Snow        supported_fmts=['qcow2'],
310*b30b8077SVladimir Sementsov-Ogievskiy        supported_protocols=['file'],
311*b30b8077SVladimir Sementsov-Ogievskiy        unsupported_imgopts=['compat']
31222968996SJohn Snow    )
31322968996SJohn Snow
31422968996SJohn Snow
315a44be033SVladimir Sementsov-Ogievskiyif __name__ == '__main__':
31622968996SJohn Snow    main()
317