#
# Test virtio-scsi and virtio-blk queue settings for all machine types
#
# Copyright (c) 2019 Virtuozzo International GmbH
#
# 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 sys
import os
import re
import logging

from qemu.machine import QEMUMachine
from avocado_qemu import QemuSystemTest
from avocado import skip

#list of machine types and virtqueue properties to test
VIRTIO_SCSI_PROPS = {'seg_max_adjust': 'seg_max_adjust'}
VIRTIO_BLK_PROPS = {'seg_max_adjust': 'seg-max-adjust'}

DEV_TYPES = {'virtio-scsi-pci': VIRTIO_SCSI_PROPS,
             'virtio-blk-pci': VIRTIO_BLK_PROPS}

VM_DEV_PARAMS = {'virtio-scsi-pci': ['-device', 'virtio-scsi-pci,id=scsi0'],
                 'virtio-blk-pci': ['-device',
                                    'virtio-blk-pci,id=scsi0,drive=drive0',
                                    '-drive',
                                    'driver=null-co,id=drive0,if=none']}


class VirtioMaxSegSettingsCheck(QemuSystemTest):
    @staticmethod
    def make_pattern(props):
        pattern_items = [r'{0} = \w+'.format(prop) for prop in props]
        return '|'.join(pattern_items)

    def query_virtqueue(self, vm, dev_type_name):
        query_ok = False
        error = None
        props = None

        output = vm.cmd('human-monitor-command',
                        command_line = 'info qtree')
        props_list = DEV_TYPES[dev_type_name].values();
        pattern = self.make_pattern(props_list)
        res = re.findall(pattern, output)

        if len(res) != len(props_list):
            props_list = set(props_list)
            res = set(res)
            not_found = props_list.difference(res)
            not_found = ', '.join(not_found)
            error = '({0}): The following properties not found: {1}'\
                     .format(dev_type_name, not_found)
        else:
            query_ok = True
            props = dict()
            for prop in res:
                p = prop.split(' = ')
                props[p[0]] = p[1]
        return query_ok, props, error

    def check_mt(self, mt, dev_type_name):
        mt['device'] = dev_type_name # Only for the debug() call.
        logger = logging.getLogger('machine')
        logger.debug(mt)
        with QEMUMachine(self.qemu_bin) as vm:
            vm.set_machine(mt["name"])
            vm.add_args('-nodefaults')
            for s in VM_DEV_PARAMS[dev_type_name]:
                vm.add_args(s)
            try:
                vm.launch()
                query_ok, props, error = self.query_virtqueue(vm, dev_type_name)
            except:
                query_ok = False
                error = sys.exc_info()[0]

        if not query_ok:
            self.fail('machine type {0}: {1}'.format(mt['name'], error))

        for prop_name, prop_val in props.items():
            expected_val = mt[prop_name]
            self.assertEqual(expected_val, prop_val)

    @staticmethod
    def seg_max_adjust_enabled(mt):
        # machine types >= 5.0 should have seg_max_adjust = true
        # others seg_max_adjust = false
        mt = mt.split("-")

        # machine types with one line name and name like pc-x.x
        if len(mt) <= 2:
            return False

        # machine types like pc-<chip_name>-x.x[.x]
        ver = mt[2]
        ver = ver.split(".");

        # versions >= 5.0 goes with seg_max_adjust enabled
        major = int(ver[0])

        if major >= 5:
            return True
        return False

    @skip("break multi-arch CI")
    def test_machine_types(self):
        # collect all machine types except 'none', 'isapc', 'microvm'
        with QEMUMachine(self.qemu_bin) as vm:
            vm.launch()
            machines = [m['name'] for m in vm.cmd('query-machines')]
            vm.shutdown()
        machines.remove('none')
        machines.remove('isapc')
        machines.remove('microvm')

        for dev_type in DEV_TYPES:
            # create the list of machine types and their parameters.
            mtypes = list()
            for m in machines:
                if self.seg_max_adjust_enabled(m):
                    enabled = 'true'
                else:
                    enabled = 'false'
                mtypes.append({'name': m,
                               DEV_TYPES[dev_type]['seg_max_adjust']: enabled})

            # test each machine type for a device type
            for mt in mtypes:
                self.check_mt(mt, dev_type)
