backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / qemuhotplugtest.c
blob6ad67c89021f713dd2d56235b33a3d0f3f1b160b
1 /*
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/>.
20 #include <config.h>
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"
31 #include "virerror.h"
32 #include "virstring.h"
33 #include "virthread.h"
34 #include "virfile.h"
36 #define VIR_FROM_THIS VIR_FROM_NONE
38 static virQEMUDriver driver;
40 enum {
41 ATTACH,
42 DETACH,
43 UPDATE
46 #define QEMU_HOTPLUG_TEST_DOMAIN_ID 7
48 struct qemuHotplugTestData {
49 const char *domain_filename;
50 const char *device_filename;
51 bool fail;
52 const char *const *mon;
53 int action;
54 bool keep;
55 virDomainObjPtr vm;
56 bool deviceDeletedEvent;
59 static int
60 qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt,
61 virDomainObjPtr *vm,
62 const char *domxml)
64 int ret = -1;
65 qemuDomainObjPrivatePtr priv = NULL;
66 const unsigned int parseFlags = 0;
68 if (!(*vm = virDomainObjNew(xmlopt)))
69 goto cleanup;
71 priv = (*vm)->privateData;
73 if (!(priv->qemuCaps = virQEMUCapsNew()))
74 goto cleanup;
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)
84 goto cleanup;
86 if (!((*vm)->def = virDomainDefParseString(domxml,
87 driver.caps,
88 driver.xmlopt,
89 NULL,
90 parseFlags)))
91 goto cleanup;
93 if (qemuDomainAssignAddresses((*vm)->def, priv->qemuCaps,
94 &driver, *vm, true) < 0) {
95 goto cleanup;
98 if (qemuAssignDeviceAliases((*vm)->def, priv->qemuCaps) < 0)
99 goto cleanup;
101 (*vm)->def->id = QEMU_HOTPLUG_TEST_DOMAIN_ID;
103 if (qemuDomainSetPrivatePaths(&driver, *vm) < 0)
104 goto cleanup;
106 ret = 0;
107 cleanup:
108 return ret;
111 static int
112 testQemuHotplugAttach(virDomainObjPtr vm,
113 virDomainDeviceDefPtr dev)
115 int ret = -1;
117 switch (dev->type) {
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);
123 break;
124 case VIR_DOMAIN_DEVICE_CHR:
125 ret = qemuDomainAttachChrDevice(&driver, vm, dev->data.chr);
126 break;
127 case VIR_DOMAIN_DEVICE_SHMEM:
128 ret = qemuDomainAttachShmemDevice(&driver, vm, dev->data.shmem);
129 break;
130 case VIR_DOMAIN_DEVICE_WATCHDOG:
131 ret = qemuDomainAttachWatchdog(&driver, vm, dev->data.watchdog);
132 break;
133 default:
134 VIR_TEST_VERBOSE("device type '%s' cannot be attached\n",
135 virDomainDeviceTypeToString(dev->type));
136 break;
139 return ret;
142 static int
143 testQemuHotplugDetach(virDomainObjPtr vm,
144 virDomainDeviceDefPtr dev,
145 bool async)
147 int ret = -1;
149 switch (dev->type) {
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);
155 break;
156 default:
157 VIR_TEST_VERBOSE("device type '%s' cannot be detached\n",
158 virDomainDeviceTypeToString(dev->type));
159 break;
162 return ret;
165 static int
166 testQemuHotplugUpdate(virDomainObjPtr vm,
167 virDomainDeviceDefPtr dev)
169 int ret = -1;
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. */
176 switch (dev->type) {
177 case VIR_DOMAIN_DEVICE_GRAPHICS:
178 ret = qemuDomainChangeGraphics(&driver, vm, dev->data.graphics);
179 break;
180 default:
181 VIR_TEST_VERBOSE("device type '%s' cannot be updated\n",
182 virDomainDeviceTypeToString(dev->type));
183 break;
186 return ret;
189 static int
190 testQemuHotplugCheckResult(virDomainObjPtr vm,
191 const char *expected,
192 const char *expectedFile,
193 bool fail)
195 char *actual;
196 int ret;
198 actual = virDomainDefFormat(vm->def, driver.caps,
199 VIR_DOMAIN_DEF_FORMAT_SECURE);
200 if (!actual)
201 return -1;
202 vm->def->id = QEMU_HOTPLUG_TEST_DOMAIN_ID;
204 if (STREQ(expected, actual)) {
205 if (fail)
206 VIR_TEST_VERBOSE("domain XML should not match the expected result\n");
207 ret = 0;
208 } else {
209 if (!fail)
210 virTestDifferenceFull(stderr,
211 expected, expectedFile,
212 actual, NULL);
213 ret = -1;
216 VIR_FREE(actual);
217 return ret;
220 static int
221 testQemuHotplug(const void *data)
223 int ret = -1;
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)
249 goto cleanup;
251 if (virTestLoadFile(domain_filename, &domain_xml) < 0 ||
252 virTestLoadFile(device_filename, &device_xml) < 0)
253 goto cleanup;
255 if (test->action == ATTACH &&
256 virTestLoadFile(result_filename, &result_xml) < 0)
257 goto cleanup;
259 if (!(caps = virQEMUDriverGetCapabilities(&driver, false)))
260 goto cleanup;
262 if (test->vm) {
263 vm = test->vm;
264 if (!vm->def) {
265 VIR_TEST_VERBOSE("test skipped due to failure of dependent test\n");
266 goto cleanup;
268 } else {
269 if (qemuHotplugCreateObjects(driver.xmlopt, &vm, domain_xml) < 0)
270 goto cleanup;
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)))
279 goto cleanup;
281 /* Now is the best time to feed the spoofed monitor with predefined
282 * replies. */
283 if (!(test_mon = qemuMonitorTestNew(driver.xmlopt, vm, &driver,
284 NULL, NULL)))
285 goto cleanup;
287 tmp = test->mon;
288 while (tmp && *tmp) {
289 const char *command_name;
290 const char *response;
292 if (!(command_name = *tmp++) ||
293 !(response = *tmp++))
294 break;
295 if (qemuMonitorTestAddItem(test_mon, command_name, response) < 0)
296 goto cleanup;
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) {
308 case ATTACH:
309 ret = testQemuHotplugAttach(vm, dev);
310 if (ret == 0) {
311 /* vm->def stolen dev->data.* so we just need to free the dev
312 * envelope */
313 VIR_FREE(dev);
315 if (ret == 0 || fail)
316 ret = testQemuHotplugCheckResult(vm, result_xml,
317 result_filename, fail);
318 break;
320 case DETACH:
321 ret = testQemuHotplugDetach(vm, dev, false);
322 if (ret == 0 || fail)
323 ret = testQemuHotplugCheckResult(vm, domain_xml,
324 domain_filename, fail);
325 break;
327 case UPDATE:
328 ret = testQemuHotplugUpdate(vm, dev);
331 cleanup:
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 */
339 if (priv)
340 priv->mon = NULL;
341 if (keep) {
342 test->vm = vm;
343 } else {
344 virObjectUnref(vm);
345 test->vm = NULL;
347 virDomainDeviceDefFree(dev);
348 virObjectUnref(caps);
349 qemuMonitorTestFree(test_mon);
350 return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1;
354 struct testQemuHotplugCpuData {
355 char *file_xml_dom;
356 char *file_xml_res_live;
357 char *file_xml_res_conf;
358 char *file_json_monitor;
360 char *xml_dom;
362 virDomainObjPtr vm;
363 qemuMonitorTestPtr mon;
364 bool modern;
368 static void
369 testQemuHotplugCpuDataFree(struct testQemuHotplugCpuData *data)
371 qemuDomainObjPrivatePtr priv;
373 if (!data)
374 return;
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);
383 if (data->vm) {
384 priv = data->vm->privateData;
385 priv->mon = NULL;
387 virObjectUnref(data->vm);
390 qemuMonitorTestFree(data->mon);
391 VIR_FREE(data);
395 static struct testQemuHotplugCpuData *
396 testQemuHotplugCpuPrepare(const char *test,
397 bool modern,
398 virHashTablePtr qmpschema)
400 qemuDomainObjPrivatePtr priv = NULL;
401 virCapsPtr caps = NULL;
402 char *prefix = NULL;
403 struct testQemuHotplugCpuData *data = NULL;
405 if (virAsprintf(&prefix, "%s/qemuhotplugtestcpus/%s", abs_srcdir, test) < 0)
406 return NULL;
408 if (VIR_ALLOC(data) < 0)
409 goto error;
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)
417 goto error;
419 if (virTestLoadFile(data->file_xml_dom, &data->xml_dom) < 0)
420 goto error;
422 if (qemuHotplugCreateObjects(driver.xmlopt, &data->vm, data->xml_dom) < 0)
423 goto error;
425 if (!(caps = virQEMUDriverGetCapabilities(&driver, false)))
426 goto error;
428 /* create vm->newDef */
429 data->vm->persistent = true;
430 if (virDomainObjSetDefTransient(caps, driver.xmlopt, data->vm, NULL) < 0)
431 goto error;
433 priv = data->vm->privateData;
435 if (data->modern)
436 virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS);
438 if (!(data->mon = qemuMonitorTestNewFromFileFull(data->file_json_monitor,
439 &driver, data->vm, qmpschema)))
440 goto error;
442 priv->mon = qemuMonitorTestGetMonitor(data->mon);
443 virObjectUnlock(priv->mon);
445 if (qemuDomainRefreshVcpuInfo(&driver, data->vm, 0, false) < 0)
446 goto error;
448 VIR_FREE(prefix);
450 return data;
452 error:
453 virObjectUnref(caps);
454 testQemuHotplugCpuDataFree(data);
455 VIR_FREE(prefix);
456 return NULL;
460 static int
461 testQemuHotplugCpuFinalize(struct testQemuHotplugCpuData *data)
463 int ret = -1;
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)))
470 goto cleanup;
472 if (virTestCompareToFile(activeXML, data->file_xml_res_live) < 0)
473 goto cleanup;
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)))
480 goto cleanup;
482 if (virTestCompareToFile(configXML, data->file_xml_res_conf) < 0)
483 goto cleanup;
486 ret = 0;
488 cleanup:
489 VIR_FREE(activeXML);
490 VIR_FREE(configXML);
491 return ret;
495 struct testQemuHotplugCpuParams {
496 const char *test;
497 int newcpus;
498 const char *cpumap;
499 bool state;
500 bool modern;
501 bool fail;
502 virHashTablePtr schema;
506 static int
507 testQemuHotplugCpuGroup(const void *opaque)
509 const struct testQemuHotplugCpuParams *params = opaque;
510 struct testQemuHotplugCpuData *data = NULL;
511 int ret = -1;
512 int rc;
514 if (!(data = testQemuHotplugCpuPrepare(params->test, params->modern,
515 params->schema)))
516 return -1;
518 rc = qemuDomainSetVcpusInternal(&driver, data->vm, data->vm->def,
519 data->vm->newDef, params->newcpus,
520 params->modern);
522 if (params->fail) {
523 if (rc == 0)
524 fprintf(stderr, "cpu test '%s' should have failed\n", params->test);
525 else
526 ret = 0;
528 goto cleanup;
529 } else {
530 if (rc < 0)
531 goto cleanup;
534 ret = testQemuHotplugCpuFinalize(data);
536 cleanup:
537 testQemuHotplugCpuDataFree(data);
538 return ret;
542 static int
543 testQemuHotplugCpuIndividual(const void *opaque)
545 const struct testQemuHotplugCpuParams *params = opaque;
546 struct testQemuHotplugCpuData *data = NULL;
547 virBitmapPtr map = NULL;
548 int ret = -1;
549 int rc;
551 if (!(data = testQemuHotplugCpuPrepare(params->test, params->modern,
552 params->schema)))
553 return -1;
555 if (virBitmapParse(params->cpumap, &map, 128) < 0)
556 goto cleanup;
558 rc = qemuDomainSetVcpuInternal(&driver, data->vm, data->vm->def,
559 data->vm->newDef, map, params->state);
561 if (params->fail) {
562 if (rc == 0)
563 fprintf(stderr, "cpu test '%s' should have failed\n", params->test);
564 else
565 ret = 0;
567 goto cleanup;
568 } else {
569 if (rc < 0)
570 goto cleanup;
573 ret = testQemuHotplugCpuFinalize(data);
575 cleanup:
576 virBitmapFree(map);
577 testQemuHotplugCpuDataFree(data);
578 return ret;
583 static int
584 mymain(void)
586 VIR_AUTOPTR(virHashTable) qmpschema = NULL;
587 int ret = 0;
588 struct qemuHotplugTestData data = {0};
589 struct testQemuHotplugCpuParams cpudata;
591 #if !WITH_YAJL
592 fputs("libvirt not compiled with JSON support, skipping this test\n", stderr);
593 return EXIT_AM_SKIP;
594 #endif
596 if (virThreadInitialize() < 0 ||
597 qemuTestDriverInit(&driver) < 0)
598 return EXIT_FAILURE;
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)
606 return EXIT_FAILURE;
608 if (!(driver.domainEventState = virObjectEventStateNew()))
609 return EXIT_FAILURE;
611 if (!(qmpschema = testQEMUSchemaLoad())) {
612 VIR_TEST_VERBOSE("failed to load qapi schema\n");
613 return EXIT_FAILURE;
616 cpudata.schema = qmpschema;
618 driver.lockManager = virLockManagerPluginNew("nop", "qemu",
619 driver.config->configBaseDir,
621 if (!driver.lockManager)
622 return EXIT_FAILURE;
624 /* wait only 100ms for DEVICE_DELETED event */
625 qemuDomainRemoveDeviceWaitTime = 100;
627 #define DO_TEST(file, ACTION, dev, fial, kep, ...) \
628 do { \
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; \
634 data.fail = fial; \
635 data.mon = my_mon; \
636 data.keep = kep; \
637 if (virTestRun(name, testQemuHotplug, &data) < 0) \
638 ret = -1; \
639 } while (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) \
655 "{" \
656 " \"timestamp\": {" \
657 " \"seconds\": 1374137171," \
658 " \"microseconds\": 2659" \
659 " }," \
660 " \"event\": \"DEVICE_DELETED\"," \
661 " \"data\": {" \
662 " \"device\": \"" dev "\"," \
663 " \"path\": \"/machine/peripheral/" dev "\"" \
664 " }" \
665 "}\r\n"
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"),
723 /* Disk added */
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) \
811 do { \
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) \
818 ret = -1; \
819 } while (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) \
829 do { \
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) \
837 ret = -1; \
838 } while (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)