#!/usr/bin/env python3
# group: migration
#
# Copyright (C) 2020 Red Hat, Inc.
#
# Tests for dirty bitmaps migration with node aliases
#
# 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 random
import re
from typing import Dict, List, Optional, Union
import iotests
import qemu

BlockBitmapMapping = List[Dict[str, Union[str, List[Dict[str, str]]]]]

assert iotests.sock_dir is not None
mig_sock = os.path.join(iotests.sock_dir, 'mig_sock')


class TestDirtyBitmapMigration(iotests.QMPTestCase):
    src_node_name: str = ''
    dst_node_name: str = ''
    src_bmap_name: str = ''
    dst_bmap_name: str = ''

    def setUp(self) -> None:
        self.vm_a = iotests.VM(path_suffix='-a')
        self.vm_a.add_blockdev(f'node-name={self.src_node_name},'
                               'driver=null-co')
        self.vm_a.launch()

        self.vm_b = iotests.VM(path_suffix='-b')
        self.vm_b.add_blockdev(f'node-name={self.dst_node_name},'
                               'driver=null-co')
        self.vm_b.add_incoming(f'unix:{mig_sock}')
        self.vm_b.launch()

        result = self.vm_a.qmp('block-dirty-bitmap-add',
                               node=self.src_node_name,
                               name=self.src_bmap_name)
        self.assert_qmp(result, 'return', {})

        # Dirty some random megabytes
        for _ in range(9):
            mb_ofs = random.randrange(1024)
            self.vm_a.hmp_qemu_io(self.src_node_name, f'discard {mb_ofs}M 1M')

        result = self.vm_a.qmp('x-debug-block-dirty-bitmap-sha256',
                               node=self.src_node_name,
                               name=self.src_bmap_name)
        self.bitmap_hash_reference = result['return']['sha256']

        caps = [{'capability': name, 'state': True}
                for name in ('dirty-bitmaps', 'events')]

        for vm in (self.vm_a, self.vm_b):
            result = vm.qmp('migrate-set-capabilities', capabilities=caps)
            self.assert_qmp(result, 'return', {})

    def tearDown(self) -> None:
        self.vm_a.shutdown()
        self.vm_b.shutdown()
        try:
            os.remove(mig_sock)
        except OSError:
            pass

    def check_bitmap(self, bitmap_name_valid: bool) -> None:
        result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
                               node=self.dst_node_name,
                               name=self.dst_bmap_name)
        if bitmap_name_valid:
            self.assert_qmp(result, 'return/sha256',
                            self.bitmap_hash_reference)
        else:
            self.assert_qmp(result, 'error/desc',
                            f"Dirty bitmap '{self.dst_bmap_name}' not found")

    def migrate(self, bitmap_name_valid: bool = True,
                migration_success: bool = True) -> None:
        result = self.vm_a.qmp('migrate', uri=f'unix:{mig_sock}')
        self.assert_qmp(result, 'return', {})

        with iotests.Timeout(5, 'Timeout waiting for migration to complete'):
            self.assertEqual(self.vm_a.wait_migration('postmigrate'),
                             migration_success)
            self.assertEqual(self.vm_b.wait_migration('running'),
                             migration_success)

        if migration_success:
            self.check_bitmap(bitmap_name_valid)

    def verify_dest_error(self, msg: Optional[str]) -> None:
        """
        Check whether the given error message is present in vm_b's log.
        (vm_b is shut down to do so.)
        If @msg is None, check that there has not been any error.
        """
        self.vm_b.shutdown()
        if msg is None:
            self.assertNotIn('qemu-system-', self.vm_b.get_log())
        else:
            self.assertIn(msg, self.vm_b.get_log())

    @staticmethod
    def mapping(node_name: str, node_alias: str,
                bitmap_name: str, bitmap_alias: str) -> BlockBitmapMapping:
        return [{
            'node-name': node_name,
            'alias': node_alias,
            'bitmaps': [{
                'name': bitmap_name,
                'alias': bitmap_alias
            }]
        }]

    def set_mapping(self, vm: iotests.VM, mapping: BlockBitmapMapping,
                    error: Optional[str] = None) -> None:
        """
        Invoke migrate-set-parameters on @vm to set the given @mapping.
        Check for success if @error is None, or verify the error message
        if it is not.
        On success, verify that "info migrate_parameters" on HMP returns
        our mapping.  (Just to check its formatting code.)
        """
        result = vm.qmp('migrate-set-parameters',
                        block_bitmap_mapping=mapping)

        if error is None:
            self.assert_qmp(result, 'return', {})

            result = vm.qmp('human-monitor-command',
                            command_line='info migrate_parameters')

            m = re.search(r'^block-bitmap-mapping:\r?(\n  .*)*\n',
                          result['return'], flags=re.MULTILINE)
            hmp_mapping = m.group(0).replace('\r', '') if m else None

            self.assertEqual(hmp_mapping, self.to_hmp_mapping(mapping))
        else:
            self.assert_qmp(result, 'error/desc', error)

    @staticmethod
    def to_hmp_mapping(mapping: BlockBitmapMapping) -> str:
        result = 'block-bitmap-mapping:\n'

        for node in mapping:
            result += f"  '{node['node-name']}' -> '{node['alias']}'\n"

            assert isinstance(node['bitmaps'], list)
            for bitmap in node['bitmaps']:
                result += f"    '{bitmap['name']}' -> '{bitmap['alias']}'\n"

        return result


class TestAliasMigration(TestDirtyBitmapMigration):
    src_node_name = 'node0'
    dst_node_name = 'node0'
    src_bmap_name = 'bmap0'
    dst_bmap_name = 'bmap0'

    def test_migration_without_alias(self) -> None:
        self.migrate(self.src_node_name == self.dst_node_name and
                     self.src_bmap_name == self.dst_bmap_name)

        # Check for error message on the destination
        if self.src_node_name != self.dst_node_name:
            self.verify_dest_error(f"Cannot find "
                                   f"device={self.src_node_name} nor "
                                   f"node_name={self.src_node_name}")
        else:
            self.verify_dest_error(None)

    def test_alias_on_src_migration(self) -> None:
        mapping = self.mapping(self.src_node_name, self.dst_node_name,
                               self.src_bmap_name, self.dst_bmap_name)

        self.set_mapping(self.vm_a, mapping)
        self.migrate()
        self.verify_dest_error(None)

    def test_alias_on_dst_migration(self) -> None:
        mapping = self.mapping(self.dst_node_name, self.src_node_name,
                               self.dst_bmap_name, self.src_bmap_name)

        self.set_mapping(self.vm_b, mapping)
        self.migrate()
        self.verify_dest_error(None)

    def test_alias_on_both_migration(self) -> None:
        src_map = self.mapping(self.src_node_name, 'node-alias',
                               self.src_bmap_name, 'bmap-alias')

        dst_map = self.mapping(self.dst_node_name, 'node-alias',
                               self.dst_bmap_name, 'bmap-alias')

        self.set_mapping(self.vm_a, src_map)
        self.set_mapping(self.vm_b, dst_map)
        self.migrate()
        self.verify_dest_error(None)


class TestNodeAliasMigration(TestAliasMigration):
    src_node_name = 'node-src'
    dst_node_name = 'node-dst'


class TestBitmapAliasMigration(TestAliasMigration):
    src_bmap_name = 'bmap-src'
    dst_bmap_name = 'bmap-dst'


class TestFullAliasMigration(TestAliasMigration):
    src_node_name = 'node-src'
    dst_node_name = 'node-dst'
    src_bmap_name = 'bmap-src'
    dst_bmap_name = 'bmap-dst'


class TestLongBitmapNames(TestAliasMigration):
    # Giving long bitmap names is OK, as long as there is a short alias for
    # migration
    src_bmap_name = 'a' * 512
    dst_bmap_name = 'b' * 512

    # Skip all tests that do not use the intermediate alias
    def test_migration_without_alias(self) -> None:
        pass

    def test_alias_on_src_migration(self) -> None:
        pass

    def test_alias_on_dst_migration(self) -> None:
        pass


class TestBlockBitmapMappingErrors(TestDirtyBitmapMigration):
    src_node_name = 'node0'
    dst_node_name = 'node0'
    src_bmap_name = 'bmap0'
    dst_bmap_name = 'bmap0'

    """
    Note that mapping nodes or bitmaps that do not exist is not an error.
    """

    def test_non_injective_node_mapping(self) -> None:
        mapping: BlockBitmapMapping = [
            {
                'node-name': 'node0',
                'alias': 'common-alias',
                'bitmaps': [{
                    'name': 'bmap0',
                    'alias': 'bmap-alias0'
                }]
            },
            {
                'node-name': 'node1',
                'alias': 'common-alias',
                'bitmaps': [{
                    'name': 'bmap1',
                    'alias': 'bmap-alias1'
                }]
            }
        ]

        self.set_mapping(self.vm_a, mapping,
                         "Invalid mapping given for block-bitmap-mapping: "
                         "The node alias 'common-alias' is used twice")

    def test_non_injective_bitmap_mapping(self) -> None:
        mapping: BlockBitmapMapping = [{
            'node-name': 'node0',
            'alias': 'node-alias0',
            'bitmaps': [
                {
                    'name': 'bmap0',
                    'alias': 'common-alias'
                },
                {
                    'name': 'bmap1',
                    'alias': 'common-alias'
                }
            ]
        }]

        self.set_mapping(self.vm_a, mapping,
                         "Invalid mapping given for block-bitmap-mapping: "
                         "The bitmap alias 'node-alias0'/'common-alias' is "
                         "used twice")

    def test_ambiguous_node_mapping(self) -> None:
        mapping: BlockBitmapMapping = [
            {
                'node-name': 'node0',
                'alias': 'node-alias0',
                'bitmaps': [{
                    'name': 'bmap0',
                    'alias': 'bmap-alias0'
                }]
            },
            {
                'node-name': 'node0',
                'alias': 'node-alias1',
                'bitmaps': [{
                    'name': 'bmap0',
                    'alias': 'bmap-alias0'
                }]
            }
        ]

        self.set_mapping(self.vm_a, mapping,
                         "Invalid mapping given for block-bitmap-mapping: "
                         "The node name 'node0' is mapped twice")

    def test_ambiguous_bitmap_mapping(self) -> None:
        mapping: BlockBitmapMapping = [{
            'node-name': 'node0',
            'alias': 'node-alias0',
            'bitmaps': [
                {
                    'name': 'bmap0',
                    'alias': 'bmap-alias0'
                },
                {
                    'name': 'bmap0',
                    'alias': 'bmap-alias1'
                }
            ]
        }]

        self.set_mapping(self.vm_a, mapping,
                         "Invalid mapping given for block-bitmap-mapping: "
                         "The bitmap 'node0'/'bmap0' is mapped twice")

    def test_migratee_node_is_not_mapped_on_src(self) -> None:
        self.set_mapping(self.vm_a, [])
        # Should just ignore all bitmaps on unmapped nodes
        self.migrate(False)
        self.verify_dest_error(None)

    def test_migratee_node_is_not_mapped_on_dst(self) -> None:
        self.set_mapping(self.vm_b, [])
        self.migrate(False)
        self.verify_dest_error(f"Unknown node alias '{self.src_node_name}'")

    def test_migratee_bitmap_is_not_mapped_on_src(self) -> None:
        mapping: BlockBitmapMapping = [{
            'node-name': self.src_node_name,
            'alias': self.dst_node_name,
            'bitmaps': []
        }]

        self.set_mapping(self.vm_a, mapping)
        # Should just ignore all unmapped bitmaps
        self.migrate(False)
        self.verify_dest_error(None)

    def test_migratee_bitmap_is_not_mapped_on_dst(self) -> None:
        mapping: BlockBitmapMapping = [{
            'node-name': self.dst_node_name,
            'alias': self.src_node_name,
            'bitmaps': []
        }]

        self.set_mapping(self.vm_b, mapping)
        self.migrate(False)
        self.verify_dest_error(f"Unknown bitmap alias "
                               f"'{self.src_bmap_name}' "
                               f"on node '{self.dst_node_name}' "
                               f"(alias '{self.src_node_name}')")

    def test_unused_mapping_on_dst(self) -> None:
        # Let the source not send any bitmaps
        self.set_mapping(self.vm_a, [])

        # Establish some mapping on the destination
        self.set_mapping(self.vm_b, [])

        # The fact that there is a mapping on B without any bitmaps
        # being received should be fine, not fatal
        self.migrate(False)
        self.verify_dest_error(None)

    def test_non_wellformed_node_alias(self) -> None:
        alias = '123-foo'

        mapping: BlockBitmapMapping = [{
            'node-name': self.src_node_name,
            'alias': alias,
            'bitmaps': []
        }]

        self.set_mapping(self.vm_a, mapping,
                         f"Invalid mapping given for block-bitmap-mapping: "
                         f"The node alias '{alias}' is not well-formed")

    def test_node_alias_too_long(self) -> None:
        alias = 'a' * 256

        mapping: BlockBitmapMapping = [{
            'node-name': self.src_node_name,
            'alias': alias,
            'bitmaps': []
        }]

        self.set_mapping(self.vm_a, mapping,
                         f"Invalid mapping given for block-bitmap-mapping: "
                         f"The node alias '{alias}' is longer than 255 bytes")

    def test_bitmap_alias_too_long(self) -> None:
        alias = 'a' * 256

        mapping = self.mapping(self.src_node_name, self.dst_node_name,
                               self.src_bmap_name, alias)

        self.set_mapping(self.vm_a, mapping,
                         f"Invalid mapping given for block-bitmap-mapping: "
                         f"The bitmap alias '{alias}' is longer than 255 "
                         f"bytes")

    def test_bitmap_name_too_long(self) -> None:
        name = 'a' * 256

        result = self.vm_a.qmp('block-dirty-bitmap-add',
                               node=self.src_node_name,
                               name=name)
        self.assert_qmp(result, 'return', {})

        self.migrate(False, False)

        # Check for the error in the source's log
        self.vm_a.shutdown()
        self.assertIn(f"Cannot migrate bitmap '{name}' on node "
                      f"'{self.src_node_name}': Name is longer than 255 bytes",
                      self.vm_a.get_log())

        # Expect abnormal shutdown of the destination VM because of
        # the failed migration
        try:
            self.vm_b.shutdown()
        except qemu.machine.AbnormalShutdown:
            pass

    def test_aliased_bitmap_name_too_long(self) -> None:
        # Longer than the maximum for bitmap names
        self.dst_bmap_name = 'a' * 1024

        mapping = self.mapping(self.dst_node_name, self.src_node_name,
                               self.dst_bmap_name, self.src_bmap_name)

        # We would have to create this bitmap during migration, and
        # that would fail, because the name is too long.  Better to
        # catch it early.
        self.set_mapping(self.vm_b, mapping,
                         f"Invalid mapping given for block-bitmap-mapping: "
                         f"The bitmap name '{self.dst_bmap_name}' is longer "
                         f"than 1023 bytes")

    def test_node_name_too_long(self) -> None:
        # Longer than the maximum for node names
        self.dst_node_name = 'a' * 32

        mapping = self.mapping(self.dst_node_name, self.src_node_name,
                               self.dst_bmap_name, self.src_bmap_name)

        # During migration, this would appear simply as a node that
        # cannot be found.  Still better to catch impossible node
        # names early (similar to test_non_wellformed_node_alias).
        self.set_mapping(self.vm_b, mapping,
                         f"Invalid mapping given for block-bitmap-mapping: "
                         f"The node name '{self.dst_node_name}' is longer "
                         f"than 31 bytes")


class TestCrossAliasMigration(TestDirtyBitmapMigration):
    """
    Swap aliases, both to see that qemu does not get confused, and
    that we can migrate multiple things at once.

    So we migrate this:
      node-a.bmap-a -> node-b.bmap-b
      node-a.bmap-b -> node-b.bmap-a
      node-b.bmap-a -> node-a.bmap-b
      node-b.bmap-b -> node-a.bmap-a
    """

    src_node_name = 'node-a'
    dst_node_name = 'node-b'
    src_bmap_name = 'bmap-a'
    dst_bmap_name = 'bmap-b'

    def setUp(self) -> None:
        TestDirtyBitmapMigration.setUp(self)

        # Now create another block device and let both have two bitmaps each
        result = self.vm_a.qmp('blockdev-add',
                               node_name='node-b', driver='null-co')
        self.assert_qmp(result, 'return', {})

        result = self.vm_b.qmp('blockdev-add',
                               node_name='node-a', driver='null-co')
        self.assert_qmp(result, 'return', {})

        bmaps_to_add = (('node-a', 'bmap-b'),
                        ('node-b', 'bmap-a'),
                        ('node-b', 'bmap-b'))

        for (node, bmap) in bmaps_to_add:
            result = self.vm_a.qmp('block-dirty-bitmap-add',
                                   node=node, name=bmap)
            self.assert_qmp(result, 'return', {})

    @staticmethod
    def cross_mapping() -> BlockBitmapMapping:
        return [
            {
                'node-name': 'node-a',
                'alias': 'node-b',
                'bitmaps': [
                    {
                        'name': 'bmap-a',
                        'alias': 'bmap-b'
                    },
                    {
                        'name': 'bmap-b',
                        'alias': 'bmap-a'
                    }
                ]
            },
            {
                'node-name': 'node-b',
                'alias': 'node-a',
                'bitmaps': [
                    {
                        'name': 'bmap-b',
                        'alias': 'bmap-a'
                    },
                    {
                        'name': 'bmap-a',
                        'alias': 'bmap-b'
                    }
                ]
            }
        ]

    def verify_dest_has_all_bitmaps(self) -> None:
        bitmaps = self.vm_b.query_bitmaps()

        # Extract and sort bitmap names
        for node in bitmaps:
            bitmaps[node] = sorted((bmap['name'] for bmap in bitmaps[node]))

        self.assertEqual(bitmaps,
                         {'node-a': ['bmap-a', 'bmap-b'],
                          'node-b': ['bmap-a', 'bmap-b']})

    def test_alias_on_src(self) -> None:
        self.set_mapping(self.vm_a, self.cross_mapping())

        # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and
        # that is enough
        self.migrate()
        self.verify_dest_has_all_bitmaps()
        self.verify_dest_error(None)

    def test_alias_on_dst(self) -> None:
        self.set_mapping(self.vm_b, self.cross_mapping())

        # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and
        # that is enough
        self.migrate()
        self.verify_dest_has_all_bitmaps()
        self.verify_dest_error(None)


if __name__ == '__main__':
    iotests.main(supported_protocols=['file'])
