#!/usr/bin/env python3
# group: rw auto
#
# Tests for image block commit.
#
# Copyright (C) 2012 IBM, Corp.
# Copyright (C) 2012 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/>.
#
# Test for live block commit
# Derived from Image Streaming Test 030

import time
import os
import iotests
from iotests import qemu_img, qemu_io
import struct
import errno

backing_img = os.path.join(iotests.test_dir, 'backing.img')
mid_img = os.path.join(iotests.test_dir, 'mid.img')
test_img = os.path.join(iotests.test_dir, 'test.img')

class ImageCommitTestCase(iotests.QMPTestCase):
    '''Abstract base class for image commit test cases'''

    def wait_for_complete(self, need_ready=False):
        completed = False
        ready = False
        while not completed:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assert_qmp_absent(event, 'data/error')
                    self.assert_qmp(event, 'data/type', 'commit')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.assert_qmp(event, 'data/offset', event['data']['len'])
                    if need_ready:
                        self.assertTrue(ready, "Expecting BLOCK_JOB_COMPLETED event")
                    completed = True
                elif event['event'] == 'BLOCK_JOB_READY':
                    ready = True
                    self.assert_qmp(event, 'data/type', 'commit')
                    self.assert_qmp(event, 'data/device', 'drive0')
                    self.vm.qmp('block-job-complete', device='drive0')

        self.assert_no_active_block_jobs()
        self.vm.shutdown()

    def run_commit_test(self, top, base, need_ready=False, node_names=False):
        self.assert_no_active_block_jobs()
        if node_names:
            result = self.vm.qmp('block-commit', device='drive0', top_node=top, base_node=base)
        else:
            result = self.vm.qmp('block-commit', device='drive0', top=top, base=base)
        self.assert_qmp(result, 'return', {})
        self.wait_for_complete(need_ready)

    def run_default_commit_test(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0')
        self.assert_qmp(result, 'return', {})
        self.wait_for_complete()

class TestSingleDrive(ImageCommitTestCase):
    # Need some space after the copied data so that throttling is effective in
    # tests that use it rather than just completing the job immediately
    image_len = 2 * 1024 * 1024
    test_len = 1 * 1024 * 256

    def setUp(self):
        iotests.create_image(backing_img, self.image_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img, '-F', 'raw', mid_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % mid_img,
                 '-F', iotests.imgfmt, test_img)
        if self.image_len:
            qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
            qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288',
                    mid_img)
        self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
        self.vm.add_device('virtio-scsi')
        self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(mid_img)
        os.remove(backing_img)

    def test_commit(self):
        self.run_commit_test(mid_img, backing_img)
        if not self.image_len:
            return
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)

    def test_commit_node(self):
        self.run_commit_test("mid", "base", node_names=True)
        if not self.image_len:
            return
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)

    @iotests.skip_if_unsupported(['throttle'])
    def test_commit_with_filter_and_quit(self):
        result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
        self.assert_qmp(result, 'return', {})

        # Add a filter outside of the backing chain
        result = self.vm.qmp('blockdev-add', driver='throttle', node_name='filter', throttle_group='tg', file='mid')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-commit', device='drive0')
        self.assert_qmp(result, 'return', {})

        # Quit immediately, thus forcing a simultaneous cancel of the
        # block job and a bdrv_drain_all()
        result = self.vm.qmp('quit')
        self.assert_qmp(result, 'return', {})

    # Same as above, but this time we add the filter after starting the job
    @iotests.skip_if_unsupported(['throttle'])
    def test_commit_plus_filter_and_quit(self):
        result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('block-commit', device='drive0')
        self.assert_qmp(result, 'return', {})

        # Add a filter outside of the backing chain
        result = self.vm.qmp('blockdev-add', driver='throttle', node_name='filter', throttle_group='tg', file='mid')
        self.assert_qmp(result, 'return', {})

        # Quit immediately, thus forcing a simultaneous cancel of the
        # block job and a bdrv_drain_all()
        result = self.vm.qmp('quit')
        self.assert_qmp(result, 'return', {})

    def test_device_not_found(self):
        result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img)
        self.assert_qmp(result, 'error/class', 'DeviceNotFound')

    def test_top_same_base(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % backing_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find '%s' in the backing chain" % backing_img)

    def test_top_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % backing_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', 'Top image file badfile not found')

    def test_base_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img, base='badfile')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find 'badfile' in the backing chain")

    def test_top_node_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top_node='badfile', base_node='base')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Cannot find device='' nor node-name='badfile'")

    def test_base_node_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top_node='mid', base_node='badfile')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Cannot find device='' nor node-name='badfile'")

    def test_top_path_and_node(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top_node='mid', base_node='base', top='%s' % mid_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "'top-node' and 'top' are mutually exclusive")

    def test_base_path_and_node(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top_node='mid', base_node='base', base='%s' % backing_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "'base-node' and 'base' are mutually exclusive")

    def test_top_is_active(self):
        self.run_commit_test(test_img, backing_img, need_ready=True)
        if not self.image_len:
            return
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)

    def test_top_is_default_active(self):
        self.run_default_commit_test()
        if not self.image_len:
            return
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)

    def test_top_and_base_reversed(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find '%s' in the backing chain" % mid_img)

    def test_top_and_base_node_reversed(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top_node='base', base_node='top')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "'top' is not in this backing file chain")

    def test_top_node_in_wrong_chain(self):
        self.assert_no_active_block_jobs()

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

        result = self.vm.qmp('block-commit', device='drive0', top_node='null', base_node='base')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "'null' is not in this backing file chain")

    # When the job is running on a BB that is automatically deleted on hot
    # unplug, the job is cancelled when the device disappears
    def test_hot_unplug(self):
        if self.image_len == 0:
            return

        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
                             base=backing_img, speed=(self.image_len // 4))
        self.assert_qmp(result, 'return', {})
        result = self.vm.qmp('device_del', id='scsi0')
        self.assert_qmp(result, 'return', {})

        cancelled = False
        deleted = False
        while not cancelled or not deleted:
            for event in self.vm.get_qmp_events(wait=True):
                if event['event'] == 'DEVICE_DELETED':
                    self.assert_qmp(event, 'data/device', 'scsi0')
                    deleted = True
                elif event['event'] == 'BLOCK_JOB_CANCELLED':
                    self.assert_qmp(event, 'data/device', 'drive0')
                    cancelled = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', 'drive0')
                else:
                    self.fail("Unexpected event %s" % (event['event']))

        self.assert_no_active_block_jobs()

    # Tests that the insertion of the commit_top filter node doesn't make a
    # difference to query-blockstat
    def test_implicit_node(self):
        if self.image_len == 0:
            return

        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
                             base=backing_img, speed=(self.image_len // 4))
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('query-block')
        self.assert_qmp(result, 'return[0]/inserted/file', test_img)
        self.assert_qmp(result, 'return[0]/inserted/drv', iotests.imgfmt)
        self.assert_qmp(result, 'return[0]/inserted/backing_file', mid_img)
        self.assert_qmp(result, 'return[0]/inserted/backing_file_depth', 2)
        self.assert_qmp(result, 'return[0]/inserted/image/filename', test_img)
        self.assert_qmp(result, 'return[0]/inserted/image/backing-image/filename', mid_img)
        self.assert_qmp(result, 'return[0]/inserted/image/backing-image/backing-image/filename', backing_img)

        result = self.vm.qmp('query-blockstats')
        self.assert_qmp(result, 'return[0]/node-name', 'top')
        self.assert_qmp(result, 'return[0]/backing/node-name', 'mid')
        self.assert_qmp(result, 'return[0]/backing/backing/node-name', 'base')

        self.cancel_and_wait()
        self.assert_no_active_block_jobs()

class TestRelativePaths(ImageCommitTestCase):
    image_len = 1 * 1024 * 1024
    test_len = 1 * 1024 * 256

    dir1 = "dir1"
    dir2 = "dir2/"
    dir3 = "dir2/dir3/"

    test_img = os.path.join(iotests.test_dir, dir3, 'test.img')
    mid_img = "../mid.img"
    backing_img = "../dir1/backing.img"

    backing_img_abs = os.path.join(iotests.test_dir, dir1, 'backing.img')
    mid_img_abs = os.path.join(iotests.test_dir, dir2, 'mid.img')

    def setUp(self):
        try:
            os.mkdir(os.path.join(iotests.test_dir, self.dir1))
            os.mkdir(os.path.join(iotests.test_dir, self.dir2))
            os.mkdir(os.path.join(iotests.test_dir, self.dir3))
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise
        iotests.create_image(self.backing_img_abs, TestRelativePaths.image_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % self.backing_img_abs,
                 '-F', 'raw', self.mid_img_abs)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % self.mid_img_abs,
                 '-F', iotests.imgfmt, self.test_img)
        qemu_img('rebase', '-u', '-b', self.backing_img,
                 '-F', 'raw', self.mid_img_abs)
        qemu_img('rebase', '-u', '-b', self.mid_img,
                 '-F', iotests.imgfmt, self.test_img)
        qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', self.backing_img_abs)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', self.mid_img_abs)
        self.vm = iotests.VM().add_drive(self.test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(self.test_img)
        os.remove(self.mid_img_abs)
        os.remove(self.backing_img_abs)
        try:
            os.rmdir(os.path.join(iotests.test_dir, self.dir1))
            os.rmdir(os.path.join(iotests.test_dir, self.dir3))
            os.rmdir(os.path.join(iotests.test_dir, self.dir2))
        except OSError as exception:
            if exception.errno != errno.EEXIST and exception.errno != errno.ENOTEMPTY:
                raise

    def test_commit(self):
        self.run_commit_test(self.mid_img, self.backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs)

    def test_device_not_found(self):
        result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % self.mid_img)
        self.assert_qmp(result, 'error/class', 'DeviceNotFound')

    def test_top_same_base(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='%s' % self.mid_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find '%s' in the backing chain" % self.mid_img)

    def test_top_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % self.backing_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', 'Top image file badfile not found')

    def test_base_invalid(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='badfile')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find 'badfile' in the backing chain")

    def test_top_is_active(self):
        self.run_commit_test(self.test_img, self.backing_img)
        qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs)
        qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs)

    def test_top_and_base_reversed(self):
        self.assert_no_active_block_jobs()
        result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.backing_img, base='%s' % self.mid_img)
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', "Can't find '%s' in the backing chain" % self.mid_img)


class TestSetSpeed(ImageCommitTestCase):
    image_len = 80 * 1024 * 1024 # MB

    def setUp(self):
        qemu_img('create', backing_img, str(TestSetSpeed.image_len))
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img, '-F', 'raw', mid_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % mid_img,
                 '-F', iotests.imgfmt, test_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 0 512', test_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
        self.vm = iotests.VM().add_drive('blkdebug::' + test_img)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(mid_img)
        os.remove(backing_img)

    def test_set_speed(self):
        self.assert_no_active_block_jobs()

        self.vm.pause_drive('drive0')
        result = self.vm.qmp('block-commit', device='drive0', top=mid_img, speed=1024 * 1024)
        self.assert_qmp(result, 'return', {})

        # Ensure the speed we set was accepted
        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return[0]/device', 'drive0')
        self.assert_qmp(result, 'return[0]/speed', 1024 * 1024)

        self.cancel_and_wait(resume=True)

class TestActiveZeroLengthImage(TestSingleDrive):
    image_len = 0

class TestReopenOverlay(ImageCommitTestCase):
    image_len = 1024 * 1024
    img0 = os.path.join(iotests.test_dir, '0.img')
    img1 = os.path.join(iotests.test_dir, '1.img')
    img2 = os.path.join(iotests.test_dir, '2.img')
    img3 = os.path.join(iotests.test_dir, '3.img')

    def setUp(self):
        iotests.create_image(self.img0, self.image_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % self.img0, '-F', 'raw', self.img1)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % self.img1,
                 '-F', iotests.imgfmt, self.img2)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % self.img2,
                 '-F', iotests.imgfmt, self.img3)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xab 0 128K', self.img1)
        self.vm = iotests.VM().add_drive(self.img3)
        self.vm.launch()

    def tearDown(self):
        self.vm.shutdown()
        os.remove(self.img0)
        os.remove(self.img1)
        os.remove(self.img2)
        os.remove(self.img3)

    # This tests what happens when the overlay image of the 'top' node
    # needs to be reopened in read-write mode in order to update the
    # backing image string.
    def test_reopen_overlay(self):
        self.run_commit_test(self.img1, self.img0)

class TestErrorHandling(iotests.QMPTestCase):
    image_len = 2 * 1024 * 1024

    def setUp(self):
        iotests.create_image(backing_img, self.image_len)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % backing_img,
                 '-F', 'raw', mid_img)
        qemu_img('create', '-f', iotests.imgfmt,
                 '-o', 'backing_file=%s' % mid_img,
                 '-F', iotests.imgfmt, test_img)

        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x11 0 512k', mid_img)
        qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x22 0 512k', test_img)

        self.vm = iotests.VM()
        self.vm.launch()

        self.blkdebug_file = iotests.file_path("blkdebug.conf")

    def tearDown(self):
        self.vm.shutdown()
        os.remove(test_img)
        os.remove(mid_img)
        os.remove(backing_img)

    def blockdev_add(self, **kwargs):
        result = self.vm.qmp('blockdev-add', **kwargs)
        self.assert_qmp(result, 'return', {})

    def add_block_nodes(self, base_debug=None, mid_debug=None, top_debug=None):
        self.blockdev_add(node_name='base-file', driver='file',
                          filename=backing_img)
        self.blockdev_add(node_name='mid-file', driver='file',
                          filename=mid_img)
        self.blockdev_add(node_name='top-file', driver='file',
                          filename=test_img)

        if base_debug:
            self.blockdev_add(node_name='base-dbg', driver='blkdebug',
                              image='base-file', inject_error=base_debug)
        if mid_debug:
            self.blockdev_add(node_name='mid-dbg', driver='blkdebug',
                              image='mid-file', inject_error=mid_debug)
        if top_debug:
            self.blockdev_add(node_name='top-dbg', driver='blkdebug',
                              image='top-file', inject_error=top_debug)

        self.blockdev_add(node_name='base-fmt', driver='raw',
                          file=('base-dbg' if base_debug else 'base-file'))
        self.blockdev_add(node_name='mid-fmt', driver=iotests.imgfmt,
                          file=('mid-dbg' if mid_debug else 'mid-file'),
                          backing='base-fmt')
        self.blockdev_add(node_name='top-fmt', driver=iotests.imgfmt,
                          file=('top-dbg' if top_debug else 'top-file'),
                          backing='mid-fmt')

    def run_job(self, expected_events, error_pauses_job=False):
        match_device = {'data': {'device': 'job0'}}
        events = [
            ('BLOCK_JOB_COMPLETED', match_device),
            ('BLOCK_JOB_CANCELLED', match_device),
            ('BLOCK_JOB_ERROR', match_device),
            ('BLOCK_JOB_READY', match_device),
        ]

        completed = False
        log = []
        while not completed:
            ev = self.vm.events_wait(events, timeout=5.0)
            if ev['event'] == 'BLOCK_JOB_COMPLETED':
                completed = True
            elif ev['event'] == 'BLOCK_JOB_ERROR':
                if error_pauses_job:
                    result = self.vm.qmp('block-job-resume', device='job0')
                    self.assert_qmp(result, 'return', {})
            elif ev['event'] == 'BLOCK_JOB_READY':
                result = self.vm.qmp('block-job-complete', device='job0')
                self.assert_qmp(result, 'return', {})
            else:
                self.fail("Unexpected event: %s" % ev)
            log.append(iotests.filter_qmp_event(ev))

        self.maxDiff = None
        self.assertEqual(expected_events, log)

    def event_error(self, op, action):
        return {
            'event': 'BLOCK_JOB_ERROR',
            'data': {'action': action, 'device': 'job0', 'operation': op},
            'timestamp': {'microseconds': 'USECS', 'seconds': 'SECS'}
        }

    def event_ready(self):
        return {
            'event': 'BLOCK_JOB_READY',
            'data': {'device': 'job0',
                     'len': 524288,
                     'offset': 524288,
                     'speed': 0,
                     'type': 'commit'},
            'timestamp': {'microseconds': 'USECS', 'seconds': 'SECS'},
        }

    def event_completed(self, errmsg=None, active=True):
        max_len = 524288 if active else self.image_len
        data = {
            'device': 'job0',
            'len': max_len,
            'offset': 0 if errmsg else max_len,
            'speed': 0,
            'type': 'commit'
        }
        if errmsg:
            data['error'] = errmsg

        return {
            'event': 'BLOCK_JOB_COMPLETED',
            'data': data,
            'timestamp': {'microseconds': 'USECS', 'seconds': 'SECS'},
        }

    def blkdebug_event(self, event, is_raw=False):
        if event:
            return [{
                'event': event,
                'sector': 512 if is_raw else 1024,
                'once': True,
            }]
        return None

    def prepare_and_start_job(self, on_error, active=True,
                              top_event=None, mid_event=None, base_event=None):

        top_debug = self.blkdebug_event(top_event)
        mid_debug = self.blkdebug_event(mid_event)
        base_debug = self.blkdebug_event(base_event, True)

        self.add_block_nodes(top_debug=top_debug, mid_debug=mid_debug,
                             base_debug=base_debug)

        result = self.vm.qmp('block-commit', job_id='job0', device='top-fmt',
                             top_node='top-fmt' if active else 'mid-fmt',
                             base_node='mid-fmt' if active else 'base-fmt',
                             on_error=on_error)
        self.assert_qmp(result, 'return', {})

    def testActiveReadErrorReport(self):
        self.prepare_and_start_job('report', top_event='read_aio')
        self.run_job([
            self.event_error('read', 'report'),
            self.event_completed('Input/output error')
        ])

        self.vm.shutdown()
        self.assertFalse(iotests.compare_images(test_img, mid_img),
                         'target image matches source after error')

    def testActiveReadErrorStop(self):
        self.prepare_and_start_job('stop', top_event='read_aio')
        self.run_job([
            self.event_error('read', 'stop'),
            self.event_ready(),
            self.event_completed()
        ], error_pauses_job=True)

        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(test_img, mid_img),
                        'target image does not match source after commit')

    def testActiveReadErrorIgnore(self):
        self.prepare_and_start_job('ignore', top_event='read_aio')
        self.run_job([
            self.event_error('read', 'ignore'),
            self.event_ready(),
            self.event_completed()
        ])

        # For commit, 'ignore' actually means retry, so this will succeed
        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(test_img, mid_img),
                        'target image does not match source after commit')

    def testActiveWriteErrorReport(self):
        self.prepare_and_start_job('report', mid_event='write_aio')
        self.run_job([
            self.event_error('write', 'report'),
            self.event_completed('Input/output error')
        ])

        self.vm.shutdown()
        self.assertFalse(iotests.compare_images(test_img, mid_img),
                         'target image matches source after error')

    def testActiveWriteErrorStop(self):
        self.prepare_and_start_job('stop', mid_event='write_aio')
        self.run_job([
            self.event_error('write', 'stop'),
            self.event_ready(),
            self.event_completed()
        ], error_pauses_job=True)

        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(test_img, mid_img),
                        'target image does not match source after commit')

    def testActiveWriteErrorIgnore(self):
        self.prepare_and_start_job('ignore', mid_event='write_aio')
        self.run_job([
            self.event_error('write', 'ignore'),
            self.event_ready(),
            self.event_completed()
        ])

        # For commit, 'ignore' actually means retry, so this will succeed
        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(test_img, mid_img),
                        'target image does not match source after commit')

    def testIntermediateReadErrorReport(self):
        self.prepare_and_start_job('report', active=False, mid_event='read_aio')
        self.run_job([
            self.event_error('read', 'report'),
            self.event_completed('Input/output error', active=False)
        ])

        self.vm.shutdown()
        self.assertFalse(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                         'target image matches source after error')

    def testIntermediateReadErrorStop(self):
        self.prepare_and_start_job('stop', active=False, mid_event='read_aio')
        self.run_job([
            self.event_error('read', 'stop'),
            self.event_completed(active=False)
        ], error_pauses_job=True)

        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                        'target image does not match source after commit')

    def testIntermediateReadErrorIgnore(self):
        self.prepare_and_start_job('ignore', active=False, mid_event='read_aio')
        self.run_job([
            self.event_error('read', 'ignore'),
            self.event_completed(active=False)
        ])

        # For commit, 'ignore' actually means retry, so this will succeed
        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                        'target image does not match source after commit')

    def testIntermediateWriteErrorReport(self):
        self.prepare_and_start_job('report', active=False, base_event='write_aio')
        self.run_job([
            self.event_error('write', 'report'),
            self.event_completed('Input/output error', active=False)
        ])

        self.vm.shutdown()
        self.assertFalse(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                         'target image matches source after error')

    def testIntermediateWriteErrorStop(self):
        self.prepare_and_start_job('stop', active=False, base_event='write_aio')
        self.run_job([
            self.event_error('write', 'stop'),
            self.event_completed(active=False)
        ], error_pauses_job=True)

        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                        'target image does not match source after commit')

    def testIntermediateWriteErrorIgnore(self):
        self.prepare_and_start_job('ignore', active=False, base_event='write_aio')
        self.run_job([
            self.event_error('write', 'ignore'),
            self.event_completed(active=False)
        ])

        # For commit, 'ignore' actually means retry, so this will succeed
        self.vm.shutdown()
        self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
                        'target image does not match source after commit')

class TestCommitWithFilters(iotests.QMPTestCase):
    img0 = os.path.join(iotests.test_dir, '0.img')
    img1 = os.path.join(iotests.test_dir, '1.img')
    img2 = os.path.join(iotests.test_dir, '2.img')
    img3 = os.path.join(iotests.test_dir, '3.img')

    def do_test_io(self, read_or_write):
        for index, pattern_file in enumerate(self.pattern_files):
            qemu_io('-f', iotests.imgfmt,
                    '-c',
                    f'{read_or_write} -P {index + 1} {index}M 1M',
                    pattern_file)

    @iotests.skip_if_unsupported(['throttle'])
    def setUp(self):
        qemu_img('create', '-f', iotests.imgfmt, self.img0, '64M')
        qemu_img('create', '-f', iotests.imgfmt, self.img1, '64M')
        qemu_img('create', '-f', iotests.imgfmt, self.img2, '64M')
        qemu_img('create', '-f', iotests.imgfmt, self.img3, '64M')

        # Distributions of the patterns in the files; this is checked
        # by tearDown() and should be changed by the test cases as is
        # necessary
        self.pattern_files = [self.img0, self.img1, self.img2, self.img3]

        self.do_test_io('write')

        self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi')
        self.vm.launch()

        result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
        self.assert_qmp(result, 'return', {})

        result = self.vm.qmp('blockdev-add', **{
                'node-name': 'top-filter',
                'driver': 'throttle',
                'throttle-group': 'tg',
                'file': {
                    'node-name': 'cow-3',
                    'driver': iotests.imgfmt,
                    'file': {
                        'driver': 'file',
                        'filename': self.img3
                    },
                    'backing': {
                        'node-name': 'cow-2',
                        'driver': iotests.imgfmt,
                        'file': {
                            'driver': 'file',
                            'filename': self.img2
                        },
                        'backing': {
                            'node-name': 'cow-1',
                            'driver': iotests.imgfmt,
                            'file': {
                                'driver': 'file',
                                'filename': self.img1
                            },
                            'backing': {
                                'node-name': 'bottom-filter',
                                'driver': 'throttle',
                                'throttle-group': 'tg',
                                'file': {
                                    'node-name': 'cow-0',
                                    'driver': iotests.imgfmt,
                                    'file': {
                                        'driver': 'file',
                                        'filename': self.img0
                                    }
                                }
                            }
                        }
                    }
                }
            })
        self.assert_qmp(result, 'return', {})

    def tearDown(self):
        self.vm.shutdown()
        self.do_test_io('read')

        os.remove(self.img3)
        os.remove(self.img2)
        os.remove(self.img1)
        os.remove(self.img0)

    # Filters make for funny filenames, so we cannot just use
    # self.imgX to get them
    def get_filename(self, node):
        return self.vm.node_info(node)['image']['filename']

    def test_filterless_commit(self):
        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top-filter',
                             top_node='cow-2',
                             base_node='cow-1',
                             backing_file=self.img1)
        self.assert_qmp(result, 'return', {})
        self.wait_until_completed(drive='commit')

        self.assertIsNotNone(self.vm.node_info('cow-3'))
        self.assertIsNone(self.vm.node_info('cow-2'))
        self.assertIsNotNone(self.vm.node_info('cow-1'))

        # 2 has been committed into 1
        self.pattern_files[2] = self.img1

    def test_commit_through_filter(self):
        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top-filter',
                             top_node='cow-1',
                             base_node='cow-0',
                             backing_file=self.img0)
        self.assert_qmp(result, 'return', {})
        self.wait_until_completed(drive='commit')

        self.assertIsNotNone(self.vm.node_info('cow-2'))
        self.assertIsNone(self.vm.node_info('cow-1'))
        self.assertIsNone(self.vm.node_info('bottom-filter'))
        self.assertIsNotNone(self.vm.node_info('cow-0'))

        # 1 has been committed into 0
        self.pattern_files[1] = self.img0

    def test_filtered_active_commit_with_filter(self):
        # Add a device, so the commit job finds a parent it can change
        # to point to the base node (so we can test that top-filter is
        # dropped from the graph)
        result = self.vm.qmp('device_add', id='drv0', driver='scsi-hd',
                             bus='vio-scsi.0', drive='top-filter')
        self.assert_qmp(result, 'return', {})

        # Try to release our reference to top-filter; that should not
        # work because drv0 uses it
        result = self.vm.qmp('blockdev-del', node_name='top-filter')
        self.assert_qmp(result, 'error/class', 'GenericError')
        self.assert_qmp(result, 'error/desc', 'Node top-filter is in use')

        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top-filter',
                             base_node='cow-2')
        self.assert_qmp(result, 'return', {})
        self.complete_and_wait(drive='commit')

        # Try to release our reference to top-filter again
        result = self.vm.qmp('blockdev-del', node_name='top-filter')
        self.assert_qmp(result, 'return', {})

        self.assertIsNone(self.vm.node_info('top-filter'))
        self.assertIsNone(self.vm.node_info('cow-3'))
        self.assertIsNotNone(self.vm.node_info('cow-2'))

        # Check that drv0 is now connected to cow-2
        blockdevs = self.vm.qmp('query-block')['return']
        drv0 = next(dev for dev in blockdevs if dev['qdev'] == 'drv0')
        self.assertEqual(drv0['inserted']['node-name'], 'cow-2')

        # 3 has been committed into 2
        self.pattern_files[3] = self.img2

    def test_filtered_active_commit_without_filter(self):
        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top-filter',
                             top_node='cow-3',
                             base_node='cow-2')
        self.assert_qmp(result, 'return', {})
        self.complete_and_wait(drive='commit')

        self.assertIsNotNone(self.vm.node_info('top-filter'))
        self.assertIsNone(self.vm.node_info('cow-3'))
        self.assertIsNotNone(self.vm.node_info('cow-2'))

        # 3 has been committed into 2
        self.pattern_files[3] = self.img2

class TestCommitWithOverriddenBacking(iotests.QMPTestCase):
    img_base_a = os.path.join(iotests.test_dir, 'base_a.img')
    img_base_b = os.path.join(iotests.test_dir, 'base_b.img')
    img_top = os.path.join(iotests.test_dir, 'top.img')

    def setUp(self):
        qemu_img('create', '-f', iotests.imgfmt, self.img_base_a, '1M')
        qemu_img('create', '-f', iotests.imgfmt, self.img_base_b, '1M')
        qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a,
                 '-F', iotests.imgfmt, self.img_top)

        self.vm = iotests.VM()
        self.vm.launch()

        # Use base_b instead of base_a as the backing of top
        result = self.vm.qmp('blockdev-add', **{
                                'node-name': 'top',
                                'driver': iotests.imgfmt,
                                'file': {
                                    'driver': 'file',
                                    'filename': self.img_top
                                },
                                'backing': {
                                    'node-name': 'base',
                                    'driver': iotests.imgfmt,
                                    'file': {
                                        'driver': 'file',
                                        'filename': self.img_base_b
                                    }
                                }
                            })
        self.assert_qmp(result, 'return', {})

    def tearDown(self):
        self.vm.shutdown()
        os.remove(self.img_top)
        os.remove(self.img_base_a)
        os.remove(self.img_base_b)

    def test_commit_to_a(self):
        # Try committing to base_a (which should fail, as top's
        # backing image is base_b instead)
        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top',
                             base=self.img_base_a)
        self.assert_qmp(result, 'error/class', 'GenericError')

    def test_commit_to_b(self):
        # Try committing to base_b (which should work, since that is
        # actually top's backing image)
        result = self.vm.qmp('block-commit',
                             job_id='commit',
                             device='top',
                             base=self.img_base_b)
        self.assert_qmp(result, 'return', {})

        self.vm.event_wait('BLOCK_JOB_READY')
        self.vm.qmp('block-job-complete', device='commit')
        self.vm.event_wait('BLOCK_JOB_COMPLETED')

if __name__ == '__main__':
    iotests.main(supported_fmts=['qcow2', 'qed'],
                 supported_protocols=['file'])
