Merge tag 'pull-request-2026-07-07' of https://gitlab.com/huth/qemu into staging

* Add test for hotplugging a virtio-scsi disk
* Improve boot completion detection in aspeed tests
* Use QMP to query available machines in functional tests

# -----BEGIN PGP SIGNATURE-----
#
# iQJGBAABCAAwFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmpMl5oSHHRoLmh1dGhA
# cG9zdGVvLmV1AAoJEC7Z13T+cC21pmAQAJa2bVXA7cvKz0w7p7R0AAGrYfetiqbR
# f/HLuO17OE6Df2quoIpcYzAOjyLwFFBjb4RyPVMdcuKWPWcFnCA9i5ft30TLK84I
# 3SIx6M7N9OZnAlxPOGsVy8eyoIny8bQOm1/RsGP+SDkNpfQSPcQzp6IAVazEFcM/
# g6sOPuHp2SOUe+as1+ZTqGDTS5O9VTna/WLGV/Hka1+KCtAwAYws9SWnczHdFvMd
# rvTJOSKVe2gfs0vLdTIOx44Bj8xhty402+jQqvL8Rwm5wjXRECEQQe7g+qPXINot
# pnR2LCe952KHhkSoL+70N4SZTimX+UMt0qACr03isqSpVJDcYDD9T/rY5RL9PYPE
# TdVZM66ZfxmQGSfqNI0GI0vrEXr7zilOjowq/F8BBgT1RG8EzMM23WykPQtwqXuu
# vsVuu1IV99vbSH76EJEsMra5JuQrAnTNAkXLBtI9BQvlrP/553dl/2DQd7GUb8we
# B+bFtIk9QXkmkBGOGWOtOfkazPir5GKyy6zLFomZt1SBsbKyL8ZdHvV/XHeChSqO
# boMFfO67WnoqZeVhc53U3Hm8poo8sIw5UIRU/HAc3thE+esDXnYALEDwwcy8fdnE
# 2FB0PVzqVOuLXe0rNGsPFP/h+Fd30YFsTGQxxvS65ADAGkP5bztuZqejR2tVgeOU
# iHgw5kauDJ31
# =RNE6
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 07 Jul 2026 08:07:22 CEST
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "th.huth@posteo.eu"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg: issuer "th.huth@posteo.eu" does not match any User ID
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2026-07-07' of https://gitlab.com/huth/qemu:
  tests/functional: use QMP to query available machines
  tests/functional/aspeed: unify boot completion detection on 'login:' prompt
  tests/functional: Add hotplug_scsi test to hotplug virtio-scsi disk

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2026-07-07 19:11:53 +02:00
9 changed files with 127 additions and 34 deletions

View File

@@ -2338,6 +2338,7 @@ F: tests/qtest/virtio-scsi-test.c
F: tests/qtest/fuzz-virtio-scsi-test.c
F: tests/qtest/am53c974-test.c
F: tests/qtest/fuzz-lsi53c895a-test.c
F: tests/functional/x86_64/test_hotplug_scsi.py
T: git https://github.com/bonzini/qemu.git scsi-next
SSI

View File

@@ -5,10 +5,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from aspeed import FacebookAspeedTest
from aspeed import AspeedTest
class AnacapaMachine(FacebookAspeedTest):
class AnacapaMachine(AspeedTest):
ASSET_ANACAPA_FLASH = Asset(
'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/anacapa-bmc/openbmc-20260616025349/obmc-phosphor-image-anacapa-20260616025349.static.mtd.xz',
@@ -22,4 +22,4 @@ class AnacapaMachine(FacebookAspeedTest):
soc='AST2600 rev A3')
if __name__ == '__main__':
FacebookAspeedTest.main()
AspeedTest.main()

View File

@@ -5,10 +5,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from aspeed import FacebookAspeedTest
from aspeed import AspeedTest
class BletchleyMachine(FacebookAspeedTest):
class BletchleyMachine(AspeedTest):
ASSET_BLETCHLEY_FLASH = Asset(
'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz',
@@ -22,4 +22,4 @@ class BletchleyMachine(FacebookAspeedTest):
soc='AST2600 rev A3')
if __name__ == '__main__':
FacebookAspeedTest.main()
AspeedTest.main()

View File

@@ -5,10 +5,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from aspeed import FacebookAspeedTest
from aspeed import AspeedTest
class CatalinaMachine(FacebookAspeedTest):
class CatalinaMachine(AspeedTest):
ASSET_CATALINA_FLASH = Asset(
'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz',
@@ -22,4 +22,4 @@ class CatalinaMachine(FacebookAspeedTest):
soc='AST2600 rev A3')
if __name__ == '__main__':
FacebookAspeedTest.main()
AspeedTest.main()

View File

@@ -19,8 +19,7 @@ class GB200Machine(AspeedTest):
self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path,
uboot='2019.04', cpu_id='0xf00',
soc='AST2600 rev A3',
image_hostname='gb200nvl-obmc')
soc='AST2600 rev A3')
if __name__ == '__main__':
AspeedTest.main()

View File

@@ -8,14 +8,7 @@ from qemu_test import LinuxKernelTest
class AspeedTest(LinuxKernelTest):
def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04',
cpu_id='0x0', soc='AST2500 rev A1',
image_hostname=None):
# Allow for the image hostname to not end in "-bmc"
if image_hostname is not None:
hostname = image_hostname
else:
hostname = machine.removesuffix('-bmc')
cpu_id='0x0', soc='AST2500 rev A1'):
self.set_machine(machine)
self.vm.set_console()
self.vm.add_args('-drive', f'file={image},if=mtd,format=raw',
@@ -28,10 +21,10 @@ class AspeedTest(LinuxKernelTest):
self.wait_for_console_pattern(f'Booting Linux on physical CPU {cpu_id}')
self.wait_for_console_pattern(f'ASPEED {soc}')
self.wait_for_console_pattern('/init as init process')
self.wait_for_boot_complete(hostname)
self.wait_for_boot_complete()
def wait_for_boot_complete(self, hostname):
self.wait_for_console_pattern(f'systemd[1]: Hostname set to <{hostname}>.')
def wait_for_boot_complete(self):
self.wait_for_console_pattern('login:')
def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'):
self.require_netdev('user')
@@ -71,9 +64,3 @@ class AspeedTest(LinuxKernelTest):
with open(path, "wb") as f:
f.write(pattern)
return path
class FacebookAspeedTest(AspeedTest):
def wait_for_boot_complete(self, hostname):
self.wait_for_console_pattern(f'{hostname} login:')

View File

@@ -314,13 +314,32 @@ class QemuSystemTest(QemuBaseTest):
console_log.addHandler(self._console_log_fh)
def set_machine(self, machinename):
# TODO: We should use QMP to get the list of available machines
if not self._machinehelp:
self._machinehelp = run(
[self.qemu_bin, '-M', 'help'],
capture_output=True, check=True, encoding='utf8').stdout
if self._machinehelp.find(machinename) < 0:
cls = type(self)
if not hasattr(cls, "_machines"):
tmp_vm = QEMUMachine(self.qemu_bin)
tmp_vm.set_machine('none')
try:
tmp_vm.launch()
resp = tmp_vm.qmp('query-machines')
machines = resp.get('return', [])
cls._machines = [
m.get('name') for m in machines if 'name' in m
]
finally:
try:
tmp_vm.shutdown()
except Exception:
pass
self._machines = cls._machines
if machinename not in self._machines:
self.skipTest('no support for machine ' + machinename)
self.machine = machinename
def require_accelerator(self, accelerator):

View File

@@ -31,6 +31,7 @@ endif
tests_x86_64_system_thorough = [
'acpi_bits',
'hotplug_blk',
'hotplug_scsi',
'hotplug_cpu',
'intel_iommu',
'kvm_xen',

View File

@@ -0,0 +1,86 @@
#!/usr/bin/env python3
#
# Functional test that hotplugs a virtio scsi disk and checks it on a Linux
# guest
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
class HotPlugScsi(LinuxKernelTest):
ASSET_KERNEL = Asset(
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
'/31/Server/x86_64/os/images/pxeboot/vmlinuz'),
'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129')
ASSET_INITRD = Asset(
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
'/31/Server/x86_64/os/images/pxeboot/initrd.img'),
'277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b')
def blockdev_add(self) -> None:
self.vm.cmd('blockdev-add', **{
'driver': 'null-co',
'size': 1073741824,
'node-name': 'disk0'
})
def add_scsi_controller(self) -> None:
self.vm.cmd('device_add', {
'driver': 'virtio-scsi-pci',
'id': 'scsi0',
'bus': 'pci.1',
'addr': '1',
})
def assert_sda(self) -> None:
exec_command_and_wait_for_pattern(self, 'while ! test -e /sys/block/sda ;'
' do sleep 0.2 ; done', '# ')
def assert_no_sda(self) -> None:
exec_command_and_wait_for_pattern(self, 'while test -e /sys/block/sda ;'
' do sleep 0.2 ; done', '# ')
def plug(self) -> None:
args = {
'driver':'scsi-hd',
'drive':'disk0',
'bus':'scsi0.0',
'id':'scsi-disk0',
}
self.assert_no_sda()
self.vm.cmd('device_add', args)
self.wait_for_console_pattern('[sda] Attached SCSI disk')
self.assert_sda()
def unplug(self) -> None:
self.vm.cmd('device_del', id='scsi-disk0')
self.vm.event_wait('DEVICE_DELETED', 1.0,
match={'data': {'device': 'scsi-disk0'}})
self.assert_no_sda()
def test(self) -> None:
self.require_accelerator('kvm')
self.set_machine('q35')
self.vm.add_args('-accel', 'kvm')
self.vm.add_args('-device', 'pcie-pci-bridge,id=pci.1,bus=pcie.0')
self.vm.add_args('-m', '1G')
self.vm.add_args('-append', 'console=ttyS0 rd.rescue')
self.launch_kernel(self.ASSET_KERNEL.fetch(),
self.ASSET_INITRD.fetch(),
wait_for='Entering emergency mode.')
self.wait_for_console_pattern('# ')
self.blockdev_add()
self.add_scsi_controller()
self.plug()
self.unplug()
if __name__ == '__main__':
LinuxKernelTest.main()