backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / qemuagenttest.c
blob2f79986207d2351f657deb4746a9067e0e5af265
1 /*
2 * Copyright (C) 2013, 2014 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 "testutils.h"
23 #include "testutilsqemu.h"
24 #include "qemumonitortestutils.h"
25 #include "qemu/qemu_conf.h"
26 #include "qemu/qemu_agent.h"
27 #include "virthread.h"
28 #include "virerror.h"
29 #include "virstring.h"
32 #define VIR_FROM_THIS VIR_FROM_NONE
35 virQEMUDriver driver;
38 static int
39 testQemuAgentFSFreeze(const void *data)
41 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
42 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
43 const char *mountpoints[] = {"/fs1", "/fs2", "/fs3", "/fs4", "/fs5"};
44 int ret = -1;
46 if (!test)
47 return -1;
49 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
50 goto cleanup;
52 if (qemuMonitorTestAddItem(test, "guest-fsfreeze-freeze-list",
53 "{ \"return\" : 5 }") < 0)
54 goto cleanup;
56 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
57 goto cleanup;
59 if (qemuMonitorTestAddItem(test, "guest-fsfreeze-freeze",
60 "{ \"return\" : 7 }") < 0)
61 goto cleanup;
63 if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test),
64 mountpoints, 5)) < 0)
65 goto cleanup;
67 if (ret != 5) {
68 virReportError(VIR_ERR_INTERNAL_ERROR,
69 "expected 5 frozen filesystems, got %d", ret);
70 goto cleanup;
73 if ((ret = qemuAgentFSFreeze(qemuMonitorTestGetAgent(test), NULL, 0)) < 0)
74 goto cleanup;
76 if (ret != 7) {
77 virReportError(VIR_ERR_INTERNAL_ERROR,
78 "expected 7 frozen filesystems, got %d", ret);
79 goto cleanup;
82 ret = 0;
84 cleanup:
85 qemuMonitorTestFree(test);
86 return ret;
90 static int
91 testQemuAgentFSThaw(const void *data)
93 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
94 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
95 int ret = -1;
97 if (!test)
98 return -1;
100 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
101 goto cleanup;
103 if (qemuMonitorTestAddItem(test, "guest-fsfreeze-thaw",
104 "{ \"return\" : 5 }") < 0)
105 goto cleanup;
107 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
108 goto cleanup;
110 if (qemuMonitorTestAddItem(test, "guest-fsfreeze-thaw",
111 "{ \"return\" : 7 }") < 0)
112 goto cleanup;
114 if ((ret = qemuAgentFSThaw(qemuMonitorTestGetAgent(test))) < 0)
115 goto cleanup;
117 if (ret != 5) {
118 virReportError(VIR_ERR_INTERNAL_ERROR,
119 "expected 5 thawed filesystems, got %d", ret);
120 goto cleanup;
123 if ((ret = qemuAgentFSThaw(qemuMonitorTestGetAgent(test))) < 0)
124 goto cleanup;
126 if (ret != 7) {
127 virReportError(VIR_ERR_INTERNAL_ERROR,
128 "expected 7 thawed filesystems, got %d", ret);
129 goto cleanup;
132 ret = 0;
134 cleanup:
135 qemuMonitorTestFree(test);
136 return ret;
140 static int
141 testQemuAgentFSTrim(const void *data)
143 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
144 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
145 int ret = -1;
147 if (!test)
148 return -1;
150 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
151 goto cleanup;
153 if (qemuMonitorTestAddItemParams(test, "guest-fstrim",
154 "{ \"return\" : {} }",
155 "minimum", "1337",
156 NULL) < 0)
157 goto cleanup;
159 if (qemuAgentFSTrim(qemuMonitorTestGetAgent(test), 1337) < 0)
160 goto cleanup;
162 ret = 0;
164 cleanup:
165 qemuMonitorTestFree(test);
166 return ret;
170 static int
171 testQemuAgentGetFSInfo(const void *data)
173 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
174 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
175 char *domain_filename = NULL;
176 virDomainDefPtr def = NULL;
177 virDomainFSInfoPtr *info = NULL;
178 int ret = -1, ninfo = 0, i;
180 if (!test)
181 return -1;
183 if (virAsprintf(&domain_filename, "%s/qemuagentdata/fsinfo.xml",
184 abs_srcdir) < 0)
185 goto cleanup;
187 if (!(def = virDomainDefParseFile(domain_filename, driver.caps, xmlopt,
188 NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE)))
189 goto cleanup;
191 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
192 goto cleanup;
194 if (qemuMonitorTestAddItem(test, "guest-get-fsinfo",
195 "{\"return\": ["
196 " {\"name\": \"sda1\", \"mountpoint\": \"/\","
197 " \"disk\": ["
198 " {\"bus-type\": \"ide\","
199 " \"bus\": 1, \"unit\": 0,"
200 " \"pci-controller\": {"
201 " \"bus\": 0, \"slot\": 1,"
202 " \"domain\": 0, \"function\": 1},"
203 " \"target\": 0}],"
204 " \"type\": \"ext4\"},"
205 " {\"name\": \"dm-1\","
206 " \"mountpoint\": \"/opt\","
207 " \"disk\": ["
208 " {\"bus-type\": \"virtio\","
209 " \"bus\": 0, \"unit\": 0,"
210 " \"pci-controller\": {"
211 " \"bus\": 0, \"slot\": 6,"
212 " \"domain\": 0, \"function\": 0},"
213 " \"target\": 0},"
214 " {\"bus-type\": \"virtio\","
215 " \"bus\": 0, \"unit\": 0,"
216 " \"pci-controller\": {"
217 " \"bus\": 0, \"slot\": 7,"
218 " \"domain\": 0, \"function\": 0},"
219 " \"target\": 0}],"
220 " \"type\": \"vfat\"},"
221 " {\"name\": \"sdb1\","
222 " \"mountpoint\": \"/mnt/disk\","
223 " \"disk\": [], \"type\": \"xfs\"}]}") < 0)
224 goto cleanup;
226 if ((ninfo = qemuAgentGetFSInfo(qemuMonitorTestGetAgent(test),
227 &info, def)) < 0)
228 goto cleanup;
230 if (ninfo != 3) {
231 virReportError(VIR_ERR_INTERNAL_ERROR,
232 "expected 3 filesystems information, got %d", ninfo);
233 ret = -1;
234 goto cleanup;
236 if (STRNEQ(info[2]->name, "sda1") ||
237 STRNEQ(info[2]->mountpoint, "/") ||
238 STRNEQ(info[2]->fstype, "ext4") ||
239 info[2]->ndevAlias != 1 ||
240 !info[2]->devAlias || !info[2]->devAlias[0] ||
241 STRNEQ(info[2]->devAlias[0], "hdc")) {
242 virReportError(VIR_ERR_INTERNAL_ERROR,
243 "unexpected filesystems information returned for sda1 (%s,%s)",
244 info[2]->name, info[2]->devAlias ? info[2]->devAlias[0] : "null");
245 ret = -1;
246 goto cleanup;
248 if (STRNEQ(info[1]->name, "dm-1") ||
249 STRNEQ(info[1]->mountpoint, "/opt") ||
250 STRNEQ(info[1]->fstype, "vfat") ||
251 info[1]->ndevAlias != 2 ||
252 !info[1]->devAlias || !info[1]->devAlias[0] || !info[1]->devAlias[1] ||
253 STRNEQ(info[1]->devAlias[0], "vda") ||
254 STRNEQ(info[1]->devAlias[1], "vdb")) {
255 virReportError(VIR_ERR_INTERNAL_ERROR,
256 "unexpected filesystems information returned for dm-1 (%s,%s)",
257 info[0]->name, info[0]->devAlias ? info[0]->devAlias[0] : "null");
258 ret = -1;
259 goto cleanup;
261 if (STRNEQ(info[0]->name, "sdb1") ||
262 STRNEQ(info[0]->mountpoint, "/mnt/disk") ||
263 STRNEQ(info[0]->fstype, "xfs") ||
264 info[0]->ndevAlias != 0 || info[0]->devAlias) {
265 virReportError(VIR_ERR_INTERNAL_ERROR,
266 "unexpected filesystems information returned for sdb1 (%s,%s)",
267 info[0]->name, info[0]->devAlias ? info[0]->devAlias[0] : "null");
268 ret = -1;
269 goto cleanup;
272 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
273 goto cleanup;
275 if (qemuMonitorTestAddItem(test, "guest-get-fsinfo",
276 "{\"error\":"
277 " {\"class\":\"CommandDisabled\","
278 " \"desc\":\"The command guest-get-fsinfo "
279 "has been disabled for "
280 "this instance\","
281 " \"data\":{\"name\":\"guest-get-fsinfo\"}"
282 " }"
283 "}") < 0)
284 goto cleanup;
286 if (qemuAgentGetFSInfo(qemuMonitorTestGetAgent(test), &info, def) != -1) {
287 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
288 "agent get-fsinfo command should have failed");
289 goto cleanup;
292 ret = 0;
294 cleanup:
295 for (i = 0; i < ninfo; i++)
296 virDomainFSInfoFree(info[i]);
297 VIR_FREE(info);
298 VIR_FREE(domain_filename);
299 virDomainDefFree(def);
300 qemuMonitorTestFree(test);
301 return ret;
305 static int
306 testQemuAgentSuspend(const void *data)
308 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
309 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
310 int ret = -1;
311 size_t i;
313 if (!test)
314 return -1;
316 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
317 goto cleanup;
319 if (qemuMonitorTestAddItem(test, "guest-suspend-ram",
320 "{ \"return\" : {} }") < 0)
321 goto cleanup;
323 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
324 goto cleanup;
326 if (qemuMonitorTestAddItem(test, "guest-suspend-disk",
327 "{ \"return\" : {} }") < 0)
328 goto cleanup;
330 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
331 goto cleanup;
333 if (qemuMonitorTestAddItem(test, "guest-suspend-hybrid",
334 "{ \"return\" : {} }") < 0)
335 goto cleanup;
337 /* try the commands - fail if ordering changes */
338 for (i = 0; i < VIR_NODE_SUSPEND_TARGET_LAST; i++) {
339 if (qemuAgentSuspend(qemuMonitorTestGetAgent(test), i) < 0)
340 goto cleanup;
343 ret = 0;
345 cleanup:
346 qemuMonitorTestFree(test);
347 return ret;
351 struct qemuAgentShutdownTestData {
352 const char *mode;
353 qemuAgentEvent event;
357 static int
358 qemuAgentShutdownTestMonitorHandler(qemuMonitorTestPtr test,
359 qemuMonitorTestItemPtr item,
360 const char *cmdstr)
362 struct qemuAgentShutdownTestData *data;
363 virJSONValuePtr val = NULL;
364 virJSONValuePtr args;
365 const char *cmdname;
366 const char *mode;
367 int ret = -1;
369 data = qemuMonitorTestItemGetPrivateData(item);
371 if (!(val = virJSONValueFromString(cmdstr)))
372 return -1;
374 if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
375 ret = qemuMonitorReportError(test, "Missing command name in %s", cmdstr);
376 goto cleanup;
379 if (STRNEQ(cmdname, "guest-shutdown")) {
380 ret = qemuMonitorTestAddInvalidCommandResponse(test, "guest-shutdown",
381 cmdname);
382 goto cleanup;
385 if (!(args = virJSONValueObjectGet(val, "arguments"))) {
386 ret = qemuMonitorReportError(test,
387 "Missing arguments section");
388 goto cleanup;
391 if (!(mode = virJSONValueObjectGetString(args, "mode"))) {
392 ret = qemuMonitorReportError(test, "Missing shutdown mode");
393 goto cleanup;
396 if (STRNEQ(mode, data->mode)) {
397 ret = qemuMonitorReportError(test,
398 "expected shutdown mode '%s' got '%s'",
399 data->mode, mode);
400 goto cleanup;
403 /* now don't reply but return a qemu agent event */
404 qemuAgentNotifyEvent(qemuMonitorTestGetAgent(test),
405 data->event);
407 ret = 0;
409 cleanup:
410 virJSONValueFree(val);
411 return ret;
416 static int
417 testQemuAgentShutdown(const void *data)
419 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
420 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
421 struct qemuAgentShutdownTestData priv;
422 int ret = -1;
424 if (!test)
425 return -1;
427 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
428 goto cleanup;
430 priv.event = QEMU_AGENT_EVENT_SHUTDOWN;
431 priv.mode = "halt";
433 if (qemuMonitorTestAddHandler(test, qemuAgentShutdownTestMonitorHandler,
434 &priv, NULL) < 0)
435 goto cleanup;
437 if (qemuAgentShutdown(qemuMonitorTestGetAgent(test),
438 QEMU_AGENT_SHUTDOWN_HALT) < 0)
439 goto cleanup;
441 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
442 goto cleanup;
444 priv.event = QEMU_AGENT_EVENT_SHUTDOWN;
445 priv.mode = "powerdown";
447 if (qemuMonitorTestAddHandler(test, qemuAgentShutdownTestMonitorHandler,
448 &priv, NULL) < 0)
449 goto cleanup;
451 if (qemuAgentShutdown(qemuMonitorTestGetAgent(test),
452 QEMU_AGENT_SHUTDOWN_POWERDOWN) < 0)
453 goto cleanup;
455 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
456 goto cleanup;
458 priv.event = QEMU_AGENT_EVENT_RESET;
459 priv.mode = "reboot";
461 if (qemuMonitorTestAddHandler(test, qemuAgentShutdownTestMonitorHandler,
462 &priv, NULL) < 0)
463 goto cleanup;
465 if (qemuAgentShutdown(qemuMonitorTestGetAgent(test),
466 QEMU_AGENT_SHUTDOWN_REBOOT) < 0)
467 goto cleanup;
469 /* check negative response, so that we can verify that the agent breaks
470 * out from sleep */
472 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
473 goto cleanup;
475 if (qemuMonitorTestAddItem(test, "guest-shutdown",
476 "{\"error\":"
477 " {\"class\":\"CommandDisabled\","
478 " \"desc\":\"The command guest-shutdown has "
479 "been disabled for this instance\","
480 " \"data\":{\"name\":\"guest-shutdown\"}"
481 " }"
482 "}") < 0)
483 goto cleanup;
485 if (qemuAgentShutdown(qemuMonitorTestGetAgent(test),
486 QEMU_AGENT_SHUTDOWN_REBOOT) != -1) {
487 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
488 "agent shutdown command should have failed");
489 goto cleanup;
492 ret = 0;
494 cleanup:
495 qemuMonitorTestFree(test);
496 return ret;
500 static const char testQemuAgentCPUResponse[] =
501 "{\"return\": "
502 " ["
503 " {\"online\": true,"
504 " \"can-offline\": false,"
505 " \"logical-id\": 0"
506 " },"
507 " {\"online\": true,"
508 " \"can-offline\": true,"
509 " \"logical-id\": 1"
510 " },"
511 " {\"online\": true,"
512 " \"can-offline\": true,"
513 " \"logical-id\": 2"
514 " },"
515 " {\"online\": false,"
516 " \"can-offline\": true,"
517 " \"logical-id\": 3"
518 " }"
519 " ]"
520 "}";
522 static const char testQemuAgentCPUArguments1[] =
523 "[{\"logical-id\":1,\"online\":false}]";
525 static const char testQemuAgentCPUArguments2[] =
526 "[{\"logical-id\":1,\"online\":true},"
527 "{\"logical-id\":3,\"online\":true}]";
529 static const char testQemuAgentCPUArguments3[] =
530 "[{\"logical-id\":3,\"online\":true}]";
532 static int
533 testQemuAgentCPU(const void *data)
535 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
536 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
537 qemuAgentCPUInfoPtr cpuinfo = NULL;
538 int nvcpus;
539 int ret = -1;
541 if (!test)
542 return -1;
544 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
545 goto cleanup;
547 if (qemuMonitorTestAddItem(test, "guest-get-vcpus",
548 testQemuAgentCPUResponse) < 0)
549 goto cleanup;
551 /* get cpus */
552 if ((nvcpus = qemuAgentGetVCPUs(qemuMonitorTestGetAgent(test),
553 &cpuinfo)) < 0)
554 goto cleanup;
556 if (nvcpus != 4) {
557 virReportError(VIR_ERR_INTERNAL_ERROR,
558 "Expected '4' cpus, got '%d'", nvcpus);
559 goto cleanup;
562 /* try to unplug one */
563 if (qemuAgentUpdateCPUInfo(2, cpuinfo, nvcpus) < 0)
564 goto cleanup;
566 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
567 goto cleanup;
569 if (qemuMonitorTestAddItemParams(test, "guest-set-vcpus",
570 "{ \"return\" : 1 }",
571 "vcpus", testQemuAgentCPUArguments1,
572 NULL) < 0)
573 goto cleanup;
575 if (qemuAgentSetVCPUs(qemuMonitorTestGetAgent(test), cpuinfo, nvcpus) < 0)
576 goto cleanup;
578 /* try to hotplug two, second one will fail*/
579 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
580 goto cleanup;
582 if (qemuMonitorTestAddItemParams(test, "guest-set-vcpus",
583 "{ \"return\" : 1 }",
584 "vcpus", testQemuAgentCPUArguments2,
585 NULL) < 0)
586 goto cleanup;
588 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
589 goto cleanup;
591 if (qemuMonitorTestAddItemParams(test, "guest-set-vcpus",
592 "{ \"error\" : \"random error\" }",
593 "vcpus", testQemuAgentCPUArguments3,
594 NULL) < 0)
595 goto cleanup;
597 if (qemuAgentUpdateCPUInfo(4, cpuinfo, nvcpus) < 0)
598 goto cleanup;
600 /* this should fail */
601 if (qemuAgentSetVCPUs(qemuMonitorTestGetAgent(test), cpuinfo, nvcpus) != -1)
602 goto cleanup;
604 ret = 0;
606 cleanup:
607 VIR_FREE(cpuinfo);
608 qemuMonitorTestFree(test);
609 return ret;
613 static const char testQemuAgentArbitraryCommandResponse[] =
614 "{\"return\":\"bla\"}";
616 static int
617 testQemuAgentArbitraryCommand(const void *data)
619 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
620 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
621 int ret = -1;
622 char *reply = NULL;
624 if (!test)
625 return -1;
627 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
628 goto cleanup;
630 if (qemuMonitorTestAddItem(test, "ble",
631 testQemuAgentArbitraryCommandResponse) < 0)
632 goto cleanup;
634 if (qemuAgentArbitraryCommand(qemuMonitorTestGetAgent(test),
635 "{\"execute\":\"ble\"}",
636 &reply,
637 VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
638 goto cleanup;
640 if (STRNEQ(reply, testQemuAgentArbitraryCommandResponse)) {
641 virReportError(VIR_ERR_INTERNAL_ERROR,
642 "invalid processing of guest agent reply: "
643 "got '%s' expected '%s'",
644 reply, testQemuAgentArbitraryCommandResponse);
645 goto cleanup;
648 ret = 0;
650 cleanup:
651 VIR_FREE(reply);
652 qemuMonitorTestFree(test);
653 return ret;
657 static int
658 qemuAgentTimeoutTestMonitorHandler(qemuMonitorTestPtr test ATTRIBUTE_UNUSED,
659 qemuMonitorTestItemPtr item ATTRIBUTE_UNUSED,
660 const char *cmdstr ATTRIBUTE_UNUSED)
662 return 0;
666 static int
667 testQemuAgentTimeout(const void *data)
669 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
670 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
671 char *reply = NULL;
672 int ret = -1;
674 if (!test)
675 return -1;
677 if (virTestGetExpensive() == 0) {
678 ret = EXIT_AM_SKIP;
679 goto cleanup;
682 if (qemuMonitorTestAddHandler(test, qemuAgentTimeoutTestMonitorHandler,
683 NULL, NULL) < 0)
684 goto cleanup;
686 if (qemuAgentFSFreeze(qemuMonitorTestGetAgent(test), NULL, 0) != -1) {
687 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
688 "agent command should have failed");
689 goto cleanup;
692 /* test timeout */
693 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
694 goto cleanup;
696 if (qemuMonitorTestAddHandler(test, qemuAgentTimeoutTestMonitorHandler,
697 NULL, NULL) < 0)
698 goto cleanup;
700 if (qemuAgentArbitraryCommand(qemuMonitorTestGetAgent(test),
701 "{\"execute\":\"ble\"}",
702 &reply,
703 1) != -2) {
704 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
705 "agent command didn't time out");
706 goto cleanup;
709 ret = 0;
711 cleanup:
712 VIR_FREE(reply);
713 qemuMonitorTestFree(test);
714 return ret;
717 static const char testQemuAgentGetInterfacesResponse[] =
718 "{\"return\": "
719 " ["
720 " {\"name\":\"eth2\","
721 " \"hardware-address\":\"52:54:00:36:2a:e5\""
722 " },"
723 " {\"name\":\"eth1:0\","
724 " \"ip-addresses\":"
725 " ["
726 " {\"ip-address-type\":\"ipv4\","
727 " \"ip-address\":\"192.168.10.91\","
728 " \"prefix\":24"
729 " },"
730 " {\"ip-address-type\":\"ipv6\","
731 " \"ip-address\":\"fe80::fc54:ff:fefe:4c4f\","
732 " \"prefix\":64"
733 " }"
734 " ],"
735 " \"hardware-address\":\"52:54:00:d3:39:ee\""
736 " },"
737 " {\"name\":\"eth0\","
738 " \"ip-addresses\":"
739 " ["
740 " {\"ip-address-type\":\"ipv6\","
741 " \"ip-address\":\"fe80::5054:ff:fe89:ad35\","
742 " \"prefix\":64"
743 " },"
744 " {\"ip-address-type\":\"ipv4\","
745 " \"ip-address\":\"192.168.102.142\","
746 " \"prefix\":24"
747 " },"
748 " {\"ip-address-type\":\"ipv4\","
749 " \"ip-address\":\"192.168.234.152\","
750 " \"prefix\":16"
751 " },"
752 " {\"ip-address-type\":\"ipv6\","
753 " \"ip-address\":\"fe80::5054:ff:fec3:68bb\","
754 " \"prefix\":64"
755 " }"
756 " ],"
757 " \"hardware-address\":\"52:54:00:89:ad:35\""
758 " },"
759 " {\"name\":\"eth1\","
760 " \"ip-addresses\":"
761 " ["
762 " {\"ip-address-type\":\"ipv4\","
763 " \"ip-address\":\"192.168.103.83\","
764 " \"prefix\":32"
765 " },"
766 " {\"ip-address-type\":\"ipv6\","
767 " \"ip-address\":\"fe80::5054:ff:fed3:39ee\","
768 " \"prefix\":64"
769 " }"
770 " ],"
771 " \"hardware-address\":\"52:54:00:d3:39:ee\""
772 " },"
773 " {\"name\":\"lo\","
774 " \"ip-addresses\":"
775 " ["
776 " {\"ip-address-type\":\"ipv4\","
777 " \"ip-address\":\"127.0.0.1\","
778 " \"prefix\":8"
779 " },"
780 " {\"ip-address-type\":\"ipv6\","
781 " \"ip-address\":\"::1\","
782 " \"prefix\":128"
783 " }"
784 " ],"
785 " \"hardware-address\":\"00:00:00:00:00:00\""
786 " }"
787 " ]"
788 "}";
790 static int
791 testQemuAgentGetInterfaces(const void *data)
793 virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
794 qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
795 size_t i;
796 int ret = -1;
797 int ifaces_count = 0;
798 virDomainInterfacePtr *ifaces = NULL;
800 if (!test)
801 return -1;
803 if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
804 goto cleanup;
806 if (qemuMonitorTestAddItem(test, "guest-network-get-interfaces",
807 testQemuAgentGetInterfacesResponse) < 0)
808 goto cleanup;
810 if ((ifaces_count = qemuAgentGetInterfaces(qemuMonitorTestGetAgent(test),
811 &ifaces)) < 0)
812 goto cleanup;
814 if (ifaces_count != 4) {
815 virReportError(VIR_ERR_INTERNAL_ERROR,
816 "expected 4 interfaces, got %d", ret);
817 goto cleanup;
820 if (STRNEQ(ifaces[0]->name, "eth2") ||
821 STRNEQ(ifaces[1]->name, "eth1") ||
822 STRNEQ(ifaces[2]->name, "eth0") ||
823 STRNEQ(ifaces[3]->name, "lo")) {
824 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
825 "unexpected return values for interface names");
826 goto cleanup;
829 if (STRNEQ(ifaces[0]->hwaddr, "52:54:00:36:2a:e5") ||
830 STRNEQ(ifaces[1]->hwaddr, "52:54:00:d3:39:ee") ||
831 STRNEQ(ifaces[2]->hwaddr, "52:54:00:89:ad:35") ||
832 STRNEQ(ifaces[3]->hwaddr, "00:00:00:00:00:00")) {
833 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
834 "unexpected return values for MAC addresses");
835 goto cleanup;
838 if (ifaces[0]->naddrs != 0 ||
839 ifaces[1]->naddrs != 4 ||
840 ifaces[2]->naddrs != 4 ||
841 ifaces[3]->naddrs != 2) {
842 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
843 "unexpected return values for number of IP addresses");
844 goto cleanup;
847 if (ifaces[1]->addrs[0].type != VIR_IP_ADDR_TYPE_IPV4 ||
848 ifaces[1]->addrs[1].type != VIR_IP_ADDR_TYPE_IPV6 ||
849 ifaces[1]->addrs[2].type != VIR_IP_ADDR_TYPE_IPV4 ||
850 ifaces[1]->addrs[3].type != VIR_IP_ADDR_TYPE_IPV6 ||
851 ifaces[2]->addrs[0].type != VIR_IP_ADDR_TYPE_IPV6 ||
852 ifaces[2]->addrs[1].type != VIR_IP_ADDR_TYPE_IPV4 ||
853 ifaces[2]->addrs[2].type != VIR_IP_ADDR_TYPE_IPV4 ||
854 ifaces[2]->addrs[3].type != VIR_IP_ADDR_TYPE_IPV6 ||
855 ifaces[3]->addrs[0].type != VIR_IP_ADDR_TYPE_IPV4 ||
856 ifaces[3]->addrs[1].type != VIR_IP_ADDR_TYPE_IPV6) {
857 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
858 "unexpected return values for IP address types");
859 goto cleanup;
862 if (ifaces[1]->addrs[0].prefix != 24 ||
863 ifaces[1]->addrs[1].prefix != 64 ||
864 ifaces[1]->addrs[2].prefix != 32 ||
865 ifaces[1]->addrs[3].prefix != 64 ||
866 ifaces[2]->addrs[0].prefix != 64 ||
867 ifaces[2]->addrs[1].prefix != 24 ||
868 ifaces[2]->addrs[2].prefix != 16 ||
869 ifaces[2]->addrs[3].prefix != 64 ||
870 ifaces[3]->addrs[0].prefix != 8 ||
871 ifaces[3]->addrs[1].prefix != 128) {
872 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
873 "unexpected return values for IP address prefix");
874 goto cleanup;
877 if (STRNEQ(ifaces[1]->addrs[0].addr, "192.168.10.91") ||
878 STRNEQ(ifaces[1]->addrs[1].addr, "fe80::fc54:ff:fefe:4c4f") ||
879 STRNEQ(ifaces[1]->addrs[2].addr, "192.168.103.83") ||
880 STRNEQ(ifaces[1]->addrs[3].addr, "fe80::5054:ff:fed3:39ee") ||
881 STRNEQ(ifaces[2]->addrs[0].addr, "fe80::5054:ff:fe89:ad35") ||
882 STRNEQ(ifaces[2]->addrs[1].addr, "192.168.102.142") ||
883 STRNEQ(ifaces[2]->addrs[2].addr, "192.168.234.152") ||
884 STRNEQ(ifaces[2]->addrs[3].addr, "fe80::5054:ff:fec3:68bb") ||
885 STRNEQ(ifaces[3]->addrs[0].addr, "127.0.0.1") ||
886 STRNEQ(ifaces[3]->addrs[1].addr, "::1")) {
887 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
888 "unexpected return values for IP address values");
889 goto cleanup;
892 ret = 0;
894 cleanup:
895 qemuMonitorTestFree(test);
896 if (ifaces) {
897 for (i = 0; i < ifaces_count; i++)
898 virDomainInterfaceFree(ifaces[i]);
900 VIR_FREE(ifaces);
902 return ret;
905 static int
906 mymain(void)
908 int ret = 0;
910 #if !WITH_YAJL
911 fputs("libvirt not compiled with JSON support, skipping this test\n", stderr);
912 return EXIT_AM_SKIP;
913 #endif
915 if (virThreadInitialize() < 0 ||
916 qemuTestDriverInit(&driver) < 0)
917 return EXIT_FAILURE;
919 virEventRegisterDefaultImpl();
921 #define DO_TEST(name) \
922 if (virTestRun(# name, testQemuAgent ## name, driver.xmlopt) < 0) \
923 ret = -1
925 DO_TEST(FSFreeze);
926 DO_TEST(FSThaw);
927 DO_TEST(FSTrim);
928 DO_TEST(GetFSInfo);
929 DO_TEST(Suspend);
930 DO_TEST(Shutdown);
931 DO_TEST(CPU);
932 DO_TEST(ArbitraryCommand);
933 DO_TEST(GetInterfaces);
935 DO_TEST(Timeout); /* Timeout should always be called last */
937 qemuTestDriverFree(&driver);
939 return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
942 VIR_TEST_MAIN(mymain)