#!/usr/bin/env python
#
# Test bitmap merges.
#
# Copyright (c) 2018 John Snow for Red Hat, Inc.
#
# 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/>.
#
# owner=jsnow@redhat.com

import iotests
from iotests import log

iotests.verify_image_format(supported_fmts=['generic'])
size = 64 * 1024 * 1024
granularity = 64 * 1024

patterns = [("0x5d", "0",         "64k"),
            ("0xd5", "1M",        "64k"),
            ("0xdc", "32M",       "64k"),
            ("0xcd", "0x3ff0000", "64k")]  # 64M - 64K

overwrite = [("0xab", "0",         "64k"), # Full overwrite
             ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K)
             ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K)
             ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K)

def query_bitmaps(vm):
    res = vm.qmp("query-block")
    return { "bitmaps": { device['device']: device.get('dirty-bitmaps', []) for
                          device in res['return'] } }

with iotests.FilePath('img') as img_path, \
     iotests.VM() as vm:

    log('--- Preparing image & VM ---\n')
    iotests.qemu_img_create('-f', iotests.imgfmt, img_path, str(size))
    vm.add_drive(img_path)
    vm.launch()

    log('\n--- Adding preliminary bitmaps A & B ---\n')
    vm.qmp_log("block-dirty-bitmap-add", node="drive0",
               name="bitmapA", granularity=granularity)
    vm.qmp_log("block-dirty-bitmap-add", node="drive0",
               name="bitmapB", granularity=granularity)

    # Dirties 4 clusters. count=262144
    log('\n--- Emulating writes ---\n')
    for p in patterns:
        cmd = "write -P%s %s %s" % p
        log(cmd)
        log(vm.hmp_qemu_io("drive0", cmd))

    log(query_bitmaps(vm), indent=2)

    log('\n--- Submitting & Aborting Transaction ---\n')
    vm.qmp_log("transaction", indent=2, actions=[
        { "type": "block-dirty-bitmap-disable",
          "data": { "node": "drive0", "name": "bitmapB" }},
        { "type": "block-dirty-bitmap-add",
          "data": { "node": "drive0", "name": "bitmapC",
                    "granularity": granularity }},
        { "type": "block-dirty-bitmap-clear",
          "data": { "node": "drive0", "name": "bitmapA" }},
        { "type": "abort", "data": {}}
    ])
    log(query_bitmaps(vm), indent=2)

    log('\n--- Disabling B & Adding C ---\n')
    vm.qmp_log("transaction", indent=2, actions=[
        { "type": "block-dirty-bitmap-disable",
          "data": { "node": "drive0", "name": "bitmapB" }},
        { "type": "block-dirty-bitmap-add",
          "data": { "node": "drive0", "name": "bitmapC",
                    "granularity": granularity }},
        # Purely extraneous, but test that it works:
        { "type": "block-dirty-bitmap-disable",
          "data": { "node": "drive0", "name": "bitmapC" }},
        { "type": "block-dirty-bitmap-enable",
          "data": { "node": "drive0", "name": "bitmapC" }},
    ])

    log('\n--- Emulating further writes ---\n')
    # Dirties 6 clusters, 3 of which are new in contrast to "A".
    # A = 64 * 1024 * (4 + 3) = 458752
    # C = 64 * 1024 * 6       = 393216
    for p in overwrite:
        cmd = "write -P%s %s %s" % p
        log(cmd)
        log(vm.hmp_qemu_io("drive0", cmd))

    log('\n--- Disabling A & C ---\n')
    vm.qmp_log("transaction", indent=2, actions=[
        { "type": "block-dirty-bitmap-disable",
          "data": { "node": "drive0", "name": "bitmapA" }},
        { "type": "block-dirty-bitmap-disable",
          "data": { "node": "drive0", "name": "bitmapC" }}
    ])

    # A: 7 clusters
    # B: 4 clusters
    # C: 6 clusters
    log(query_bitmaps(vm), indent=2)

    log('\n--- Submitting & Aborting Merge Transaction ---\n')
    vm.qmp_log("transaction", indent=2, actions=[
        { "type": "block-dirty-bitmap-add",
          "data": { "node": "drive0", "name": "bitmapD",
                    "disabled": True, "granularity": granularity }},
        { "type": "block-dirty-bitmap-merge",
          "data": { "node": "drive0", "target": "bitmapD",
                    "bitmaps": ["bitmapB", "bitmapC"] }},
        { "type": "abort", "data": {}}
    ])
    log(query_bitmaps(vm), indent=2)

    log('\n--- Creating D as a merge of B & C ---\n')
    # Good hygiene: create a disabled bitmap as a merge target.
    vm.qmp_log("transaction", indent=2, actions=[
        { "type": "block-dirty-bitmap-add",
          "data": { "node": "drive0", "name": "bitmapD",
                    "disabled": True, "granularity": granularity }},
        { "type": "block-dirty-bitmap-merge",
          "data": { "node": "drive0", "target": "bitmapD",
                    "bitmaps": ["bitmapB", "bitmapC"] }}
    ])

    # A and D should now both have 7 clusters apiece.
    # B and C remain unchanged with 4 and 6 respectively.
    log(query_bitmaps(vm), indent=2)

    # A and D should be equivalent.
    # Some formats round the size of the disk, so don't print the checksums.
    check_a = vm.qmp('x-debug-block-dirty-bitmap-sha256',
                     node="drive0", name="bitmapA")['return']['sha256']
    check_d = vm.qmp('x-debug-block-dirty-bitmap-sha256',
                     node="drive0", name="bitmapD")['return']['sha256']
    assert(check_a == check_d)

    log('\n--- Removing bitmaps A, B, C, and D ---\n')
    vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapA")
    vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapB")
    vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapC")
    vm.qmp_log("block-dirty-bitmap-remove", node="drive0", name="bitmapD")

    log('\n--- Final Query ---\n')
    log(query_bitmaps(vm), indent=2)

    log('\n--- Done ---\n')
    vm.shutdown()
