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