diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2023-10-16 12:37:48 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2023-10-16 12:37:48 -0400 |
commit | 800485762e6564e04e2ab315132d477069562d91 (patch) | |
tree | 19ff602da72d056916ca091498584869c82d332e /scripts | |
parent | 9390f0fd3e30ac61e94ea2fc4a923d88ed486645 (diff) | |
parent | b6aed193e5ecca32bb07e062f58f0daca06e7009 (diff) | |
download | qemu-800485762e6564e04e2ab315132d477069562d91.zip qemu-800485762e6564e04e2ab315132d477069562d91.tar.gz qemu-800485762e6564e04e2ab315132d477069562d91.tar.bz2 |
Merge tag 'python-pull-request' of https://gitlab.com/jsnow/qemu into staging
Python Pullreq
Python PR:
- Use socketpair for all machine.py connections
- Support Python 3.12
- Switch iotests over to using raise-on-error QMP command interface
(Thank you very much, Vladimir!)
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmUpldkACgkQfe+BBqr8
# OQ4NtRAAnkEmXsECAxQ2ewvf3yK8PTFm4Oq5nqMIw+KB94ATrsGzk3z1rLvatSl3
# 6VLsV2+FWoOEyKrsfu5DIfbuo4d3TZTU7N2DIZpVpvO166K+fXbzp8skAg+n3BMC
# tWkSOcnsT6+8aqyxxyASdHvbbE7pvPw8OA3oIIstsYeZ5/HHpOWXNj1kjCsnL0lW
# 7y5h6UUKGmnCPdixyk042+AvKkT7GAKVjFnjUF5JHv0iR2KpQ+O9H7OEalqQT5w5
# eab4oMGuIYhzYe+MNpyybAB3Xd2pxhcppk+sl4dCE8qmMn7KRoTNw1iu+qhsNQfQ
# JILZoCPtYMhpef4X0ulH8PFBMweBptqOjo4lpz9QIdMWTf86IE0yIT9DCy3aSjpp
# ywwxhFKJS43gz4WHkEJlrY9PHwLsULaV/Cz6HKJAU6h9aFtcNdT4pkCOERnZ8X4C
# yHlNReTG5Dz1sYzKJ/k9LTjAaVDasumR8/yadaUCwalj5zexQ27qlIM6oc5wdIRQ
# up1VHi7odF5KHb6GeqdniuuEF6NBCYRAV5nz+dbd6exfKOaxYRrr48yh9SUm8QS6
# JCvMMFFAZCIrI/nkRVajbLi9L5O3fg5abtlzSzh9o4iyf8Rf/1gtKNxZRK1NZIjQ
# cTYBJXpMulNx7bM2CPNsPWGqCTAjAcu10svqTA8luGj4fqdTNyU=
# =02Bd
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 13 Oct 2023 15:09:13 EDT
# gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full]
# Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB
# Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E
* tag 'python-pull-request' of https://gitlab.com/jsnow/qemu: (25 commits)
python: use vm.cmd() instead of vm.qmp() where appropriate
scripts: add python_qmp_updater.py
tests/vm/basevm.py: use cmd() instead of qmp()
iotests.py: pause_job(): drop return value
iotests: drop some extra ** in qmp() call
iotests: drop some extra semicolons
iotests: refactor some common qmp result checks into generic pattern
iotests: add some missed checks of qmp result
iotests: QemuStorageDaemon: add cmd() method like in QEMUMachine.
python/machine.py: upgrade vm.cmd() method
python/qemu: rename command() to cmd()
python: rename QEMUMonitorProtocol.cmd() to cmd_raw()
scripts/cpu-x86-uarch-abi.py: use .command() instead of .cmd()
qmp_shell.py: _fill_completion() use .command() instead of .cmd()
python/qemu/qmp/legacy: cmd(): drop cmd_id unused argument
Python: Enable python3.12 support
configure: fix error message to say Python 3.8
python/qmp: remove Server.wait_closed() call for Python 3.12
Python/iotests: Add type hint for nbd module
python/machine: remove unused sock_dir argument
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/cpu-x86-uarch-abi.py | 8 | ||||
-rwxr-xr-x | scripts/device-crash-test | 8 | ||||
-rwxr-xr-x | scripts/python_qmp_updater.py | 136 | ||||
-rwxr-xr-x | scripts/render_block_graph.py | 8 |
4 files changed, 148 insertions, 12 deletions
diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py index 82ff075..f6baeef 100644 --- a/scripts/cpu-x86-uarch-abi.py +++ b/scripts/cpu-x86-uarch-abi.py @@ -85,7 +85,7 @@ skip = [ names = [] -for model in models["return"]: +for model in models: if "alias-of" in model: continue names.append(model["name"]) @@ -94,11 +94,11 @@ models = {} for name in sorted(names): cpu = shell.cmd("query-cpu-model-expansion", - { "type": "static", - "model": { "name": name }}) + { "type": "static", + "model": { "name": name }}) got = {} - for (feature, present) in cpu["return"]["model"]["props"].items(): + for (feature, present) in cpu["model"]["props"].items(): if present and feature not in skip: got[feature] = True diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 353aa57..da8b56e 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -269,14 +269,14 @@ def formatTestCase(t): def qomListTypeNames(vm, **kwargs): """Run qom-list-types QMP command, return type names""" - types = vm.command('qom-list-types', **kwargs) + types = vm.cmd('qom-list-types', **kwargs) return [t['name'] for t in types] def infoQDM(vm): """Parse 'info qdm' output""" args = {'command-line': 'info qdm'} - devhelp = vm.command('human-monitor-command', **args) + devhelp = vm.cmd('human-monitor-command', **args) for l in devhelp.split('\n'): l = l.strip() if l == '' or l.endswith(':'): @@ -304,9 +304,9 @@ class QemuBinaryInfo(object): # there's no way to query DeviceClass::user_creatable using QMP, # so use 'info qdm': self.no_user_devs = set([d['name'] for d in infoQDM(vm, ) if d['no-user']]) - self.machines = list(m['name'] for m in vm.command('query-machines')) + self.machines = list(m['name'] for m in vm.cmd('query-machines')) self.user_devs = self.alldevs.difference(self.no_user_devs) - self.kvm_available = vm.command('query-kvm')['enabled'] + self.kvm_available = vm.cmd('query-kvm')['enabled'] finally: vm.shutdown() diff --git a/scripts/python_qmp_updater.py b/scripts/python_qmp_updater.py new file mode 100755 index 0000000..494a169 --- /dev/null +++ b/scripts/python_qmp_updater.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# +# Intended usage: +# +# git grep -l '\.qmp(' | xargs ./scripts/python_qmp_updater.py +# + +import re +import sys +from typing import Optional + +start_reg = re.compile(r'^(?P<padding> *)(?P<res>\w+) = (?P<vm>.*).qmp\(', + flags=re.MULTILINE) + +success_reg_templ = re.sub('\n *', '', r""" + (\n*{padding}(?P<comment>\#.*$))? + \n*{padding} + ( + self.assert_qmp\({res},\ 'return',\ {{}}\) + | + assert\ {res}\['return'\]\ ==\ {{}} + | + assert\ {res}\ ==\ {{'return':\ {{}}}} + | + self.assertEqual\({res}\['return'\],\ {{}}\) + )""") + +some_check_templ = re.sub('\n *', '', r""" + (\n*{padding}(?P<comment>\#.*$))? + \s*self.assert_qmp\({res},""") + + +def tmatch(template: str, text: str, + padding: str, res: str) -> Optional[re.Match[str]]: + return re.match(template.format(padding=padding, res=res), text, + flags=re.MULTILINE) + + +def find_closing_brace(text: str, start: int) -> int: + """ + Having '(' at text[start] search for pairing ')' and return its index. + """ + assert text[start] == '(' + + height = 1 + + for i in range(start + 1, len(text)): + if text[i] == '(': + height += 1 + elif text[i] == ')': + height -= 1 + if height == 0: + return i + + raise ValueError + + +def update(text: str) -> str: + result = '' + + while True: + m = start_reg.search(text) + if m is None: + result += text + break + + result += text[:m.start()] + + args_ind = m.end() + args_end = find_closing_brace(text, args_ind - 1) + + all_args = text[args_ind:args_end].split(',', 1) + + name = all_args[0] + args = None if len(all_args) == 1 else all_args[1] + + unchanged_call = text[m.start():args_end+1] + text = text[args_end+1:] + + padding, res, vm = m.group('padding', 'res', 'vm') + + m = tmatch(success_reg_templ, text, padding, res) + + if m is None: + result += unchanged_call + + if ('query-' not in name and + 'x-debug-block-dirty-bitmap-sha256' not in name and + not tmatch(some_check_templ, text, padding, res)): + print(unchanged_call + text[:200] + '...\n\n') + + continue + + if m.group('comment'): + result += f'{padding}{m.group("comment")}\n' + + result += f'{padding}{vm}.cmd({name}' + + if args: + result += ',' + + if '\n' in args: + m_args = re.search('(?P<pad> *).*$', args) + assert m_args is not None + + cur_padding = len(m_args.group('pad')) + expected = len(f'{padding}{res} = {vm}.qmp(') + drop = len(f'{res} = ') + if cur_padding == expected - 1: + # tolerate this bad style + drop -= 1 + elif cur_padding < expected - 1: + # assume nothing to do + drop = 0 + + if drop: + args = re.sub('\n' + ' ' * drop, '\n', args) + + result += args + + result += ')' + + text = text[m.end():] + + return result + + +for fname in sys.argv[1:]: + print(fname) + with open(fname) as f: + t = f.read() + + t = update(t) + + with open(fname, 'w') as f: + f.write(t) diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index 8f731a5..3e1a2e3 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -43,13 +43,13 @@ def render_block_graph(qmp, filename, format='png'): representation in @format into "@filename.@format" ''' - bds_nodes = qmp.command('query-named-block-nodes') + bds_nodes = qmp.cmd('query-named-block-nodes') bds_nodes = {n['node-name']: n for n in bds_nodes} - job_nodes = qmp.command('query-block-jobs') + job_nodes = qmp.cmd('query-block-jobs') job_nodes = {n['device']: n for n in job_nodes} - block_graph = qmp.command('x-debug-query-block-graph') + block_graph = qmp.cmd('x-debug-query-block-graph') graph = Digraph(comment='Block Nodes Graph') graph.format = format @@ -94,7 +94,7 @@ class LibvirtGuest(): def __init__(self, name): self.name = name - def command(self, cmd): + def cmd(self, cmd): # only supports qmp commands without parameters m = {'execute': cmd} ar = ['virsh', 'qemu-monitor-command', self.name, json.dumps(m)] |