From 74b56bb5539553d93908d6acb2bc2c5e2f019f7d Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Wed, 11 Dec 2019 13:55:35 -0500 Subject: python/qemu: Add set_qmp_monitor() to QEMUMachine The QEMUMachine VM has a monitor setup on which an QMP connection is always attempted on _post_launch() (executed by launch()). In case the QEMU process immediatly exits then the qmp.accept() (used to establish the connection) stalls until it reaches timeout and consequently an exception raises. That behavior is undesirable when, for instance, it needs to gather information from the QEMU binary ($ qemu -cpu list) or a test which launches the VM expecting its failure. This patch adds the set_qmp_monitor() method to QEMUMachine that allows turn off the creation of the monitor machinery on VM launch. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Cleber Rosa Message-Id: <20191211185536.16962-2-wainersm@redhat.com> [Cleber: trivial indentation fix] Signed-off-by: Cleber Rosa --- python/qemu/machine.py | 70 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 25 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/machine.py b/python/qemu/machine.py index a4631d6..734efd8 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -104,6 +104,7 @@ class QEMUMachine(object): self._events = [] self._iolog = None self._socket_scm_helper = socket_scm_helper + self._qmp_set = True # Enable QMP monitor by default. self._qmp = None self._qemu_full_args = None self._test_dir = test_dir @@ -228,15 +229,16 @@ class QEMUMachine(object): self._iolog = iolog.read() def _base_args(self): - if isinstance(self._monitor_address, tuple): - moncdev = "socket,id=mon,host=%s,port=%s" % ( - self._monitor_address[0], - self._monitor_address[1]) - else: - moncdev = 'socket,id=mon,path=%s' % self._vm_monitor - args = ['-chardev', moncdev, - '-mon', 'chardev=mon,mode=control', - '-display', 'none', '-vga', 'none'] + args = ['-display', 'none', '-vga', 'none'] + if self._qmp_set: + if isinstance(self._monitor_address, tuple): + moncdev = "socket,id=mon,host=%s,port=%s" % ( + self._monitor_address[0], + self._monitor_address[1]) + else: + moncdev = 'socket,id=mon,path=%s' % self._vm_monitor + args.extend(['-chardev', moncdev, '-mon', + 'chardev=mon,mode=control']) if self._machine is not None: args.extend(['-machine', self._machine]) if self._console_set: @@ -255,20 +257,21 @@ class QEMUMachine(object): def _pre_launch(self): self._temp_dir = tempfile.mkdtemp(dir=self._test_dir) - if self._monitor_address is not None: - self._vm_monitor = self._monitor_address - else: - self._vm_monitor = os.path.join(self._sock_dir, - self._name + "-monitor.sock") - self._remove_files.append(self._vm_monitor) self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') - self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, - server=True) + if self._qmp_set: + if self._monitor_address is not None: + self._vm_monitor = self._monitor_address + else: + self._vm_monitor = os.path.join(self._sock_dir, + self._name + "-monitor.sock") + self._remove_files.append(self._vm_monitor) + self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, server=True) def _post_launch(self): - self._qmp.accept() + if self._qmp: + self._qmp.accept() def _post_shutdown(self): if self._qemu_log_file is not None: @@ -330,7 +333,8 @@ class QEMUMachine(object): Wait for the VM to power off """ self._popen.wait() - self._qmp.close() + if self._qmp: + self._qmp.close() self._load_io_log() self._post_shutdown() @@ -346,12 +350,13 @@ class QEMUMachine(object): self._console_socket = None if self.is_running(): - try: - if not has_quit: - self._qmp.cmd('quit') - self._qmp.close() - except: - self._popen.kill() + if self._qmp: + try: + if not has_quit: + self._qmp.cmd('quit') + self._qmp.close() + except: + self._popen.kill() self._popen.wait() self._load_io_log() @@ -368,6 +373,21 @@ class QEMUMachine(object): self._launched = False + def set_qmp_monitor(self, enabled=True): + """ + Set the QMP monitor. + + @param enabled: if False, qmp monitor options will be removed from + the base arguments of the resulting QEMU command + line. Default is True. + @note: call this function before launch(). + """ + if enabled: + self._qmp_set = True + else: + self._qmp_set = False + self._qmp = None + def qmp(self, cmd, conv_keys=True, **args): """ Invoke a QMP command and return the response dict -- cgit v1.1 From 8b272e001868581736144dbedca41aa8bbe82019 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 16 Dec 2019 16:14:34 -0300 Subject: python/qemu: Move kvm_available() to its own module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This creates the 'accel' Python module to be the home for utilities that deal with accelerators. Also moved kvm_available() from __init__.py to this new module. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20191216191438.93418-2-wainersm@redhat.com> Signed-off-by: Cleber Rosa --- python/qemu/__init__.py | 20 +------------------- python/qemu/accel.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 python/qemu/accel.py (limited to 'python/qemu') diff --git a/python/qemu/__init__.py b/python/qemu/__init__.py index 6c919a3..eff17a3 100644 --- a/python/qemu/__init__.py +++ b/python/qemu/__init__.py @@ -12,24 +12,6 @@ # Based on qmp.py. # -import logging -import os - from . import qmp from . import machine - -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" -} - -def kvm_available(target_arch=None): - host_arch = os.uname()[4] - if target_arch and target_arch != host_arch: - if target_arch != ADDITIONAL_ARCHES.get(host_arch): - return False - return os.access("/dev/kvm", os.R_OK | os.W_OK) +from . import accel diff --git a/python/qemu/accel.py b/python/qemu/accel.py new file mode 100644 index 0000000..cbeac10 --- /dev/null +++ b/python/qemu/accel.py @@ -0,0 +1,31 @@ +""" +QEMU accel module: + +This module provides utilities for discover and check the availability of +accelerators. +""" +# Copyright (C) 2015-2016 Red Hat Inc. +# Copyright (C) 2012 IBM Corp. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2. See +# the COPYING file in the top-level directory. +# + +import os + +# Mapping host architecture to any additional architectures it can +# support which often includes its 32 bit cousin. +ADDITIONAL_ARCHES = { + "x86_64" : "i386", + "aarch64" : "armhf" +} + +def kvm_available(target_arch=None): + host_arch = os.uname()[4] + if target_arch and target_arch != host_arch: + if target_arch != ADDITIONAL_ARCHES.get(host_arch): + return False + return os.access("/dev/kvm", os.R_OK | os.W_OK) -- cgit v1.1 From 1650c3e3043ac7e8f16bdfb746430a106e49c18f Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 16 Dec 2019 16:14:35 -0300 Subject: python/qemu: accel: Add list_accel() method Since commit cbe6d6365a48 the command `qemu -accel help` returns the list of accelerators enabled in the QEMU binary. This adds the list_accel() method which return that same list. Signed-off-by: Wainer dos Santos Moschetta Message-Id: <20191216191438.93418-3-wainersm@redhat.com> Reviewed-by: Cleber Rosa Tested-by: Cleber Rosa Signed-off-by: Cleber Rosa --- python/qemu/accel.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'python/qemu') diff --git a/python/qemu/accel.py b/python/qemu/accel.py index cbeac10..7395cee 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -14,7 +14,11 @@ accelerators. # the COPYING file in the top-level directory. # +import logging import os +import subprocess + +LOG = logging.getLogger(__name__) # Mapping host architecture to any additional architectures it can # support which often includes its 32 bit cousin. @@ -23,6 +27,25 @@ ADDITIONAL_ARCHES = { "aarch64" : "armhf" } +def list_accel(qemu_bin): + """ + List accelerators enabled in the QEMU binary. + + @param qemu_bin (str): path to the QEMU binary. + @raise Exception: if failed to run `qemu -accel help` + @return a list of accelerator names. + """ + if not qemu_bin: + return [] + try: + out = subprocess.check_output([qemu_bin, '-accel', 'help'], + universal_newlines=True) + except: + LOG.debug("Failed to get the list of accelerators in %s", qemu_bin) + raise + # Skip the first line which is the header. + return [acc.strip() for acc in out.splitlines()[1:]] + def kvm_available(target_arch=None): host_arch = os.uname()[4] if target_arch and target_arch != host_arch: -- cgit v1.1 From 53a049d7d78e5ccf6d4c0d7b0edb18f8b999df94 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 16 Dec 2019 16:14:36 -0300 Subject: python/qemu: accel: Strengthen kvm_available() checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently kvm_available() checks for the presence of kvm module and, if target and host arches don't mismatch. This patch adds an 3rd checking: if QEMU binary was compiled with kvm support. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Alex Bennée Reviewed-by: Cleber Rosa Reviewed-by: Philippe Mathieu-Daudé Tested-by: Cleber Rosa Message-Id: <20191216191438.93418-4-wainersm@redhat.com> Signed-off-by: Cleber Rosa --- python/qemu/accel.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/accel.py b/python/qemu/accel.py index 7395cee..5fce3aa 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -46,9 +46,24 @@ 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): - host_arch = os.uname()[4] - if target_arch and target_arch != host_arch: - if target_arch != ADDITIONAL_ARCHES.get(host_arch): - return False - return os.access("/dev/kvm", os.R_OK | os.W_OK) +def kvm_available(target_arch=None, qemu_bin=None): + """ + Check if KVM is available using the following heuristic: + - Kernel module is present in the host; + - Target and host arches don't mismatch; + - KVM is enabled in the QEMU binary. + + @param target_arch (str): target architecture + @param qemu_bin (str): path to the QEMU binary + @return True if kvm is available, otherwise False. + """ + if not os.access("/dev/kvm", os.R_OK | os.W_OK): + return False + if target_arch: + host_arch = os.uname()[4] + if target_arch != host_arch: + if target_arch != ADDITIONAL_ARCHES.get(host_arch): + return False + if qemu_bin and "kvm" not in list_accel(qemu_bin): + return False + return True -- cgit v1.1 From d3ca7bb599b777271316c17a5221c5ee28815833 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 16 Dec 2019 16:14:37 -0300 Subject: python/qemu: accel: Add tcg_available() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a method to check if the tcg accelerator is enabled in the QEMU binary. Signed-off-by: Wainer dos Santos Moschetta Reviewed-by: Alex Bennée Reviewed-by: Cleber Rosa Reviewed-by: Philippe Mathieu-Daudé Tested-by: Cleber Rosa Message-Id: <20191216191438.93418-5-wainersm@redhat.com> Signed-off-by: Cleber Rosa --- python/qemu/accel.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'python/qemu') diff --git a/python/qemu/accel.py b/python/qemu/accel.py index 5fce3aa..0b38ddf 100644 --- a/python/qemu/accel.py +++ b/python/qemu/accel.py @@ -67,3 +67,11 @@ def kvm_available(target_arch=None, qemu_bin=None): if qemu_bin and "kvm" not in list_accel(qemu_bin): return False return True + +def tcg_available(qemu_bin): + """ + Check if TCG is available. + + @param qemu_bin (str): path to the QEMU binary + """ + return 'tcg' in list_accel(qemu_bin) -- cgit v1.1 From e42cb9678cee7ff7c28afe7917c1002d6d8fdc0d Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 16 Dec 2019 16:14:38 -0300 Subject: python/qemu: Remove unneeded imports in __init__ __init_.py import some sub-modules unnecessarily. So let's clean it up. Signed-off-by: Wainer dos Santos Moschetta Suggested-by: Cleber Rosa Reviewed-by: Cleber Rosa Tested-by: Cleber Rosa Message-Id: <20191216191438.93418-6-wainersm@redhat.com> Signed-off-by: Cleber Rosa --- python/qemu/__init__.py | 6 ------ 1 file changed, 6 deletions(-) (limited to 'python/qemu') diff --git a/python/qemu/__init__.py b/python/qemu/__init__.py index eff17a3..4ca06c3 100644 --- a/python/qemu/__init__.py +++ b/python/qemu/__init__.py @@ -9,9 +9,3 @@ # This work is licensed under the terms of the GNU GPL, version 2. See # the COPYING file in the top-level directory. # -# Based on qmp.py. -# - -from . import qmp -from . import machine -from . import accel -- cgit v1.1