2 * Copyright (C) 2011-2013 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
22 #include "qemu/qemu_alias.h"
23 #include "qemu/qemu_conf.h"
24 #include "qemu/qemu_hotplug.h"
25 #define LIBVIRT_QEMU_HOTPLUGPRIV_H_ALLOW
26 #include "qemu/qemu_hotplugpriv.h"
27 #include "qemumonitortestutils.h"
28 #include "testutils.h"
29 #include "testutilsqemu.h"
30 #include "testutilsqemuschema.h"
32 #include "virstring.h"
33 #include "virthread.h"
36 #define VIR_FROM_THIS VIR_FROM_NONE
38 static virQEMUDriver driver
;
46 #define QEMU_HOTPLUG_TEST_DOMAIN_ID 7
48 struct qemuHotplugTestData
{
49 const char *domain_filename
;
50 const char *device_filename
;
52 const char *const *mon
;
56 bool deviceDeletedEvent
;
60 qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt
,
65 qemuDomainObjPrivatePtr priv
= NULL
;
66 const unsigned int parseFlags
= 0;
68 if (!(*vm
= virDomainObjNew(xmlopt
)))
71 priv
= (*vm
)->privateData
;
73 if (!(priv
->qemuCaps
= virQEMUCapsNew()))
76 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_VIRTIO_SCSI
);
77 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_DEVICE_USB_STORAGE
);
78 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_CCW
);
79 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_DEVICE_IVSHMEM_PLAIN
);
80 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL
);
81 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_SCSI_DISK_WWN
);
83 if (qemuTestCapsCacheInsert(driver
.qemuCapsCache
, priv
->qemuCaps
) < 0)
86 if (!((*vm
)->def
= virDomainDefParseString(domxml
,
93 if (qemuDomainAssignAddresses((*vm
)->def
, priv
->qemuCaps
,
94 &driver
, *vm
, true) < 0) {
98 if (qemuAssignDeviceAliases((*vm
)->def
, priv
->qemuCaps
) < 0)
101 (*vm
)->def
->id
= QEMU_HOTPLUG_TEST_DOMAIN_ID
;
103 if (qemuDomainSetPrivatePaths(&driver
, *vm
) < 0)
112 testQemuHotplugAttach(virDomainObjPtr vm
,
113 virDomainDeviceDefPtr dev
)
118 case VIR_DOMAIN_DEVICE_DISK
:
119 /* conn in only used for storage pool and secrets lookup so as long
120 * as we don't use any of them, passing NULL should be safe
122 ret
= qemuDomainAttachDeviceDiskLive(&driver
, vm
, dev
);
124 case VIR_DOMAIN_DEVICE_CHR
:
125 ret
= qemuDomainAttachChrDevice(&driver
, vm
, dev
->data
.chr
);
127 case VIR_DOMAIN_DEVICE_SHMEM
:
128 ret
= qemuDomainAttachShmemDevice(&driver
, vm
, dev
->data
.shmem
);
130 case VIR_DOMAIN_DEVICE_WATCHDOG
:
131 ret
= qemuDomainAttachWatchdog(&driver
, vm
, dev
->data
.watchdog
);
134 VIR_TEST_VERBOSE("device type '%s' cannot be attached\n",
135 virDomainDeviceTypeToString(dev
->type
));
143 testQemuHotplugDetach(virDomainObjPtr vm
,
144 virDomainDeviceDefPtr dev
,
150 case VIR_DOMAIN_DEVICE_DISK
:
151 case VIR_DOMAIN_DEVICE_CHR
:
152 case VIR_DOMAIN_DEVICE_SHMEM
:
153 case VIR_DOMAIN_DEVICE_WATCHDOG
:
154 ret
= qemuDomainDetachDeviceLive(vm
, dev
, &driver
, async
);
157 VIR_TEST_VERBOSE("device type '%s' cannot be detached\n",
158 virDomainDeviceTypeToString(dev
->type
));
166 testQemuHotplugUpdate(virDomainObjPtr vm
,
167 virDomainDeviceDefPtr dev
)
171 /* XXX Ideally, we would call qemuDomainUpdateDeviceLive here. But that
172 * would require us to provide virConnectPtr and virDomainPtr (they're used
173 * in case of updating a disk device. So for now, we will proceed with
174 * breaking the function into pieces. If we ever learn how to fake those
175 * required object, we can replace this code then. */
177 case VIR_DOMAIN_DEVICE_GRAPHICS
:
178 ret
= qemuDomainChangeGraphics(&driver
, vm
, dev
->data
.graphics
);
181 VIR_TEST_VERBOSE("device type '%s' cannot be updated\n",
182 virDomainDeviceTypeToString(dev
->type
));
190 testQemuHotplugCheckResult(virDomainObjPtr vm
,
191 const char *expected
,
192 const char *expectedFile
,
198 actual
= virDomainDefFormat(vm
->def
, driver
.caps
,
199 VIR_DOMAIN_DEF_FORMAT_SECURE
);
202 vm
->def
->id
= QEMU_HOTPLUG_TEST_DOMAIN_ID
;
204 if (STREQ(expected
, actual
)) {
206 VIR_TEST_VERBOSE("domain XML should not match the expected result\n");
210 virTestDifferenceFull(stderr
,
211 expected
, expectedFile
,
221 testQemuHotplug(const void *data
)
224 struct qemuHotplugTestData
*test
= (struct qemuHotplugTestData
*) data
;
225 char *domain_filename
= NULL
;
226 char *device_filename
= NULL
;
227 char *result_filename
= NULL
;
228 char *domain_xml
= NULL
;
229 char *device_xml
= NULL
;
230 char *result_xml
= NULL
;
231 const char *const *tmp
;
232 bool fail
= test
->fail
;
233 bool keep
= test
->keep
;
234 unsigned int device_parse_flags
= 0;
235 virDomainObjPtr vm
= NULL
;
236 virDomainDeviceDefPtr dev
= NULL
;
237 virCapsPtr caps
= NULL
;
238 qemuMonitorTestPtr test_mon
= NULL
;
239 qemuDomainObjPrivatePtr priv
= NULL
;
241 if (virAsprintf(&domain_filename
, "%s/qemuhotplugtestdomains/qemuhotplug-%s.xml",
242 abs_srcdir
, test
->domain_filename
) < 0 ||
243 virAsprintf(&device_filename
, "%s/qemuhotplugtestdevices/qemuhotplug-%s.xml",
244 abs_srcdir
, test
->device_filename
) < 0 ||
245 virAsprintf(&result_filename
,
246 "%s/qemuhotplugtestdomains/qemuhotplug-%s+%s.xml",
247 abs_srcdir
, test
->domain_filename
,
248 test
->device_filename
) < 0)
251 if (virTestLoadFile(domain_filename
, &domain_xml
) < 0 ||
252 virTestLoadFile(device_filename
, &device_xml
) < 0)
255 if (test
->action
== ATTACH
&&
256 virTestLoadFile(result_filename
, &result_xml
) < 0)
259 if (!(caps
= virQEMUDriverGetCapabilities(&driver
, false)))
265 VIR_TEST_VERBOSE("test skipped due to failure of dependent test\n");
269 if (qemuHotplugCreateObjects(driver
.xmlopt
, &vm
, domain_xml
) < 0)
273 if (test
->action
== ATTACH
)
274 device_parse_flags
= VIR_DOMAIN_DEF_PARSE_INACTIVE
;
276 if (!(dev
= virDomainDeviceDefParse(device_xml
, vm
->def
,
277 caps
, driver
.xmlopt
, NULL
,
278 device_parse_flags
)))
281 /* Now is the best time to feed the spoofed monitor with predefined
283 if (!(test_mon
= qemuMonitorTestNew(driver
.xmlopt
, vm
, &driver
,
288 while (tmp
&& *tmp
) {
289 const char *command_name
;
290 const char *response
;
292 if (!(command_name
= *tmp
++) ||
293 !(response
= *tmp
++))
295 if (qemuMonitorTestAddItem(test_mon
, command_name
, response
) < 0)
299 priv
= vm
->privateData
;
300 priv
->mon
= qemuMonitorTestGetMonitor(test_mon
);
302 /* XXX We need to unlock the monitor here, as
303 * qemuDomainObjEnterMonitorInternal (called from qemuDomainChangeGraphics)
304 * tries to lock it again */
305 virObjectUnlock(priv
->mon
);
307 switch (test
->action
) {
309 ret
= testQemuHotplugAttach(vm
, dev
);
311 /* vm->def stolen dev->data.* so we just need to free the dev
315 if (ret
== 0 || fail
)
316 ret
= testQemuHotplugCheckResult(vm
, result_xml
,
317 result_filename
, fail
);
321 ret
= testQemuHotplugDetach(vm
, dev
, false);
322 if (ret
== 0 || fail
)
323 ret
= testQemuHotplugCheckResult(vm
, domain_xml
,
324 domain_filename
, fail
);
328 ret
= testQemuHotplugUpdate(vm
, dev
);
332 VIR_FREE(domain_filename
);
333 VIR_FREE(device_filename
);
334 VIR_FREE(result_filename
);
335 VIR_FREE(domain_xml
);
336 VIR_FREE(device_xml
);
337 VIR_FREE(result_xml
);
338 /* don't dispose test monitor with VM */
347 virDomainDeviceDefFree(dev
);
348 virObjectUnref(caps
);
349 qemuMonitorTestFree(test_mon
);
350 return ((ret
< 0 && fail
) || (!ret
&& !fail
)) ? 0 : -1;
354 struct testQemuHotplugCpuData
{
356 char *file_xml_res_live
;
357 char *file_xml_res_conf
;
358 char *file_json_monitor
;
363 qemuMonitorTestPtr mon
;
369 testQemuHotplugCpuDataFree(struct testQemuHotplugCpuData
*data
)
371 qemuDomainObjPrivatePtr priv
;
376 VIR_FREE(data
->file_xml_dom
);
377 VIR_FREE(data
->file_xml_res_live
);
378 VIR_FREE(data
->file_xml_res_conf
);
379 VIR_FREE(data
->file_json_monitor
);
381 VIR_FREE(data
->xml_dom
);
384 priv
= data
->vm
->privateData
;
387 virObjectUnref(data
->vm
);
390 qemuMonitorTestFree(data
->mon
);
395 static struct testQemuHotplugCpuData
*
396 testQemuHotplugCpuPrepare(const char *test
,
398 virHashTablePtr qmpschema
)
400 qemuDomainObjPrivatePtr priv
= NULL
;
401 virCapsPtr caps
= NULL
;
403 struct testQemuHotplugCpuData
*data
= NULL
;
405 if (virAsprintf(&prefix
, "%s/qemuhotplugtestcpus/%s", abs_srcdir
, test
) < 0)
408 if (VIR_ALLOC(data
) < 0)
411 data
->modern
= modern
;
413 if (virAsprintf(&data
->file_xml_dom
, "%s-domain.xml", prefix
) < 0 ||
414 virAsprintf(&data
->file_xml_res_live
, "%s-result-live.xml", prefix
) < 0 ||
415 virAsprintf(&data
->file_xml_res_conf
, "%s-result-conf.xml", prefix
) < 0 ||
416 virAsprintf(&data
->file_json_monitor
, "%s-monitor.json", prefix
) < 0)
419 if (virTestLoadFile(data
->file_xml_dom
, &data
->xml_dom
) < 0)
422 if (qemuHotplugCreateObjects(driver
.xmlopt
, &data
->vm
, data
->xml_dom
) < 0)
425 if (!(caps
= virQEMUDriverGetCapabilities(&driver
, false)))
428 /* create vm->newDef */
429 data
->vm
->persistent
= true;
430 if (virDomainObjSetDefTransient(caps
, driver
.xmlopt
, data
->vm
, NULL
) < 0)
433 priv
= data
->vm
->privateData
;
436 virQEMUCapsSet(priv
->qemuCaps
, QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS
);
438 if (!(data
->mon
= qemuMonitorTestNewFromFileFull(data
->file_json_monitor
,
439 &driver
, data
->vm
, qmpschema
)))
442 priv
->mon
= qemuMonitorTestGetMonitor(data
->mon
);
443 virObjectUnlock(priv
->mon
);
445 if (qemuDomainRefreshVcpuInfo(&driver
, data
->vm
, 0, false) < 0)
453 virObjectUnref(caps
);
454 testQemuHotplugCpuDataFree(data
);
461 testQemuHotplugCpuFinalize(struct testQemuHotplugCpuData
*data
)
464 char *activeXML
= NULL
;
465 char *configXML
= NULL
;
467 if (data
->file_xml_res_live
) {
468 if (!(activeXML
= virDomainDefFormat(data
->vm
->def
, driver
.caps
,
469 VIR_DOMAIN_DEF_FORMAT_SECURE
)))
472 if (virTestCompareToFile(activeXML
, data
->file_xml_res_live
) < 0)
476 if (data
->file_xml_res_conf
) {
477 if (!(configXML
= virDomainDefFormat(data
->vm
->newDef
, driver
.caps
,
478 VIR_DOMAIN_DEF_FORMAT_SECURE
|
479 VIR_DOMAIN_DEF_FORMAT_INACTIVE
)))
482 if (virTestCompareToFile(configXML
, data
->file_xml_res_conf
) < 0)
495 struct testQemuHotplugCpuParams
{
502 virHashTablePtr schema
;
507 testQemuHotplugCpuGroup(const void *opaque
)
509 const struct testQemuHotplugCpuParams
*params
= opaque
;
510 struct testQemuHotplugCpuData
*data
= NULL
;
514 if (!(data
= testQemuHotplugCpuPrepare(params
->test
, params
->modern
,
518 rc
= qemuDomainSetVcpusInternal(&driver
, data
->vm
, data
->vm
->def
,
519 data
->vm
->newDef
, params
->newcpus
,
524 fprintf(stderr
, "cpu test '%s' should have failed\n", params
->test
);
534 ret
= testQemuHotplugCpuFinalize(data
);
537 testQemuHotplugCpuDataFree(data
);
543 testQemuHotplugCpuIndividual(const void *opaque
)
545 const struct testQemuHotplugCpuParams
*params
= opaque
;
546 struct testQemuHotplugCpuData
*data
= NULL
;
547 virBitmapPtr map
= NULL
;
551 if (!(data
= testQemuHotplugCpuPrepare(params
->test
, params
->modern
,
555 if (virBitmapParse(params
->cpumap
, &map
, 128) < 0)
558 rc
= qemuDomainSetVcpuInternal(&driver
, data
->vm
, data
->vm
->def
,
559 data
->vm
->newDef
, map
, params
->state
);
563 fprintf(stderr
, "cpu test '%s' should have failed\n", params
->test
);
573 ret
= testQemuHotplugCpuFinalize(data
);
577 testQemuHotplugCpuDataFree(data
);
586 VIR_AUTOPTR(virHashTable
) qmpschema
= NULL
;
588 struct qemuHotplugTestData data
= {0};
589 struct testQemuHotplugCpuParams cpudata
;
592 fputs("libvirt not compiled with JSON support, skipping this test\n", stderr
);
596 if (virThreadInitialize() < 0 ||
597 qemuTestDriverInit(&driver
) < 0)
600 virEventRegisterDefaultImpl();
602 VIR_FREE(driver
.config
->spiceListen
);
603 VIR_FREE(driver
.config
->vncListen
);
604 /* some dummy values from 'config file' */
605 if (VIR_STRDUP_QUIET(driver
.config
->spicePassword
, "123456") < 0)
608 if (!(driver
.domainEventState
= virObjectEventStateNew()))
611 if (!(qmpschema
= testQEMUSchemaLoad())) {
612 VIR_TEST_VERBOSE("failed to load qapi schema\n");
616 cpudata
.schema
= qmpschema
;
618 driver
.lockManager
= virLockManagerPluginNew("nop", "qemu",
619 driver
.config
->configBaseDir
,
621 if (!driver
.lockManager
)
624 /* wait only 100ms for DEVICE_DELETED event */
625 qemuDomainRemoveDeviceWaitTime
= 100;
627 #define DO_TEST(file, ACTION, dev, fial, kep, ...) \
629 const char *my_mon[] = { __VA_ARGS__, NULL}; \
630 const char *name = file " " #ACTION " " dev; \
631 data.action = ACTION; \
632 data.domain_filename = file; \
633 data.device_filename = dev; \
637 if (virTestRun(name, testQemuHotplug, &data) < 0) \
641 #define DO_TEST_ATTACH(file, dev, fial, kep, ...) \
642 DO_TEST(file, ATTACH, dev, fial, kep, __VA_ARGS__)
644 #define DO_TEST_DETACH(file, dev, fial, kep, ...) \
645 DO_TEST(file, DETACH, dev, fial, kep, __VA_ARGS__)
647 #define DO_TEST_UPDATE(file, dev, fial, kep, ...) \
648 DO_TEST(file, UPDATE, dev, fial, kep, __VA_ARGS__)
651 #define QMP_OK "{\"return\": {}}"
652 #define HMP(msg) "{\"return\": \"" msg "\"}"
654 #define QMP_DEVICE_DELETED(dev) \
656 " \"timestamp\": {" \
657 " \"seconds\": 1374137171," \
658 " \"microseconds\": 2659" \
660 " \"event\": \"DEVICE_DELETED\"," \
662 " \"device\": \"" dev "\"," \
663 " \"path\": \"/machine/peripheral/" dev "\"" \
667 DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, NULL
);
668 DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false,
669 "set_password", QMP_OK
, "expire_password", QMP_OK
);
670 DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-password", false, false,
671 "set_password", QMP_OK
, "expire_password", QMP_OK
);
672 DO_TEST_UPDATE("graphics-spice", "graphics-spice-listen", true, false, NULL
);
673 DO_TEST_UPDATE("graphics-spice-listen-network", "graphics-spice-listen-network-password", false, false,
674 "set_password", QMP_OK
, "expire_password", QMP_OK
);
675 /* Strange huh? Currently, only graphics can be updated :-P */
676 DO_TEST_UPDATE("disk-cdrom", "disk-cdrom-nochange", true, false, NULL
);
678 DO_TEST_ATTACH("console-compat-2-live", "console-virtio", false, true,
679 "chardev-add", "{\"return\": {\"pty\": \"/dev/pts/26\"}}",
680 "device_add", QMP_OK
);
682 DO_TEST_DETACH("console-compat-2-live", "console-virtio", false, false,
683 "device_del", QMP_DEVICE_DELETED("console1") QMP_OK
,
684 "chardev-remove", QMP_OK
);
686 DO_TEST_ATTACH("base-live", "disk-virtio", false, true,
687 "human-monitor-command", HMP("OK\\r\\n"),
688 "device_add", QMP_OK
);
689 DO_TEST_DETACH("base-live", "disk-virtio", true, true,
690 "device_del", QMP_OK
,
691 "human-monitor-command", HMP(""));
692 DO_TEST_DETACH("base-live", "disk-virtio", false, false,
693 "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK
,
694 "human-monitor-command", HMP(""));
696 DO_TEST_ATTACH("base-live", "disk-usb", false, true,
697 "human-monitor-command", HMP("OK\\r\\n"),
698 "device_add", QMP_OK
);
699 DO_TEST_DETACH("base-live", "disk-usb", true, true,
700 "device_del", QMP_OK
,
701 "human-monitor-command", HMP(""));
702 DO_TEST_DETACH("base-live", "disk-usb", false, false,
703 "device_del", QMP_DEVICE_DELETED("usb-disk16") QMP_OK
,
704 "human-monitor-command", HMP(""));
706 DO_TEST_ATTACH("base-live", "disk-scsi", false, true,
707 "human-monitor-command", HMP("OK\\r\\n"),
708 "device_add", QMP_OK
);
709 DO_TEST_DETACH("base-live", "disk-scsi", true, true,
710 "device_del", QMP_OK
,
711 "human-monitor-command", HMP(""));
712 DO_TEST_DETACH("base-live", "disk-scsi", false, false,
713 "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK
,
714 "human-monitor-command", HMP(""));
716 DO_TEST_ATTACH("base-without-scsi-controller-live", "disk-scsi-2", false, true,
717 /* Four controllers added */
718 "device_add", QMP_OK
,
719 "device_add", QMP_OK
,
720 "device_add", QMP_OK
,
721 "device_add", QMP_OK
,
722 "human-monitor-command", HMP("OK\\r\\n"),
724 "device_add", QMP_OK
);
725 DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", true, true,
726 "device_del", QMP_OK
,
727 "human-monitor-command", HMP(""));
728 DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false,
729 "device_del", QMP_DEVICE_DELETED("scsi3-0-5-6") QMP_OK
,
730 "human-monitor-command", HMP(""));
732 DO_TEST_ATTACH("base-live", "qemu-agent", false, true,
733 "chardev-add", QMP_OK
,
734 "device_add", QMP_OK
);
735 DO_TEST_DETACH("base-live", "qemu-agent-detach", false, false,
736 "device_del", QMP_DEVICE_DELETED("channel0") QMP_OK
,
737 "chardev-remove", QMP_OK
);
739 DO_TEST_ATTACH("base-ccw-live", "ccw-virtio", false, true,
740 "human-monitor-command", HMP("OK\\r\\n"),
741 "device_add", QMP_OK
);
742 DO_TEST_DETACH("base-ccw-live", "ccw-virtio", false, false,
743 "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK
,
744 "human-monitor-command", HMP(""));
746 DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, true,
747 "human-monitor-command", HMP("OK\\r\\n"),
748 "device_add", QMP_OK
);
750 DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, false,
751 "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK
,
752 "human-monitor-command", HMP(""));
754 DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true,
755 "human-monitor-command", HMP("OK\\r\\n"),
756 "device_add", QMP_OK
);
758 DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, false,
759 "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK
,
760 "human-monitor-command", HMP(""));
762 /* Attach a second device, then detach the first one. Then attach the first one again. */
763 DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true,
764 "human-monitor-command", HMP("OK\\r\\n"),
765 "device_add", QMP_OK
);
767 DO_TEST_DETACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-explicit", false, true,
768 "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK
,
769 "human-monitor-command", HMP(""));
771 DO_TEST_ATTACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-reverse", false, false,
772 "human-monitor-command", HMP("OK\\r\\n"),
773 "device_add", QMP_OK
);
775 DO_TEST_ATTACH("base-live", "ivshmem-plain", false, true,
776 "object-add", QMP_OK
,
777 "device_add", QMP_OK
);
778 DO_TEST_ATTACH("base-live", "ivshmem-doorbell", false, true,
779 "chardev-add", QMP_OK
,
780 "device_add", QMP_OK
);
781 DO_TEST_DETACH("base-live+ivshmem-plain", "ivshmem-doorbell-detach", false, true,
782 "device_del", QMP_DEVICE_DELETED("shmem1") QMP_OK
,
783 "chardev-remove", QMP_OK
);
784 DO_TEST_DETACH("base-live", "ivshmem-plain-detach", false, false,
785 "device_del", QMP_DEVICE_DELETED("shmem0") QMP_OK
,
786 "object-del", QMP_OK
);
787 DO_TEST_ATTACH("base-live+disk-scsi-wwn",
788 "disk-scsi-duplicate-wwn", false, false,
789 "human-monitor-command", HMP("OK\\r\\n"),
790 "device_add", QMP_OK
);
792 DO_TEST_ATTACH("base-live", "watchdog", false, true,
793 "watchdog-set-action", QMP_OK
,
794 "device_add", QMP_OK
);
795 DO_TEST_DETACH("base-live", "watchdog-full", false, false,
796 "device_del", QMP_DEVICE_DELETED("watchdog0") QMP_OK
);
798 DO_TEST_ATTACH("base-live", "watchdog-user-alias", false, true,
799 "watchdog-set-action", QMP_OK
,
800 "device_add", QMP_OK
);
801 DO_TEST_DETACH("base-live", "watchdog-user-alias-full", false, false,
802 "device_del", QMP_DEVICE_DELETED("ua-UserWatchdog") QMP_OK
);
804 DO_TEST_ATTACH("base-live", "guestfwd", false, true,
805 "chardev-add", QMP_OK
,
806 "netdev_add", QMP_OK
);
807 DO_TEST_DETACH("base-live", "guestfwd", false, false,
808 "netdev_del", QMP_OK
);
810 #define DO_TEST_CPU_GROUP(prefix, vcpus, modernhp, expectfail) \
812 cpudata.test = prefix; \
813 cpudata.newcpus = vcpus; \
814 cpudata.modern = modernhp; \
815 cpudata.fail = expectfail; \
816 if (virTestRun("hotplug vcpus group " prefix, \
817 testQemuHotplugCpuGroup, &cpudata) < 0) \
821 DO_TEST_CPU_GROUP("x86-modern-bulk", 7, true, false);
822 DO_TEST_CPU_GROUP("x86-old-bulk", 7, false, false);
823 DO_TEST_CPU_GROUP("ppc64-modern-bulk", 24, true, false);
824 DO_TEST_CPU_GROUP("ppc64-modern-bulk", 15, true, true);
825 DO_TEST_CPU_GROUP("ppc64-modern-bulk", 23, true, true);
826 DO_TEST_CPU_GROUP("ppc64-modern-bulk", 25, true, true);
828 #define DO_TEST_CPU_INDIVIDUAL(prefix, mapstr, statefl, modernhp, expectfail) \
830 cpudata.test = prefix; \
831 cpudata.cpumap = mapstr; \
832 cpudata.state = statefl; \
833 cpudata.modern = modernhp; \
834 cpudata.fail = expectfail; \
835 if (virTestRun("hotplug vcpus group " prefix, \
836 testQemuHotplugCpuIndividual, &cpudata) < 0) \
840 DO_TEST_CPU_INDIVIDUAL("x86-modern-individual-add", "7", true, true, false);
841 DO_TEST_CPU_INDIVIDUAL("x86-modern-individual-add", "6,7", true, true, true);
842 DO_TEST_CPU_INDIVIDUAL("x86-modern-individual-add", "7", false, true, true);
843 DO_TEST_CPU_INDIVIDUAL("x86-modern-individual-add", "7", true, false, true);
845 DO_TEST_CPU_INDIVIDUAL("ppc64-modern-individual", "16-23", true, true, false);
846 DO_TEST_CPU_INDIVIDUAL("ppc64-modern-individual", "16-22", true, true, true);
847 DO_TEST_CPU_INDIVIDUAL("ppc64-modern-individual", "17", true, true, true);
849 qemuTestDriverFree(&driver
);
850 virObjectUnref(data
.vm
);
851 return (ret
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;
854 VIR_TEST_MAIN(mymain
)