Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 1 | # |
| 2 | # Test virtio-scsi and virtio-blk queue settings for all machine types |
| 3 | # |
| 4 | # Copyright (c) 2019 Virtuozzo International GmbH |
| 5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify |
| 7 | # it under the terms of the GNU General Public License as published by |
| 8 | # the Free Software Foundation; either version 2 of the License, or |
| 9 | # (at your option) any later version. |
| 10 | # |
| 11 | # This program is distributed in the hope that it will be useful, |
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | # GNU General Public License for more details. |
| 15 | # |
| 16 | # You should have received a copy of the GNU General Public License |
| 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | # |
| 19 | |
| 20 | import sys |
| 21 | import os |
| 22 | import re |
Philippe Mathieu-Daudé | e435f66 | 2020-01-29 22:23:34 +0100 | [diff] [blame] | 23 | import logging |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 24 | |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 25 | from qemu.machine import QEMUMachine |
Philippe Mathieu-Daudé | 2283b62 | 2021-09-27 18:14:33 +0200 | [diff] [blame] | 26 | from avocado_qemu import QemuSystemTest |
Philippe Mathieu-Daudé | 2d6a6e2 | 2020-02-06 18:17:15 +0100 | [diff] [blame] | 27 | from avocado import skip |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 28 | |
| 29 | #list of machine types and virtqueue properties to test |
| 30 | VIRTIO_SCSI_PROPS = {'seg_max_adjust': 'seg_max_adjust'} |
| 31 | VIRTIO_BLK_PROPS = {'seg_max_adjust': 'seg-max-adjust'} |
| 32 | |
| 33 | DEV_TYPES = {'virtio-scsi-pci': VIRTIO_SCSI_PROPS, |
| 34 | 'virtio-blk-pci': VIRTIO_BLK_PROPS} |
| 35 | |
| 36 | VM_DEV_PARAMS = {'virtio-scsi-pci': ['-device', 'virtio-scsi-pci,id=scsi0'], |
| 37 | 'virtio-blk-pci': ['-device', |
| 38 | 'virtio-blk-pci,id=scsi0,drive=drive0', |
| 39 | '-drive', |
| 40 | 'driver=null-co,id=drive0,if=none']} |
| 41 | |
| 42 | |
Philippe Mathieu-Daudé | 2283b62 | 2021-09-27 18:14:33 +0200 | [diff] [blame] | 43 | class VirtioMaxSegSettingsCheck(QemuSystemTest): |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 44 | @staticmethod |
| 45 | def make_pattern(props): |
| 46 | pattern_items = ['{0} = \w+'.format(prop) for prop in props] |
| 47 | return '|'.join(pattern_items) |
| 48 | |
| 49 | def query_virtqueue(self, vm, dev_type_name): |
| 50 | query_ok = False |
| 51 | error = None |
| 52 | props = None |
| 53 | |
| 54 | output = vm.command('human-monitor-command', |
| 55 | command_line = 'info qtree') |
| 56 | props_list = DEV_TYPES[dev_type_name].values(); |
| 57 | pattern = self.make_pattern(props_list) |
| 58 | res = re.findall(pattern, output) |
| 59 | |
| 60 | if len(res) != len(props_list): |
| 61 | props_list = set(props_list) |
| 62 | res = set(res) |
| 63 | not_found = props_list.difference(res) |
| 64 | not_found = ', '.join(not_found) |
| 65 | error = '({0}): The following properties not found: {1}'\ |
| 66 | .format(dev_type_name, not_found) |
| 67 | else: |
| 68 | query_ok = True |
| 69 | props = dict() |
| 70 | for prop in res: |
| 71 | p = prop.split(' = ') |
| 72 | props[p[0]] = p[1] |
| 73 | return query_ok, props, error |
| 74 | |
| 75 | def check_mt(self, mt, dev_type_name): |
Philippe Mathieu-Daudé | e435f66 | 2020-01-29 22:23:34 +0100 | [diff] [blame] | 76 | mt['device'] = dev_type_name # Only for the debug() call. |
| 77 | logger = logging.getLogger('machine') |
| 78 | logger.debug(mt) |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 79 | with QEMUMachine(self.qemu_bin) as vm: |
| 80 | vm.set_machine(mt["name"]) |
Philippe Mathieu-Daudé | 77f50e8 | 2020-01-29 22:23:40 +0100 | [diff] [blame] | 81 | vm.add_args('-nodefaults') |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 82 | for s in VM_DEV_PARAMS[dev_type_name]: |
| 83 | vm.add_args(s) |
Philippe Mathieu-Daudé | 0400937 | 2020-01-29 22:23:33 +0100 | [diff] [blame] | 84 | try: |
| 85 | vm.launch() |
| 86 | query_ok, props, error = self.query_virtqueue(vm, dev_type_name) |
| 87 | except: |
| 88 | query_ok = False |
| 89 | error = sys.exc_info()[0] |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 90 | |
| 91 | if not query_ok: |
| 92 | self.fail('machine type {0}: {1}'.format(mt['name'], error)) |
| 93 | |
| 94 | for prop_name, prop_val in props.items(): |
| 95 | expected_val = mt[prop_name] |
| 96 | self.assertEqual(expected_val, prop_val) |
| 97 | |
| 98 | @staticmethod |
| 99 | def seg_max_adjust_enabled(mt): |
| 100 | # machine types >= 5.0 should have seg_max_adjust = true |
| 101 | # others seg_max_adjust = false |
| 102 | mt = mt.split("-") |
| 103 | |
| 104 | # machine types with one line name and name like pc-x.x |
| 105 | if len(mt) <= 2: |
| 106 | return False |
| 107 | |
| 108 | # machine types like pc-<chip_name>-x.x[.x] |
| 109 | ver = mt[2] |
| 110 | ver = ver.split("."); |
| 111 | |
| 112 | # versions >= 5.0 goes with seg_max_adjust enabled |
| 113 | major = int(ver[0]) |
| 114 | |
| 115 | if major >= 5: |
| 116 | return True |
| 117 | return False |
| 118 | |
Philippe Mathieu-Daudé | 2d6a6e2 | 2020-02-06 18:17:15 +0100 | [diff] [blame] | 119 | @skip("break multi-arch CI") |
Denis Plotnikov | cec0242 | 2019-12-20 17:09:05 +0300 | [diff] [blame] | 120 | def test_machine_types(self): |
| 121 | # collect all machine types except 'none', 'isapc', 'microvm' |
| 122 | with QEMUMachine(self.qemu_bin) as vm: |
| 123 | vm.launch() |
| 124 | machines = [m['name'] for m in vm.command('query-machines')] |
| 125 | vm.shutdown() |
| 126 | machines.remove('none') |
| 127 | machines.remove('isapc') |
| 128 | machines.remove('microvm') |
| 129 | |
| 130 | for dev_type in DEV_TYPES: |
| 131 | # create the list of machine types and their parameters. |
| 132 | mtypes = list() |
| 133 | for m in machines: |
| 134 | if self.seg_max_adjust_enabled(m): |
| 135 | enabled = 'true' |
| 136 | else: |
| 137 | enabled = 'false' |
| 138 | mtypes.append({'name': m, |
| 139 | DEV_TYPES[dev_type]['seg_max_adjust']: enabled}) |
| 140 | |
| 141 | # test each machine type for a device type |
| 142 | for mt in mtypes: |
| 143 | self.check_mt(mt, dev_type) |