aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-03-19 12:33:50 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-03-19 12:33:50 +0000
commita1ba62a0f304291c96939cbf7c38e2ab68770326 (patch)
tree836d9da300465eb53e0ce447d562cec25620fb12
parentce73691e2588950a854b8b63a8ecd81f69eda458 (diff)
parenta51d6a549361fd1a20dd2ac1d6a42ac0a4c708c7 (diff)
downloadqemu-a1ba62a0f304291c96939cbf7c38e2ab68770326.zip
qemu-a1ba62a0f304291c96939cbf7c38e2ab68770326.tar.gz
qemu-a1ba62a0f304291c96939cbf7c38e2ab68770326.tar.bz2
Merge remote-tracking branch 'remotes/cleber/tags/python-next-pull-request' into staging
Python and tests (mostly acceptance) patches 2020-03-17 # gpg: Signature made Wed 18 Mar 2020 00:16:03 GMT # gpg: using RSA key 7ABB96EB8B46B94D5E0FE9BB657E8D33A5F209F3 # gpg: Good signature from "Cleber Rosa <crosa@redhat.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 7ABB 96EB 8B46 B94D 5E0F E9BB 657E 8D33 A5F2 09F3 * remotes/cleber/tags/python-next-pull-request: tests/docker: make "buildah bud" output similar to "docker build" tests/docker: add CentOS 8 Dockerfile Acceptance tests: add make targets to download images Acceptance test: add "boot_linux" tests Acceptance tests: introduce BUILD_DIR and SOURCE_DIR python/qemu/qmp.py: QMP debug with VM label Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--.travis.yml2
-rw-r--r--python/qemu/machine.py3
-rw-r--r--python/qemu/qmp.py5
-rw-r--r--tests/Makefile.include20
-rw-r--r--tests/acceptance/avocado_qemu/__init__.py25
-rw-r--r--tests/acceptance/boot_linux.py222
-rw-r--r--tests/docker/dockerfiles/centos8.docker32
-rw-r--r--tests/docker/dockerfiles/debian-win32-cross.docker2
-rw-r--r--tests/requirements.txt1
9 files changed, 300 insertions, 12 deletions
diff --git a/.travis.yml b/.travis.yml
index ccf68aa..5672d12 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -316,7 +316,7 @@ jobs:
- name: "GCC check-acceptance"
dist: bionic
env:
- - CONFIG="--target-list=aarch64-softmmu,alpha-softmmu,arm-softmmu,m68k-softmmu,microblaze-softmmu,mips-softmmu,mips64el-softmmu,nios2-softmmu,or1k-softmmu,ppc-softmmu,ppc64-softmmu,s390x-softmmu,sparc-softmmu,x86_64-softmmu,xtensa-softmmu"
+ - CONFIG="--enable-tools --target-list=aarch64-softmmu,alpha-softmmu,arm-softmmu,m68k-softmmu,microblaze-softmmu,mips-softmmu,mips64el-softmmu,nios2-softmmu,or1k-softmmu,ppc-softmmu,ppc64-softmmu,s390x-softmmu,sparc-softmmu,x86_64-softmmu,xtensa-softmmu"
- TEST_CMD="make check-acceptance"
after_script:
- python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP")]' | xargs cat
diff --git a/python/qemu/machine.py b/python/qemu/machine.py
index 183d8f3..f53abfa 100644
--- a/python/qemu/machine.py
+++ b/python/qemu/machine.py
@@ -270,7 +270,8 @@ class QEMUMachine(object):
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)
+ self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor, server=True,
+ nickname=self._name)
def _post_launch(self):
if self._qmp:
diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py
index f40586e..d6c9b2f 100644
--- a/python/qemu/qmp.py
+++ b/python/qemu/qmp.py
@@ -46,7 +46,7 @@ class QEMUMonitorProtocol:
#: Logger object for debugging messages
logger = logging.getLogger('QMP')
- def __init__(self, address, server=False):
+ def __init__(self, address, server=False, nickname=None):
"""
Create a QEMUMonitorProtocol class.
@@ -62,6 +62,9 @@ class QEMUMonitorProtocol:
self.__address = address
self.__sock = self.__get_sock()
self.__sockfile = None
+ self._nickname = nickname
+ if self._nickname:
+ self.logger = logging.getLogger('QMP').getChild(self._nickname)
if server:
self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.__sock.bind(self.__address)
diff --git a/tests/Makefile.include b/tests/Makefile.include
index d134030..51de676 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -20,6 +20,8 @@ check-help:
@echo " $(MAKE) check-venv Creates a Python venv for tests"
@echo " $(MAKE) check-clean Clean the tests and related data"
@echo
+ @echo " $(MAKE) get-vm-images Downloads all images used by acceptance tests, according to configured targets (~350 MB each, 1.5 GB max)"
+ @echo
@echo
@echo "The variable SPEED can be set to control the gtester speed setting."
@echo "Default options are -k and (for $(MAKE) V=1) --verbose; they can be"
@@ -890,7 +892,21 @@ $(TESTS_RESULTS_DIR):
check-venv: $(TESTS_VENV_DIR)
-check-acceptance: check-venv $(TESTS_RESULTS_DIR)
+FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(TARGETS))
+FEDORA_31_ARCHES := x86_64 aarch64 ppc64le s390x
+FEDORA_31_DOWNLOAD=$(filter $(FEDORA_31_ARCHES),$(FEDORA_31_ARCHES_CANDIDATES))
+
+# download one specific Fedora 31 image
+get-vm-image-fedora-31-%: check-venv
+ $(call quiet-command, \
+ $(TESTS_VENV_DIR)/bin/python -m avocado vmimage get \
+ --distro=fedora --distro-version=31 --arch=$*, \
+ "AVOCADO", "Downloading acceptance tests VM image for $*")
+
+# download all vm images, according to defined targets
+get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOWNLOAD))
+
+check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images
$(call quiet-command, \
$(TESTS_VENV_DIR)/bin/python -m avocado \
--show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
@@ -901,7 +917,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR)
# Consolidated targets
-.PHONY: check-block check-qapi-schema check-qtest check-unit check check-clean
+.PHONY: check-block check-qapi-schema check-qtest check-unit check check-clean get-vm-images
check-qapi-schema: check-tests/qapi-schema/frontend check-tests/qapi-schema/doc-good.texi
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
ifeq ($(CONFIG_TOOLS),y)
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py
index d4358eb..59e7b4f 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -16,8 +16,21 @@ import tempfile
import avocado
-SRC_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..', '..')
-sys.path.append(os.path.join(SRC_ROOT_DIR, 'python'))
+#: The QEMU build root directory. It may also be the source directory
+#: if building from the source dir, but it's safer to use BUILD_DIR for
+#: that purpose. Be aware that if this code is moved outside of a source
+#: and build tree, it will not be accurate.
+BUILD_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
+
+if os.path.islink(os.path.dirname(os.path.dirname(__file__))):
+ # The link to the acceptance tests dir in the source code directory
+ lnk = os.path.dirname(os.path.dirname(__file__))
+ #: The QEMU root source directory
+ SOURCE_DIR = os.path.dirname(os.path.dirname(os.readlink(lnk)))
+else:
+ SOURCE_DIR = BUILD_DIR
+
+sys.path.append(os.path.join(SOURCE_DIR, 'python'))
from qemu.machine import QEMUMachine
@@ -49,10 +62,10 @@ def pick_default_qemu_bin(arch=None):
if is_readable_executable_file(qemu_bin_relative_path):
return qemu_bin_relative_path
- qemu_bin_from_src_dir_path = os.path.join(SRC_ROOT_DIR,
+ qemu_bin_from_bld_dir_path = os.path.join(BUILD_DIR,
qemu_bin_relative_path)
- if is_readable_executable_file(qemu_bin_from_src_dir_path):
- return qemu_bin_from_src_dir_path
+ if is_readable_executable_file(qemu_bin_from_bld_dir_path):
+ return qemu_bin_from_bld_dir_path
def _console_interaction(test, success_message, failure_message,
@@ -153,7 +166,7 @@ class Test(avocado.Test):
self.qemu_bin = self.params.get('qemu_bin',
default=default_qemu_bin)
if self.qemu_bin is None:
- self.cancel("No QEMU binary defined or found in the source tree")
+ self.cancel("No QEMU binary defined or found in the build tree")
def _new_vm(self, *args):
vm = QEMUMachine(self.qemu_bin, sock_dir=tempfile.mkdtemp())
diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py
new file mode 100644
index 0000000..075a386
--- /dev/null
+++ b/tests/acceptance/boot_linux.py
@@ -0,0 +1,222 @@
+# Functional test that boots a complete Linux system via a cloud image
+#
+# Copyright (c) 2018-2020 Red Hat, Inc.
+#
+# Author:
+# Cleber Rosa <crosa@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+
+import os
+
+from avocado_qemu import Test, BUILD_DIR
+
+from qemu.accel import kvm_available
+from qemu.accel import tcg_available
+
+from avocado.utils import cloudinit
+from avocado.utils import network
+from avocado.utils import vmimage
+from avocado.utils import datadrainer
+from avocado.utils.path import find_command
+
+ACCEL_NOT_AVAILABLE_FMT = "%s accelerator does not seem to be available"
+KVM_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "KVM"
+TCG_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "TCG"
+
+
+class BootLinux(Test):
+ """
+ Boots a Linux system, checking for a successful initialization
+ """
+
+ timeout = 900
+ chksum = None
+
+ def setUp(self):
+ super(BootLinux, self).setUp()
+ self.vm.add_args('-smp', '2')
+ self.vm.add_args('-m', '1024')
+ self.prepare_boot()
+ self.prepare_cloudinit()
+
+ def prepare_boot(self):
+ self.log.debug('Looking for and selecting a qemu-img binary to be '
+ 'used to create the bootable snapshot image')
+ # If qemu-img has been built, use it, otherwise the system wide one
+ # will be used. If none is available, the test will cancel.
+ qemu_img = os.path.join(BUILD_DIR, 'qemu-img')
+ if not os.path.exists(qemu_img):
+ qemu_img = find_command('qemu-img', False)
+ if qemu_img is False:
+ self.cancel('Could not find "qemu-img", which is required to '
+ 'create the bootable image')
+ vmimage.QEMU_IMG = qemu_img
+
+ self.log.info('Downloading/preparing boot image')
+ # Fedora 31 only provides ppc64le images
+ image_arch = self.arch
+ if image_arch == 'ppc64':
+ image_arch = 'ppc64le'
+ try:
+ self.boot = vmimage.get(
+ 'fedora', arch=image_arch, version='31',
+ checksum=self.chksum,
+ algorithm='sha256',
+ cache_dir=self.cache_dirs[0],
+ snapshot_dir=self.workdir)
+ self.vm.add_args('-drive', 'file=%s' % self.boot.path)
+ except:
+ self.cancel('Failed to download/prepare boot image')
+
+ def prepare_cloudinit(self):
+ self.log.info('Preparing cloudinit image')
+ try:
+ cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso')
+ self.phone_home_port = network.find_free_port()
+ cloudinit.iso(cloudinit_iso, self.name,
+ username='root',
+ password='password',
+ # QEMU's hard coded usermode router address
+ phone_home_host='10.0.2.2',
+ phone_home_port=self.phone_home_port)
+ self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso)
+ except Exception:
+ self.cancel('Failed to prepared cloudinit image')
+
+ def launch_and_wait(self):
+ self.vm.set_console()
+ self.vm.launch()
+ console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(),
+ logger=self.log.getChild('console'))
+ console_drainer.start()
+ self.log.info('VM launched, waiting for boot confirmation from guest')
+ cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name)
+
+
+class BootLinuxX8664(BootLinux):
+ """
+ :avocado: tags=arch:x86_64
+ """
+
+ chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
+
+ def test_pc_i440fx_tcg(self):
+ """
+ :avocado: tags=machine:pc
+ :avocado: tags=accel:tcg
+ """
+ if not tcg_available(self.qemu_bin):
+ self.cancel(TCG_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "tcg")
+ self.launch_and_wait()
+
+ def test_pc_i440fx_kvm(self):
+ """
+ :avocado: tags=machine:pc
+ :avocado: tags=accel:kvm
+ """
+ if not kvm_available(self.arch, self.qemu_bin):
+ self.cancel(KVM_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "kvm")
+ self.launch_and_wait()
+
+ def test_pc_q35_tcg(self):
+ """
+ :avocado: tags=machine:q35
+ :avocado: tags=accel:tcg
+ """
+ if not tcg_available(self.qemu_bin):
+ self.cancel(TCG_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "tcg")
+ self.launch_and_wait()
+
+ def test_pc_q35_kvm(self):
+ """
+ :avocado: tags=machine:q35
+ :avocado: tags=accel:kvm
+ """
+ if not kvm_available(self.arch, self.qemu_bin):
+ self.cancel(KVM_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "kvm")
+ self.launch_and_wait()
+
+
+class BootLinuxAarch64(BootLinux):
+ """
+ :avocado: tags=arch:aarch64
+ :avocado: tags=machine:virt
+ :avocado: tags=machine:gic-version=2
+ """
+
+ chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
+
+ def add_common_args(self):
+ self.vm.add_args('-bios',
+ os.path.join(BUILD_DIR, 'pc-bios',
+ 'edk2-aarch64-code.fd'))
+ self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
+ self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
+
+ def test_virt_tcg(self):
+ """
+ :avocado: tags=accel:tcg
+ :avocado: tags=cpu:max
+ """
+ if not tcg_available(self.qemu_bin):
+ self.cancel(TCG_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "tcg")
+ self.vm.add_args("-cpu", "max")
+ self.vm.add_args("-machine", "virt,gic-version=2")
+ self.add_common_args()
+ self.launch_and_wait()
+
+ def test_virt_kvm(self):
+ """
+ :avocado: tags=accel:kvm
+ :avocado: tags=cpu:host
+ """
+ if not kvm_available(self.arch, self.qemu_bin):
+ self.cancel(KVM_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "kvm")
+ self.vm.add_args("-cpu", "host")
+ self.vm.add_args("-machine", "virt,gic-version=2")
+ self.add_common_args()
+ self.launch_and_wait()
+
+
+class BootLinuxPPC64(BootLinux):
+ """
+ :avocado: tags=arch:ppc64
+ """
+
+ chksum = '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58'
+
+ def test_pseries_tcg(self):
+ """
+ :avocado: tags=machine:pseries
+ :avocado: tags=accel:tcg
+ """
+ if not tcg_available(self.qemu_bin):
+ self.cancel(TCG_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "tcg")
+ self.launch_and_wait()
+
+
+class BootLinuxS390X(BootLinux):
+ """
+ :avocado: tags=arch:s390x
+ """
+
+ chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d'
+
+ def test_s390_ccw_virtio_tcg(self):
+ """
+ :avocado: tags=machine:s390-ccw-virtio
+ :avocado: tags=accel:tcg
+ """
+ if not tcg_available(self.qemu_bin):
+ self.cancel(TCG_NOT_AVAILABLE)
+ self.vm.add_args("-accel", "tcg")
+ self.launch_and_wait()
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker
new file mode 100644
index 0000000..bfa0d33
--- /dev/null
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -0,0 +1,32 @@
+FROM centos:8.1.1911
+
+RUN dnf -y update
+ENV PACKAGES \
+ SDL-devel \
+ bison \
+ bzip2 \
+ bzip2-devel \
+ dbus-daemon \
+ flex \
+ gcc \
+ gcc-c++ \
+ gettext \
+ git \
+ glib2-devel \
+ libaio-devel \
+ libepoxy-devel \
+ lzo-devel \
+ make \
+ mesa-libEGL-devel \
+ nettle-devel \
+ perl-Test-Harness \
+ pixman-devel \
+ python36 \
+ rdma-core-devel \
+ spice-glib-devel \
+ spice-server \
+ tar \
+ zlib-devel
+
+RUN dnf install -y $PACKAGES
+RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/tests/docker/dockerfiles/debian-win32-cross.docker b/tests/docker/dockerfiles/debian-win32-cross.docker
index 9d7053e..d16d643 100644
--- a/tests/docker/dockerfiles/debian-win32-cross.docker
+++ b/tests/docker/dockerfiles/debian-win32-cross.docker
@@ -9,7 +9,7 @@ MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
ENV TARGET i686
-ENV PATH $PATH:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/bin
+ENV PATH $PATH:/usr/lib/mxe/usr/bin:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/bin
ENV PKG_CONFIG_PATH \
$PKG_CONFIG_PATH:/usr/lib/mxe/usr/$TARGET-w64-mingw32.shared/lib/pkgconfig
diff --git a/tests/requirements.txt b/tests/requirements.txt
index f4f1736..f9c84b4 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -2,3 +2,4 @@
# in the tests/venv Python virtual environment. For more info,
# refer to: https://pip.pypa.io/en/stable/user_guide/#id1
avocado-framework==76.0
+pycdlib==1.9.0