From e0e925a61141552bca7277d06516ad78258423da Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 17 Feb 2020 18:02:42 +0300 Subject: python/qemu/machine: add kill() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add method to hard-kill vm, without any quit commands. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Andrey Shinkevich Message-Id: <20200217150246.29180-19-vsementsov@virtuozzo.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index b9a98e2..d2f531f 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -342,7 +342,7 @@ class QEMUMachine(object): self._load_io_log() self._post_shutdown() - def shutdown(self, has_quit=False): + def shutdown(self, has_quit=False, hard=False): """ Terminate the VM and clean up """ @@ -354,7 +354,9 @@ class QEMUMachine(object): self._console_socket = None if self.is_running(): - if self._qmp: + if hard: + self._popen.kill() + elif self._qmp: try: if not has_quit: self._qmp.cmd('quit') @@ -368,7 +370,8 @@ class QEMUMachine(object): self._post_shutdown() exitcode = self.exitcode() - if exitcode is not None and exitcode < 0: + if exitcode is not None and exitcode < 0 and \ + not (exitcode == -9 and hard): msg = 'qemu received signal %i: %s' if self._qemu_full_args: command = ' '.join(self._qemu_full_args) @@ -378,6 +381,9 @@ class QEMUMachine(object): self._launched = False + def kill(self): + self.shutdown(hard=True) + def set_qmp_monitor(self, enabled=True): """ Set the QMP monitor. -- cgit v1.1 From 053774bdecf60c0500d66a05e02e48ff24ab23cf Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:52 -0400 Subject: python/qemu/machine: remove logging configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3.5 and above do not print a warning when logging is not configured. As a library, it's best practice to leave logging configuration to the client executable. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-22-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'python') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index d2f531f..41554de 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -119,9 +119,6 @@ class QEMUMachine(object): self._console_socket = None self._remove_files = [] - # just in case logging wasn't configured by the main script: - logging.basicConfig() - def __enter__(self): return self -- cgit v1.1 From 9b8ccd6d5b81f10436764bf7e334e087f3918d12 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 28 May 2020 18:21:28 -0400 Subject: python/qemu: delint and add pylintrc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bring our these files up to speed with pylint 2.5.0. Add a pylintrc file to formalize which pylint subset we are targeting. The similarity ignore is there to suppress similarity reports across imports, which for typing constants, are going to trigger this report erroneously. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200528222129.23826-4-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 6 +++--- python/qemu/pylintrc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ python/qemu/qtest.py | 42 +++++++++++++++++++++++------------- 3 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 python/qemu/pylintrc (limited to 'python') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 41554de..8e4ecd1 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -58,7 +58,7 @@ class MonitorResponseError(qmp.QMPError): self.reply = reply -class QEMUMachine(object): +class QEMUMachine: """ A QEMU VM @@ -239,7 +239,7 @@ class QEMUMachine(object): 'chardev=mon,mode=control']) if self._machine is not None: args.extend(['-machine', self._machine]) - for i in range(self._console_index): + for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: self._console_address = os.path.join(self._sock_dir, @@ -374,7 +374,7 @@ class QEMUMachine(object): command = ' '.join(self._qemu_full_args) else: command = '' - LOG.warning(msg, -exitcode, command) + LOG.warning(msg, -int(exitcode), command) self._launched = False diff --git a/python/qemu/pylintrc b/python/qemu/pylintrc new file mode 100644 index 0000000..5d6ae73 --- /dev/null +++ b/python/qemu/pylintrc @@ -0,0 +1,58 @@ +[MASTER] + +[MESSAGES CONTROL] + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=too-many-arguments, + too-many-instance-attributes, + too-many-public-methods, + +[REPORTS] + +[REFACTORING] + +[MISCELLANEOUS] + +[LOGGING] + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _, + fd, + +[VARIABLES] + +[STRING] + +[SPELLING] + +[FORMAT] + +[SIMILARITIES] + +# Ignore imports when computing similarities. +ignore-imports=yes + +[TYPECHECK] + +[CLASSES] + +[IMPORTS] + +[DESIGN] + +[EXCEPTIONS] diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index d24ad04..53d814c 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -1,5 +1,11 @@ -# QEMU qtest library -# +""" +QEMU qtest library + +qtest offers the QEMUQtestProtocol and QEMUQTestMachine classes, which +offer a connection to QEMU's qtest protocol socket, and a qtest-enabled +subclass of QEMUMachine, respectively. +""" + # Copyright (C) 2015 Red Hat Inc. # # Authors: @@ -17,19 +23,21 @@ import os from .machine import QEMUMachine -class QEMUQtestProtocol(object): - def __init__(self, address, server=False): - """ - Create a QEMUQtestProtocol object. +class QEMUQtestProtocol: + """ + QEMUQtestProtocol implements a connection to a qtest socket. - @param address: QEMU address, can be either a unix socket path (string) - or a tuple in the form ( address, port ) for a TCP - connection - @param server: server mode, listens on the socket (bool) - @raise socket.error on socket connection errors - @note No connection is established, this is done by the connect() or - accept() methods - """ + :param address: QEMU address, can be either a unix socket path (string) + or a tuple in the form ( address, port ) for a TCP + connection + :param server: server mode, listens on the socket (bool) + :raise socket.error: on socket connection errors + + .. note:: + No conection is estabalished by __init__(), this is done + by the connect() or accept() methods. + """ + def __init__(self, address, server=False): self._address = address self._sock = self._get_sock() self._sockfile = None @@ -73,15 +81,19 @@ class QEMUQtestProtocol(object): return resp def close(self): + """Close this socket.""" self._sock.close() self._sockfile.close() def settimeout(self, timeout): + """Set a timeout, in seconds.""" self._sock.settimeout(timeout) class QEMUQtestMachine(QEMUMachine): - '''A QEMU VM''' + """ + A QEMU VM, with a qtest socket available. + """ def __init__(self, binary, args=None, name=None, test_dir="/var/tmp", socket_scm_helper=None, sock_dir=None): -- cgit v1.1 From 8dfac2edb2146d87b25543c70e25723f3d4dbd60 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 28 May 2020 18:21:29 -0400 Subject: python/qemu: delint; add flake8 config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mostly, ignore the "no bare except" rule, because flake8 is not contextual and cannot determine if we re-raise. Pylint can, though, so always prefer pylint for that. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200528222129.23826-5-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/.flake8 | 2 ++ python/qemu/accel.py | 9 ++++++--- python/qemu/machine.py | 13 +++++++++---- python/qemu/qmp.py | 4 ++-- 4 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 python/qemu/.flake8 (limited to 'python') diff --git a/python/qemu/.flake8 b/python/qemu/.flake8 new file mode 100644 index 0000000..45d8146 --- /dev/null +++ b/python/qemu/.flake8 @@ -0,0 +1,2 @@ +[flake8] +extend-ignore = E722 # Pylint handles this, but smarter. \ No newline at end of file diff --git a/python/qemu/accel.py b/python/qemu/accel.py index 36ae857..7fabe62 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -23,11 +23,12 @@ LOG = logging.getLogger(__name__) # Mapping host architecture to any additional architectures it can # support which often includes its 32 bit cousin. ADDITIONAL_ARCHES = { - "x86_64" : "i386", - "aarch64" : "armhf", - "ppc64le" : "ppc64", + "x86_64": "i386", + "aarch64": "armhf", + "ppc64le": "ppc64", } + def list_accel(qemu_bin): """ List accelerators enabled in the QEMU binary. @@ -47,6 +48,7 @@ def list_accel(qemu_bin): # Skip the first line which is the header. return [acc.strip() for acc in out.splitlines()[1:]] + def kvm_available(target_arch=None, qemu_bin=None): """ Check if KVM is available using the following heuristic: @@ -69,6 +71,7 @@ def kvm_available(target_arch=None, qemu_bin=None): return False return True + def tcg_available(qemu_bin): """ Check if TCG is available. diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 8e4ecd1..187790c 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -29,6 +29,7 @@ from . import qmp LOG = logging.getLogger(__name__) + class QEMUMachineError(Exception): """ Exception called when an error in QEMUMachine happens. @@ -62,7 +63,8 @@ class QEMUMachine: """ A QEMU VM - Use this object as a context manager to ensure the QEMU process terminates:: + Use this object as a context manager to ensure + the QEMU process terminates:: with VM(binary) as vm: ... @@ -185,8 +187,10 @@ class QEMUMachine: fd_param.append(str(fd)) devnull = open(os.path.devnull, 'rb') - proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, close_fds=False) + proc = subprocess.Popen( + fd_param, stdin=devnull, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, close_fds=False + ) output = proc.communicate()[0] if output: LOG.debug(output) @@ -485,7 +489,8 @@ class QEMUMachine: def events_wait(self, events, timeout=60.0): """ - events_wait waits for and returns a named event from QMP with a timeout. + events_wait waits for and returns a named event + from QMP with a timeout. events: a sequence of (name, match_criteria) tuples. The match criteria are optional and may be None. diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index d6c9b2f..6ae7693 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -168,8 +168,8 @@ class QEMUMonitorProtocol: @param timeout: timeout in seconds (nonnegative float number, or None). The value passed will set the behavior of the - underneath QMP socket as described in [1]. Default value - is set to 15.0. + underneath QMP socket as described in [1]. + Default value is set to 15.0. @return QMP greeting dict @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received -- cgit v1.1 From 3797dbcbb7bf1dffdd74ef84b5b21ed9c825e171 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:42 -0400 Subject: python/qemu: remove Python2 style super() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the Python3 style instead. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-12-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 2 +- python/qemu/qtest.py | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'python') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 187790c..95a20a1 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -55,7 +55,7 @@ class MonitorResponseError(qmp.QMPError): desc = reply["error"]["desc"] except KeyError: desc = reply - super(MonitorResponseError, self).__init__(desc) + super().__init__(desc) self.reply = reply diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index 53d814c..7943487 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -101,29 +101,28 @@ class QEMUQtestMachine(QEMUMachine): name = "qemu-%d" % os.getpid() if sock_dir is None: sock_dir = test_dir - super(QEMUQtestMachine, - self).__init__(binary, args, name=name, test_dir=test_dir, - socket_scm_helper=socket_scm_helper, - sock_dir=sock_dir) + super().__init__(binary, args, name=name, test_dir=test_dir, + socket_scm_helper=socket_scm_helper, + sock_dir=sock_dir) self._qtest = None self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock") def _base_args(self): - args = super(QEMUQtestMachine, self)._base_args() + args = super()._base_args() args.extend(['-qtest', 'unix:path=' + self._qtest_path, '-accel', 'qtest']) return args def _pre_launch(self): - super(QEMUQtestMachine, self)._pre_launch() + super()._pre_launch() self._qtest = QEMUQtestProtocol(self._qtest_path, server=True) def _post_launch(self): - super(QEMUQtestMachine, self)._post_launch() + super()._post_launch() self._qtest.accept() def _post_shutdown(self): - super(QEMUQtestMachine, self)._post_shutdown() + super()._post_shutdown() self._remove_if_exists(self._qtest_path) def qtest(self, cmd): -- cgit v1.1 From 0add048fbd9992151e4c592977df9cff8558ca60 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:43 -0400 Subject: python/qemu: fix socket.makefile() typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: A bug in typeshed (https://github.com/python/typeshed/issues/3977) misinterprets the type of makefile(). Work around this by explicitly stating that we are opening a text-mode file. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-13-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 10 +++++++--- python/qemu/qtest.py | 12 ++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'python') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 6ae7693..73d4905 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -11,6 +11,10 @@ import json import errno import socket import logging +from typing import ( + Optional, + TextIO, +) class QMPError(Exception): @@ -61,7 +65,7 @@ class QEMUMonitorProtocol: self.__events = [] self.__address = address self.__sock = self.__get_sock() - self.__sockfile = None + self.__sockfile: Optional[TextIO] = None self._nickname = nickname if self._nickname: self.logger = logging.getLogger('QMP').getChild(self._nickname) @@ -157,7 +161,7 @@ class QEMUMonitorProtocol: @raise QMPCapabilitiesError if fails to negotiate capabilities """ self.__sock.connect(self.__address) - self.__sockfile = self.__sock.makefile() + self.__sockfile = self.__sock.makefile(mode='r') if negotiate: return self.__negotiate_capabilities() return None @@ -180,7 +184,7 @@ class QEMUMonitorProtocol: """ self.__sock.settimeout(timeout) self.__sock, _ = self.__sock.accept() - self.__sockfile = self.__sock.makefile() + self.__sockfile = self.__sock.makefile(mode='r') return self.__negotiate_capabilities() def cmd_obj(self, qmp_cmd): diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index 7943487..4c88590 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -19,6 +19,7 @@ subclass of QEMUMachine, respectively. import socket import os +from typing import Optional, TextIO from .machine import QEMUMachine @@ -40,7 +41,7 @@ class QEMUQtestProtocol: def __init__(self, address, server=False): self._address = address self._sock = self._get_sock() - self._sockfile = None + self._sockfile: Optional[TextIO] = None if server: self._sock.bind(self._address) self._sock.listen(1) @@ -59,7 +60,7 @@ class QEMUQtestProtocol: @raise socket.error on socket connection errors """ self._sock.connect(self._address) - self._sockfile = self._sock.makefile() + self._sockfile = self._sock.makefile(mode='r') def accept(self): """ @@ -68,7 +69,7 @@ class QEMUQtestProtocol: @raise socket.error on socket connection errors """ self._sock, _ = self._sock.accept() - self._sockfile = self._sock.makefile() + self._sockfile = self._sock.makefile(mode='r') def cmd(self, qtest_cmd): """ @@ -76,6 +77,7 @@ class QEMUQtestProtocol: @param qtest_cmd: qtest command text to be sent """ + assert self._sockfile is not None self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) resp = self._sockfile.readline() return resp @@ -83,7 +85,9 @@ class QEMUQtestProtocol: def close(self): """Close this socket.""" self._sock.close() - self._sockfile.close() + if self._sockfile: + self._sockfile.close() + self._sockfile = None def settimeout(self, timeout): """Set a timeout, in seconds.""" -- cgit v1.1 From 1dda0404d8afeb0ed45fbeae85e380e1ff57da35 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:44 -0400 Subject: python/qemu: Adjust traceback typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mypy considers it incorrect to use `bool` to statically return false, because it will assume that it could conceivably return True, and gives different analysis in that case. Use a None return to achieve the same effect, but make mypy happy. Note: Pylint considers function signatures as code that might trip the duplicate-code checker. I'd rather not disable this as it does not trigger often in practice, so I'm disabling it as a one-off and filed a change request; see https://github.com/PyCQA/pylint/issues/3619 Signed-off-by: John Snow Acked-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-14-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 8 ++++++-- python/qemu/qmp.py | 10 ++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'python') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 95a20a1..041c615 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -24,6 +24,8 @@ import subprocess import shutil import socket import tempfile +from typing import Optional, Type +from types import TracebackType from . import qmp @@ -124,9 +126,11 @@ class QEMUMachine: def __enter__(self): return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType]) -> None: self.shutdown() - return False def add_monitor_null(self): """ diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 73d4905..b91c9d5 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -14,7 +14,9 @@ import logging from typing import ( Optional, TextIO, + Type, ) +from types import TracebackType class QMPError(Exception): @@ -146,10 +148,14 @@ class QEMUMonitorProtocol: # Implement context manager enter function. return self - def __exit__(self, exc_type, exc_value, exc_traceback): + def __exit__(self, + # pylint: disable=duplicate-code + # see https://github.com/PyCQA/pylint/issues/3619 + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType]) -> None: # Implement context manager exit function. self.close() - return False def connect(self, negotiate=True): """ -- cgit v1.1 From 7af67d694e289ab116c7abeca8a5bd752fbd46d7 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:45 -0400 Subject: python/qemu/qmp: use True/False for non/blocking modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The type system doesn't want integers. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-15-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index b91c9d5..a634c4e 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -120,14 +120,14 @@ class QEMUMonitorProtocol: """ # Check for new events regardless and pull them into the cache: - self.__sock.setblocking(0) + self.__sock.setblocking(False) try: self.__json_read() except OSError as err: if err.errno == errno.EAGAIN: # No data available pass - self.__sock.setblocking(1) + self.__sock.setblocking(True) # Wait for new events, if needed. # if wait is 0.0, this means "no wait" and is also implicitly false. -- cgit v1.1 From de210ec53c842fa67aa10110a7a351d64f91c487 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:53:51 -0400 Subject: python/qemu/qmp: assert sockfile is not None MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In truth, if you don't do this, you'll just get a TypeError exception. Now, you'll get an AssertionError. Is this tangibly better? No. Does mypy complain less? Yes. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-21-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 1 + 1 file changed, 1 insertion(+) (limited to 'python') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index a634c4e..e64b6b5 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -94,6 +94,7 @@ class QEMUMonitorProtocol: raise QMPCapabilitiesError def __json_read(self, only_event=False): + assert self.__sockfile is not None while True: data = self.__sockfile.readline() if not data: -- cgit v1.1 From c95dddce4910c9cd5315b942180b03ca4e48a6a6 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 14 May 2020 01:54:00 -0400 Subject: python/qemu/qtest: Check before accessing _qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can be None; so add assertions or exceptions where appropriate to guard the access accordingly. Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200514055403.18902-30-jsnow@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qtest.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py index 4c88590..888c8bd 100644 --- a/python/qemu/qtest.py +++ b/python/qemu/qtest.py @@ -121,7 +121,8 @@ class QEMUQtestMachine(QEMUMachine): super()._pre_launch() self._qtest = QEMUQtestProtocol(self._qtest_path, server=True) - def _post_launch(self): + def _post_launch(self) -> None: + assert self._qtest is not None super()._post_launch() self._qtest.accept() @@ -129,6 +130,13 @@ class QEMUQtestMachine(QEMUMachine): super()._post_shutdown() self._remove_if_exists(self._qtest_path) - def qtest(self, cmd): - '''Send a qtest command to guest''' + def qtest(self, cmd: str) -> str: + """ + Send a qtest command to the guest. + + :param cmd: qtest command to send + :return: qtest server response + """ + if self._qtest is None: + raise RuntimeError("qtest socket not available") return self._qtest.cmd(cmd) -- cgit v1.1