#!/usr/bin/env python
#
# This test covers the basic fleecing workflow, which provides a
# point-in-time snapshot of a node that can be queried over NBD.
#
# Copyright (C) 2018 Red Hat, Inc.
# John helped, too.
#
# 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/>.
#
# Creator/Owner: John Snow <jsnow@redhat.com>

import iotests
from iotests import log, qemu_img, qemu_io, qemu_io_silent

iotests.verify_platform(['linux'])
iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk',
                                            'vhdx', 'raw'])

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)

zeroes = [("0", "0x00f8000", "32k"), # Left-end of partial-left (1M-32K)
          ("0", "0x2010000", "32k"), # Right-end of partial-right (32M+64K)
          ("0", "0x3fe0000", "64k")] # overwrite[3]

remainder = [("0xd5", "0x108000",  "32k"), # Right-end of partial-left [1]
             ("0xdc", "32M",       "32k"), # Left-end of partial-right [2]
             ("0xcd", "0x3ff0000", "64k")] # patterns[3]

with iotests.FilePath('base.img') as base_img_path, \
     iotests.FilePath('fleece.img') as fleece_img_path, \
     iotests.FilePath('nbd.sock') as nbd_sock_path, \
     iotests.VM() as vm:

    log('--- Setting up images ---')
    log('')

    assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
    assert qemu_img('create', '-f', "qcow2", fleece_img_path, '64M') == 0

    for p in patterns:
        qemu_io('-f', iotests.imgfmt,
                '-c', 'write -P%s %s %s' % p, base_img_path)

    log('Done')

    log('')
    log('--- Launching VM ---')
    log('')

    vm.add_drive(base_img_path)
    vm.launch()
    log('Done')

    log('')
    log('--- Setting up Fleecing Graph ---')
    log('')

    src_node = "drive0"
    tgt_node = "fleeceNode"

    # create tgt_node backed by src_node
    log(vm.qmp("blockdev-add", **{
        "driver": "qcow2",
        "node-name": tgt_node,
        "file": {
            "driver": "file",
            "filename": fleece_img_path,
        },
        "backing": src_node,
    }))

    # Establish COW from source to fleecing node
    log(vm.qmp("blockdev-backup",
               device=src_node,
               target=tgt_node,
               sync="none"))

    log('')
    log('--- Setting up NBD Export ---')
    log('')

    nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
    log(vm.qmp("nbd-server-start",
               **{"addr": { "type": "unix",
                            "data": { "path": nbd_sock_path } } }))

    log(vm.qmp("nbd-server-add", device=tgt_node))

    log('')
    log('--- Sanity Check ---')
    log('')

    for p in (patterns + zeroes):
        cmd = "read -P%s %s %s" % p
        log(cmd)
        assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0

    log('')
    log('--- Testing COW ---')
    log('')

    for p in overwrite:
        cmd = "write -P%s %s %s" % p
        log(cmd)
        log(vm.hmp_qemu_io(src_node, cmd))

    log('')
    log('--- Verifying Data ---')
    log('')

    for p in (patterns + zeroes):
        cmd = "read -P%s %s %s" % p
        log(cmd)
        assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0

    log('')
    log('--- Cleanup ---')
    log('')

    log(vm.qmp('block-job-cancel', device=src_node))
    log(vm.event_wait('BLOCK_JOB_CANCELLED'),
        filters=[iotests.filter_qmp_event])
    log(vm.qmp('nbd-server-stop'))
    log(vm.qmp('blockdev-del', node_name=tgt_node))
    vm.shutdown()

    log('')
    log('--- Confirming writes ---')
    log('')

    for p in (overwrite + remainder):
        cmd = "read -P%s %s %s" % p
        log(cmd)
        assert qemu_io_silent(base_img_path, '-c', cmd) == 0

    log('')
    log('Done')
