xref: /openbmc/qemu/tests/qemu-iotests/tests/migrate-bitmaps-test (revision d8c2e47dbe998d00dcfe0ca5fc0766a98b69a591)
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 os
23a44be033SVladimir Sementsov-Ogievskiyimport itertools
24a44be033SVladimir Sementsov-Ogievskiyimport operator
25a44be033SVladimir Sementsov-Ogievskiyimport re
26*d8c2e47dSHanna Reitzimport iotests
27a44be033SVladimir Sementsov-Ogievskiyfrom iotests import qemu_img, qemu_img_create, Timeout
28a44be033SVladimir Sementsov-Ogievskiy
29a44be033SVladimir Sementsov-Ogievskiy
30a44be033SVladimir Sementsov-Ogievskiydisk_a = os.path.join(iotests.test_dir, 'disk_a')
31a44be033SVladimir Sementsov-Ogievskiydisk_b = os.path.join(iotests.test_dir, 'disk_b')
32a44be033SVladimir Sementsov-Ogievskiybase_a = os.path.join(iotests.test_dir, 'base_a')
33a44be033SVladimir Sementsov-Ogievskiysize = '1M'
34a44be033SVladimir Sementsov-Ogievskiymig_file = os.path.join(iotests.test_dir, 'mig_file')
35a44be033SVladimir Sementsov-Ogievskiymig_cmd = 'exec: cat > ' + mig_file
36a44be033SVladimir Sementsov-Ogievskiyincoming_cmd = 'exec: cat ' + mig_file
37a44be033SVladimir Sementsov-Ogievskiy
38a44be033SVladimir Sementsov-Ogievskiy
39*d8c2e47dSHanna Reitzdef get_bitmap_hash(vm):
40*d8c2e47dSHanna Reitz    result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
41*d8c2e47dSHanna Reitz                    node='drive0', name='bitmap0')
42*d8c2e47dSHanna Reitz    return result['return']['sha256']
43*d8c2e47dSHanna Reitz
44*d8c2e47dSHanna Reitz
45a44be033SVladimir Sementsov-Ogievskiyclass TestDirtyBitmapMigration(iotests.QMPTestCase):
46a44be033SVladimir Sementsov-Ogievskiy    def tearDown(self):
47a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.shutdown()
48a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.shutdown()
49a44be033SVladimir Sementsov-Ogievskiy        os.remove(disk_a)
50a44be033SVladimir Sementsov-Ogievskiy        os.remove(disk_b)
51a44be033SVladimir Sementsov-Ogievskiy        os.remove(mig_file)
52a44be033SVladimir Sementsov-Ogievskiy
53a44be033SVladimir Sementsov-Ogievskiy    def setUp(self):
54a44be033SVladimir Sementsov-Ogievskiy        qemu_img('create', '-f', iotests.imgfmt, disk_a, size)
55a44be033SVladimir Sementsov-Ogievskiy        qemu_img('create', '-f', iotests.imgfmt, disk_b, size)
56a44be033SVladimir Sementsov-Ogievskiy
57a44be033SVladimir Sementsov-Ogievskiy        self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a)
58a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.launch()
59a44be033SVladimir Sementsov-Ogievskiy
60a44be033SVladimir Sementsov-Ogievskiy        self.vm_b = iotests.VM(path_suffix='b')
61a44be033SVladimir Sementsov-Ogievskiy
62a44be033SVladimir Sementsov-Ogievskiy    def add_bitmap(self, vm, granularity, persistent):
63a44be033SVladimir Sementsov-Ogievskiy        params = {'node': 'drive0',
64a44be033SVladimir Sementsov-Ogievskiy                  'name': 'bitmap0',
65a44be033SVladimir Sementsov-Ogievskiy                  'granularity': granularity}
66a44be033SVladimir Sementsov-Ogievskiy        if persistent:
67a44be033SVladimir Sementsov-Ogievskiy            params['persistent'] = True
68a44be033SVladimir Sementsov-Ogievskiy
69a44be033SVladimir Sementsov-Ogievskiy        result = vm.qmp('block-dirty-bitmap-add', **params)
70*d8c2e47dSHanna Reitz        self.assert_qmp(result, 'return', {})
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:
76*d8c2e47dSHanna Reitz            self.assert_qmp(result, 'return/sha256', sha256)
77a44be033SVladimir Sementsov-Ogievskiy        else:
78a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'error/desc',
79*d8c2e47dSHanna 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
93a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate-set-capabilities',
94a44be033SVladimir Sementsov-Ogievskiy                               capabilities=mig_caps)
95a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
96a44be033SVladimir Sementsov-Ogievskiy
97a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
98a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
99a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
100*d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
101a44be033SVladimir Sementsov-Ogievskiy
102a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate', uri=mig_cmd)
103a44be033SVladimir Sementsov-Ogievskiy        while True:
104a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
105a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
106a44be033SVladimir Sementsov-Ogievskiy                break
107a44be033SVladimir Sementsov-Ogievskiy        while True:
108a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_a.qmp('query-status')
109*d8c2e47dSHanna Reitz            if result['return']['status'] == 'postmigrate':
110a44be033SVladimir Sementsov-Ogievskiy                break
111a44be033SVladimir Sementsov-Ogievskiy
112a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here
113a44be033SVladimir Sementsov-Ogievskiy        removed = (not migrate_bitmaps) and persistent
114a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, False if removed else sha256)
115a44be033SVladimir Sementsov-Ogievskiy
116a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('cont')
117a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
118a44be033SVladimir Sementsov-Ogievskiy
119a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still here after invalidation
120a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256)
121a44be033SVladimir Sementsov-Ogievskiy
122a44be033SVladimir Sementsov-Ogievskiy        # shutdown and check that invalidation didn't fail
123a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.shutdown()
124a44be033SVladimir Sementsov-Ogievskiy
125a44be033SVladimir Sementsov-Ogievskiy        # catch 'Could not reopen qcow2 layer: Bitmap already exists'
126a44be033SVladimir Sementsov-Ogievskiy        # possible error
127a44be033SVladimir Sementsov-Ogievskiy        log = self.vm_a.get_log()
128a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
129a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'^(wrote .* bytes at offset .*\n.*KiB.*ops.*sec.*\n){3}',
130a44be033SVladimir Sementsov-Ogievskiy                     '', log)
131a44be033SVladimir Sementsov-Ogievskiy        log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
132a44be033SVladimir Sementsov-Ogievskiy        self.assertEqual(log, '')
133a44be033SVladimir Sementsov-Ogievskiy
134a44be033SVladimir Sementsov-Ogievskiy        # test that bitmap is still persistent
135a44be033SVladimir Sementsov-Ogievskiy        self.vm_a.launch()
136a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_a, sha256 if persistent else False)
137a44be033SVladimir Sementsov-Ogievskiy
138a44be033SVladimir Sementsov-Ogievskiy    def do_test_migration(self, persistent, migrate_bitmaps, online,
139a44be033SVladimir Sementsov-Ogievskiy                          shared_storage, pre_shutdown):
140a44be033SVladimir Sementsov-Ogievskiy        granularity = 512
141a44be033SVladimir Sementsov-Ogievskiy
142a44be033SVladimir Sementsov-Ogievskiy        # regions = ((start, count), ...)
143a44be033SVladimir Sementsov-Ogievskiy        regions = ((0, 0x10000),
144a44be033SVladimir Sementsov-Ogievskiy                   (0xf0000, 0x10000),
145a44be033SVladimir Sementsov-Ogievskiy                   (0xa0201, 0x1000))
146a44be033SVladimir Sementsov-Ogievskiy
147a44be033SVladimir Sementsov-Ogievskiy        should_migrate = \
148a44be033SVladimir Sementsov-Ogievskiy            (migrate_bitmaps and (persistent or not pre_shutdown)) or \
149a44be033SVladimir Sementsov-Ogievskiy            (persistent and shared_storage)
150a44be033SVladimir Sementsov-Ogievskiy        mig_caps = [{'capability': 'events', 'state': True}]
151a44be033SVladimir Sementsov-Ogievskiy        if migrate_bitmaps:
152a44be033SVladimir Sementsov-Ogievskiy            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})
153a44be033SVladimir Sementsov-Ogievskiy
154a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_incoming(incoming_cmd if online else "defer")
155a44be033SVladimir Sementsov-Ogievskiy        self.vm_b.add_drive(disk_a if shared_storage else disk_b)
156a44be033SVladimir Sementsov-Ogievskiy
157a44be033SVladimir Sementsov-Ogievskiy        if online:
158a44be033SVladimir Sementsov-Ogievskiy            os.mkfifo(mig_file)
159a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
160a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-set-capabilities',
161a44be033SVladimir Sementsov-Ogievskiy                                   capabilities=mig_caps)
162a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
163a44be033SVladimir Sementsov-Ogievskiy
164a44be033SVladimir Sementsov-Ogievskiy        self.add_bitmap(self.vm_a, granularity, persistent)
165a44be033SVladimir Sementsov-Ogievskiy        for r in regions:
166a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
167*d8c2e47dSHanna Reitz        sha256 = get_bitmap_hash(self.vm_a)
168a44be033SVladimir Sementsov-Ogievskiy
169a44be033SVladimir Sementsov-Ogievskiy        if pre_shutdown:
170a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
171a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.launch()
172a44be033SVladimir Sementsov-Ogievskiy
173a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate-set-capabilities',
174a44be033SVladimir Sementsov-Ogievskiy                               capabilities=mig_caps)
175a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
176a44be033SVladimir Sementsov-Ogievskiy
177a44be033SVladimir Sementsov-Ogievskiy        result = self.vm_a.qmp('migrate', uri=mig_cmd)
178a44be033SVladimir Sementsov-Ogievskiy        while True:
179a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_a.event_wait('MIGRATION')
180a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
181a44be033SVladimir Sementsov-Ogievskiy                break
182a44be033SVladimir Sementsov-Ogievskiy
183a44be033SVladimir Sementsov-Ogievskiy        if not online:
184a44be033SVladimir Sementsov-Ogievskiy            self.vm_a.shutdown()
185a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
186a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-set-capabilities',
187a44be033SVladimir Sementsov-Ogievskiy                                   capabilities=mig_caps)
188a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
189a44be033SVladimir Sementsov-Ogievskiy            result = self.vm_b.qmp('migrate-incoming', uri=incoming_cmd)
190a44be033SVladimir Sementsov-Ogievskiy            self.assert_qmp(result, 'return', {})
191a44be033SVladimir Sementsov-Ogievskiy
192a44be033SVladimir Sementsov-Ogievskiy        while True:
193a44be033SVladimir Sementsov-Ogievskiy            event = self.vm_b.event_wait('MIGRATION')
194a44be033SVladimir Sementsov-Ogievskiy            if event['data']['status'] == 'completed':
195a44be033SVladimir Sementsov-Ogievskiy                break
196a44be033SVladimir Sementsov-Ogievskiy
197a44be033SVladimir Sementsov-Ogievskiy        self.check_bitmap(self.vm_b, sha256 if should_migrate else False)
198a44be033SVladimir Sementsov-Ogievskiy
199a44be033SVladimir Sementsov-Ogievskiy        if should_migrate:
200a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.shutdown()
201a44be033SVladimir Sementsov-Ogievskiy
202a44be033SVladimir Sementsov-Ogievskiy            # catch 'Could not reopen qcow2 layer: Bitmap already exists'
203a44be033SVladimir Sementsov-Ogievskiy            # possible error
204a44be033SVladimir Sementsov-Ogievskiy            log = self.vm_b.get_log()
205a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
206a44be033SVladimir Sementsov-Ogievskiy            log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
207a44be033SVladimir Sementsov-Ogievskiy            self.assertEqual(log, '')
208a44be033SVladimir Sementsov-Ogievskiy
209a44be033SVladimir Sementsov-Ogievskiy            # recreate vm_b, as we don't want -incoming option (this will lead
210a44be033SVladimir Sementsov-Ogievskiy            # to "cat" process left alive after test finish)
211a44be033SVladimir Sementsov-Ogievskiy            self.vm_b = iotests.VM(path_suffix='b')
212a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.add_drive(disk_a if shared_storage else disk_b)
213a44be033SVladimir Sementsov-Ogievskiy            self.vm_b.launch()
214a44be033SVladimir Sementsov-Ogievskiy            self.check_bitmap(self.vm_b, sha256 if persistent else False)
215a44be033SVladimir Sementsov-Ogievskiy
216a44be033SVladimir Sementsov-Ogievskiy
217*d8c2e47dSHanna Reitzdef inject_test_case(klass, suffix, method, *args, **kwargs):
218a44be033SVladimir Sementsov-Ogievskiy    mc = operator.methodcaller(method, *args, **kwargs)
219*d8c2e47dSHanna Reitz    # We want to add a function attribute to `klass`, so that it is
220*d8c2e47dSHanna Reitz    # correctly converted to a method on instantiation.  The
221*d8c2e47dSHanna Reitz    # methodcaller object `mc` is a callable, not a function, so we
222*d8c2e47dSHanna Reitz    # need the lambda to turn it into a function.
223*d8c2e47dSHanna Reitz    # pylint: disable=unnecessary-lambda
224*d8c2e47dSHanna Reitz    setattr(klass, 'test_' + method + suffix, lambda self: mc(self))
225*d8c2e47dSHanna Reitz
226a44be033SVladimir Sementsov-Ogievskiy
227a44be033SVladimir Sementsov-Ogievskiyfor cmb in list(itertools.product((True, False), repeat=5)):
228a44be033SVladimir Sementsov-Ogievskiy    name = ('_' if cmb[0] else '_not_') + 'persistent_'
229a44be033SVladimir Sementsov-Ogievskiy    name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
230a44be033SVladimir Sementsov-Ogievskiy    name += '_online' if cmb[2] else '_offline'
231a44be033SVladimir Sementsov-Ogievskiy    name += '_shared' if cmb[3] else '_nonshared'
232*d8c2e47dSHanna Reitz    if cmb[4]:
233a44be033SVladimir Sementsov-Ogievskiy        name += '__pre_shutdown'
234a44be033SVladimir Sementsov-Ogievskiy
235a44be033SVladimir Sementsov-Ogievskiy    inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
236a44be033SVladimir Sementsov-Ogievskiy                     *list(cmb))
237a44be033SVladimir Sementsov-Ogievskiy
238a44be033SVladimir Sementsov-Ogievskiyfor cmb in list(itertools.product((True, False), repeat=2)):
239a44be033SVladimir Sementsov-Ogievskiy    name = ('_' if cmb[0] else '_not_') + 'persistent_'
240a44be033SVladimir Sementsov-Ogievskiy    name += ('_' if cmb[1] else '_not_') + 'migbitmap'
241a44be033SVladimir Sementsov-Ogievskiy
242a44be033SVladimir Sementsov-Ogievskiy    inject_test_case(TestDirtyBitmapMigration, name,
243a44be033SVladimir Sementsov-Ogievskiy                     'do_test_migration_resume_source', *list(cmb))
244a44be033SVladimir Sementsov-Ogievskiy
245a44be033SVladimir Sementsov-Ogievskiy
246a44be033SVladimir Sementsov-Ogievskiyclass TestDirtyBitmapBackingMigration(iotests.QMPTestCase):
247a44be033SVladimir Sementsov-Ogievskiy    def setUp(self):
248a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, base_a, size)
249a44be033SVladimir Sementsov-Ogievskiy        qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
250a44be033SVladimir Sementsov-Ogievskiy                        '-b', base_a, disk_a, size)
251a44be033SVladimir Sementsov-Ogievskiy
252a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
253a44be033SVladimir Sementsov-Ogievskiy            qemu_img('bitmap', '--add', f, 'bmap0')
254a44be033SVladimir Sementsov-Ogievskiy
255a44be033SVladimir Sementsov-Ogievskiy        blockdev = {
256a44be033SVladimir Sementsov-Ogievskiy            'node-name': 'node0',
257a44be033SVladimir Sementsov-Ogievskiy            'driver': iotests.imgfmt,
258a44be033SVladimir Sementsov-Ogievskiy            'file': {
259a44be033SVladimir Sementsov-Ogievskiy                'driver': 'file',
260a44be033SVladimir Sementsov-Ogievskiy                'filename': disk_a
261a44be033SVladimir Sementsov-Ogievskiy            },
262a44be033SVladimir Sementsov-Ogievskiy            'backing': {
263a44be033SVladimir Sementsov-Ogievskiy                'node-name': 'node0-base',
264a44be033SVladimir Sementsov-Ogievskiy                'driver': iotests.imgfmt,
265a44be033SVladimir Sementsov-Ogievskiy                'file': {
266a44be033SVladimir Sementsov-Ogievskiy                    'driver': 'file',
267a44be033SVladimir Sementsov-Ogievskiy                    'filename': base_a
268a44be033SVladimir Sementsov-Ogievskiy                }
269a44be033SVladimir Sementsov-Ogievskiy            }
270a44be033SVladimir Sementsov-Ogievskiy        }
271a44be033SVladimir Sementsov-Ogievskiy
272a44be033SVladimir Sementsov-Ogievskiy        self.vm = iotests.VM()
273a44be033SVladimir Sementsov-Ogievskiy        self.vm.launch()
274a44be033SVladimir Sementsov-Ogievskiy
275a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('blockdev-add', **blockdev)
276a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
277a44be033SVladimir Sementsov-Ogievskiy
278a44be033SVladimir Sementsov-Ogievskiy        # Check that the bitmaps are there
279*d8c2e47dSHanna Reitz        nodes = self.vm.qmp('query-named-block-nodes', flat=True)['return']
280*d8c2e47dSHanna Reitz        for node in nodes:
281a44be033SVladimir Sementsov-Ogievskiy            if 'node0' in node['node-name']:
282a44be033SVladimir Sementsov-Ogievskiy                self.assert_qmp(node, 'dirty-bitmaps[0]/name', 'bmap0')
283a44be033SVladimir Sementsov-Ogievskiy
284a44be033SVladimir Sementsov-Ogievskiy        caps = [{'capability': 'events', 'state': True}]
285a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('migrate-set-capabilities', capabilities=caps)
286a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
287a44be033SVladimir Sementsov-Ogievskiy
288a44be033SVladimir Sementsov-Ogievskiy    def tearDown(self):
289a44be033SVladimir Sementsov-Ogievskiy        self.vm.shutdown()
290a44be033SVladimir Sementsov-Ogievskiy        for f in (disk_a, base_a):
291a44be033SVladimir Sementsov-Ogievskiy            os.remove(f)
292a44be033SVladimir Sementsov-Ogievskiy
293a44be033SVladimir Sementsov-Ogievskiy    def test_cont_on_source(self):
294a44be033SVladimir Sementsov-Ogievskiy        """
295a44be033SVladimir Sementsov-Ogievskiy        Continue the source after migration.
296a44be033SVladimir Sementsov-Ogievskiy        """
297*d8c2e47dSHanna Reitz        result = self.vm.qmp('migrate', uri='exec: cat > /dev/null')
298a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
299a44be033SVladimir Sementsov-Ogievskiy
300a44be033SVladimir Sementsov-Ogievskiy        with Timeout(10, 'Migration timeout'):
301a44be033SVladimir Sementsov-Ogievskiy            self.vm.wait_migration('postmigrate')
302a44be033SVladimir Sementsov-Ogievskiy
303a44be033SVladimir Sementsov-Ogievskiy        result = self.vm.qmp('cont')
304a44be033SVladimir Sementsov-Ogievskiy        self.assert_qmp(result, 'return', {})
305a44be033SVladimir Sementsov-Ogievskiy
306a44be033SVladimir Sementsov-Ogievskiy
307a44be033SVladimir Sementsov-Ogievskiyif __name__ == '__main__':
308a44be033SVladimir Sementsov-Ogievskiy    iotests.main(supported_fmts=['qcow2'],
309a44be033SVladimir Sementsov-Ogievskiy                 supported_protocols=['file'])
310