#!/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')
mig_cmd = 'exec: cat > ' + mig_file
incoming_cmd = 'exec: cat ' + 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')

    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
        mig_caps = [{'capability': 'events', 'state': True}]
        if migrate_bitmaps:
            mig_caps.append({'capability': 'dirty-bitmaps', 'state': True})

        result = self.vm_a.qmp('migrate-set-capabilities',
                               capabilities=mig_caps)
        self.assert_qmp(result, 'return', {})

        self.vm_b.add_incoming(incoming_cmd if online else "defer")
        self.vm_b.add_drive(disk_a if shared_storage else disk_b)

        if online:
            os.mkfifo(mig_file)
            self.vm_b.launch()
            result = self.vm_b.qmp('migrate-set-capabilities',
                                   capabilities=mig_caps)
            self.assert_qmp(result, 'return', {})

        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)

        result = self.vm_a.qmp('migrate', uri=mig_cmd)
        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()
            result = self.vm_b.qmp('migrate-set-capabilities',
                                   capabilities=mig_caps)
            self.assert_qmp(result, 'return', {})
            result = self.vm_b.qmp('migrate-incoming', uri=incoming_cmd)
            self.assert_qmp(result, 'return', {})

        while True:
            event = self.vm_b.event_wait('MIGRATION')
            if event['data']['status'] == 'completed':
                break

        self.check_bitmap(self.vm_b, sha256 if should_migrate else False)

        if should_migrate:
            self.vm_b.shutdown()
            # recreate vm_b, as we don't want -incoming option (this will lead
            # to "cat" process left alive after test finish)
            self.vm_b = iotests.VM(path_suffix='b')
            self.vm_b.add_drive(disk_a if shared_storage else disk_b)
            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=4)):
    name = ('_' if cmb[0] else '_not_') + 'persistent_'
    name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
    name += '_online' if cmb[2] else '_offline'
    name += '_shared' if cmb[3] else '_nonshared'

    inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
                     *list(cmb))


if __name__ == '__main__':
    iotests.main(supported_fmts=['qcow2'])
