From 10e163c0395f5c9460ec2f2fe7947a1d056cda30 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 27 Dec 2019 10:40:57 -0300 Subject: python/qemu: qmp: Replace socket.error with OSError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The socket.error is deprecated from Python 3.3, instead it is made a link to OSError. This change replaces the occurences of socket.error with OSError. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: John Snow Message-Id: <20191227134101.244496-2-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 5c8cf6a..8c6c984 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -47,7 +47,7 @@ class QEMUMonitorProtocol(object): 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 + @raise OSError on socket connection errors @note No connection is established, this is done by the connect() or accept() methods """ @@ -107,8 +107,8 @@ class QEMUMonitorProtocol(object): self.__sock.setblocking(0) try: self.__json_read() - except socket.error as err: - if err[0] == errno.EAGAIN: + except OSError as err: + if err.errno == errno.EAGAIN: # No data available pass self.__sock.setblocking(1) @@ -133,7 +133,7 @@ class QEMUMonitorProtocol(object): Connect to the QMP Monitor and perform capabilities negotiation. @return QMP greeting dict - @raise socket.error on socket connection errors + @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities """ @@ -147,7 +147,7 @@ class QEMUMonitorProtocol(object): Await connection from QMP Monitor and perform capabilities negotiation. @return QMP greeting dict - @raise socket.error on socket connection errors + @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities """ @@ -167,10 +167,10 @@ class QEMUMonitorProtocol(object): self.logger.debug(">>> %s", qmp_cmd) try: self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8')) - except socket.error as err: - if err[0] == errno.EPIPE: + except OSError as err: + if err.errno == errno.EPIPE: return - raise socket.error(err) + raise err resp = self.__json_read() self.logger.debug("<<< %s", resp) return resp -- cgit v1.1 From a0a261e47252f2b7b44cbb0999cdafeb6b01bdbb Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 27 Dec 2019 10:40:58 -0300 Subject: python/qemu: Delint the qmp module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This clean up the pylint-3 report on qmp: ************* Module qemu.qmp python/qemu/qmp.py:1:0: C0111: Missing module docstring (missing-docstring) python/qemu/qmp.py:17:0: C0111: Missing class docstring (missing-docstring) python/qemu/qmp.py:21:0: C0111: Missing class docstring (missing-docstring) python/qemu/qmp.py:25:0: C0111: Missing class docstring (missing-docstring) python/qemu/qmp.py:29:0: C0111: Missing class docstring (missing-docstring) python/qemu/qmp.py:33:0: C0111: Missing class docstring (missing-docstring) python/qemu/qmp.py:33:0: R0205: Class 'QEMUMonitorProtocol' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance) python/qemu/qmp.py:80:4: R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements) python/qemu/qmp.py:131:4: R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements) python/qemu/qmp.py:159:4: R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements) python/qemu/qmp.py:245:4: C0111: Missing method docstring (missing-docstring) python/qemu/qmp.py:249:4: C0111: Missing method docstring (missing-docstring) python/qemu/qmp.py:252:4: C0111: Missing method docstring (missing-docstring) python/qemu/qmp.py:255:4: C0111: Missing method docstring (missing-docstring) Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20191227134101.244496-3-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 8c6c984..f4e04a6 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -1,5 +1,4 @@ -# QEMU Monitor Protocol Python class -# +""" QEMU Monitor Protocol Python class """ # Copyright (C) 2009, 2010 Red Hat Inc. # # Authors: @@ -15,22 +14,34 @@ import logging class QMPError(Exception): - pass + """ + QMP base exception + """ class QMPConnectError(QMPError): - pass + """ + QMP connection exception + """ class QMPCapabilitiesError(QMPError): - pass + """ + QMP negotiate capabilities exception + """ class QMPTimeoutError(QMPError): - pass + """ + QMP timeout exception + """ -class QEMUMonitorProtocol(object): +class QEMUMonitorProtocol: + """ + Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then + allow to handle commands and events. + """ #: Logger object for debugging messages logger = logging.getLogger('QMP') @@ -81,7 +92,7 @@ class QEMUMonitorProtocol(object): while True: data = self.__sockfile.readline() if not data: - return + return None resp = json.loads(data) if 'event' in resp: self.logger.debug("<<< %s", resp) @@ -132,7 +143,7 @@ class QEMUMonitorProtocol(object): """ Connect to the QMP Monitor and perform capabilities negotiation. - @return QMP greeting dict + @return QMP greeting dict, or None if negotiate is false @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities @@ -141,6 +152,7 @@ class QEMUMonitorProtocol(object): self.__sockfile = self.__sock.makefile() if negotiate: return self.__negotiate_capabilities() + return None def accept(self): """ @@ -169,7 +181,7 @@ class QEMUMonitorProtocol(object): self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8')) except OSError as err: if err.errno == errno.EPIPE: - return + return None raise err resp = self.__json_read() self.logger.debug("<<< %s", resp) @@ -243,14 +255,33 @@ class QEMUMonitorProtocol(object): self.__events = [] def close(self): + """ + Close the socket and socket file. + """ self.__sock.close() self.__sockfile.close() def settimeout(self, timeout): + """ + Set the socket timeout. + + @param timeout (float): timeout in seconds, or None. + @note This is a wrap around socket.settimeout + """ self.__sock.settimeout(timeout) def get_sock_fd(self): + """ + Get the socket file descriptor. + + @return The file descriptor number. + """ return self.__sock.fileno() def is_scm_available(self): + """ + Check if the socket allows for SCM_RIGHTS. + + @return True if SCM_RIGHTS is available, otherwise False. + """ return self.__sock.family == socket.AF_UNIX -- cgit v1.1 From 54aafc2fc65231871e744308705c4aa6d283a22d Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Tue, 4 Feb 2020 11:11:09 -0300 Subject: python/qemu: qmp: Make accept()'s timeout configurable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the timeout of QEMUMonitorProtocol.accept() is hard-coded to 15.0 seconds. This added the parameter `timeout` so the value can be configured by the user. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: John Snow Message-Id: <20200204141111.3207-4-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index f4e04a6..0e07d80 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -154,16 +154,23 @@ class QEMUMonitorProtocol: return self.__negotiate_capabilities() return None - def accept(self): + def accept(self, timeout=15.0): """ Await connection from QMP Monitor and perform capabilities negotiation. + @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. @return QMP greeting dict @raise OSError on socket connection errors @raise QMPConnectError if the greeting is not received @raise QMPCapabilitiesError if fails to negotiate capabilities + + [1] + https://docs.python.org/3/library/socket.html#socket.socket.settimeout """ - self.__sock.settimeout(15) + self.__sock.settimeout(timeout) self.__sock, _ = self.__sock.accept() self.__sockfile = self.__sock.makefile() return self.__negotiate_capabilities() -- cgit v1.1 From 07608e807d4e7bd2daa7fe154bd9dc2235c1a323 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Tue, 4 Feb 2020 11:11:10 -0300 Subject: python/qemu: qmp: Make QEMUMonitorProtocol a context manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implement the __enter__ and __exit__ functions on QEMUMonitorProtocol class so that it can be used on 'with' statement and the resources will be free up on block end: with QEMUMonitorProtocol(socket_path) as qmp: qmp.connect() qmp.command('query-status') Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: John Snow Message-Id: <20200204141111.3207-5-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 0e07d80..486a566 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -139,6 +139,15 @@ class QEMUMonitorProtocol: raise QMPConnectError("Error while reading from socket") self.__sock.settimeout(None) + def __enter__(self): + # Implement context manager enter function. + return self + + def __exit__(self, exc_type, exc_value, exc_traceback): + # Implement context manager exit function. + self.close() + return False + def connect(self, negotiate=True): """ Connect to the QMP Monitor and perform capabilities negotiation. @@ -265,8 +274,10 @@ class QEMUMonitorProtocol: """ Close the socket and socket file. """ - self.__sock.close() - self.__sockfile.close() + if self.__sock: + self.__sock.close() + if self.__sockfile: + self.__sockfile.close() def settimeout(self, timeout): """ -- cgit v1.1 From 50d189c97ab8ed3de80d0ed22a867e1d5361fd02 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 27 Dec 2019 10:41:01 -0300 Subject: python/qemu: qmp: Remove unnused attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `error` and `timeout` attributes in QEMUMonitorProtocol are not used, so this delete them. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20191227134101.244496-6-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 486a566..4b9a362 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -45,10 +45,6 @@ class QEMUMonitorProtocol: #: Logger object for debugging messages logger = logging.getLogger('QMP') - #: Socket's error class - error = socket.error - #: Socket's timeout - timeout = socket.timeout def __init__(self, address, server=False): """ -- cgit v1.1 From 51aa9d127d4ecaaaf6dfa10da130e3974b0e5286 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Wed, 5 Feb 2020 15:32:46 -0500 Subject: python/qemu: accel: Fix kvm_available() on ppc64le MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ppc64le, the accel.kvm_available() check may wrongly return False because the host arch (as returned by os.uname[4]) and the target arch (ppc64) mismatch. In order to solve this it is added an ppc64le -> ppc64 mapping which is used as an fallback verification. Fixes: 53a049d7d78e5ccf6d4c0d7 Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200205203250.30526-5-wainersm@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/accel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'python/qemu') diff --git a/python/qemu/accel.py b/python/qemu/accel.py index 0b38ddf..36ae857 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -24,7 +24,8 @@ LOG = logging.getLogger(__name__) # support which often includes its 32 bit cousin. ADDITIONAL_ARCHES = { "x86_64" : "i386", - "aarch64" : "armhf" + "aarch64" : "armhf", + "ppc64le" : "ppc64", } def list_accel(qemu_bin): -- cgit v1.1 From 52c68b8abb614a744fd1d2099bbb3768a6aad8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Doktor?= Date: Mon, 20 Jan 2020 08:12:02 +0100 Subject: python: Treat None-return of greeting cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case qemu process dies the "monitor.cmd" returns None which gets passed to the "__negotiate_capabilities" and leads to unhandled exception. Let's only check the resp in case it has a value. Signed-off-by: Lukáš Doktor Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Wainer dos Santos Moschetta Message-Id: <20200120071202.30646-1-ldoktor@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/qmp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/qemu') diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py index 4b9a362..f40586e 100644 --- a/python/qemu/qmp.py +++ b/python/qemu/qmp.py @@ -80,7 +80,7 @@ class QEMUMonitorProtocol: raise QMPConnectError # Greeting seems ok, negotiate capabilities resp = self.cmd('qmp_capabilities') - if "return" in resp: + if resp and "return" in resp: return greeting raise QMPCapabilitiesError -- cgit v1.1 From 746f244d9720233f42a5a5745e28a4fac9fe8395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 21 Jan 2020 00:51:56 +0100 Subject: python/qemu/machine: Allow to use other serial consoles than default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the QEMU Python module limits the QEMUMachine class to use the first serial console. Some machines/guest might use another console than the first one as the 'boot console'. For example the Raspberry Pi uses the second (AUX) console. To be able to use the Nth console as default, we simply need to connect all the N - 1 consoles to the null chardev. Add an index argument, so we can use a specific serial console as default. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Liam Merwick Tested-by: Liam Merwick Reviewed-by: Wainer dos Santos Moschetta Message-Id: <20200120235159.18510-5-f4bug@amsat.org> [PMD: zero-initialize _console_index in __init__()] Signed-off-by: Philippe Mathieu-Daudé --- python/qemu/machine.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'python/qemu') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 734efd8..183d8f3 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -112,6 +112,7 @@ class QEMUMachine(object): self._sock_dir = sock_dir self._launched = False self._machine = None + self._console_index = 0 self._console_set = False self._console_device_type = None self._console_address = None @@ -241,6 +242,8 @@ 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): + args.extend(['-serial', 'null']) if self._console_set: self._console_address = os.path.join(self._sock_dir, self._name + "-console.sock") @@ -527,7 +530,7 @@ class QEMUMachine(object): """ self._machine = machine_type - def set_console(self, device_type=None): + def set_console(self, device_type=None, console_index=0): """ Sets the device type for a console device @@ -548,9 +551,14 @@ class QEMUMachine(object): chardev:console" command line argument will be used instead, resorting to the machine's default device type. + @param console_index: the index of the console device to use. + If not zero, the command line will create + 'index - 1' consoles and connect them to + the 'null' backing character device. """ self._console_set = True self._console_device_type = device_type + self._console_index = console_index @property def console_socket(self): -- cgit v1.1