[PATCH 0/7] qemu: add async vCPU unplug coverage
This series adds qemuhotplugtest coverage for async vCPU unplug. Async vCPU unplug does not complete at the device_del reply. The guest CPU remains in a pending removal state until QEMU reports DEVICE_DELETED and the QEMU driver handles the resulting process event. The new harness support lets the tests observe that intermediate state and then complete the unplug through the same process-event path used by the driver. The setvcpu coverage exercises both a single-vCPU x86 hotplug entity and a grouped ppc64 hotplug entity. These cases check the pending live XML before completion and the final live/config XML after completion, while also validating the expected vcpu-removed domain events. The setvcpus coverage adds a separate count-based x86 downscale case. This keeps the independent count-to-entity selection path covered without duplicating the grouped-entity coverage from setvcpu. The series also includes a small domain API cleanup to use the vCPU-specific flag aliases consistently in the vCPU entry points. This keeps the implementation and diagnostics aligned with the API being handled. This is a cosmetic change only, since the underlying values are all mapped to their equivalent enums. While adding this coverage, I realised that virsh was being too restrictive in its parameter combination validation; only QEMU does not support both `--async` and `--guest`. Other drivers may wish to support this behaviour. Accordingly, I've changed the behaviour so that virsh now lets the drivers reject the combination if they're unsupported. The decision now rests with the driver, which is more appropriate. Akash Kulhalli (7): qemu: expose process event handler to tests tests: add helper for DEVICE_DELETED events qemuhotplugtest: support async vcpu unplug completion qemuhotplugtest: test setvcpu async unplug qemuhotplugtest: test setvcpus async downscale domain: use vcpu-specific flag aliases consistently virsh: allow async vcpu options to reach drivers -- 2.49.0
Async QEMU process events are normally completed through qemuProcessEventHandler(). Tests that exercise DEVICE_DELETED completion need to drive that same path instead of mirroring the production logic locally. Move the declaration to a guarded private header and make the handler non-static so test code can wire it into a test worker pool. This does not change runtime behaviour. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- src/qemu/qemu_driver.c | 9 +++++---- src/qemu/qemu_driverpriv.h | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 src/qemu/qemu_driverpriv.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index eda1f42054af..c6d18f6575b7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -31,6 +31,8 @@ #include <sys/ioctl.h> #include "qemu_driver.h" +#define LIBVIRT_QEMU_DRIVERPRIV_H_ALLOW +#include "qemu_driverpriv.h" #include "qemu_agent.h" #include "qemu_alias.h" #include "qemu_block.h" @@ -139,9 +141,6 @@ VIR_ENUM_IMPL(qemuDumpFormat, "win-dmp", ); - -static void qemuProcessEventHandler(void *data, void *opaque); - static int qemuStateCleanup(void); static int qemuDomainObjStart(virConnectPtr conn, @@ -4149,7 +4148,9 @@ processShutdownCompletedEvent(virDomainObj *vm) } -static void qemuProcessEventHandler(void *data, void *opaque) +void +qemuProcessEventHandler(void *data, + void *opaque) { struct qemuProcessEvent *processEvent = data; virDomainObj *vm = processEvent->vm; diff --git a/src/qemu/qemu_driverpriv.h b/src/qemu/qemu_driverpriv.h new file mode 100644 index 000000000000..4fb0cc22b026 --- /dev/null +++ b/src/qemu/qemu_driverpriv.h @@ -0,0 +1,27 @@ +/* + * qemu_driverpriv.h: private declarations for QEMU driver internals + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBVIRT_QEMU_DRIVERPRIV_H_ALLOW +# error "qemu_driverpriv.h may only be included by qemu_driver.c or test suites" +#endif /* LIBVIRT_QEMU_DRIVERPRIV_H_ALLOW */ + +#pragma once + +void +qemuProcessEventHandler(void *data, + void *opaque); -- 2.47.3
Add qemuMonitorTestEmitDeviceDeleted() so monitor tests can emit a DEVICE_DELETED event after the command reply has already been consumed. The helper uses the monitor callback path directly and avoids adding event JSON to command/reply fixtures. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- tests/qemumonitortestutils.c | 9 +++++++++ tests/qemumonitortestutils.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index b6e17fc2cac4..e83dd1d9c40b 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -1240,3 +1240,12 @@ qemuMonitorTestGetDomainObj(qemuMonitorTest *test) { return test->vm; } + +void +qemuMonitorTestEmitDeviceDeleted(qemuMonitorTest *test, + const char *alias) +{ + virObjectLock(test->mon); + qemuMonitorEmitDeviceDeleted(test->mon, alias); + virObjectUnlock(test->mon); +} diff --git a/tests/qemumonitortestutils.h b/tests/qemumonitortestutils.h index 4f136410ee61..c87cdf0e6a32 100644 --- a/tests/qemumonitortestutils.h +++ b/tests/qemumonitortestutils.h @@ -109,5 +109,8 @@ qemuAgent * qemuMonitorTestGetAgent(qemuMonitorTest *test); virDomainObj * qemuMonitorTestGetDomainObj(qemuMonitorTest *test); +void +qemuMonitorTestEmitDeviceDeleted(qemuMonitorTest *test, + const char *alias); G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorTest, qemuMonitorTestFree); -- 2.47.3
Add async CPU hotplug harness support so tests can observe the state between device_del and DEVICE_DELETED, and then complete the unplug through the QEMU driver's normal process-event path. The async path compares the pending live XML, emits DEVICE_DELETED events via the monitor test helper, waits for the driver worker to process them, and validates the vcpu-removed events before running the existing final XML checks. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- tests/qemuhotplugtest.c | 350 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 7e49b9ad3661..9696448e5b4e 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -19,8 +19,11 @@ #include <config.h> +#include "domain_event.h" #include "qemu/qemu_alias.h" #include "qemu/qemu_conf.h" +#define LIBVIRT_QEMU_DRIVERPRIV_H_ALLOW +#include "qemu/qemu_driverpriv.h" #include "qemu/qemu_hotplug.h" #include "qemumonitortestutils.h" #include "testutils.h" @@ -28,6 +31,9 @@ #include "testutilsqemuschema.h" #include "virhostdev.h" #include "virfile.h" +#include "virthread.h" +#include "virthreadpool.h" +#include "virtime.h" #include "qemufakedrivers.h" #define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW @@ -44,6 +50,7 @@ enum { }; #define QEMU_HOTPLUG_TEST_DOMAIN_ID 7 +#define QEMU_HOTPLUG_TEST_DOMAIN_PID 12345 struct qemuHotplugTestData { const char *domain_filename; @@ -325,6 +332,146 @@ struct testQemuHotplugCpuParams { }; +struct testQemuHotplugCpuAsyncParams { + const char *test; + int newcpus; + const char *cpumap; + virConnectPtr conn; + const char **deviceDeletedAliases; + size_t ndeviceDeletedAliases; + const char *removedVcpus; + const char *arch; + GHashTable *capsLatestFiles; + GHashTable *capsCache; + GHashTable *schemaCache; +}; + + +struct testQemuHotplugCpuAsyncData { + int eventCallbackID; + virMutex lock; + virCond cond; + bool lockInitialized; + bool condInitialized; + virBitmap *removedVcpusExpected; + virBitmap *removedVcpusActual; + bool removedVcpusInvalid; + bool removedVcpusDuplicate; + bool ownsWorkerPool; +}; + + +static int +testQemuHotplugCpuAsyncDataInit(struct testQemuHotplugCpuAsyncData *asyncData, + const char *test) +{ + asyncData->eventCallbackID = -1; + + if (driver.workerPool) { + VIR_TEST_VERBOSE("stale qemu worker pool in async cpu test '%s'", + test); + return -1; + } + + if (virMutexInit(&asyncData->lock) < 0) + return -1; + asyncData->lockInitialized = true; + + if (virCondInit(&asyncData->cond) < 0) + return -1; + asyncData->condInitialized = true; + + if (!(driver.workerPool = virThreadPoolNewFull(0, 1, 0, + qemuProcessEventHandler, + "qemuProcessEventHandler", + NULL, &driver))) + return -1; + + asyncData->ownsWorkerPool = true; + + return 0; +} + + +static void +testQemuHotplugCpuAsyncDataClear(struct testQemuHotplugCpuAsyncData *asyncData, + virConnectPtr conn) +{ + if (asyncData->eventCallbackID >= 0) + virObjectEventStateDeregisterID(conn, driver.domainEventState, + asyncData->eventCallbackID, true); + + if (asyncData->ownsWorkerPool) + g_clear_pointer(&driver.workerPool, virThreadPoolFree); + + if (asyncData->condInitialized) + virCondDestroy(&asyncData->cond); + if (asyncData->lockInitialized) + virMutexDestroy(&asyncData->lock); + + g_clear_pointer(&asyncData->removedVcpusExpected, virBitmapFree); + g_clear_pointer(&asyncData->removedVcpusActual, virBitmapFree); +} + + +static int +testQemuHotplugCpuWaitVcpuRemoved(struct testQemuHotplugCpuAsyncData *asyncData) +{ + g_autofree char *expected = NULL; + g_autofree char *actual = NULL; + unsigned long long now; + unsigned long long deadline; + size_t expectedCount = virBitmapCountBits(asyncData->removedVcpusExpected); + size_t actualCount; + int ret = -1; + + if (virTimeMillisNow(&now) < 0) + return -1; + deadline = now + 1000; + + virMutexLock(&asyncData->lock); + while (virBitmapCountBits(asyncData->removedVcpusActual) < expectedCount) { + if (virCondWaitUntil(&asyncData->cond, &asyncData->lock, deadline) < 0) + break; + } + + actualCount = virBitmapCountBits(asyncData->removedVcpusActual); + + if (asyncData->removedVcpusInvalid) { + VIR_TEST_VERBOSE("async cpu test reported an unexpected vCPU id"); + goto cleanup; + } + + if (asyncData->removedVcpusDuplicate) { + VIR_TEST_VERBOSE("async cpu test received duplicate vcpu-removed events"); + goto cleanup; + } + + if (actualCount < expectedCount) { + VIR_TEST_VERBOSE("timed out waiting for vcpu-removed events" + " (%zu/%zu received)", + actualCount, expectedCount); + goto cleanup; + } + + if (!virBitmapEqual(asyncData->removedVcpusExpected, + asyncData->removedVcpusActual)) { + expected = virBitmapFormat(asyncData->removedVcpusExpected); + actual = virBitmapFormat(asyncData->removedVcpusActual); + VIR_TEST_VERBOSE("expected removed vCPUs '%s', got '%s'", + NULLSTR(expected), NULLSTR(actual)); + goto cleanup; + } + + ret = 0; + + cleanup: + virMutexUnlock(&asyncData->lock); + + return ret; +} + + static struct testQemuHotplugCpuData * testQemuHotplugCpuPrepare(const struct testQemuHotplugCpuParams *params) { @@ -407,6 +554,124 @@ testQemuHotplugCpuFinalize(struct testQemuHotplugCpuData *data) } +static void +testQemuHotplugCpuVcpuRemoved(virConnectPtr conn G_GNUC_UNUSED, + virDomainPtr dom G_GNUC_UNUSED, + unsigned int vcpuid, + void *opaque) +{ + struct testQemuHotplugCpuAsyncData *asyncData = opaque; + + virMutexLock(&asyncData->lock); + + if (virBitmapIsBitSet(asyncData->removedVcpusActual, vcpuid)) + asyncData->removedVcpusDuplicate = true; + + if (virBitmapSetBit(asyncData->removedVcpusActual, vcpuid) < 0) + asyncData->removedVcpusInvalid = true; + + virCondBroadcast(&asyncData->cond); + virMutexUnlock(&asyncData->lock); +} + + +static int +testQemuHotplugCpuRegisterVcpuRemoved(struct testQemuHotplugCpuData *data, + const struct testQemuHotplugCpuAsyncParams *async, + struct testQemuHotplugCpuAsyncData *asyncData) +{ + g_autoptr(virBitmap) expected = NULL; + size_t maxvcpus = virDomainDefGetVcpusMax(data->vm->def); + + if (!async->removedVcpus) { + VIR_TEST_VERBOSE("async cpu test '%s' is missing expected removed vCPUs", + async->test); + return -1; + } + + if (virBitmapParse(async->removedVcpus, &expected, maxvcpus) < 0) + return -1; + + if (!(asyncData->removedVcpusActual = virBitmapNew(maxvcpus))) + return -1; + + asyncData->removedVcpusExpected = g_steal_pointer(&expected); + + if (virDomainEventStateRegisterID(async->conn, + driver.domainEventState, + NULL, + VIR_DOMAIN_EVENT_ID_VCPU_REMOVED, + VIR_DOMAIN_EVENT_CALLBACK(testQemuHotplugCpuVcpuRemoved), + asyncData, + NULL, + &asyncData->eventCallbackID) < 0) + return -1; + + return 0; +} + + +static int +testQemuHotplugCpuCompleteAsync(struct testQemuHotplugCpuData *data, + const struct testQemuHotplugCpuAsyncParams *async, + struct testQemuHotplugCpuAsyncData *asyncData) +{ + g_autofree char *activeXML = NULL; + g_autofree char *pendingLiveFile = NULL; + size_t i; + bool vmUnlocked = false; + int ret = -1; + + if (!async->deviceDeletedAliases || + async->ndeviceDeletedAliases == 0) { + VIR_TEST_VERBOSE("async cpu test '%s' is missing DEVICE_DELETED aliases", + async->test); + return -1; + } + + if (!(activeXML = virDomainDefFormat(data->vm->def, driver.xmlopt, + VIR_DOMAIN_DEF_FORMAT_SECURE))) + return -1; + + pendingLiveFile = g_strdup_printf("%s/qemuhotplugtestcpus/%s-result-pending-live.xml", + abs_srcdir, async->test); + + if (virTestCompareToFile(activeXML, pendingLiveFile) < 0) + return -1; + + if (testQemuHotplugCpuRegisterVcpuRemoved(data, async, asyncData) < 0) + return -1; + + /* qemuDomainRefreshVcpuInfo() validates vCPU TIDs against the emulator + * PID. A running QEMU process always has a non-zero PID, so mirror that + * before DEVICE_DELETED processing reports unplugged vCPUs with tid == 0. */ + data->vm->pid = QEMU_HOTPLUG_TEST_DOMAIN_PID; + + virObjectUnlock(data->vm); + vmUnlocked = true; + + for (i = 0; i < async->ndeviceDeletedAliases; i++) + qemuMonitorTestEmitDeviceDeleted(data->mon, + async->deviceDeletedAliases[i]); + + if (testQemuHotplugCpuWaitVcpuRemoved(asyncData) < 0) + goto cleanup; + + virThreadPoolDrain(driver.workerPool); + + virObjectLock(data->vm); + vmUnlocked = false; + + ret = 0; + + cleanup: + if (vmUnlocked) + virObjectLock(data->vm); + + return ret; +} + + static int testQemuHotplugCpuGroup(const void *opaque) { @@ -442,6 +707,71 @@ testQemuHotplugCpuGroup(const void *opaque) } +static int +testQemuHotplugCpuAsync(const struct testQemuHotplugCpuAsyncParams *async, + bool group) +{ + struct testQemuHotplugCpuData *data = NULL; + struct testQemuHotplugCpuAsyncData asyncData = { .eventCallbackID = -1 }; + struct testQemuHotplugCpuParams params = { + .test = async->test, + .arch = async->arch, + .capsLatestFiles = async->capsLatestFiles, + .capsCache = async->capsCache, + .schemaCache = async->schemaCache, + }; + g_autoptr(virBitmap) map = NULL; + int ret = -1; + int rc; + + if (!(data = testQemuHotplugCpuPrepare(¶ms))) + return -1; + + if (testQemuHotplugCpuAsyncDataInit(&asyncData, async->test) < 0) + goto cleanup; + + if (group) { + rc = qemuDomainSetVcpusInternal(&driver, data->vm, data->vm->def, + data->vm->newDef, async->newcpus, + true, true); + } else { + if (virBitmapParse(async->cpumap, &map, 128) < 0) + goto cleanup; + + rc = qemuDomainSetVcpuInternal(&driver, data->vm, data->vm->def, + data->vm->newDef, map, false, + true); + } + + if (rc < 0) + goto cleanup; + + if (testQemuHotplugCpuCompleteAsync(data, async, &asyncData) < 0) + goto cleanup; + + ret = testQemuHotplugCpuFinalize(data); + + cleanup: + testQemuHotplugCpuAsyncDataClear(&asyncData, async->conn); + testQemuHotplugCpuDataFree(data); + return ret; +} + + +static int +testQemuHotplugCpuGroupAsync(const void *opaque) +{ + return testQemuHotplugCpuAsync(opaque, true); +} + + +static int +testQemuHotplugCpuIndividualAsync(const void *opaque) +{ + return testQemuHotplugCpuAsync(opaque, false); +} + + static int testQemuHotplugCpuIndividual(const void *opaque) { @@ -818,6 +1148,26 @@ mymain(void) ret = -1; \ } while (0) +#define DO_TEST_CPU_INDIVIDUAL_ASYNC(archname, prefix, mapstr, alias, removed) \ + do { \ + const char *aliases[] = { alias }; \ + const struct testQemuHotplugCpuAsyncParams async = { \ + .test = prefix, \ + .cpumap = mapstr, \ + .conn = conn, \ + .deviceDeletedAliases = aliases, \ + .ndeviceDeletedAliases = G_N_ELEMENTS(aliases), \ + .removedVcpus = removed, \ + .arch = archname, \ + .capsLatestFiles = capsLatestFiles, \ + .capsCache = capsCache, \ + .schemaCache = schemaCache, \ + }; \ + if (virTestRun("hotplug vcpus individual async " prefix, \ + testQemuHotplugCpuIndividualAsync, &async) < 0) \ + ret = -1; \ + } while (0) + DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "7", true, false); DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "6,7", true, true); DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "7", false, true); -- 2.47.3
Add async unplug coverage for the setvcpu path. The x86 case covers removal of a single hotpluggable vCPU entity, while the ppc64 case covers removal of a grouped hotpluggable entity. Both cases verify the pending XML before DEVICE_DELETED, the final XML after completion, and the expected vcpu-removed events. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- tests/qemuhotplugtest.c | 4 + ...c64-modern-individual-del-async-domain.xml | 68 ++++++ ...4-modern-individual-del-async-monitor.json | 227 ++++++++++++++++++ ...odern-individual-del-async-result-conf.xml | 68 ++++++ ...odern-individual-del-async-result-live.xml | 71 ++++++ ...dividual-del-async-result-pending-live.xml | 71 ++++++ ...x86-modern-individual-del-async-domain.xml | 42 ++++ ...6-modern-individual-del-async-monitor.json | 186 ++++++++++++++ ...odern-individual-del-async-result-conf.xml | 42 ++++ ...odern-individual-del-async-result-live.xml | 50 ++++ ...dividual-del-async-result-pending-live.xml | 50 ++++ 11 files changed, 879 insertions(+) create mode 100644 tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-domain.xml create mode 100644 tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-monitor.json create mode 100644 tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-conf.xml create mode 100644 tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-live.xml create mode 100644 tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-pending-live.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-individual-del-async-domain.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-individual-del-async-monitor.json create mode 100644 tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-conf.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-live.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-pending-live.xml diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 9696448e5b4e..402f58cbfc19 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -1171,10 +1171,14 @@ mymain(void) DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "7", true, false); DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "6,7", true, true); DO_TEST_CPU_INDIVIDUAL("x86_64", "x86-modern-individual-add", "7", false, true); + DO_TEST_CPU_INDIVIDUAL_ASYNC("x86_64", "x86-modern-individual-del-async", + "7", "vcpu7", "7"); DO_TEST_CPU_INDIVIDUAL("ppc64", "ppc64-modern-individual", "16-23", true, false); DO_TEST_CPU_INDIVIDUAL("ppc64", "ppc64-modern-individual", "16-22", true, true); DO_TEST_CPU_INDIVIDUAL("ppc64", "ppc64-modern-individual", "17", true, true); + DO_TEST_CPU_INDIVIDUAL_ASYNC("ppc64", "ppc64-modern-individual-del-async", + "16-23", "vcpu16", "16-23"); qemuTestDriverFree(&driver); virObjectUnref(data.vm); diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-domain.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-domain.xml new file mode 100644 index 000000000000..29f1a5ac45dc --- /dev/null +++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-domain.xml @@ -0,0 +1,68 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='16'>32</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='yes' hotpluggable='no'/> + <vcpu id='6' enabled='yes' hotpluggable='no'/> + <vcpu id='7' enabled='yes' hotpluggable='no'/> + <vcpu id='8' enabled='no' hotpluggable='yes'/> + <vcpu id='9' enabled='no' hotpluggable='yes'/> + <vcpu id='10' enabled='no' hotpluggable='yes'/> + <vcpu id='11' enabled='no' hotpluggable='yes'/> + <vcpu id='12' enabled='no' hotpluggable='yes'/> + <vcpu id='13' enabled='no' hotpluggable='yes'/> + <vcpu id='14' enabled='no' hotpluggable='yes'/> + <vcpu id='15' enabled='no' hotpluggable='yes'/> + <vcpu id='16' enabled='yes' hotpluggable='yes'/> + <vcpu id='17' enabled='yes' hotpluggable='yes'/> + <vcpu id='18' enabled='yes' hotpluggable='yes'/> + <vcpu id='19' enabled='yes' hotpluggable='yes'/> + <vcpu id='20' enabled='yes' hotpluggable='yes'/> + <vcpu id='21' enabled='yes' hotpluggable='yes'/> + <vcpu id='22' enabled='yes' hotpluggable='yes'/> + <vcpu id='23' enabled='yes' hotpluggable='yes'/> + <vcpu id='24' enabled='no' hotpluggable='yes'/> + <vcpu id='25' enabled='no' hotpluggable='yes'/> + <vcpu id='26' enabled='no' hotpluggable='yes'/> + <vcpu id='27' enabled='no' hotpluggable='yes'/> + <vcpu id='28' enabled='no' hotpluggable='yes'/> + <vcpu id='29' enabled='no' hotpluggable='yes'/> + <vcpu id='30' enabled='no' hotpluggable='yes'/> + <vcpu id='31' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + <topology sockets='1' dies='1' clusters='1' cores='4' threads='8'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0' model='pci-ohci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-monitor.json b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-monitor.json new file mode 100644 index 000000000000..c4b0a4b45d01 --- /dev/null +++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-monitor.json @@ -0,0 +1,227 @@ +{"execute":"query-hotpluggable-cpus","id":"libvirt-1"} + +{ + "return": [ + { + "props": { + "core-id": 24 + }, + "vcpus-count": 8, + "type": "host-spapr-cpu-core" + }, + { + "props": { + "core-id": 16 + }, + "vcpus-count": 8, + "qom-path": "/machine/peripheral/vcpu16", + "type": "host-spapr-cpu-core" + }, + { + "props": { + "core-id": 8 + }, + "vcpus-count": 8, + "type": "host-spapr-cpu-core" + }, + { + "props": { + "core-id": 0 + }, + "vcpus-count": 8, + "qom-path": "/machine/unattached/device[1]", + "type": "host-spapr-cpu-core" + } + ], + "id": "libvirt-15" +} + +{"execute":"query-cpus-fast","id":"libvirt-2"} + +{ + "return": [ + { + "target": "ppc", + "current": true, + "cpu-index": 0, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[0]", + "halted": false, + "thread-id": 21925 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 1, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[1]", + "halted": false, + "thread-id": 21926 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 2, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[2]", + "halted": false, + "thread-id": 21927 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 3, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[3]", + "halted": false, + "thread-id": 21928 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 4, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[4]", + "halted": false, + "thread-id": 21930 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 5, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[5]", + "halted": false, + "thread-id": 21931 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 6, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[6]", + "halted": false, + "thread-id": 21932 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 7, + "nip": -4611686018426772172, + "qom-path": "/machine/unattached/device[1]/thread[7]", + "halted": false, + "thread-id": 21933 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 8, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[0]", + "halted": false, + "thread-id": 22131 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 9, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[1]", + "halted": false, + "thread-id": 22132 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 10, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[2]", + "halted": false, + "thread-id": 22133 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 11, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[3]", + "halted": false, + "thread-id": 22134 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 12, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[4]", + "halted": false, + "thread-id": 22135 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 13, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[5]", + "halted": false, + "thread-id": 22136 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 14, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[6]", + "halted": false, + "thread-id": 22137 + }, + { + "target": "ppc", + "current": false, + "cpu-index": 15, + "nip": -4611686018426772172, + "qom-path": "/machine/peripheral/vcpu16/thread[7]", + "halted": false, + "thread-id": 22138 + } + ], + "id": "libvirt-14" +} + +{ + "execute": "device_del", + "arguments": { + "id": "vcpu16" + }, + "id": "libvirt-3" +} + +{"return": {}} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-4"} + +{ + "return": [ + {"props":{"core-id":0},"vcpus-count":8,"qom-path":"/machine/unattached/device[1]","type":"host-spapr-cpu-core"}, + {"props":{"core-id":8},"vcpus-count":8,"type":"host-spapr-cpu-core"}, + {"props":{"core-id":16},"vcpus-count":8,"type":"host-spapr-cpu-core"}, + {"props":{"core-id":24},"vcpus-count":8,"type":"host-spapr-cpu-core"} + ], + "id": "libvirt-4" +} + +{"execute":"query-cpus-fast","id":"libvirt-5"} + +{ + "return": [ + {"target":"ppc","current":true,"cpu-index":0,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[0]","halted":false,"thread-id":21925}, + {"target":"ppc","current":false,"cpu-index":1,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[1]","halted":false,"thread-id":21926}, + {"target":"ppc","current":false,"cpu-index":2,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[2]","halted":false,"thread-id":21927}, + {"target":"ppc","current":false,"cpu-index":3,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[3]","halted":false,"thread-id":21928}, + {"target":"ppc","current":false,"cpu-index":4,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[4]","halted":false,"thread-id":21930}, + {"target":"ppc","current":false,"cpu-index":5,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[5]","halted":false,"thread-id":21931}, + {"target":"ppc","current":false,"cpu-index":6,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[6]","halted":false,"thread-id":21932}, + {"target":"ppc","current":false,"cpu-index":7,"nip":-4611686018426772172,"qom-path":"/machine/unattached/device[1]/thread[7]","halted":false,"thread-id":21933} + ], + "id": "libvirt-5" +} diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-conf.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-conf.xml new file mode 100644 index 000000000000..dac1f476d45d --- /dev/null +++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-conf.xml @@ -0,0 +1,68 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='8'>32</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='yes' hotpluggable='no'/> + <vcpu id='6' enabled='yes' hotpluggable='no'/> + <vcpu id='7' enabled='yes' hotpluggable='no'/> + <vcpu id='8' enabled='no' hotpluggable='yes'/> + <vcpu id='9' enabled='no' hotpluggable='yes'/> + <vcpu id='10' enabled='no' hotpluggable='yes'/> + <vcpu id='11' enabled='no' hotpluggable='yes'/> + <vcpu id='12' enabled='no' hotpluggable='yes'/> + <vcpu id='13' enabled='no' hotpluggable='yes'/> + <vcpu id='14' enabled='no' hotpluggable='yes'/> + <vcpu id='15' enabled='no' hotpluggable='yes'/> + <vcpu id='16' enabled='no' hotpluggable='yes'/> + <vcpu id='17' enabled='no' hotpluggable='yes'/> + <vcpu id='18' enabled='no' hotpluggable='yes'/> + <vcpu id='19' enabled='no' hotpluggable='yes'/> + <vcpu id='20' enabled='no' hotpluggable='yes'/> + <vcpu id='21' enabled='no' hotpluggable='yes'/> + <vcpu id='22' enabled='no' hotpluggable='yes'/> + <vcpu id='23' enabled='no' hotpluggable='yes'/> + <vcpu id='24' enabled='no' hotpluggable='yes'/> + <vcpu id='25' enabled='no' hotpluggable='yes'/> + <vcpu id='26' enabled='no' hotpluggable='yes'/> + <vcpu id='27' enabled='no' hotpluggable='yes'/> + <vcpu id='28' enabled='no' hotpluggable='yes'/> + <vcpu id='29' enabled='no' hotpluggable='yes'/> + <vcpu id='30' enabled='no' hotpluggable='yes'/> + <vcpu id='31' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + <topology sockets='1' dies='1' clusters='1' cores='4' threads='8'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0' model='pci-ohci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-live.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-live.xml new file mode 100644 index 000000000000..1e5d4b030263 --- /dev/null +++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-live.xml @@ -0,0 +1,71 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='8'>32</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='yes' hotpluggable='no'/> + <vcpu id='6' enabled='yes' hotpluggable='no'/> + <vcpu id='7' enabled='yes' hotpluggable='no'/> + <vcpu id='8' enabled='no' hotpluggable='yes'/> + <vcpu id='9' enabled='no' hotpluggable='yes'/> + <vcpu id='10' enabled='no' hotpluggable='yes'/> + <vcpu id='11' enabled='no' hotpluggable='yes'/> + <vcpu id='12' enabled='no' hotpluggable='yes'/> + <vcpu id='13' enabled='no' hotpluggable='yes'/> + <vcpu id='14' enabled='no' hotpluggable='yes'/> + <vcpu id='15' enabled='no' hotpluggable='yes'/> + <vcpu id='16' enabled='no' hotpluggable='yes'/> + <vcpu id='17' enabled='no' hotpluggable='yes'/> + <vcpu id='18' enabled='no' hotpluggable='yes'/> + <vcpu id='19' enabled='no' hotpluggable='yes'/> + <vcpu id='20' enabled='no' hotpluggable='yes'/> + <vcpu id='21' enabled='no' hotpluggable='yes'/> + <vcpu id='22' enabled='no' hotpluggable='yes'/> + <vcpu id='23' enabled='no' hotpluggable='yes'/> + <vcpu id='24' enabled='no' hotpluggable='yes'/> + <vcpu id='25' enabled='no' hotpluggable='yes'/> + <vcpu id='26' enabled='no' hotpluggable='yes'/> + <vcpu id='27' enabled='no' hotpluggable='yes'/> + <vcpu id='28' enabled='no' hotpluggable='yes'/> + <vcpu id='29' enabled='no' hotpluggable='yes'/> + <vcpu id='30' enabled='no' hotpluggable='yes'/> + <vcpu id='31' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + <topology sockets='1' dies='1' clusters='1' cores='4' threads='8'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0' model='pci-ohci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + <alias name='pci.0'/> + </controller> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-pending-live.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-pending-live.xml new file mode 100644 index 000000000000..afa196de15f4 --- /dev/null +++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-del-async-result-pending-live.xml @@ -0,0 +1,71 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='16'>32</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='yes' hotpluggable='no'/> + <vcpu id='6' enabled='yes' hotpluggable='no'/> + <vcpu id='7' enabled='yes' hotpluggable='no'/> + <vcpu id='8' enabled='no' hotpluggable='yes'/> + <vcpu id='9' enabled='no' hotpluggable='yes'/> + <vcpu id='10' enabled='no' hotpluggable='yes'/> + <vcpu id='11' enabled='no' hotpluggable='yes'/> + <vcpu id='12' enabled='no' hotpluggable='yes'/> + <vcpu id='13' enabled='no' hotpluggable='yes'/> + <vcpu id='14' enabled='no' hotpluggable='yes'/> + <vcpu id='15' enabled='no' hotpluggable='yes'/> + <vcpu id='16' enabled='yes' hotpluggable='yes'/> + <vcpu id='17' enabled='yes' hotpluggable='yes'/> + <vcpu id='18' enabled='yes' hotpluggable='yes'/> + <vcpu id='19' enabled='yes' hotpluggable='yes'/> + <vcpu id='20' enabled='yes' hotpluggable='yes'/> + <vcpu id='21' enabled='yes' hotpluggable='yes'/> + <vcpu id='22' enabled='yes' hotpluggable='yes'/> + <vcpu id='23' enabled='yes' hotpluggable='yes'/> + <vcpu id='24' enabled='no' hotpluggable='yes'/> + <vcpu id='25' enabled='no' hotpluggable='yes'/> + <vcpu id='26' enabled='no' hotpluggable='yes'/> + <vcpu id='27' enabled='no' hotpluggable='yes'/> + <vcpu id='28' enabled='no' hotpluggable='yes'/> + <vcpu id='29' enabled='no' hotpluggable='yes'/> + <vcpu id='30' enabled='no' hotpluggable='yes'/> + <vcpu id='31' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>POWER9</model> + <topology sockets='1' dies='1' clusters='1' cores='4' threads='8'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <controller type='usb' index='0' model='pci-ohci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + <alias name='pci.0'/> + </controller> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-domain.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-domain.xml new file mode 100644 index 000000000000..539f607818cd --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-domain.xml @@ -0,0 +1,42 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='6'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='yes' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-monitor.json b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-monitor.json new file mode 100644 index 000000000000..6e96775c18b9 --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-monitor.json @@ -0,0 +1,186 @@ +{"execute":"query-hotpluggable-cpus","id":"libvirt-1"} + +{ + "return": [ + { + "props": { + "core-id": 1, + "thread-id": 1, + "socket-id": 1 + }, + "vcpus-count": 1, + "qom-path": "/machine/peripheral/vcpu7", + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 1, + "thread-id": 0, + "socket-id": 1 + }, + "vcpus-count": 1, + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 0, + "thread-id": 1, + "socket-id": 1 + }, + "vcpus-count": 1, + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 0, + "thread-id": 0, + "socket-id": 1 + }, + "vcpus-count": 1, + "qom-path": "/machine/unattached/device[5]", + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 1, + "thread-id": 1, + "socket-id": 0 + }, + "vcpus-count": 1, + "qom-path": "/machine/unattached/device[4]", + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 1, + "thread-id": 0, + "socket-id": 0 + }, + "vcpus-count": 1, + "qom-path": "/machine/unattached/device[3]", + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 0, + "thread-id": 1, + "socket-id": 0 + }, + "vcpus-count": 1, + "qom-path": "/machine/unattached/device[2]", + "type": "qemu64-x86_64-cpu" + }, + { + "props": { + "core-id": 0, + "thread-id": 0, + "socket-id": 0 + }, + "vcpus-count": 1, + "qom-path": "/machine/unattached/device[0]", + "type": "qemu64-x86_64-cpu" + } + ], + "id": "libvirt-23" +} + +{"execute":"query-cpus-fast","id":"libvirt-2"} + +{ + "return": [ + { + "target": "x86", + "current": true, + "cpu-index": 0, + "qom-path": "/machine/unattached/device[0]", + "pc": -2130415978, + "halted": true, + "thread-id": 518291 + }, + { + "target": "x86", + "current": false, + "cpu-index": 1, + "qom-path": "/machine/unattached/device[2]", + "pc": -2130415978, + "halted": true, + "thread-id": 518292 + }, + { + "target": "x86", + "current": false, + "cpu-index": 2, + "qom-path": "/machine/unattached/device[3]", + "pc": -2130415978, + "halted": true, + "thread-id": 518294 + }, + { + "target": "x86", + "current": false, + "cpu-index": 3, + "qom-path": "/machine/unattached/device[4]", + "pc": -2130415978, + "halted": true, + "thread-id": 518295 + }, + { + "target": "x86", + "current": false, + "cpu-index": 4, + "qom-path": "/machine/unattached/device[5]", + "pc": -2130415978, + "halted": true, + "thread-id": 518296 + }, + { + "target": "x86", + "current": false, + "cpu-index": 5, + "qom-path": "/machine/peripheral/vcpu7", + "pc": -2130415978, + "halted": true, + "thread-id": 518297 + } + ], + "id": "libvirt-22" +} + +{ + "execute": "device_del", + "arguments": { + "id": "vcpu7" + }, + "id": "libvirt-3" +} + +{"return": {}} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-4"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[5]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-4" +} + +{"execute":"query-cpus-fast","id":"libvirt-5"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295}, + {"target":"x86","current":false,"cpu-index":4,"qom-path":"/machine/unattached/device[5]","pc":-2130415978,"halted":true,"thread-id":518296} + ], + "id": "libvirt-5" +} diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-conf.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-conf.xml new file mode 100644 index 000000000000..f13f75d8d373 --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-conf.xml @@ -0,0 +1,42 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='5'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-live.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-live.xml new file mode 100644 index 000000000000..be9c15e6c119 --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-live.xml @@ -0,0 +1,50 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='5'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci.0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-pending-live.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-pending-live.xml new file mode 100644 index 000000000000..6a6c20e29031 --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-individual-del-async-result-pending-live.xml @@ -0,0 +1,50 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='6'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='no'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='yes' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci.0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> -- 2.47.3
Add async unplug coverage for the setvcpus count-based path. The test downscales an x86 domain by multiple hotpluggable vCPU entities, verifying the pending XML before completion, the final XML after DEVICE_DELETED processing, and one vcpu-removed event for each removed vCPU. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- tests/qemuhotplugtest.c | 20 +++ ...x86-modern-bulk-downscale-async-domain.xml | 42 +++++ ...6-modern-bulk-downscale-async-monitor.json | 159 ++++++++++++++++++ ...odern-bulk-downscale-async-result-conf.xml | 42 +++++ ...odern-bulk-downscale-async-result-live.xml | 50 ++++++ ...lk-downscale-async-result-pending-live.xml | 50 ++++++ 6 files changed, 363 insertions(+) create mode 100644 tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-domain.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-monitor.json create mode 100644 tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-conf.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-live.xml create mode 100644 tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-pending-live.xml diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 402f58cbfc19..60940a5df750 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -1180,6 +1180,26 @@ mymain(void) DO_TEST_CPU_INDIVIDUAL_ASYNC("ppc64", "ppc64-modern-individual-del-async", "16-23", "vcpu16", "16-23"); + do { + const char *aliases[] = { "vcpu7", "vcpu6", "vcpu5", "vcpu4" }; + const struct testQemuHotplugCpuAsyncParams async = { + .test = "x86-modern-bulk-downscale-async", + .newcpus = 4, + .conn = conn, + .deviceDeletedAliases = aliases, + .ndeviceDeletedAliases = G_N_ELEMENTS(aliases), + .removedVcpus = "4-7", + .arch = "x86_64", + .capsLatestFiles = capsLatestFiles, + .capsCache = capsCache, + .schemaCache = schemaCache, + }; + + if (virTestRun("hotplug vcpus group async x86-modern-bulk-downscale-async", + testQemuHotplugCpuGroupAsync, &async) < 0) + ret = -1; + } while (0); + qemuTestDriverFree(&driver); virObjectUnref(data.vm); return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-domain.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-domain.xml new file mode 100644 index 000000000000..513735211b7f --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-domain.xml @@ -0,0 +1,42 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='8'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='yes'/> + <vcpu id='5' enabled='yes' hotpluggable='yes'/> + <vcpu id='6' enabled='yes' hotpluggable='yes'/> + <vcpu id='7' enabled='yes' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-monitor.json b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-monitor.json new file mode 100644 index 000000000000..fafe41a9893f --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-monitor.json @@ -0,0 +1,159 @@ +{"execute":"query-hotpluggable-cpus","id":"libvirt-1"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/peripheral/vcpu4","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/peripheral/vcpu5","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/peripheral/vcpu6","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/peripheral/vcpu7","type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-1" +} + +{"execute":"query-cpus-fast","id":"libvirt-2"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295}, + {"target":"x86","current":false,"cpu-index":4,"qom-path":"/machine/peripheral/vcpu4","pc":-2130415978,"halted":true,"thread-id":518296}, + {"target":"x86","current":false,"cpu-index":5,"qom-path":"/machine/peripheral/vcpu5","pc":-2130415978,"halted":true,"thread-id":518297}, + {"target":"x86","current":false,"cpu-index":6,"qom-path":"/machine/peripheral/vcpu6","pc":-2130415978,"halted":true,"thread-id":518298}, + {"target":"x86","current":false,"cpu-index":7,"qom-path":"/machine/peripheral/vcpu7","pc":-2130415978,"halted":true,"thread-id":518299} + ], + "id": "libvirt-2" +} + +{"execute":"device_del","arguments":{"id":"vcpu7"},"id":"libvirt-3"} + +{"return": {}} + +{"execute":"device_del","arguments":{"id":"vcpu6"},"id":"libvirt-4"} + +{"return": {}} + +{"execute":"device_del","arguments":{"id":"vcpu5"},"id":"libvirt-5"} + +{"return": {}} + +{"execute":"device_del","arguments":{"id":"vcpu4"},"id":"libvirt-6"} + +{"return": {}} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-7"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-7" +} + +{"execute":"query-cpus-fast","id":"libvirt-8"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295} + ], + "id": "libvirt-8" +} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-9"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-9" +} + +{"execute":"query-cpus-fast","id":"libvirt-10"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295} + ], + "id": "libvirt-10" +} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-11"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-11" +} + +{"execute":"query-cpus-fast","id":"libvirt-12"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295} + ], + "id": "libvirt-12" +} + +{"execute":"query-hotpluggable-cpus","id":"libvirt-13"} + +{ + "return": [ + {"props":{"socket-id":0,"core-id":0,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[0]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":0,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[2]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":0},"vcpus-count":1,"qom-path":"/machine/unattached/device[3]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":0,"core-id":1,"thread-id":1},"vcpus-count":1,"qom-path":"/machine/unattached/device[4]","type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":0,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":0},"vcpus-count":1,"type":"qemu64-x86_64-cpu"}, + {"props":{"socket-id":1,"core-id":1,"thread-id":1},"vcpus-count":1,"type":"qemu64-x86_64-cpu"} + ], + "id": "libvirt-13" +} + +{"execute":"query-cpus-fast","id":"libvirt-14"} + +{ + "return": [ + {"target":"x86","current":true,"cpu-index":0,"qom-path":"/machine/unattached/device[0]","pc":-2130415978,"halted":true,"thread-id":518291}, + {"target":"x86","current":false,"cpu-index":1,"qom-path":"/machine/unattached/device[2]","pc":-2130415978,"halted":true,"thread-id":518292}, + {"target":"x86","current":false,"cpu-index":2,"qom-path":"/machine/unattached/device[3]","pc":-2130415978,"halted":true,"thread-id":518294}, + {"target":"x86","current":false,"cpu-index":3,"qom-path":"/machine/unattached/device[4]","pc":-2130415978,"halted":true,"thread-id":518295} + ], + "id": "libvirt-14" +} diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-conf.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-conf.xml new file mode 100644 index 000000000000..c35bc678f56f --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-conf.xml @@ -0,0 +1,42 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='4'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='no' hotpluggable='yes'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-live.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-live.xml new file mode 100644 index 000000000000..110c935f1c56 --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-live.xml @@ -0,0 +1,50 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' current='4'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='no' hotpluggable='yes'/> + <vcpu id='5' enabled='no' hotpluggable='yes'/> + <vcpu id='6' enabled='no' hotpluggable='yes'/> + <vcpu id='7' enabled='no' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci.0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-pending-live.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-pending-live.xml new file mode 100644 index 000000000000..1b843827aaeb --- /dev/null +++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-downscale-async-result-pending-live.xml @@ -0,0 +1,50 @@ +<domain type='qemu' id='7'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>8</vcpu> + <vcpus> + <vcpu id='0' enabled='yes' hotpluggable='no'/> + <vcpu id='1' enabled='yes' hotpluggable='no'/> + <vcpu id='2' enabled='yes' hotpluggable='no'/> + <vcpu id='3' enabled='yes' hotpluggable='no'/> + <vcpu id='4' enabled='yes' hotpluggable='yes'/> + <vcpu id='5' enabled='yes' hotpluggable='yes'/> + <vcpu id='6' enabled='yes' hotpluggable='yes'/> + <vcpu id='7' enabled='yes' hotpluggable='yes'/> + </vcpus> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <topology sockets='4' dies='1' clusters='1' cores='2' threads='1'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci.0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> -- 2.47.3
The vCPU APIs have API-specific flag enums that alias the generic VIR_DOMAIN_AFFECT_* values for live and config state. Use the vCPU-specific aliases in the public API checks, QEMU driver flag masks, and virsh flag construction. The values are unchanged; this is only a consistency cleanup. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- src/libvirt-domain.c | 4 ++-- src/qemu/qemu_driver.c | 8 ++++---- tools/virsh-domain.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index a4cbeb8ad486..a37cc741351a 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -7803,11 +7803,11 @@ virDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, virCheckReadOnlyGoto(domain->conn->flags, error); VIR_REQUIRE_FLAG_GOTO(VIR_DOMAIN_VCPU_MAXIMUM, - VIR_DOMAIN_AFFECT_CONFIG, + VIR_DOMAIN_VCPU_CONFIG, error); VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_VCPU_GUEST, - VIR_DOMAIN_AFFECT_CONFIG, + VIR_DOMAIN_VCPU_CONFIG, error); virCheckNonZeroArgGoto(nvcpus, error); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c6d18f6575b7..48cad937d8bb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4331,8 +4331,8 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, bool useAgent = !!(flags & VIR_DOMAIN_VCPU_GUEST); int ret = -1; - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_AFFECT_CONFIG | + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_GUEST | VIR_DOMAIN_VCPU_HOTPLUGGABLE | @@ -19377,8 +19377,8 @@ qemuDomainSetVcpu(virDomainPtr dom, ssize_t lastvcpu; int ret = -1; - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_AFFECT_CONFIG | + virCheckFlags(VIR_DOMAIN_SETVCPU_AFFECT_LIVE | + VIR_DOMAIN_SETVCPU_AFFECT_CONFIG | VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG, -1); if (state != 0 && state != 1) { diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 76369e8694ce..513129cda71b 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -7696,9 +7696,9 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) VSH_REQUIRE_OPTION_VAR(maximum, config); if (config) - flags |= VIR_DOMAIN_AFFECT_CONFIG; + flags |= VIR_DOMAIN_VCPU_CONFIG; if (live) - flags |= VIR_DOMAIN_AFFECT_LIVE; + flags |= VIR_DOMAIN_VCPU_LIVE; if (guest) flags |= VIR_DOMAIN_VCPU_GUEST; if (maximum) @@ -7867,9 +7867,9 @@ cmdSetvcpu(vshControl *ctl, const vshCmd *cmd) VSH_EXCLUSIVE_OPTIONS("async", "enable"); if (config) - flags |= VIR_DOMAIN_AFFECT_CONFIG; + flags |= VIR_DOMAIN_SETVCPU_AFFECT_CONFIG; if (live) - flags |= VIR_DOMAIN_AFFECT_LIVE; + flags |= VIR_DOMAIN_SETVCPU_AFFECT_LIVE; if (async) flags |= VIR_DOMAIN_SETVCPU_ASYNC_UNPLUG; -- 2.47.3
Do not reject setvcpu --enable --async or setvcpus --guest --async in virsh. For setvcpu, async only affects live unplug and is documented as having no effect when enabling vCPUs. For setvcpus, guest+async is a driver-visible flag combination; drivers should decide whether they can support it. Keep virsh validation limited to API-level constraints and let drivers report unsupported combinations. Signed-off-by: Akash Kulhalli <akash.kulhalli@oracle.com> --- tools/virsh-domain.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 513129cda71b..0687a3190ead 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -7691,7 +7691,6 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) VSH_EXCLUSIVE_OPTIONS_VAR(current, live); VSH_EXCLUSIVE_OPTIONS_VAR(current, config); VSH_EXCLUSIVE_OPTIONS_VAR(guest, config); - VSH_EXCLUSIVE_OPTIONS_VAR(async, guest); VSH_REQUIRE_OPTION_VAR(maximum, config); @@ -7864,7 +7863,6 @@ cmdSetvcpu(vshControl *ctl, const vshCmd *cmd) VSH_EXCLUSIVE_OPTIONS("current", "live"); VSH_EXCLUSIVE_OPTIONS("current", "config"); - VSH_EXCLUSIVE_OPTIONS("async", "enable"); if (config) flags |= VIR_DOMAIN_SETVCPU_AFFECT_CONFIG; -- 2.47.3
Bumping, been a couple of weeks since this one was sent, feedback would be appreciated! On 2026-05-20 4:49 PM, Akash Kulhalli wrote:
This series adds qemuhotplugtest coverage for async vCPU unplug.
Async vCPU unplug does not complete at the device_del reply. The guest CPU remains in a pending removal state until QEMU reports DEVICE_DELETED and the QEMU driver handles the resulting process event. The new harness support lets the tests observe that intermediate state and then complete the unplug through the same process-event path used by the driver.
The setvcpu coverage exercises both a single-vCPU x86 hotplug entity and a grouped ppc64 hotplug entity. These cases check the pending live XML before completion and the final live/config XML after completion, while also validating the expected vcpu-removed domain events.
The setvcpus coverage adds a separate count-based x86 downscale case. This keeps the independent count-to-entity selection path covered without duplicating the grouped-entity coverage from setvcpu.
The series also includes a small domain API cleanup to use the vCPU-specific flag aliases consistently in the vCPU entry points. This keeps the implementation and diagnostics aligned with the API being handled. This is a cosmetic change only, since the underlying values are all mapped to their equivalent enums.
While adding this coverage, I realised that virsh was being too restrictive in its parameter combination validation; only QEMU does not support both `--async` and `--guest`. Other drivers may wish to support this behaviour. Accordingly, I've changed the behaviour so that virsh now lets the drivers reject the combination if they're unsupported. The decision now rests with the driver, which is more appropriate.
Akash Kulhalli (7): qemu: expose process event handler to tests tests: add helper for DEVICE_DELETED events qemuhotplugtest: support async vcpu unplug completion qemuhotplugtest: test setvcpu async unplug qemuhotplugtest: test setvcpus async downscale domain: use vcpu-specific flag aliases consistently virsh: allow async vcpu options to reach drivers
participants (1)
-
Akash Kulhalli