From e2f948a8b579c382065012c34aa7e46304ec8759 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 9 Aug 2021 11:00:59 +0200 Subject: python: qemu: add timer parameter for qmp.accept socket Also add a new _qmp_timer field to the QEMUMachine class. Let's change the default socket timeout to None, so that if a subclass needs to add a timer, it can be done by modifying this private field. At the same time, restore the timer to be 15 seconds in iotests.py, to give an upper bound to the QMP monitor test command execution. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Acked-by: John Snow Reviewed-by: Max Reitz Message-Id: <20210809090114.64834-2-eesposit@redhat.com> Signed-off-by: Hanna Reitz --- python/qemu/machine/machine.py | 7 +++++-- python/qemu/machine/qtest.py | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 971ed7e..14c4d17 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -97,7 +97,8 @@ class QEMUMachine: sock_dir: Optional[str] = None, drain_console: bool = False, console_log: Optional[str] = None, - log_dir: Optional[str] = None): + log_dir: Optional[str] = None, + qmp_timer: Optional[float] = None): ''' Initialize a QEMUMachine @@ -112,6 +113,7 @@ class QEMUMachine: @param drain_console: (optional) True to drain console socket to buffer @param console_log: (optional) path to console log file @param log_dir: where to create and keep log files + @param qmp_timer: (optional) default QMP socket timeout @note: Qemu process is not started until launch() is used. ''' # pylint: disable=too-many-arguments @@ -121,6 +123,7 @@ class QEMUMachine: self._binary = binary self._args = list(args) self._wrapper = wrapper + self._qmp_timer = qmp_timer self._name = name or "qemu-%d" % os.getpid() self._base_temp_dir = base_temp_dir @@ -343,7 +346,7 @@ class QEMUMachine: def _post_launch(self) -> None: if self._qmp_connection: - self._qmp.accept() + self._qmp.accept(self._qmp_timer) def _post_shutdown(self) -> None: """ diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py index d6d9c6a..592be26 100644 --- a/python/qemu/machine/qtest.py +++ b/python/qemu/machine/qtest.py @@ -115,7 +115,8 @@ class QEMUQtestMachine(QEMUMachine): name: Optional[str] = None, base_temp_dir: str = "/var/tmp", socket_scm_helper: Optional[str] = None, - sock_dir: Optional[str] = None): + sock_dir: Optional[str] = None, + qmp_timer: Optional[float] = None): # pylint: disable=too-many-arguments if name is None: @@ -124,7 +125,7 @@ class QEMUQtestMachine(QEMUMachine): sock_dir = base_temp_dir super().__init__(binary, args, name=name, base_temp_dir=base_temp_dir, socket_scm_helper=socket_scm_helper, - sock_dir=sock_dir) + sock_dir=sock_dir, qmp_timer=qmp_timer) self._qtest: Optional[QEMUQtestProtocol] = None self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock") -- cgit v1.1 From 22305c2a081b8b67e1181ebd821c076cc36fdcd2 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 9 Aug 2021 11:01:00 +0200 Subject: python: Reduce strictness of pylint's duplicate-code check Pylint prior to 2.8.3 (We pin at >= 2.8.0) includes function and method signatures as part of its duplicate checking algorithm. This check does not listen to pragmas, so the only way to disable it is to turn it off completely or increase the minimum duplicate lines so that it doesn't trigger for functions with long, multi-line signatures. When we decide to upgrade to pylint 2.8.3 or greater, we will be able to use 'ignore-signatures = true' to the config instead. I'd prefer not to keep us on the very bleeding edge of pylint if I can help it -- 2.8.3 came out only three days ago at time of writing. See: https://github.com/PyCQA/pylint/pull/4474 Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Acked-by: John Snow Reviewed-by: Max Reitz Message-Id: <20210809090114.64834-3-eesposit@redhat.com> Signed-off-by: Hanna Reitz --- python/setup.cfg | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'python') diff --git a/python/setup.cfg b/python/setup.cfg index 14bab90..83909c1 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -105,6 +105,11 @@ good-names=i, # Ignore imports when computing similarities. ignore-imports=yes +# Minimum lines number of a similarity. +# TODO: Remove after we opt in to Pylint 2.8.3. See commit msg. +min-similarity-lines=6 + + [isort] force_grid_wrap=4 force_sort_within_sections=True -- cgit v1.1 From 804f7695e535da902c1c5159cf53756f182aceb4 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 9 Aug 2021 11:01:01 +0200 Subject: python: qemu: pass the wrapper field from QEMUQtestmachine to QEMUMachine Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: John Snow Reviewed-by: Max Reitz Acked-by: John Snow Message-Id: <20210809090114.64834-4-eesposit@redhat.com> Signed-off-by: Hanna Reitz --- python/qemu/machine/qtest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py index 592be26..395cc8f 100644 --- a/python/qemu/machine/qtest.py +++ b/python/qemu/machine/qtest.py @@ -112,6 +112,7 @@ class QEMUQtestMachine(QEMUMachine): def __init__(self, binary: str, args: Sequence[str] = (), + wrapper: Sequence[str] = (), name: Optional[str] = None, base_temp_dir: str = "/var/tmp", socket_scm_helper: Optional[str] = None, @@ -123,7 +124,8 @@ class QEMUQtestMachine(QEMUMachine): name = "qemu-%d" % os.getpid() if sock_dir is None: sock_dir = base_temp_dir - super().__init__(binary, args, name=name, base_temp_dir=base_temp_dir, + super().__init__(binary, args, wrapper=wrapper, name=name, + base_temp_dir=base_temp_dir, socket_scm_helper=socket_scm_helper, sock_dir=sock_dir, qmp_timer=qmp_timer) self._qtest: Optional[QEMUQtestProtocol] = None -- cgit v1.1 From eb7a91d07ad831aeb372ff21b10e7a515ca786ec Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 9 Aug 2021 11:01:13 +0200 Subject: qemu-iotests: add option to show qemu binary logs on stdout Using the flag -p, allow the qemu binary to print to stdout. Also create the common function _close_qemu_log_file() to avoid accessing machine.py private fields directly and have duplicate code. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz Message-Id: <20210809090114.64834-16-eesposit@redhat.com> Signed-off-by: Hanna Reitz --- python/qemu/machine/machine.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 14c4d17..8b93581 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -348,6 +348,11 @@ class QEMUMachine: if self._qmp_connection: self._qmp.accept(self._qmp_timer) + def _close_qemu_log_file(self) -> None: + if self._qemu_log_file is not None: + self._qemu_log_file.close() + self._qemu_log_file = None + def _post_shutdown(self) -> None: """ Called to cleanup the VM instance after the process has exited. @@ -360,9 +365,7 @@ class QEMUMachine: self._qmp.close() self._qmp_connection = None - if self._qemu_log_file is not None: - self._qemu_log_file.close() - self._qemu_log_file = None + self._close_qemu_log_file() self._load_io_log() -- cgit v1.1 From c7daa57eb57e24a9427f636906f4faf2cfcbe943 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 24 Aug 2021 11:38:45 +0300 Subject: python/qemu/machine.py: refactor _qemu_args() - use shorter construction - don't create new dict if not needed - drop extra unpacking key-val arguments - drop extra default values Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz Reviewed-by: John Snow Message-Id: <20210824083856.17408-24-vsementsov@virtuozzo.com> Signed-off-by: Hanna Reitz --- python/qemu/machine/machine.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'python') diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 8b93581..3fde73c 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -570,14 +570,12 @@ class QEMUMachine: return self._qmp_connection @classmethod - def _qmp_args(cls, _conv_keys: bool = True, **args: Any) -> Dict[str, Any]: - qmp_args = dict() - for key, value in args.items(): - if _conv_keys: - qmp_args[key.replace('_', '-')] = value - else: - qmp_args[key] = value - return qmp_args + def _qmp_args(cls, conv_keys: bool, + args: Dict[str, Any]) -> Dict[str, object]: + if conv_keys: + return {k.replace('_', '-'): v for k, v in args.items()} + + return args def qmp(self, cmd: str, conv_keys: bool = True, @@ -585,7 +583,7 @@ class QEMUMachine: """ Invoke a QMP command and return the response dict """ - qmp_args = self._qmp_args(conv_keys, **args) + qmp_args = self._qmp_args(conv_keys, args) return self._qmp.cmd(cmd, args=qmp_args) def command(self, cmd: str, @@ -596,7 +594,7 @@ class QEMUMachine: On success return the response dict. On failure raise an exception. """ - qmp_args = self._qmp_args(conv_keys, **args) + qmp_args = self._qmp_args(conv_keys, args) return self._qmp.command(cmd, **qmp_args) def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]: -- cgit v1.1 From 3f3c9b4c9dcb462b2330e50cf81b9703288884ec Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 24 Aug 2021 11:38:46 +0300 Subject: python/qemu/machine: QEMUMachine: improve qmp() method We often call qmp() with unpacking dict, like qmp('foo', **{...}). mypy don't really like it, it thinks that passed unpacked dict is a positional argument and complains that it type should be bool (because second argument of qmp() is conv_keys: bool). Allow passing dict directly, simplifying interface, and giving a way to satisfy mypy. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz Reviewed-by: John Snow Message-Id: <20210824083856.17408-25-vsementsov@virtuozzo.com> Signed-off-by: Hanna Reitz --- python/qemu/machine/machine.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 3fde73c..6ec1857 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -578,11 +578,21 @@ class QEMUMachine: return args def qmp(self, cmd: str, - conv_keys: bool = True, + args_dict: Optional[Dict[str, object]] = None, + conv_keys: Optional[bool] = None, **args: Any) -> QMPMessage: """ Invoke a QMP command and return the response dict """ + if args_dict is not None: + assert not args + assert conv_keys is None + args = args_dict + conv_keys = False + + if conv_keys is None: + conv_keys = True + qmp_args = self._qmp_args(conv_keys, args) return self._qmp.cmd(cmd, args=qmp_args) -- cgit v1.1 From 15c3b863ee6393fa326c142b725cff88bb3e719e Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Tue, 24 Aug 2021 11:38:47 +0300 Subject: python:QEMUMachine: template typing for self returning methods mypy thinks that return value of these methods in subclusses is QEMUMachine, which is wrong. So, make typing smarter. Suggested-by: John Snow Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20210824083856.17408-26-vsementsov@virtuozzo.com> Reviewed-by: Hanna Reitz Signed-off-by: Hanna Reitz --- python/qemu/machine/machine.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 6ec1857..a7081b1 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -36,6 +36,7 @@ from typing import ( Sequence, Tuple, Type, + TypeVar, ) from qemu.qmp import ( # pylint: disable=import-error @@ -73,6 +74,9 @@ class AbnormalShutdown(QEMUMachineError): """ +_T = TypeVar('_T', bound='QEMUMachine') + + class QEMUMachine: """ A QEMU VM. @@ -169,7 +173,7 @@ class QEMUMachine: self._remove_files: List[str] = [] self._user_killed = False - def __enter__(self) -> 'QEMUMachine': + def __enter__(self: _T) -> _T: return self def __exit__(self, @@ -185,8 +189,8 @@ class QEMUMachine: self._args.append('-monitor') self._args.append('null') - def add_fd(self, fd: int, fdset: int, - opaque: str, opts: str = '') -> 'QEMUMachine': + def add_fd(self: _T, fd: int, fdset: int, + opaque: str, opts: str = '') -> _T: """ Pass a file descriptor to the VM """ -- cgit v1.1