Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions libvirt/tests/cfg/libvirt_vcpu_plug_unplug.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,58 @@
vcpu_plug_num = 240
vcpu_unplug_num = 1
vcpu_max_num = 240
- kdump_after_plug_unplug:
# Hotplug vCPUs, trigger kdump, verify vmcore;
# then unplug vCPUs, trigger kdump again, verify
# a new vmcore. Confirms guest kernel stability
# under changing vCPU count.
# Requires kdump service active in the guest.
only live
only ppc64le,ppc64
kdump_after_plug_unplug = "yes"
on_crash = "restart"
crash_dir = "/var/crash/"
vcpu_max_num = "8"
vcpu_current_num = "4"
vcpu_plug_num = "8"
vcpu_unplug_num = "4"
variants:
- hotplug_kdump:
vcpu_plug = "yes"
vcpu_unplug = "no"
- unplug_kdump:
vcpu_plug = "no"
vcpu_unplug = "yes"
- plug_and_unplug_kdump:
vcpu_plug = "yes"
vcpu_unplug = "yes"
- offline_cpu_kdump:
# Offline a guest CPU, run virsh setvcpus
# (hotplug or unplug), then trigger kdump to
# verify guest kernel stability with an offline
# CPU under a changing vCPU count.
# Requires kdump service active in the guest.
only live
only ppc64le,ppc64
offline_cpu_before_setvcpus = "yes"
offline_cpu_list = "1"
kdump_after_plug_unplug = "yes"
on_crash = "restart"
crash_dir = "/var/crash/"
vcpu_max_num = "8"
vcpu_current_num = "4"
vcpu_plug_num = "8"
vcpu_unplug_num = "4"
variants:
- offline_hotplug_kdump:
vcpu_plug = "yes"
vcpu_unplug = "no"
- offline_unplug_kdump:
vcpu_plug = "no"
vcpu_unplug = "yes"
- offline_plug_and_unplug_kdump:
vcpu_plug = "yes"
vcpu_unplug = "yes"

variants:
- live:
Expand Down
89 changes: 85 additions & 4 deletions libvirt/tests/src/libvirt_vcpu_plug_unplug.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from virttest import utils_libvirtd
from virttest import utils_test
from virttest.utils_test import libvirt
from virttest import utils_kdump
from virttest.libvirt_xml.vm_xml import VMXML

from provider.cpu import patch_total_cpu_count_s390x
Expand Down Expand Up @@ -146,6 +147,30 @@ def online_new_vcpu(vm, vcpu_plug_num):
session.close()
return False not in cpu_is_online

def offline_guest_cpus(vm, cpu_list_str):
"""
Offline specified CPUs inside the guest by writing 0 to
/sys/devices/system/cpu/cpuN/online for each cpu in cpu_list_str.

:param vm: VM object
:param cpu_list_str: comma-separated CPU ids to offline, e.g. "1,2"
"""
if not cpu_list_str:
return
session = vm.wait_for_login(timeout=240)
try:
for cpu_id in cpu_list_str.split(","):
cpu_id = cpu_id.strip()
cpu_path = "/sys/devices/system/cpu/cpu%s/online" % cpu_id
ret, out = session.cmd_status_output(
"echo 0 > %s" % cpu_path)
if ret:
test.fail("Failed to offline cpu%s in guest: %s"
% (cpu_id, out))
logging.info("Offlined cpu%s in guest", cpu_id)
finally:
session.close()

def check_setvcpus_result(cmd_result, expect_error):
"""
Check command result.
Expand Down Expand Up @@ -240,6 +265,10 @@ def check_setvcpus_result(cmd_result, expect_error):
with_stress = "yes" == params.get("run_stress", "no")
iterations = int(params.get("test_itr", 1))
topology_correction = "yes" == params.get("topology_correction", "no")
kdump_after_plug_unplug = "yes" == params.get("kdump_after_plug_unplug", "no")
crash_dir = params.get("crash_dir", "/var/crash/")
offline_cpu_before_setvcpus = "yes" == params.get("offline_cpu_before_setvcpus", "no")
offline_cpu_list = params.get("offline_cpu_list", "")
# Init expect vcpu count values
expect_vcpu_num = {'max_config': vcpu_max_num, 'max_live': vcpu_max_num,
'cur_config': vcpu_current_num,
Expand Down Expand Up @@ -338,6 +367,12 @@ def check_setvcpus_result(cmd_result, expect_error):
libvirt.check_exit_status(result)
expect_vcpupin = {pin_vcpu: pin_cpu_list}

# Offline guest CPUs before hotplug if requested
if offline_cpu_before_setvcpus and offline_cpu_list:
logging.info("Offlining guest CPUs %s before hotplug",
offline_cpu_list)
offline_guest_cpus(vm, offline_cpu_list)

result = virsh.setvcpus(vm_name, vcpu_plug_num, setvcpu_option,
readonly=setvcpu_readonly,
ignore_status=True, debug=True)
Expand All @@ -352,10 +387,32 @@ def check_setvcpus_result(cmd_result, expect_error):
expect_vcpu_num['cur_live'] = vcpu_plug_num
expect_vcpu_num['guest_live'] = vcpu_plug_num
if not status_error:
if not utils_misc.wait_for(lambda: cpu.check_if_vm_vcpu_match(vcpu_plug_num, vm),
vcpu_max_timeout, text="wait for vcpu online") or not online_new_vcpu(vm, vcpu_plug_num):
# When some guest CPUs are offlined before hotplug,
# the expected online count is reduced accordingly.
offline_count = (len(offline_cpu_list.split(","))
if offline_cpu_before_setvcpus and offline_cpu_list
else 0)
expected_online = vcpu_plug_num - offline_count
if not utils_misc.wait_for(
lambda: cpu.check_if_vm_vcpu_match(expected_online, vm),
vcpu_max_timeout, text="wait for vcpu online") or not online_new_vcpu(vm, vcpu_plug_num):
test.fail("Fail to enable new added cpu")

# Trigger kdump after hotplug to verify guest kernel
# stability under the new vCPU count
if kdump_after_plug_unplug:
logging.info("Triggering kdump after vCPU hotplug")
kdump_session = vm.wait_for_login(timeout=240)
utils_kdump.trigger_crash(vm, session=kdump_session,
wait_time=120, test=test)
logging.info("Verifying vmcore generated after hotplug kdump")
pre_vmcores = utils_kdump.get_vmcores(
vm, crash_dir=crash_dir, test=test)
if not pre_vmcores:
test.fail("No vmcore generated after hotplug kdump")
logging.info("vmcore confirmed after hotplug: %s",
pre_vmcores)

# Pin vcpu
if pin_after_plug:
result = virsh.vcpupin(vm_name, pin_vcpu, pin_cpu_list,
Expand Down Expand Up @@ -447,6 +504,12 @@ def check_setvcpus_result(cmd_result, expect_error):
# So for case of unpluging vcpus from max vcpu number to 1, when
# setvcpus return, need continue to obverse if vcpu number is
# continually to be unplugged to 1 gradually.
# Offline guest CPUs before unplug if requested
if offline_cpu_before_setvcpus and offline_cpu_list:
logging.info("Offlining guest CPUs %s before unplug",
offline_cpu_list)
offline_guest_cpus(vm, offline_cpu_list)

result = virsh.setvcpus(vm_name, vcpu_unplug_num,
setvcpu_option,
readonly=setvcpu_readonly,
Expand Down Expand Up @@ -479,6 +542,21 @@ def check_setvcpus_result(cmd_result, expect_error):
if session:
session.close()

# Trigger kdump after unplug to verify guest kernel
# stability under the reduced vCPU count
if kdump_after_plug_unplug:
logging.info("Triggering kdump after vCPU unplug")
kdump_session = vm.wait_for_login(timeout=240)
utils_kdump.trigger_crash(vm, session=kdump_session,
wait_time=120, test=test)
logging.info("Verifying vmcore generated after unplug kdump")
post_vmcores = utils_kdump.get_vmcores(
vm, crash_dir=crash_dir, test=test)
if not post_vmcores:
test.fail("No vmcore generated after unplug kdump")
logging.info("vmcore confirmed after unplug: %s",
post_vmcores)

check_setvcpus_result(result, status_error)
if setvcpu_option == "--config":
expect_vcpu_num['cur_config'] = vcpu_unplug_num
Expand Down Expand Up @@ -542,8 +620,11 @@ def check_setvcpus_result(cmd_result, expect_error):
if not cpu.check_vcpu_value(vm, expect_vcpu_num, expect_vcpupin, setvcpu_option):
logging.error("Expected vcpu check failed")
result_failed += 1
if vm.uptime() < vm_uptime_init:
test.fail("Unexpected VM reboot detected in between test")
# Skip uptime check when kdump is enabled: kdump intentionally
# crashes and reboots the guest, so a lower uptime is expected.
if not kdump_after_plug_unplug:
if vm.uptime() < vm_uptime_init:
test.fail("Unexpected VM reboot detected in between test")
# Recover env
finally:
if need_mkswap:
Expand Down