#!/usr/bin/python3
# group: auto quick disabled
# VZ: disabled due to ID-9731
#
# Test default kvm features for all machine types
#
# Copyright (c) 2022 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 iotests

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
from qemu.machine import QEMUMachine

iotests.script_initialize()


def qmp_find_cpu(vm):
    cpus = vm.qmp('query-cpus-fast')['return']
    return cpus[0]['qom-path']


def get_bool_cpu_property(vm, prop_name):
    cpu_path = qmp_find_cpu(vm)

    hmp_com_line = 'qom-get ' + cpu_path + ' ' + prop_name
    qmp_ret = vm.qmp('human-monitor-command', command_line=hmp_com_line)
    feature_state = qmp_ret['return'].strip('\r\n')

    if feature_state == 'true' or feature_state == 'false':
        return (0, feature_state)
    else:
        return (-1, 'Check bool property ({0}) of the ({1}) returned ({2})'
                .format(prop_name, cpu_path, feature_state))


def check_mt(mt, props):
    vm_params = ['-machine', mt, '-accel', 'kvm']

    vm = QEMUMachine(iotests.qemu_prog, vm_params) # delete iotests dependency
    vm.launch()

    errors = 0
    for prop_name, expected_val in props.items():
        ret = get_bool_cpu_property(vm, prop_name)

        if ret[0] == -1:
            print('Error ({0}): {1}'.format(mt, ret[1]))
            vm.shutdown()
            return 1

        if ret[1] != expected_val:
            print('Error ({0}): {1} = {2} (expected {3})'
                  .format(mt, prop_name, ret[1], expected_val))
            errors += 1

    vm.shutdown()
    return errors


# collect all machine types except 'none'
vm = iotests.VM()
vm.launch()
machines = [m['name'] for m in vm.qmp('query-machines')['return']]
vm.shutdown()
machines.remove('none')

failed = 0
# set expecting values for appropriate machine types
for m in machines:
    if m.startswith('x-') or m == 'microvm':
        continue

    prefix, major, minor = m.split('.')

    props = {
        'kvm-pv-tlb-flush':   'false',
        'kvm-pv-ipi':         'false',
        'kvm-pv-sched-yield': 'false',
        'kvm-asyncpf-int':    'false'
    }

    if prefix == 'pc-q35-vz9':
        props = dict.fromkeys(props, 'true')
    elif prefix == 'pc-q35-rhel9' or \
         (prefix == 'pc-q35-rhel8' and int(major) >= 5):
        props.update({'kvm-asyncpf-int': 'true'})

    failed += check_mt(m, props)

if failed > 0:
    print('Failed')
else:
    print('Success')
