#
# 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 = ['{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)
