xref: /openbmc/qemu/tests/qemu-iotests/tests/migrate-bitmaps-test (revision 800485762e6564e04e2ab315132d477069562d91)
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
70*b6aed193SVladimir Sementsov-Ogievskiy        vm.cmd('block-dirty-bitmap-add', params)
71a44be033SVladimir Sementsov-Ogievskiy
72a44be033SVladimir Sementsov-Ogievskiy    def check_bitmap(self, vm, sha256):
73a44be033SVladimir Sementsov-Ogievskiy        result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
74a44be033SVladimir Sementsov-Ogievskiy                        node='drive0', name='bitmap0')
75a44be033SVladimir Sementsov-Ogievskiy        if sha256:
76d8c2e47dSHanna Reitz            self.assert_qmp(result, 'return/sha256', sha256)
77a44be033SVladimir Sementsov-Ogievskiy        else:
78a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'error/desc',
79d8c2e47dSHanna Reitz                            "Dirty bitmap 'bitmap0' not found")
80a44be033SVladimir Sementsov-Ogievskiy
81a44be033SVladimir Sementsov-Ogievskiy    def do_test_migration_resume_source(self, persistent, migrate_bitmaps):
82a44be033SVladimir Sementsov-Ogievskiy        granularity = 512
83a44be033SVladimir Sementsov-Ogievskiy
84a44be033SVladimir Sementsov-Ogievskiy        # regions = ((start, count), ...)
85a44be033SVladimir Sementsov-Ogievskiy        regions = ((0, 0x10000),
86a44be033SVladimir Sementsov-Ogievskiy                   (0xf0000, 0x10000),
87a44be033SVladimir Sementsov-Ogievskiy                   (0xa0201, 0x1000))
88a44be033SVladimir Sementsov-Ogievskiy
89a44be033SVladimir Sementsov-Ogievskiy        mig_caps = [{'capability': 'events', 'state': True}]
90a44be033SVladimir Sementsov-Ogievskiy        if migrate_bitmaps:
91a44be033SVladimir Sementsov-Ogievskiy            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})
92a44be033SVladimir Sementsov-Ogievskiy
93*b6aed193SVladimir Sementsov-Ogievskiy        self.vm_a.cmd('migrate-set-capabilities',
94a44be033SVladimir Sementsov-Ogievskiy                      capabilities=mig_caps)
95a44be033SVladimir Sementsov-Ogievskiy
96a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
97a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
98a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
99d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
100a44be033SVladimir Sementsov-Ogievskiy
101*b6aed193SVladimir Sementsov-Ogievskiy        self.vm_a.cmd('migrate', uri=mig_cmd)
102a44be033SVladimir Sementsov-Ogievskiy        while True:
103a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
104a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
105a44be033SVladimir Sementsov-Ogievskiy                break
106a44be033SVladimir Sementsov-Ogievskiy        while True:
107a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_a.qmp('query-status')
108d8c2e47dSHanna Reitz            if result['return']['status'] == 'postmigrate':
109a44be033SVladimir Sementsov-Ogievskiy                break
110a44be033SVladimir Sementsov-Ogievskiy
111a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here
112a44be033SVladimir Sementsov-Ogievskiy        removed = (not migrate_bitmaps) and persistent
113a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, False if removed else sha256)
114a44be033SVladimir Sementsov-Ogievskiy
115*b6aed193SVladimir Sementsov-Ogievskiy        self.vm_a.cmd('cont')
116a44be033SVladimir Sementsov-Ogievskiy
117a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here after invalidation
118a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256)
119a44be033SVladimir Sementsov-Ogievskiy
120a44be033SVladimir Sementsov-Ogievskiy        # shutdown and check that invalidation didn't fail
121a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.shutdown()
122a44be033SVladimir Sementsov-Ogievskiy
123a44be033SVladimir Sementsov-Ogievskiy        # catch 'Could not reopen qcow2 layer: Bitmap already exists'
124a44be033SVladimir Sementsov-Ogievskiy        # possible error
125a44be033SVladimir Sementsov-Ogievskiy        log = self.vm_a.get_log()
126a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
127a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^(wrote .* bytes at offset .*\n.*KiB.*ops.*sec.*\n){3}',
128a44be033SVladimir Sementsov-Ogievskiy                     '', log)
129a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
130a44be033SVladimir Sementsov-Ogievskiy        self.assertEqual(log, '')
131a44be033SVladimir Sementsov-Ogievskiy
132a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still persistent
133a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.launch()
134a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256 if persistent else False)
135a44be033SVladimir Sementsov-Ogievskiy
136a44be033SVladimir Sementsov-Ogievskiy    def do_test_migration(self, persistent, migrate_bitmaps, online,
137a44be033SVladimir Sementsov-Ogievskiy                          shared_storage, pre_shutdown):
138a44be033SVladimir Sementsov-Ogievskiy        granularity = 512
139a44be033SVladimir Sementsov-Ogievskiy
140a44be033SVladimir Sementsov-Ogievskiy        # regions = ((start, count), ...)
141a44be033SVladimir Sementsov-Ogievskiy        regions = ((0, 0x10000),
142a44be033SVladimir Sementsov-Ogievskiy                   (0xf0000, 0x10000),
143a44be033SVladimir Sementsov-Ogievskiy                   (0xa0201, 0x1000))
144a44be033SVladimir Sementsov-Ogievskiy
145a44be033SVladimir Sementsov-Ogievskiy        should_migrate = \
146a44be033SVladimir Sementsov-Ogievskiy            (migrate_bitmaps and (persistent or not pre_shutdown)) or \
147a44be033SVladimir Sementsov-Ogievskiy            (persistent and shared_storage)
148a44be033SVladimir Sementsov-Ogievskiy        mig_caps = [{'capability': 'events', 'state': True}]
149a44be033SVladimir Sementsov-Ogievskiy        if migrate_bitmaps:
150a44be033SVladimir Sementsov-Ogievskiy            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})
151a44be033SVladimir Sementsov-Ogievskiy
152a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_incoming(incoming_cmd if online else "defer")
153a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_drive(disk_a if shared_storage else disk_b)
154a44be033SVladimir Sementsov-Ogievskiy
155a44be033SVladimir Sementsov-Ogievskiy        if online:
156a44be033SVladimir Sementsov-Ogievskiy            os.mkfifo(mig_file)
157a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
158*b6aed193SVladimir Sementsov-Ogievskiy            self.vm_b.cmd('migrate-set-capabilities',
159a44be033SVladimir Sementsov-Ogievskiy                          capabilities=mig_caps)
160a44be033SVladimir Sementsov-Ogievskiy
161a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
162a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
163a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
164d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
165a44be033SVladimir Sementsov-Ogievskiy
166a44be033SVladimir Sementsov-Ogievskiy        if pre_shutdown:
167a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
168a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.launch()
169a44be033SVladimir Sementsov-Ogievskiy
170*b6aed193SVladimir Sementsov-Ogievskiy        self.vm_a.cmd('migrate-set-capabilities',
171a44be033SVladimir Sementsov-Ogievskiy                      capabilities=mig_caps)
172a44be033SVladimir Sementsov-Ogievskiy
173*b6aed193SVladimir Sementsov-Ogievskiy        self.vm_a.cmd('migrate', uri=mig_cmd)
174a44be033SVladimir Sementsov-Ogievskiy        while True:
175a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
176a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
177a44be033SVladimir Sementsov-Ogievskiy                break
178a44be033SVladimir Sementsov-Ogievskiy
179a44be033SVladimir Sementsov-Ogievskiy        if not online:
180a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
181a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
182*b6aed193SVladimir Sementsov-Ogievskiy            self.vm_b.cmd('migrate-set-capabilities',
183a44be033SVladimir Sementsov-Ogievskiy                          capabilities=mig_caps)
184*b6aed193SVladimir Sementsov-Ogievskiy            self.vm_b.cmd('migrate-incoming', uri=incoming_cmd)
185a44be033SVladimir Sementsov-Ogievskiy
186a44be033SVladimir Sementsov-Ogievskiy        while True:
187a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_b.event_wait('MIGRATION')
188a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
189a44be033SVladimir Sementsov-Ogievskiy                break
190a44be033SVladimir Sementsov-Ogievskiy
191a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_b, sha256 if should_migrate else False)
192a44be033SVladimir Sementsov-Ogievskiy
193a44be033SVladimir Sementsov-Ogievskiy        if should_migrate:
194a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.shutdown()
195a44be033SVladimir Sementsov-Ogievskiy
196a44be033SVladimir Sementsov-Ogievskiy            # catch 'Could not reopen qcow2 layer: Bitmap already exists'
197a44be033SVladimir Sementsov-Ogievskiy            # possible error
198a44be033SVladimir Sementsov-Ogievskiy            log = self.vm_b.get_log()
199a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
200a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
201a44be033SVladimir Sementsov-Ogievskiy            self.assertEqual(log, '')
202a44be033SVladimir Sementsov-Ogievskiy
203a44be033SVladimir Sementsov-Ogievskiy            # recreate vm_b, as we don't want -incoming option (this will lead
204a44be033SVladimir Sementsov-Ogievskiy            # to "cat" process left alive after test finish)
205a44be033SVladimir Sementsov-Ogievskiy            self.vm_b = iotests.VM(path_suffix='b')
206a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.add_drive(disk_a if shared_storage else disk_b)
207a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
208a44be033SVladimir Sementsov-Ogievskiy            self.check_bitmap(self.vm_b, sha256 if persistent else False)
209a44be033SVladimir Sementsov-Ogievskiy
210a44be033SVladimir Sementsov-Ogievskiy
211d8c2e47dSHanna Reitzdef inject_test_case(klass, suffix, method, *args, **kwargs):
212a44be033SVladimir Sementsov-Ogievskiy    mc = operator.methodcaller(method, *args, **kwargs)
213d8c2e47dSHanna Reitz    # We want to add a function attribute to `klass`, so that it is
214d8c2e47dSHanna Reitz    # correctly converted to a method on instantiation.  The
215d8c2e47dSHanna Reitz    # methodcaller object `mc` is a callable, not a function, so we
216d8c2e47dSHanna Reitz    # need the lambda to turn it into a function.
217d8c2e47dSHanna Reitz    # pylint: disable=unnecessary-lambda
218d8c2e47dSHanna Reitz    setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
219d8c2e47dSHanna Reitz
220a44be033SVladimir Sementsov-Ogievskiy
221a44be033SVladimir Sementsov-Ogievskiyclass TestDirtyBitmapBackingMigration(iotests.QMPTestCase):
222a44be033SVladimir Sementsov-Ogievskiy    def setUp(self):
223a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, base_a, size)
224a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
225a44be033SVladimir Sementsov-Ogievskiy                        '-b', base_a, disk_a, size)
226a44be033SVladimir Sementsov-Ogievskiy
227a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
228a44be033SVladimir Sementsov-Ogievskiy            qemu_img('bitmap', '--add', f, 'bmap0')
229a44be033SVladimir Sementsov-Ogievskiy
230a44be033SVladimir Sementsov-Ogievskiy        blockdev = {
231a44be033SVladimir Sementsov-Ogievskiy            'node-name': 'node0',
232a44be033SVladimir Sementsov-Ogievskiy            'driver': iotests.imgfmt,
233a44be033SVladimir Sementsov-Ogievskiy            'file': {
234a44be033SVladimir Sementsov-Ogievskiy                'driver': 'file',
235a44be033SVladimir Sementsov-Ogievskiy                'filename': disk_a
236a44be033SVladimir Sementsov-Ogievskiy            },
237a44be033SVladimir Sementsov-Ogievskiy            'backing': {
238a44be033SVladimir Sementsov-Ogievskiy                'node-name': 'node0-base',
239a44be033SVladimir Sementsov-Ogievskiy                'driver': iotests.imgfmt,
240a44be033SVladimir Sementsov-Ogievskiy                'file': {
241a44be033SVladimir Sementsov-Ogievskiy                    'driver': 'file',
242a44be033SVladimir Sementsov-Ogievskiy                    'filename': base_a
243a44be033SVladimir Sementsov-Ogievskiy                }
244a44be033SVladimir Sementsov-Ogievskiy            }
245a44be033SVladimir Sementsov-Ogievskiy        }
246a44be033SVladimir Sementsov-Ogievskiy
247a44be033SVladimir Sementsov-Ogievskiy        self.vm = iotests.VM()
248a44be033SVladimir Sementsov-Ogievskiy        self.vm.launch()
249a44be033SVladimir Sementsov-Ogievskiy
250*b6aed193SVladimir Sementsov-Ogievskiy        self.vm.cmd('blockdev-add', blockdev)
251a44be033SVladimir Sementsov-Ogievskiy
252a44be033SVladimir Sementsov-Ogievskiy        # Check that the bitmaps are there
253d8c2e47dSHanna Reitz        nodes = self.vm.qmp('query-named-block-nodes', flat=True)['return']
254d8c2e47dSHanna Reitz        for node in nodes:
255a44be033SVladimir Sementsov-Ogievskiy            if 'node0' in node['node-name']:
256a44be033SVladimir Sementsov-Ogievskiy                self.assert_qmp(node, 'dirty-bitmaps[0]/name', 'bmap0')
257a44be033SVladimir Sementsov-Ogievskiy
258a44be033SVladimir Sementsov-Ogievskiy        caps = [{'capability': 'events', 'state': True}]
259*b6aed193SVladimir Sementsov-Ogievskiy        self.vm.cmd('migrate-set-capabilities', capabilities=caps)
260a44be033SVladimir Sementsov-Ogievskiy
261a44be033SVladimir Sementsov-Ogievskiy    def tearDown(self):
262a44be033SVladimir Sementsov-Ogievskiy        self.vm.shutdown()
263a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
264a44be033SVladimir Sementsov-Ogievskiy            os.remove(f)
265a44be033SVladimir Sementsov-Ogievskiy
266a44be033SVladimir Sementsov-Ogievskiy    def test_cont_on_source(self):
267a44be033SVladimir Sementsov-Ogievskiy        """
268a44be033SVladimir Sementsov-Ogievskiy        Continue the source after migration.
269a44be033SVladimir Sementsov-Ogievskiy        """
270*b6aed193SVladimir Sementsov-Ogievskiy        self.vm.cmd('migrate', uri='exec: cat > /dev/null')
271a44be033SVladimir Sementsov-Ogievskiy
272a44be033SVladimir Sementsov-Ogievskiy        with Timeout(10, 'Migration timeout'):
273a44be033SVladimir Sementsov-Ogievskiy            self.vm.wait_migration('postmigrate')
274a44be033SVladimir Sementsov-Ogievskiy
275*b6aed193SVladimir Sementsov-Ogievskiy        self.vm.cmd('cont')
276a44be033SVladimir Sementsov-Ogievskiy
277a44be033SVladimir Sementsov-Ogievskiy
27822968996SJohn Snowdef main() -> None:
27922968996SJohn Snow    for cmb in list(itertools.product((True, False), repeat=5)):
28022968996SJohn Snow        name = ('_' if cmb[0] else '_not_') + 'persistent_'
28122968996SJohn Snow        name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
28222968996SJohn Snow        name += '_online' if cmb[2] else '_offline'
28322968996SJohn Snow        name += '_shared' if cmb[3] else '_nonshared'
28422968996SJohn Snow        if cmb[4]:
28522968996SJohn Snow            name += '__pre_shutdown'
28622968996SJohn Snow
28722968996SJohn Snow        inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
28822968996SJohn Snow                         *list(cmb))
28922968996SJohn Snow
29022968996SJohn Snow    for cmb in list(itertools.product((True, False), repeat=2)):
29122968996SJohn Snow        name = ('_' if cmb[0] else '_not_') + 'persistent_'
29222968996SJohn Snow        name += ('_' if cmb[1] else '_not_') + 'migbitmap'
29322968996SJohn Snow
29422968996SJohn Snow        inject_test_case(TestDirtyBitmapMigration, name,
29522968996SJohn Snow                         'do_test_migration_resume_source', *list(cmb))
29622968996SJohn Snow
29722968996SJohn Snow    iotests.main(
29822968996SJohn Snow        supported_fmts=['qcow2'],
299b30b8077SVladimir Sementsov-Ogievskiy        supported_protocols=['file'],
300b30b8077SVladimir Sementsov-Ogievskiy        unsupported_imgopts=['compat']
30122968996SJohn Snow    )
30222968996SJohn Snow
30322968996SJohn Snow
304a44be033SVladimir Sementsov-Ogievskiyif __name__ == '__main__':
30522968996SJohn Snow    main()
306