diff --git a/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg b/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg
index 74c902aa70..5f55fa1800 100644
--- a/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg
+++ b/libvirt/tests/cfg/migration/migration_misc/migration_with_cpu_mode.cfg
@@ -29,14 +29,34 @@
virsh_migrate_options = '--live --p2p --verbose'
- non_p2p:
virsh_migrate_options = '--live --verbose'
+ - p2p_tunneled:
+ virsh_migrate_options = '--live --p2p --tunnelled --verbose'
+ - postcopy:
+ virsh_migrate_options = '--live --postcopy --verbose'
+ - postcopy_p2p:
+ virsh_migrate_options = '--live --postcopy --p2p --verbose'
+ - auto_converge:
+ virsh_migrate_options = '--live --auto-converge --verbose'
+ - auto_converge_p2p:
+ virsh_migrate_options = '--live --auto-converge --p2p --verbose'
variants migration_option:
- with_xml:
- without_xml:
variants cpu_mode:
- host_model:
no s390x
- numa_cell = "'numa_cell': [{'cpus': '0-1', 'memory': '2097152', 'unit': 'KiB'}]"
- vm_attrs = {'cpu': {'mode': 'host-model', 'check': 'partial', ${numa_cell}}}
+ numa_cell = "'numa_cell': [{'cpus': '0-31', 'memory': '16777216', 'unit': 'KiB'}]"
+ vm_attrs = {'max_mem': 16777216, 'max_mem_unit': 'KiB', 'current_mem': 16777216, 'current_mem_unit': 'KiB', 'cpu': {'mode': 'host-model', 'check': 'partial', ${numa_cell}}}
- custom:
- no aarch64
+ no aarch64,ppc64le,ppc64
cpu_mode = "custom"
+ variants kdump:
+ - kdump_migration:
+ # Trigger kdump on guest after migration and verify vmcore is created
+ # Crosses with all migration variants (p2p, p2p_tunneled, postcopy,
+ # auto_converge, etc.) - only runs with host_model cpu_mode (Power arch)
+ no custom
+ post_migration_kdump = yes
+ on_crash = restart
+ - no_kdump:
+ post_migration_kdump = no
diff --git a/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py b/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py
index 262c0691dd..21f9140c33 100644
--- a/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py
+++ b/libvirt/tests/src/migration/migration_misc/migration_with_cpu_mode.py
@@ -1,6 +1,9 @@
import os
+import platform
+import re
from virttest import data_dir
+from virttest import utils_kdump
from virttest import virsh
from virttest.libvirt_xml import vm_xml
@@ -15,10 +18,22 @@ def run(test, params, env):
:param params: Dictionary with the test parameters
:param env: Dictionary with test environment.
"""
+ def get_host_cpu_model():
+ """Get host CPU model in lowercase."""
+ try:
+ caps_xml = virsh.capabilities()
+ match = re.search(r'(\w+)', caps_xml)
+ if match:
+ model = match.group(1).lower()
+ test.log.info("Detected CPU model: %s", model)
+ return model
+ except Exception as e:
+ test.log.warning("Failed to detect CPU model: %s", e)
+ return None
+
def setup_test():
"""
Setup steps
-
"""
cpu_mode = params.get("cpu_mode")
migration_option = params.get("migration_option")
@@ -28,11 +43,26 @@ def setup_test():
vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
if cpu_mode == "host_model":
vm_attrs = eval(params.get('vm_attrs', '{}'))
+ arch = platform.machine()
+ if arch in ['ppc64', 'ppc64le'] and 'cpu' in vm_attrs:
+ host_model = get_host_cpu_model()
+ if host_model:
+ vm_attrs['cpu']['model'] = host_model
+ vm_attrs['cpu']['fallback'] = params.get('model_fallback', 'forbid')
+ test.log.info("Power arch - added CPU model: %s", host_model)
vmxml.setup_attrs(**vm_attrs)
vmxml.sync()
else:
base_steps.sync_cpu_for_mig(params)
+ # If kdump will be triggered after migration, ensure the VM restarts
+ # after a crash so we can verify the vmcore and wait for reboot.
+ if params.get("post_migration_kdump") == "yes":
+ vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
+ vmxml.on_crash = "restart"
+ vmxml.sync()
+ test.log.info("Set on_crash=restart for kdump test.")
+
if not vm.is_alive():
vm.start()
vm.wait_for_login().close()
@@ -42,6 +72,70 @@ def setup_test():
virsh.dumpxml(vm_name, extra="--migratable", to_file=xmlfile, ignore_status=False)
params.update({"virsh_migrate_extra": f"--xml {xmlfile}"})
+ def _get_vmcores_via_serial(session):
+ """List vmcore files using an already-open serial session."""
+ status, output = session.cmd_status_output(
+ "find /var/crash/ -type f -name vmcore 2>/dev/null | sort",
+ timeout=60,
+ )
+ if status:
+ return []
+ return [v for v in output.split() if v]
+
+ def verify_kdump_after_migration():
+ """
+ Trigger kdump on the guest after successful migration and verify
+ a new vmcore is created.
+
+ All guest access uses wait_for_serial_login() which connects via the
+ virsh serial console (qemu+tcp://dest/system console ). This
+ bypasses the source-side ARP / address-cache verification that
+ wait_for_login() performs and that always fails after live migration
+ because the VM MAC is no longer reachable on the source host virbr0.
+
+ Guest must have on_crash=restart in its XML (set in setup_test()) so
+ it reboots after kdump allowing vmcore presence to be confirmed.
+ """
+ test.log.info("Triggering kdump on guest '%s' after migration.", vm_name)
+
+ # Pre-crash vmcore snapshot via serial console
+ pre_session = vm.wait_for_serial_login(timeout=240)
+ try:
+ pre_vmcores = _get_vmcores_via_serial(pre_session)
+ test.log.info("Pre-crash vmcores: %s", pre_vmcores)
+ finally:
+ pre_session.close()
+
+ # Trigger kernel panic via serial session
+ crash_session = vm.wait_for_serial_login(timeout=240)
+ utils_kdump.trigger_crash(
+ vm,
+ session=crash_session,
+ wait_time=300,
+ test=test,
+ )
+ test.log.info("Kernel panic triggered; waiting for guest to reboot.")
+
+ # Wait for reboot via serial (on_crash=restart ensures reboot)
+ vm.wait_for_serial_login(timeout=360).close()
+ test.log.info("Guest rebooted after kdump.")
+
+ # Post-crash vmcore list via serial
+ post_session = vm.wait_for_serial_login(timeout=240)
+ try:
+ post_vmcores = _get_vmcores_via_serial(post_session)
+ test.log.info("Post-crash vmcores: %s", post_vmcores)
+ finally:
+ post_session.close()
+
+ new_vmcores = [v for v in post_vmcores if v not in pre_vmcores]
+ if not new_vmcores:
+ test.fail(
+ "No new vmcore found in guest '%s' after kdump. "
+ "pre=%s post=%s" % (vm_name, pre_vmcores, post_vmcores)
+ )
+ test.log.info("kdump verified - new vmcore(s): %s", new_vmcores)
+
vm_name = params.get("migrate_main_vm")
vm = env.get_vm(vm_name)
@@ -51,5 +145,7 @@ def setup_test():
setup_test()
migration_obj.run_migration()
migration_obj.verify_default()
+ if params.get("post_migration_kdump") == "yes":
+ verify_kdump_after_migration()
finally:
migration_obj.cleanup_connection()