diff options
Diffstat (limited to 'tests')
-rwxr-xr-x | tests/qemu-iotests/169 | 156 | ||||
-rw-r--r-- | tests/qemu-iotests/169.out | 5 | ||||
-rwxr-xr-x | tests/qemu-iotests/199 | 118 | ||||
-rw-r--r-- | tests/qemu-iotests/199.out | 5 | ||||
-rw-r--r-- | tests/qemu-iotests/group | 2 | ||||
-rw-r--r-- | tests/qemu-iotests/iotests.py | 7 |
6 files changed, 292 insertions, 1 deletions
diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169 new file mode 100755 index 0000000000..3a8db91f6f --- /dev/null +++ b/tests/qemu-iotests/169 @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# +# Tests for dirty bitmaps migration. +# +# Copyright (c) 2016-2017 Virtuozzo International GmbH. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import os +import iotests +import time +import itertools +import operator +import new +from iotests import qemu_img + + +disk_a = os.path.join(iotests.test_dir, 'disk_a') +disk_b = os.path.join(iotests.test_dir, 'disk_b') +size = '1M' +mig_file = os.path.join(iotests.test_dir, 'mig_file') + + +class TestDirtyBitmapMigration(iotests.QMPTestCase): + def tearDown(self): + self.vm_a.shutdown() + self.vm_b.shutdown() + os.remove(disk_a) + os.remove(disk_b) + os.remove(mig_file) + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, disk_a, size) + qemu_img('create', '-f', iotests.imgfmt, disk_b, size) + + self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a) + self.vm_a.launch() + + self.vm_b = iotests.VM(path_suffix='b') + self.vm_b.add_incoming("exec: cat '" + mig_file + "'") + + def add_bitmap(self, vm, granularity, persistent): + params = {'node': 'drive0', + 'name': 'bitmap0', + 'granularity': granularity} + if persistent: + params['persistent'] = True + params['autoload'] = True + + result = vm.qmp('block-dirty-bitmap-add', **params) + self.assert_qmp(result, 'return', {}); + + def get_bitmap_hash(self, vm): + result = vm.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap0') + return result['return']['sha256'] + + def check_bitmap(self, vm, sha256): + result = vm.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap0') + if sha256: + self.assert_qmp(result, 'return/sha256', sha256); + else: + self.assert_qmp(result, 'error/desc', + "Dirty bitmap 'bitmap0' not found"); + + def do_test_migration(self, persistent, migrate_bitmaps, online, + shared_storage): + granularity = 512 + + # regions = ((start, count), ...) + regions = ((0, 0x10000), + (0xf0000, 0x10000), + (0xa0201, 0x1000)) + + should_migrate = migrate_bitmaps or persistent and shared_storage + + self.vm_b.add_drive(disk_a if shared_storage else disk_b) + + if online: + os.mkfifo(mig_file) + self.vm_b.launch() + + self.add_bitmap(self.vm_a, granularity, persistent) + for r in regions: + self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r) + sha256 = self.get_bitmap_hash(self.vm_a) + + if migrate_bitmaps: + capabilities = [{'capability': 'dirty-bitmaps', 'state': True}] + + result = self.vm_a.qmp('migrate-set-capabilities', + capabilities=capabilities) + self.assert_qmp(result, 'return', {}) + + if online: + result = self.vm_b.qmp('migrate-set-capabilities', + capabilities=capabilities) + self.assert_qmp(result, 'return', {}) + + result = self.vm_a.qmp('migrate-set-capabilities', + capabilities=[{'capability': 'events', + 'state': True}]) + self.assert_qmp(result, 'return', {}) + + result = self.vm_a.qmp('migrate', uri='exec:cat>' + mig_file) + while True: + event = self.vm_a.event_wait('MIGRATION') + if event['data']['status'] == 'completed': + break + + if not online: + self.vm_a.shutdown() + self.vm_b.launch() + # TODO enable bitmap capability for vm_b in this case + + self.vm_b.event_wait("RESUME", timeout=10.0) + + self.check_bitmap(self.vm_b, sha256 if should_migrate else False) + + if should_migrate: + self.vm_b.shutdown() + self.vm_b.launch() + self.check_bitmap(self.vm_b, sha256 if persistent else False) + + +def inject_test_case(klass, name, method, *args, **kwargs): + mc = operator.methodcaller(method, *args, **kwargs) + setattr(klass, 'test_' + name, new.instancemethod(mc, None, klass)) + +for cmb in list(itertools.product((True, False), repeat=3)): + name = ('_' if cmb[0] else '_not_') + 'persistent_' + name += ('_' if cmb[1] else '_not_') + 'migbitmap_' + name += '_online' if cmb[2] else '_offline' + + # TODO fix shared-storage bitmap migration and enable cases for it + args = list(cmb) + [False] + + inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration', + *args) + + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2']) diff --git a/tests/qemu-iotests/169.out b/tests/qemu-iotests/169.out new file mode 100644 index 0000000000..594c16f49f --- /dev/null +++ b/tests/qemu-iotests/169.out @@ -0,0 +1,5 @@ +........ +---------------------------------------------------------------------- +Ran 8 tests + +OK diff --git a/tests/qemu-iotests/199 b/tests/qemu-iotests/199 new file mode 100755 index 0000000000..651e8df5d9 --- /dev/null +++ b/tests/qemu-iotests/199 @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# +# Tests for dirty bitmaps postcopy migration. +# +# Copyright (c) 2016-2017 Virtuozzo International GmbH. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import os +import iotests +import time +from iotests import qemu_img + +disk_a = os.path.join(iotests.test_dir, 'disk_a') +disk_b = os.path.join(iotests.test_dir, 'disk_b') +size = '256G' +fifo = os.path.join(iotests.test_dir, 'mig_fifo') + +class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase): + + def tearDown(self): + self.vm_a.shutdown() + self.vm_b.shutdown() + os.remove(disk_a) + os.remove(disk_b) + os.remove(fifo) + + def setUp(self): + os.mkfifo(fifo) + qemu_img('create', '-f', iotests.imgfmt, disk_a, size) + qemu_img('create', '-f', iotests.imgfmt, disk_b, size) + self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a) + self.vm_b = iotests.VM(path_suffix='b').add_drive(disk_b) + self.vm_b.add_incoming("exec: cat '" + fifo + "'") + self.vm_a.launch() + self.vm_b.launch() + + def test_postcopy(self): + write_size = 0x40000000 + granularity = 512 + chunk = 4096 + + result = self.vm_a.qmp('block-dirty-bitmap-add', node='drive0', + name='bitmap', granularity=granularity) + self.assert_qmp(result, 'return', {}); + + s = 0 + while s < write_size: + self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk)) + s += 0x10000 + s = 0x8000 + while s < write_size: + self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk)) + s += 0x10000 + + result = self.vm_a.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap') + sha256 = result['return']['sha256'] + + result = self.vm_a.qmp('block-dirty-bitmap-clear', node='drive0', + name='bitmap') + self.assert_qmp(result, 'return', {}); + s = 0 + while s < write_size: + self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk)) + s += 0x10000 + + bitmaps_cap = {'capability': 'dirty-bitmaps', 'state': True} + events_cap = {'capability': 'events', 'state': True} + + result = self.vm_a.qmp('migrate-set-capabilities', + capabilities=[bitmaps_cap, events_cap]) + self.assert_qmp(result, 'return', {}) + + result = self.vm_b.qmp('migrate-set-capabilities', + capabilities=[bitmaps_cap]) + self.assert_qmp(result, 'return', {}) + + result = self.vm_a.qmp('migrate', uri='exec:cat>' + fifo) + self.assert_qmp(result, 'return', {}) + + result = self.vm_a.qmp('migrate-start-postcopy') + self.assert_qmp(result, 'return', {}) + + while True: + event = self.vm_a.event_wait('MIGRATION') + if event['data']['status'] == 'completed': + break + + s = 0x8000 + while s < write_size: + self.vm_b.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk)) + s += 0x10000 + + result = self.vm_b.qmp('query-block'); + while len(result['return'][0]['dirty-bitmaps']) > 1: + time.sleep(2) + result = self.vm_b.qmp('query-block'); + + result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256', + node='drive0', name='bitmap') + + self.assert_qmp(result, 'return/sha256', sha256); + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2'], supported_cache_modes=['none']) diff --git a/tests/qemu-iotests/199.out b/tests/qemu-iotests/199.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/199.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 624e1fbd4f..0f912e17b0 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -169,6 +169,7 @@ 162 auto quick 163 rw auto quick 165 rw auto quick +169 rw auto quick 170 rw auto quick 171 rw auto quick 172 auto @@ -196,6 +197,7 @@ 196 rw auto quick 197 rw auto quick 198 rw auto +199 rw auto 200 rw auto 201 rw auto migration 202 rw auto quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 90cd751e2a..845be3ad01 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -537,6 +537,10 @@ def verify_platform(supported_oses=['linux']): if True not in [sys.platform.startswith(x) for x in supported_oses]: notrun('not suitable for this OS: %s' % sys.platform) +def verify_cache_mode(supported_cache_modes=[]): + if supported_cache_modes and (cachemode not in supported_cache_modes): + notrun('not suitable for this cache mode: %s' % cachemode) + def supports_quorum(): return 'quorum' in qemu_img_pipe('--help') @@ -545,7 +549,7 @@ def verify_quorum(): if not supports_quorum(): notrun('quorum support missing') -def main(supported_fmts=[], supported_oses=['linux']): +def main(supported_fmts=[], supported_oses=['linux'], supported_cache_modes=[]): '''Run tests''' global debug @@ -562,6 +566,7 @@ def main(supported_fmts=[], supported_oses=['linux']): verbosity = 1 verify_image_format(supported_fmts) verify_platform(supported_oses) + verify_cache_mode(supported_cache_modes) # We need to filter out the time taken from the output so that qemu-iotest # can reliably diff the results against master output. |