2 * qemu_monitor_json.c: interaction with QEMU monitor console
4 * Copyright (C) 2006-2016 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
25 #include <sys/socket.h>
31 #include "qemu_monitor_text.h"
32 #include "qemu_monitor_json.h"
33 #include "qemu_alias.h"
34 #include "qemu_parse_command.h"
35 #include "qemu_capabilities.h"
39 #include "datatypes.h"
43 #include "virstring.h"
44 #include "cpu/cpu_x86.h"
45 #include "c-strcasestr.h"
48 #ifdef WITH_DTRACE_PROBES
49 # include "libvirt_qemu_probes.h"
52 #define VIR_FROM_THIS VIR_FROM_QEMU
54 VIR_LOG_INIT("qemu.qemu_monitor_json");
56 #define QOM_CPU_PATH "/machine/unattached/device[0]"
58 #define LINE_ENDING "\r\n"
60 static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data);
61 static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data);
62 static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data);
63 static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data);
64 static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data);
65 static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data);
66 static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data);
67 static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data);
68 static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data);
69 static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
70 static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
71 static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data);
72 static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
73 static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
74 static void qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon, virJSONValuePtr data);
75 static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon, virJSONValuePtr data);
76 static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, virJSONValuePtr data);
77 static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
78 static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, virJSONValuePtr data);
79 static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValuePtr data);
80 static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data);
81 static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data);
82 static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
83 static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
84 static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
85 static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, virJSONValuePtr data);
86 static void qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon, virJSONValuePtr data);
87 static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValuePtr data);
88 static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValuePtr data);
89 static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data);
90 static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
91 static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
92 static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon, virJSONValuePtr data);
93 static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon, virJSONValuePtr data);
97 void (*handler)(qemuMonitorPtr mon, virJSONValuePtr data);
100 static qemuEventHandler eventHandlers[] = {
101 { "ACPI_DEVICE_OST", qemuMonitorJSONHandleAcpiOstInfo, },
102 { "BALLOON_CHANGE", qemuMonitorJSONHandleBalloonChange, },
103 { "BLOCK_IO_ERROR", qemuMonitorJSONHandleIOError, },
104 { "BLOCK_JOB_CANCELLED", qemuMonitorJSONHandleBlockJobCanceled, },
105 { "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJobCompleted, },
106 { "BLOCK_JOB_READY", qemuMonitorJSONHandleBlockJobReady, },
107 { "BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold, },
108 { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
109 { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
110 { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
111 { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
112 { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
113 { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
114 { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
115 { "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
116 { "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
117 { "RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged, },
118 { "RESET", qemuMonitorJSONHandleReset, },
119 { "RESUME", qemuMonitorJSONHandleResume, },
120 { "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
121 { "SHUTDOWN", qemuMonitorJSONHandleShutdown, },
122 { "SPICE_CONNECTED", qemuMonitorJSONHandleSPICEConnect, },
123 { "SPICE_DISCONNECTED", qemuMonitorJSONHandleSPICEDisconnect, },
124 { "SPICE_INITIALIZED", qemuMonitorJSONHandleSPICEInitialize, },
125 { "SPICE_MIGRATE_COMPLETED", qemuMonitorJSONHandleSpiceMigrated, },
126 { "STOP", qemuMonitorJSONHandleStop, },
127 { "SUSPEND", qemuMonitorJSONHandlePMSuspend, },
128 { "SUSPEND_DISK", qemuMonitorJSONHandlePMSuspendDisk, },
129 { "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
130 { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
131 { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
132 { "VSERPORT_CHANGE", qemuMonitorJSONHandleSerialChange, },
133 { "WAKEUP", qemuMonitorJSONHandlePMWakeup, },
134 { "WATCHDOG", qemuMonitorJSONHandleWatchdog, },
135 /* We use bsearch, so keep this list sorted. */
139 qemuMonitorEventCompare(const void *key, const void *elt)
141 const char *type = key;
142 const qemuEventHandler *handler = elt;
143 return strcmp(type, handler->type);
147 qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
151 qemuEventHandler *handler;
152 virJSONValuePtr data;
153 char *details = NULL;
154 virJSONValuePtr timestamp;
155 long long seconds = -1;
156 unsigned int micros = 0;
158 VIR_DEBUG("mon=%p obj=%p", mon, obj);
160 type = virJSONValueObjectGetString(obj, "event");
162 VIR_WARN("missing event type in message");
167 /* Not all events have data; and event reporting is best-effort only */
168 if ((data = virJSONValueObjectGet(obj, "data")))
169 details = virJSONValueToString(data, false);
170 if ((timestamp = virJSONValueObjectGet(obj, "timestamp"))) {
171 ignore_value(virJSONValueObjectGetNumberLong(timestamp, "seconds",
173 ignore_value(virJSONValueObjectGetNumberUint(timestamp, "microseconds",
176 qemuMonitorEmitEvent(mon, type, seconds, micros, details);
179 handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers),
180 sizeof(eventHandlers[0]), qemuMonitorEventCompare);
182 VIR_DEBUG("handle %s handler=%p data=%p", type,
183 handler->handler, data);
184 (handler->handler)(mon, data);
190 qemuMonitorJSONIOProcessLine(qemuMonitorPtr mon,
192 qemuMonitorMessagePtr msg)
194 virJSONValuePtr obj = NULL;
197 VIR_DEBUG("Line [%s]", line);
199 if (!(obj = virJSONValueFromString(line)))
202 if (virJSONValueGetType(obj) != VIR_JSON_TYPE_OBJECT) {
203 virReportError(VIR_ERR_INTERNAL_ERROR,
204 _("Parsed JSON reply '%s' isn't an object"), line);
208 if (virJSONValueObjectHasKey(obj, "QMP") == 1) {
210 } else if (virJSONValueObjectHasKey(obj, "event") == 1) {
211 PROBE(QEMU_MONITOR_RECV_EVENT,
212 "mon=%p event=%s", mon, line);
213 ret = qemuMonitorJSONIOProcessEvent(mon, obj);
214 } else if (virJSONValueObjectHasKey(obj, "error") == 1 ||
215 virJSONValueObjectHasKey(obj, "return") == 1) {
216 PROBE(QEMU_MONITOR_RECV_REPLY,
217 "mon=%p reply=%s", mon, line);
224 virReportError(VIR_ERR_INTERNAL_ERROR,
225 _("Unexpected JSON reply '%s'"), line);
228 virReportError(VIR_ERR_INTERNAL_ERROR,
229 _("Unknown JSON reply '%s'"), line);
233 virJSONValueFree(obj);
237 int qemuMonitorJSONIOProcess(qemuMonitorPtr mon,
240 qemuMonitorMessagePtr msg)
243 /*VIR_DEBUG("Data %d bytes [%s]", len, data);*/
246 char *nl = strstr(data + used, LINE_ENDING);
249 int got = nl - (data + used);
251 if (VIR_STRNDUP(line, data + used, got) < 0)
253 used += got + strlen(LINE_ENDING);
254 line[got] = '\0'; /* kill \n */
255 if (qemuMonitorJSONIOProcessLine(mon, line, msg) < 0) {
267 VIR_DEBUG("Total used %d bytes out of %zd available in buffer", used, len);
274 qemuMonitorJSONCommandWithFd(qemuMonitorPtr mon,
277 virJSONValuePtr *reply)
280 qemuMonitorMessage msg;
281 VIR_AUTOCLEAN(virBuffer) cmdbuf = VIR_BUFFER_INITIALIZER;
286 memset(&msg, 0, sizeof(msg));
288 if (virJSONValueObjectHasKey(cmd, "execute") == 1) {
289 if (!(id = qemuMonitorNextCommandID(mon)))
291 if (virJSONValueObjectAppendString(cmd, "id", id) < 0) {
292 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
293 _("Unable to append command 'id' string"));
298 if (virJSONValueToBuffer(cmd, &cmdbuf, false) < 0)
300 virBufferAddLit(&cmdbuf, "\r\n");
302 if (virBufferCheckError(&cmdbuf) < 0)
305 msg.txLength = virBufferUse(&cmdbuf);
306 msg.txBuffer = virBufferContentAndReset(&cmdbuf);
309 ret = qemuMonitorSend(mon, &msg);
313 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
314 _("Missing monitor reply object"));
317 *reply = msg.rxObject;
323 VIR_FREE(msg.txBuffer);
330 qemuMonitorJSONCommand(qemuMonitorPtr mon,
332 virJSONValuePtr *reply)
334 return qemuMonitorJSONCommandWithFd(mon, cmd, -1, reply);
337 /* Ignoring OOM in this method, since we're already reporting
338 * a more important error
340 * XXX see qerror.h for different klasses & fill out useful params
343 qemuMonitorJSONStringifyError(virJSONValuePtr error)
345 const char *klass = virJSONValueObjectGetString(error, "class");
346 const char *detail = NULL;
348 /* The QMP 'desc' field is usually sufficient for our generic
349 * error reporting needs.
352 detail = virJSONValueObjectGetString(error, "desc");
356 detail = "unknown QEMU command error";
362 qemuMonitorJSONCommandName(virJSONValuePtr cmd)
364 const char *name = virJSONValueObjectGetString(cmd, "execute");
372 qemuMonitorJSONCheckError(virJSONValuePtr cmd,
373 virJSONValuePtr reply)
375 if (virJSONValueObjectHasKey(reply, "error")) {
376 virJSONValuePtr error = virJSONValueObjectGet(reply, "error");
377 char *cmdstr = virJSONValueToString(cmd, false);
378 char *replystr = virJSONValueToString(reply, false);
380 /* Log the full JSON formatted command & error */
381 VIR_DEBUG("unable to execute QEMU command %s: %s",
382 NULLSTR(cmdstr), NULLSTR(replystr));
384 /* Only send the user the command name + friendly error */
386 virReportError(VIR_ERR_INTERNAL_ERROR,
387 _("unable to execute QEMU command '%s'"),
388 qemuMonitorJSONCommandName(cmd));
390 virReportError(VIR_ERR_INTERNAL_ERROR,
391 _("unable to execute QEMU command '%s': %s"),
392 qemuMonitorJSONCommandName(cmd),
393 qemuMonitorJSONStringifyError(error));
398 } else if (!virJSONValueObjectHasKey(reply, "return")) {
399 char *cmdstr = virJSONValueToString(cmd, false);
400 char *replystr = virJSONValueToString(reply, false);
402 VIR_DEBUG("Neither 'return' nor 'error' is set in the JSON reply %s: %s",
403 NULLSTR(cmdstr), NULLSTR(replystr));
404 virReportError(VIR_ERR_INTERNAL_ERROR,
405 _("unable to execute QEMU command '%s'"),
406 qemuMonitorJSONCommandName(cmd));
416 qemuMonitorJSONCheckReply(virJSONValuePtr cmd,
417 virJSONValuePtr reply,
420 virJSONValuePtr data;
422 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
425 data = virJSONValueObjectGet(reply, "return");
426 if (virJSONValueGetType(data) != type) {
427 char *cmdstr = virJSONValueToString(cmd, false);
428 char *retstr = virJSONValueToString(data, false);
430 VIR_DEBUG("Unexpected return type %d (expecting %d) for command %s: %s",
431 virJSONValueGetType(data), type, cmdstr, retstr);
432 virReportError(VIR_ERR_INTERNAL_ERROR,
433 _("unexpected type returned by QEMU command '%s'"),
434 qemuMonitorJSONCommandName(cmd));
446 qemuMonitorJSONErrorIsClass(virJSONValuePtr error,
449 return STREQ_NULLABLE(virJSONValueObjectGetString(error, "class"), klass);
454 qemuMonitorJSONHasError(virJSONValuePtr reply,
457 virJSONValuePtr error;
459 if (!(error = virJSONValueObjectGet(reply, "error")))
462 return qemuMonitorJSONErrorIsClass(error, klass);
467 * qemuMonitorJSONTransactionAdd:
468 * @actions: array of actions for the 'transaction' command
469 * @cmdname: command to add to @actions
470 * @...: arguments for @cmdname (see virJSONValueObjectAddVArgs for formatting)
472 * Add a new command with arguments to the existing ones. The resulting array
473 * is intended to be used as argument for the 'transaction' command.
475 * Returns 0 on success and -1 on error.
478 qemuMonitorJSONTransactionAdd(virJSONValuePtr actions,
482 virJSONValuePtr entry = NULL;
483 virJSONValuePtr data = NULL;
487 va_start(args, cmdname);
489 if (virJSONValueObjectCreateVArgs(&data, args) < 0)
492 if (virJSONValueObjectCreate(&entry,
494 "A:data", &data, NULL) < 0)
497 if (virJSONValueArrayAppend(actions, entry) < 0)
504 virJSONValueFree(entry);
505 virJSONValueFree(data);
512 * qemuMonitorJSONMakeCommandInternal:
513 * @cmdname: QMP command name
514 * @arguments: a JSON object containing command arguments or NULL
516 * Create a JSON object used on the QMP monitor to call a command.
518 * Note that @arguments is always consumed and should not be referenced after
519 * the call to this function.
521 static virJSONValuePtr
522 qemuMonitorJSONMakeCommandInternal(const char *cmdname,
523 virJSONValuePtr arguments)
525 virJSONValuePtr ret = NULL;
527 ignore_value(virJSONValueObjectCreate(&ret,
528 "s:execute", cmdname,
529 "A:arguments", &arguments, NULL));
531 virJSONValueFree(arguments);
536 static virJSONValuePtr ATTRIBUTE_SENTINEL
537 qemuMonitorJSONMakeCommand(const char *cmdname,
540 virJSONValuePtr obj = NULL;
541 virJSONValuePtr jargs = NULL;
544 va_start(args, cmdname);
546 if (virJSONValueObjectCreateVArgs(&jargs, args) < 0)
549 obj = qemuMonitorJSONMakeCommandInternal(cmdname, jargs);
558 static virJSONValuePtr
559 qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
561 virJSONValuePtr ret = NULL;
562 char **keywords = NULL;
563 char **values = NULL;
567 if (!(ret = virJSONValueNewObject()))
570 if (qemuParseKeywords(str, &keywords, &values, &nkeywords, 1) < 0)
573 for (i = 0; i < nkeywords; i++) {
574 if (values[i] == NULL) {
576 virReportError(VIR_ERR_INTERNAL_ERROR,
577 _("unexpected empty keyword in %s"), str);
580 /* This 3rd arg isn't a typo - the way the parser works is
581 * that the value ended up in the keyword field */
582 if (virJSONValueObjectAppendString(ret, firstkeyword, keywords[i]) < 0)
586 if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0)
591 qemuParseKeywordsFree(nkeywords, keywords, values);
595 qemuParseKeywordsFree(nkeywords, keywords, values);
596 virJSONValueFree(ret);
601 static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data)
604 virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
606 if (data && virJSONValueObjectGetBoolean(data, "guest", &guest) == 0)
607 guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
609 qemuMonitorEmitShutdown(mon, guest_initiated);
612 static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
614 qemuMonitorEmitReset(mon);
617 static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
619 qemuMonitorEmitPowerdown(mon);
622 static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
624 qemuMonitorEmitStop(mon);
627 static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
629 qemuMonitorEmitResume(mon);
633 static qemuMonitorEventPanicInfoPtr
634 qemuMonitorJSONGuestPanicExtractInfoHyperv(virJSONValuePtr data)
636 qemuMonitorEventPanicInfoPtr ret;
638 if (VIR_ALLOC(ret) < 0)
641 ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV;
643 if (virJSONValueObjectGetNumberUlong(data, "arg1", &ret->data.hyperv.arg1) < 0 ||
644 virJSONValueObjectGetNumberUlong(data, "arg2", &ret->data.hyperv.arg2) < 0 ||
645 virJSONValueObjectGetNumberUlong(data, "arg3", &ret->data.hyperv.arg3) < 0 ||
646 virJSONValueObjectGetNumberUlong(data, "arg4", &ret->data.hyperv.arg4) < 0 ||
647 virJSONValueObjectGetNumberUlong(data, "arg5", &ret->data.hyperv.arg5) < 0) {
648 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
649 _("malformed hyperv panic data"));
656 qemuMonitorEventPanicInfoFree(ret);
660 static qemuMonitorEventPanicInfoPtr
661 qemuMonitorJSONGuestPanicExtractInfoS390(virJSONValuePtr data)
663 qemuMonitorEventPanicInfoPtr ret;
665 unsigned long long psw_mask, psw_addr;
666 const char *reason = NULL;
668 if (VIR_ALLOC(ret) < 0)
671 ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390;
673 if (virJSONValueObjectGetNumberInt(data, "core", &core) < 0 ||
674 virJSONValueObjectGetNumberUlong(data, "psw-mask", &psw_mask) < 0 ||
675 virJSONValueObjectGetNumberUlong(data, "psw-addr", &psw_addr) < 0 ||
676 !(reason = virJSONValueObjectGetString(data, "reason"))) {
677 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed s390 panic data"));
681 ret->data.s390.core = core;
682 ret->data.s390.psw_mask = psw_mask;
683 ret->data.s390.psw_addr = psw_addr;
685 if (VIR_STRDUP(ret->data.s390.reason, reason) < 0)
691 qemuMonitorEventPanicInfoFree(ret);
695 static qemuMonitorEventPanicInfoPtr
696 qemuMonitorJSONGuestPanicExtractInfo(virJSONValuePtr data)
698 const char *type = virJSONValueObjectGetString(data, "type");
700 if (STREQ_NULLABLE(type, "hyper-v"))
701 return qemuMonitorJSONGuestPanicExtractInfoHyperv(data);
702 else if (STREQ_NULLABLE(type, "s390"))
703 return qemuMonitorJSONGuestPanicExtractInfoS390(data);
705 virReportError(VIR_ERR_INTERNAL_ERROR,
706 _("unknown panic info type '%s'"), NULLSTR(type));
712 qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon,
713 virJSONValuePtr data)
715 virJSONValuePtr infojson = virJSONValueObjectGetObject(data, "info");
716 qemuMonitorEventPanicInfoPtr info = NULL;
719 info = qemuMonitorJSONGuestPanicExtractInfo(infojson);
721 qemuMonitorEmitGuestPanic(mon, info);
725 static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data)
727 long long offset = 0;
728 if (virJSONValueObjectGetNumberLong(data, "offset", &offset) < 0) {
729 VIR_WARN("missing offset in RTC change event");
732 qemuMonitorEmitRTCChange(mon, offset);
735 VIR_ENUM_DECL(qemuMonitorWatchdogAction);
736 VIR_ENUM_IMPL(qemuMonitorWatchdogAction,
737 VIR_DOMAIN_EVENT_WATCHDOG_LAST,
738 "none", "pause", "reset", "poweroff", "shutdown", "debug", "inject-nmi",
741 static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data)
745 if (!(action = virJSONValueObjectGetString(data, "action")))
746 VIR_WARN("missing action in watchdog event");
748 if ((actionID = qemuMonitorWatchdogActionTypeFromString(action)) < 0) {
749 VIR_WARN("unknown action %s in watchdog event", action);
750 actionID = VIR_DOMAIN_EVENT_WATCHDOG_NONE;
753 actionID = VIR_DOMAIN_EVENT_WATCHDOG_NONE;
755 qemuMonitorEmitWatchdog(mon, actionID);
758 VIR_ENUM_DECL(qemuMonitorIOErrorAction);
759 VIR_ENUM_IMPL(qemuMonitorIOErrorAction,
760 VIR_DOMAIN_EVENT_IO_ERROR_LAST,
761 "ignore", "stop", "report",
766 qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data)
769 const char *nodename;
771 const char *reason = "";
775 /* Throughout here we try our best to carry on upon errors,
776 since it's important to get as much info as possible out
777 to the application */
779 if ((action = virJSONValueObjectGetString(data, "action")) == NULL) {
780 VIR_WARN("Missing action in disk io error event");
784 if ((device = virJSONValueObjectGetString(data, "device")) == NULL)
785 VIR_WARN("missing device in disk io error event");
787 nodename = virJSONValueObjectGetString(data, "node-name");
789 if (virJSONValueObjectGetBoolean(data, "nospace", &nospc) == 0 && nospc)
792 if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) {
793 VIR_WARN("unknown disk io error action '%s'", action);
794 actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
797 qemuMonitorEmitIOError(mon, device, nodename, actionID, reason);
801 VIR_ENUM_DECL(qemuMonitorGraphicsAddressFamily);
802 VIR_ENUM_IMPL(qemuMonitorGraphicsAddressFamily,
803 VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_LAST,
804 "ipv4", "ipv6", "unix",
808 qemuMonitorJSONHandleGraphicsVNC(qemuMonitorPtr mon,
809 virJSONValuePtr data,
812 const char *localNode, *localService, *localFamily;
813 const char *remoteNode, *remoteService, *remoteFamily;
814 const char *authScheme, *saslUsername, *x509dname;
815 int localFamilyID, remoteFamilyID;
816 virJSONValuePtr client;
817 virJSONValuePtr server;
819 if (!(client = virJSONValueObjectGetObject(data, "client"))) {
820 VIR_WARN("missing client info in VNC event");
823 if (!(server = virJSONValueObjectGetObject(data, "server"))) {
824 VIR_WARN("missing server info in VNC event");
828 if (!(authScheme = virJSONValueObjectGetString(server, "auth"))) {
829 /* not all events are required to contain auth scheme */
830 VIR_DEBUG("missing auth scheme in VNC event");
834 if (!(localFamily = virJSONValueObjectGetString(server, "family"))) {
835 VIR_WARN("missing local address family in VNC event");
838 if (!(localNode = virJSONValueObjectGetString(server, "host"))) {
839 VIR_WARN("missing local hostname in VNC event");
842 if (!(localService = virJSONValueObjectGetString(server, "service"))) {
843 VIR_WARN("missing local service in VNC event");
847 if (!(remoteFamily = virJSONValueObjectGetString(client, "family"))) {
848 VIR_WARN("missing remote address family in VNC event");
851 if (!(remoteNode = virJSONValueObjectGetString(client, "host"))) {
852 VIR_WARN("missing remote hostname in VNC event");
855 if (!(remoteService = virJSONValueObjectGetString(client, "service"))) {
856 VIR_WARN("missing remote service in VNC event");
860 saslUsername = virJSONValueObjectGetString(client, "sasl_username");
861 x509dname = virJSONValueObjectGetString(client, "x509_dname");
863 if ((localFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(localFamily)) < 0) {
864 VIR_WARN("unknown address family '%s'", localFamily);
865 localFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
867 if ((remoteFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(remoteFamily)) < 0) {
868 VIR_WARN("unknown address family '%s'", remoteFamily);
869 remoteFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
872 qemuMonitorEmitGraphics(mon, phase,
873 localFamilyID, localNode, localService,
874 remoteFamilyID, remoteNode, remoteService,
875 authScheme, x509dname, saslUsername);
878 static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data)
880 qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
884 static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data)
886 qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
890 static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data)
892 qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
897 qemuMonitorJSONHandleGraphicsSPICE(qemuMonitorPtr mon,
898 virJSONValuePtr data,
901 const char *lhost, *lport, *lfamily;
902 const char *rhost, *rport, *rfamily;
903 const char *auth = "";
904 int lfamilyID, rfamilyID;
905 virJSONValuePtr client;
906 virJSONValuePtr server;
908 if (!(client = virJSONValueObjectGetObject(data, "client")) ||
909 !(server = virJSONValueObjectGetObject(data, "server"))) {
910 VIR_WARN("missing server or client info in SPICE event");
914 if (phase == VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE &&
915 !(auth = virJSONValueObjectGetString(server, "auth"))) {
916 VIR_DEBUG("missing auth scheme in SPICE event");
920 if (!(lfamily = virJSONValueObjectGetString(server, "family"))) {
921 VIR_WARN("missing local address family in SPICE event");
924 if (!(lhost = virJSONValueObjectGetString(server, "host"))) {
925 VIR_WARN("missing local hostname in SPICE event");
928 if (!(lport = virJSONValueObjectGetString(server, "port"))) {
929 VIR_WARN("missing local port in SPICE event");
933 if (!(rfamily = virJSONValueObjectGetString(client, "family"))) {
934 VIR_WARN("missing remote address family in SPICE event");
937 if (!(rhost = virJSONValueObjectGetString(client, "host"))) {
938 VIR_WARN("missing remote hostname in SPICE event");
941 if (!(rport = virJSONValueObjectGetString(client, "port"))) {
942 VIR_WARN("missing remote service in SPICE event");
946 if ((lfamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(lfamily)) < 0) {
947 VIR_WARN("unknown address family '%s'", lfamily);
948 lfamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
950 if ((rfamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(rfamily)) < 0) {
951 VIR_WARN("unknown address family '%s'", rfamily);
952 rfamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
955 qemuMonitorEmitGraphics(mon, phase, lfamilyID, lhost, lport, rfamilyID,
956 rhost, rport, auth, NULL, NULL);
960 static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data)
962 qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
966 static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data)
968 qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
972 static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data)
974 qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
978 qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
979 virJSONValuePtr data,
983 const char *type_str;
984 const char *error = NULL;
985 int type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
986 unsigned long long offset, len;
988 if ((device = virJSONValueObjectGetString(data, "device")) == NULL) {
989 VIR_WARN("missing device in block job event");
993 if (virJSONValueObjectGetNumberUlong(data, "offset", &offset) < 0) {
994 VIR_WARN("missing offset in block job event");
998 if (virJSONValueObjectGetNumberUlong(data, "len", &len) < 0) {
999 VIR_WARN("missing len in block job event");
1003 if ((type_str = virJSONValueObjectGetString(data, "type")) == NULL) {
1004 VIR_WARN("missing type in block job event");
1008 if (STREQ(type_str, "stream"))
1009 type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
1010 else if (STREQ(type_str, "commit"))
1011 type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
1012 else if (STREQ(type_str, "mirror"))
1013 type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
1015 switch ((virConnectDomainEventBlockJobStatus) event) {
1016 case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
1017 error = virJSONValueObjectGetString(data, "error");
1018 /* Make sure the whole device has been processed */
1019 if (offset != len || error)
1020 event = VIR_DOMAIN_BLOCK_JOB_FAILED;
1022 case VIR_DOMAIN_BLOCK_JOB_CANCELED:
1023 case VIR_DOMAIN_BLOCK_JOB_READY:
1025 case VIR_DOMAIN_BLOCK_JOB_FAILED:
1026 case VIR_DOMAIN_BLOCK_JOB_LAST:
1027 VIR_DEBUG("should not get here");
1032 qemuMonitorEmitBlockJob(mon, device, type, event, error);
1036 qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon,
1037 virJSONValuePtr data)
1039 const char *devAlias = virJSONValueObjectGetString(data, "device");
1040 const char *devid = virJSONValueObjectGetString(data, "id");
1044 /* drive alias is always reported but empty for -blockdev */
1045 if (*devAlias == '\0')
1048 if (!devAlias && !devid) {
1049 VIR_WARN("missing device in tray change event");
1053 if (virJSONValueObjectGetBoolean(data, "tray-open", &trayOpened) < 0) {
1054 VIR_WARN("missing tray-open in tray change event");
1059 reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN;
1061 reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE;
1063 qemuMonitorEmitTrayChange(mon, devAlias, devid, reason);
1067 qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon,
1068 virJSONValuePtr data ATTRIBUTE_UNUSED)
1070 qemuMonitorEmitPMWakeup(mon);
1074 qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon,
1075 virJSONValuePtr data ATTRIBUTE_UNUSED)
1077 qemuMonitorEmitPMSuspend(mon);
1081 qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon,
1082 virJSONValuePtr data)
1084 qemuMonitorJSONHandleBlockJobImpl(mon, data,
1085 VIR_DOMAIN_BLOCK_JOB_COMPLETED);
1089 qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon,
1090 virJSONValuePtr data)
1092 qemuMonitorJSONHandleBlockJobImpl(mon, data,
1093 VIR_DOMAIN_BLOCK_JOB_CANCELED);
1097 qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon,
1098 virJSONValuePtr data)
1100 qemuMonitorJSONHandleBlockJobImpl(mon, data,
1101 VIR_DOMAIN_BLOCK_JOB_READY);
1105 qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon,
1106 virJSONValuePtr data)
1108 unsigned long long actual = 0;
1109 if (virJSONValueObjectGetNumberUlong(data, "actual", &actual) < 0) {
1110 VIR_WARN("missing actual in balloon change event");
1113 actual = VIR_DIV_UP(actual, 1024);
1114 qemuMonitorEmitBalloonChange(mon, actual);
1118 qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon,
1119 virJSONValuePtr data ATTRIBUTE_UNUSED)
1121 qemuMonitorEmitPMSuspendDisk(mon);
1125 qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data)
1129 if (!(device = virJSONValueObjectGetString(data, "device"))) {
1130 VIR_DEBUG("missing device in device deleted event");
1134 qemuMonitorEmitDeviceDeleted(mon, device);
1139 qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data)
1143 if (!(name = virJSONValueObjectGetString(data, "name"))) {
1144 VIR_WARN("missing device in NIC_RX_FILTER_CHANGED event");
1148 qemuMonitorEmitNicRxFilterChanged(mon, name);
1153 qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon,
1154 virJSONValuePtr data)
1159 if (!(name = virJSONValueObjectGetString(data, "id"))) {
1160 VIR_WARN("missing device alias in VSERPORT_CHANGE event");
1164 if (virJSONValueObjectGetBoolean(data, "open", &connected) < 0) {
1165 VIR_WARN("missing port state for '%s' in VSERPORT_CHANGE event", name);
1169 qemuMonitorEmitSerialChange(mon, name, connected);
1174 qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon,
1175 virJSONValuePtr data ATTRIBUTE_UNUSED)
1177 qemuMonitorEmitSpiceMigrated(mon);
1182 qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon,
1183 virJSONValuePtr data)
1188 if (!(str = virJSONValueObjectGetString(data, "status"))) {
1189 VIR_WARN("missing status in migration event");
1193 if ((status = qemuMonitorMigrationStatusTypeFromString(str)) == -1) {
1194 VIR_WARN("unknown status '%s' in migration event", str);
1198 qemuMonitorEmitMigrationStatus(mon, status);
1203 qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon,
1204 virJSONValuePtr data)
1208 if (virJSONValueObjectGetNumberInt(data, "pass", &pass) < 0) {
1209 VIR_WARN("missing dirty-sync-count in migration-pass event");
1213 qemuMonitorEmitMigrationPass(mon, pass);
1218 qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data)
1220 virJSONValuePtr info;
1222 const char *slotType;
1224 unsigned int source;
1225 unsigned int status;
1227 if (!(info = virJSONValueObjectGetObject(data, "info")))
1231 alias = virJSONValueObjectGetString(info, "device");
1233 if (!(slotType = virJSONValueObjectGetString(info, "slot-type")))
1236 if (!(slot = virJSONValueObjectGetString(info, "slot")))
1239 if (virJSONValueObjectGetNumberUint(info, "source", &source) < 0)
1242 if (virJSONValueObjectGetNumberUint(info, "status", &status) < 0)
1245 qemuMonitorEmitAcpiOstInfo(mon, alias, slotType, slot, source, status);
1249 VIR_WARN("malformed ACPI_DEVICE_OST event");
1255 qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data)
1257 const char *nodename;
1258 unsigned long long threshold;
1259 unsigned long long excess;
1261 if (!(nodename = virJSONValueObjectGetString(data, "node-name")))
1264 if (virJSONValueObjectGetNumberUlong(data, "write-threshold", &threshold) < 0)
1267 if (virJSONValueObjectGetNumberUlong(data, "amount-exceeded", &excess) < 0)
1270 qemuMonitorEmitBlockThreshold(mon, nodename, threshold, excess);
1274 VIR_WARN("malformed 'BLOCK_WRITE_THRESHOLD' event");
1279 qemuMonitorJSONExtractDumpStats(virJSONValuePtr result,
1280 qemuMonitorDumpStatsPtr ret)
1282 const char *statusstr;
1284 if (!(statusstr = virJSONValueObjectGetString(result, "status"))) {
1285 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1286 _("incomplete result, failed to get status"));
1290 ret->status = qemuMonitorDumpStatusTypeFromString(statusstr);
1291 if (ret->status < 0) {
1292 virReportError(VIR_ERR_INTERNAL_ERROR,
1293 _("incomplete result, unknown status string '%s'"),
1298 if (virJSONValueObjectGetNumberUlong(result, "completed", &ret->completed) < 0) {
1299 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1300 _("incomplete result, failed to get completed"));
1304 if (virJSONValueObjectGetNumberUlong(result, "total", &ret->total) < 0) {
1305 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1306 _("incomplete result, failed to get total"));
1315 qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
1316 virJSONValuePtr data)
1318 virJSONValuePtr result;
1320 qemuMonitorDumpStats stats = { 0 };
1321 const char *error = NULL;
1323 if (!(result = virJSONValueObjectGetObject(data, "result"))) {
1324 VIR_WARN("missing result in dump completed event");
1328 status = qemuMonitorJSONExtractDumpStats(result, &stats);
1330 error = virJSONValueObjectGetString(data, "error");
1332 qemuMonitorEmitDumpCompleted(mon, status, &stats, error);
1336 static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon,
1337 virJSONValuePtr data)
1342 if (!(name = virJSONValueObjectGetString(data, "id"))) {
1343 VIR_WARN("missing pr-manager alias in PR_MANAGER_STATUS_CHANGED event");
1347 if (virJSONValueObjectGetBoolean(data, "connected", &connected) < 0) {
1348 VIR_WARN("missing connected state for %s "
1349 "in PR_MANAGER_STATUS_CHANGED event", name);
1353 qemuMonitorEmitPRManagerStatusChanged(mon, name, connected);
1357 static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon,
1358 virJSONValuePtr data)
1362 unsigned long long subnet_prefix, interface_id;
1364 if (!(netdev = virJSONValueObjectGetString(data, "netdev"))) {
1365 VIR_WARN("missing netdev in GID_STATUS_CHANGED event");
1369 if (virJSONValueObjectGetBoolean(data, "gid-status", &gid_status)) {
1370 VIR_WARN("missing gid-status in GID_STATUS_CHANGED event");
1374 if (virJSONValueObjectGetNumberUlong(data, "subnet-prefix",
1376 VIR_WARN("missing subnet-prefix in GID_STATUS_CHANGED event");
1380 if (virJSONValueObjectGetNumberUlong(data, "interface-id",
1382 VIR_WARN("missing interface-id in GID_STATUS_CHANGED event");
1386 qemuMonitorEmitRdmaGidStatusChanged(mon, netdev, gid_status, subnet_prefix,
1392 qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
1393 const char *cmd_str,
1397 virJSONValuePtr cmd = NULL;
1398 virJSONValuePtr reply = NULL;
1399 virJSONValuePtr obj;
1402 cmd = qemuMonitorJSONMakeCommand("human-monitor-command",
1403 "s:command-line", cmd_str,
1406 if (!cmd || qemuMonitorJSONCommandWithFd(mon, cmd, scm_fd, &reply) < 0)
1409 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
1410 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1411 _("Human monitor command is not available to run %s"),
1416 if (qemuMonitorJSONCheckError(cmd, reply))
1419 obj = virJSONValueObjectGet(reply, "return");
1424 data = virJSONValueGetString(obj);
1425 if (VIR_STRDUP(*reply_str, NULLSTR_EMPTY(data)) < 0)
1432 virJSONValueFree(cmd);
1433 virJSONValueFree(reply);
1439 qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon)
1442 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("qmp_capabilities", NULL);
1443 virJSONValuePtr reply = NULL;
1447 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1450 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1455 virJSONValueFree(cmd);
1456 virJSONValueFree(reply);
1462 qemuMonitorJSONStartCPUs(qemuMonitorPtr mon)
1465 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("cont", NULL);
1466 virJSONValuePtr reply = NULL;
1473 ret = qemuMonitorJSONCommand(mon, cmd, &reply);
1478 /* If no error, we're done */
1479 if ((ret = qemuMonitorJSONCheckError(cmd, reply)) == 0)
1482 /* If error class is not MigrationExpected, we're done.
1483 * Otherwise try 'cont' cmd again */
1484 if (!qemuMonitorJSONHasError(reply, "MigrationExpected"))
1487 virJSONValueFree(reply);
1490 } while (++i <= timeout);
1492 virJSONValueFree(cmd);
1493 virJSONValueFree(reply);
1499 qemuMonitorJSONStopCPUs(qemuMonitorPtr mon)
1502 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("stop", NULL);
1503 virJSONValuePtr reply = NULL;
1507 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1510 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1515 virJSONValueFree(cmd);
1516 virJSONValueFree(reply);
1522 qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
1524 virDomainPausedReason *reason)
1528 virJSONValuePtr cmd;
1529 virJSONValuePtr reply = NULL;
1530 virJSONValuePtr data;
1533 *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
1535 if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL)))
1538 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1541 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
1544 data = virJSONValueObjectGetObject(reply, "return");
1546 if (virJSONValueObjectGetBoolean(data, "running", running) < 0) {
1547 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1548 _("query-status reply was missing running state"));
1552 if ((status = virJSONValueObjectGetString(data, "status"))) {
1553 if (!*running && reason)
1554 *reason = qemuMonitorVMStatusToPausedReason(status);
1555 } else if (!*running) {
1556 VIR_DEBUG("query-status reply was missing status details");
1562 virJSONValueFree(cmd);
1563 virJSONValueFree(reply);
1568 int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon)
1571 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("system_powerdown", NULL);
1572 virJSONValuePtr reply = NULL;
1576 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1579 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1584 virJSONValueFree(cmd);
1585 virJSONValueFree(reply);
1589 int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
1591 virDomainNetInterfaceLinkState state)
1594 virJSONValuePtr reply = NULL;
1595 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("set_link",
1597 "b:up", state != VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN,
1603 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1606 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1611 virJSONValueFree(cmd);
1612 virJSONValueFree(reply);
1616 int qemuMonitorJSONSystemReset(qemuMonitorPtr mon)
1619 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("system_reset", NULL);
1620 virJSONValuePtr reply = NULL;
1624 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1627 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1632 virJSONValueFree(cmd);
1633 virJSONValueFree(reply);
1639 * qemuMonitorJSONExtractCPUS390Info:
1640 * @jsoncpu: pointer to a single JSON cpu entry
1641 * @cpu: pointer to a single cpu entry
1643 * Derive the legacy cpu info 'halted' information
1644 * from the more accurate s390 cpu state. @cpu is
1645 * modified only on success.
1647 * Note: the 'uninitialized' s390 cpu state can't be
1648 * mapped to halted yes/no.
1650 * A s390 cpu entry could look like this
1653 * "qom-path": "/machine/unattached/device[0]",
1654 * "thread_id": 3081,
1655 * "cpu-state": "operating" }
1659 qemuMonitorJSONExtractCPUS390Info(virJSONValuePtr jsoncpu,
1660 struct qemuMonitorQueryCpusEntry *cpu)
1662 const char *cpu_state = virJSONValueObjectGetString(jsoncpu, "cpu-state");
1664 if (STREQ_NULLABLE(cpu_state, "operating") ||
1665 STREQ_NULLABLE(cpu_state, "load"))
1666 cpu->halted = false;
1667 else if (STREQ_NULLABLE(cpu_state, "stopped") ||
1668 STREQ_NULLABLE(cpu_state, "check-stop"))
1674 * qemuMonitorJSONExtractCPUInfo:
1675 * @data: JSON response data
1676 * @entries: filled with detected cpu entries on success
1677 * @nentries: number of entries returned
1678 * @fast: true if this is a response from query-cpus-fast
1680 * The JSON response @data will have the following format
1681 * in case @fast == false
1685 * "qom_path": "/machine/unattached/device[0]",
1686 * "pc": -2130415978,
1688 * "thread_id": 2631237,
1692 * and for @fast == true
1700 * "qom-path": "/machine/unattached/device[0]",
1701 * "thread-id": 2631237,
1706 * [{ "arch": "s390",
1711 * "qom-path": "/machine/unattached/device[0]",
1712 * "thread-id": 1237,
1713 * "cpu-state": "operating",
1718 * Note that since QEMU 2.13.0 the "arch" output member of the
1719 * "query-cpus-fast" command is replaced by "target".
1722 qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
1723 struct qemuMonitorQueryCpusEntry **entries,
1727 const char *arch = NULL;
1728 struct qemuMonitorQueryCpusEntry *cpus = NULL;
1733 if ((ncpus = virJSONValueArraySize(data)) == 0)
1736 if (VIR_ALLOC_N(cpus, ncpus) < 0)
1739 for (i = 0; i < ncpus; i++) {
1740 virJSONValuePtr entry = virJSONValueArrayGet(data, i);
1743 bool halted = false;
1744 const char *qom_path;
1750 /* Some older qemu versions don't report the thread_id so treat this as
1751 * non-fatal, simply returning no data.
1752 * The return data of query-cpus-fast has different field names
1755 if (!(arch = virJSONValueObjectGetString(entry, "target")))
1756 arch = virJSONValueObjectGetString(entry, "arch");
1757 ignore_value(virJSONValueObjectGetNumberInt(entry, "cpu-index", &cpuid));
1758 ignore_value(virJSONValueObjectGetNumberInt(entry, "thread-id", &thread));
1759 qom_path = virJSONValueObjectGetString(entry, "qom-path");
1761 arch = virJSONValueObjectGetString(entry, "arch");
1762 ignore_value(virJSONValueObjectGetNumberInt(entry, "CPU", &cpuid));
1763 ignore_value(virJSONValueObjectGetNumberInt(entry, "thread_id", &thread));
1764 ignore_value(virJSONValueObjectGetBoolean(entry, "halted", &halted));
1765 qom_path = virJSONValueObjectGetString(entry, "qom_path");
1768 cpus[i].qemu_id = cpuid;
1769 cpus[i].tid = thread;
1770 cpus[i].halted = halted;
1771 if (VIR_STRDUP(cpus[i].qom_path, qom_path) < 0)
1774 /* process optional architecture-specific data */
1775 if (STREQ_NULLABLE(arch, "s390") || STREQ_NULLABLE(arch, "s390x"))
1776 qemuMonitorJSONExtractCPUS390Info(entry, cpus + i);
1779 VIR_STEAL_PTR(*entries, cpus);
1784 qemuMonitorQueryCpusFree(cpus, ncpus);
1790 * qemuMonitorJSONQueryCPUs:
1792 * @mon: monitor object
1793 * @entries: filled with detected entries on success
1794 * @nentries: number of entries returned
1795 * @force: force exit on error
1796 * @fast: use query-cpus-fast
1798 * Queries qemu for cpu-related information. Failure to execute the command or
1799 * extract results does not produce an error as libvirt can continue without
1800 * this information, unless the caller has specified @force == true.
1802 * Returns 0 on success, -1 on a fatal error (oom ...) and -2 if the
1803 * query failed gracefully.
1806 qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon,
1807 struct qemuMonitorQueryCpusEntry **entries,
1813 virJSONValuePtr cmd;
1814 virJSONValuePtr reply = NULL;
1815 virJSONValuePtr data;
1818 cmd = qemuMonitorJSONMakeCommand("query-cpus-fast", NULL);
1820 cmd = qemuMonitorJSONMakeCommand("query-cpus", NULL);
1825 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1828 if (force && qemuMonitorJSONCheckError(cmd, reply) < 0)
1831 if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
1836 ret = qemuMonitorJSONExtractCPUInfo(data, entries, nentries, fast);
1839 virJSONValueFree(cmd);
1840 virJSONValueFree(reply);
1845 int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
1846 virDomainVirtType *virtType)
1849 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-kvm",
1851 virJSONValuePtr reply = NULL;
1852 virJSONValuePtr data;
1855 *virtType = VIR_DOMAIN_VIRT_QEMU;
1860 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1863 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
1866 data = virJSONValueObjectGetObject(reply, "return");
1868 if (virJSONValueObjectGetBoolean(data, "enabled", &val) < 0) {
1869 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1870 _("info kvm reply missing 'enabled' field"));
1875 *virtType = VIR_DOMAIN_VIRT_KVM;
1879 virJSONValueFree(cmd);
1880 virJSONValueFree(reply);
1886 * Loads correct video memory size values from QEMU and update the video
1889 * Return 0 on success, -1 on failure and set proper error message.
1892 qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
1893 virDomainVideoDefPtr video,
1896 qemuMonitorJSONObjectProperty prop = {
1897 QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
1901 switch (video->type) {
1902 case VIR_DOMAIN_VIDEO_TYPE_VGA:
1903 if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
1904 virReportError(VIR_ERR_INTERNAL_ERROR,
1905 _("QOM Object '%s' has no property 'vgamem_mb'"),
1909 video->vram = prop.val.ul * 1024;
1911 case VIR_DOMAIN_VIDEO_TYPE_QXL:
1912 if (qemuMonitorJSONGetObjectProperty(mon, path, "vram_size", &prop) < 0) {
1913 virReportError(VIR_ERR_INTERNAL_ERROR,
1914 _("QOM Object '%s' has no property 'vram_size'"),
1918 video->vram = prop.val.ul / 1024;
1920 if (qemuMonitorJSONGetObjectProperty(mon, path, "ram_size", &prop) < 0) {
1921 virReportError(VIR_ERR_INTERNAL_ERROR,
1922 _("QOM Object '%s' has no property 'ram_size'"),
1926 video->ram = prop.val.ul / 1024;
1927 if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
1928 virReportError(VIR_ERR_INTERNAL_ERROR,
1929 _("QOM Object '%s' has no property 'vgamem_mb'"),
1933 video->vgamem = prop.val.ul * 1024;
1935 case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
1936 if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
1937 virReportError(VIR_ERR_INTERNAL_ERROR,
1938 _("QOM Object '%s' has no property 'vgamem_mb'"),
1942 video->vram = prop.val.ul * 1024;
1944 case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
1945 case VIR_DOMAIN_VIDEO_TYPE_XEN:
1946 case VIR_DOMAIN_VIDEO_TYPE_VBOX:
1947 case VIR_DOMAIN_VIDEO_TYPE_LAST:
1956 * Loads correct video vram64 size value from QEMU and update the video
1959 * Return 0 on success, -1 on failure and set proper error message.
1962 qemuMonitorJSONUpdateVideoVram64Size(qemuMonitorPtr mon,
1963 virDomainVideoDefPtr video,
1966 qemuMonitorJSONObjectProperty prop = {
1967 QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
1971 switch (video->type) {
1972 case VIR_DOMAIN_VIDEO_TYPE_QXL:
1973 if (video->vram64 != 0) {
1974 if (qemuMonitorJSONGetObjectProperty(mon, path,
1975 "vram64_size_mb", &prop) < 0) {
1976 virReportError(VIR_ERR_INTERNAL_ERROR,
1977 _("QOM Object '%s' has no property 'vram64_size_mb'"),
1981 video->vram64 = prop.val.ul * 1024;
1984 case VIR_DOMAIN_VIDEO_TYPE_VGA:
1985 case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
1986 case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
1987 case VIR_DOMAIN_VIDEO_TYPE_XEN:
1988 case VIR_DOMAIN_VIDEO_TYPE_VBOX:
1989 case VIR_DOMAIN_VIDEO_TYPE_LAST:
1998 qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
1999 unsigned long long *currmem)
2002 virJSONValuePtr data;
2003 unsigned long long mem;
2004 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-balloon",
2006 virJSONValuePtr reply = NULL;
2013 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2016 /* See if balloon soft-failed */
2017 if (qemuMonitorJSONHasError(reply, "DeviceNotActive") ||
2018 qemuMonitorJSONHasError(reply, "KVMMissingCap")) {
2023 /* See if any other fatal error occurred */
2024 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
2027 data = virJSONValueObjectGetObject(reply, "return");
2029 if (virJSONValueObjectGetNumberUlong(data, "actual", &mem) < 0) {
2030 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2031 _("info balloon reply was missing balloon data"));
2035 *currmem = (mem/1024);
2038 virJSONValueFree(cmd);
2039 virJSONValueFree(reply);
2044 /* Process the balloon driver statistics. The request and data returned
2045 * will be as follows (although the 'child[#]' entry will differ based on
2048 * { "execute": "qom-get","arguments": \
2049 * { "path": "/machine/i440fx/pci.0/child[7]","property": "guest-stats"} }
2051 * {"return": {"stats": \
2052 * {"stat-swap-out": 0,
2053 * "stat-free-memory": 686350336,
2054 * "stat-minor-faults": 697283,
2055 * "stat-major-faults": 951,
2056 * "stat-total-memory": 1019924480,
2057 * "stat-swap-in": 0},
2058 * "last-update": 1371221540}}
2060 * A value in "stats" can be -1 indicating it's never been collected/stored.
2061 * The 'last-update' value could be used in the future in order to determine
2062 * rates and/or whether data has been collected since a previous cycle.
2063 * It's currently unused.
2065 #define GET_BALLOON_STATS(OBJECT, FIELD, TAG, DIVISOR) \
2066 if (virJSONValueObjectHasKey(OBJECT, FIELD) && \
2067 (got < nr_stats)) { \
2068 if (virJSONValueObjectGetNumberUlong(OBJECT, FIELD, &mem) < 0) { \
2069 VIR_DEBUG("Failed to get '%s' value", FIELD); \
2071 /* Not being collected? No point in providing bad data */ \
2072 if (mem != -1UL) { \
2073 stats[got].tag = TAG; \
2074 stats[got].val = mem / DIVISOR; \
2081 int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
2083 virDomainMemoryStatPtr stats,
2084 unsigned int nr_stats)
2087 virJSONValuePtr cmd = NULL;
2088 virJSONValuePtr reply = NULL;
2089 virJSONValuePtr data;
2090 virJSONValuePtr statsdata;
2091 unsigned long long mem;
2094 ret = qemuMonitorJSONGetBalloonInfo(mon, &mem);
2095 if (ret == 1 && (got < nr_stats)) {
2096 stats[got].tag = VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON;
2097 stats[got].val = mem;
2104 if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
2105 "s:path", balloonpath,
2106 "s:property", "guest-stats",
2110 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2113 if ((data = virJSONValueObjectGetObject(reply, "error"))) {
2114 const char *klass = virJSONValueObjectGetString(data, "class");
2115 const char *desc = virJSONValueObjectGetString(data, "desc");
2117 if (STREQ_NULLABLE(klass, "GenericError") &&
2118 STREQ_NULLABLE(desc, "guest hasn't updated any stats yet")) {
2119 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2120 _("the guest hasn't updated any stats yet"));
2125 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
2128 data = virJSONValueObjectGetObject(reply, "return");
2130 if (!(statsdata = virJSONValueObjectGet(data, "stats"))) {
2131 VIR_DEBUG("data does not include 'stats'");
2135 GET_BALLOON_STATS(statsdata, "stat-swap-in",
2136 VIR_DOMAIN_MEMORY_STAT_SWAP_IN, 1024);
2137 GET_BALLOON_STATS(statsdata, "stat-swap-out",
2138 VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, 1024);
2139 GET_BALLOON_STATS(statsdata, "stat-major-faults",
2140 VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, 1);
2141 GET_BALLOON_STATS(statsdata, "stat-minor-faults",
2142 VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, 1);
2143 GET_BALLOON_STATS(statsdata, "stat-free-memory",
2144 VIR_DOMAIN_MEMORY_STAT_UNUSED, 1024);
2145 GET_BALLOON_STATS(statsdata, "stat-total-memory",
2146 VIR_DOMAIN_MEMORY_STAT_AVAILABLE, 1024);
2147 GET_BALLOON_STATS(statsdata, "stat-available-memory",
2148 VIR_DOMAIN_MEMORY_STAT_USABLE, 1024);
2149 GET_BALLOON_STATS(data, "last-update",
2150 VIR_DOMAIN_MEMORY_STAT_LAST_UPDATE, 1);
2151 GET_BALLOON_STATS(statsdata, "stat-disk-caches",
2152 VIR_DOMAIN_MEMORY_STAT_DISK_CACHES, 1024);
2153 GET_BALLOON_STATS(statsdata, "stat-htlb-pgalloc",
2154 VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGALLOC, 1);
2155 GET_BALLOON_STATS(statsdata, "stat-htlb-pgfail",
2156 VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGFAIL, 1);
2160 virJSONValueFree(cmd);
2161 virJSONValueFree(reply);
2164 #undef GET_BALLOON_STATS
2168 * Using the provided balloonpath, determine if we need to set the
2169 * collection interval property to enable statistics gathering.
2172 qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitorPtr mon,
2176 qemuMonitorJSONObjectProperty prop;
2178 /* Set to the value in memballoon (could enable or disable) */
2179 memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
2180 prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT;
2181 prop.val.iv = period;
2182 if (qemuMonitorJSONSetObjectProperty(mon, balloonpath,
2183 "guest-stats-polling-interval",
2191 /* qemuMonitorJSONQueryBlock:
2192 * @mon: Monitor pointer
2194 * This helper will attempt to make a "query-block" call and check for
2195 * errors before returning with the reply.
2197 * Returns: NULL on error, reply on success
2199 static virJSONValuePtr
2200 qemuMonitorJSONQueryBlock(qemuMonitorPtr mon)
2202 virJSONValuePtr cmd;
2203 virJSONValuePtr reply = NULL;
2204 virJSONValuePtr devices = NULL;
2206 if (!(cmd = qemuMonitorJSONMakeCommand("query-block", NULL)))
2209 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0 ||
2210 qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
2213 devices = virJSONValueObjectStealArray(reply, "return");
2216 virJSONValueFree(cmd);
2217 virJSONValueFree(reply);
2222 static virJSONValuePtr
2223 qemuMonitorJSONGetBlockDev(virJSONValuePtr devices,
2226 virJSONValuePtr dev = virJSONValueArrayGet(devices, idx);
2228 if (!dev || virJSONValueGetType(dev) != VIR_JSON_TYPE_OBJECT) {
2229 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2230 _("query-block device entry was not in expected format"));
2238 qemuMonitorJSONGetBlockDevDevice(virJSONValuePtr dev)
2240 const char *thisdev;
2242 if (!(thisdev = virJSONValueObjectGetString(dev, "device"))) {
2243 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2244 _("query-block device entry was not in expected format"));
2253 qemuMonitorJSONBlockInfoAdd(virHashTablePtr table,
2254 struct qemuDomainDiskInfo *info,
2255 const char *entryname)
2257 struct qemuDomainDiskInfo *tmp = NULL;
2260 if (VIR_ALLOC(tmp) < 0)
2264 tmp->nodename = NULL;
2266 if (info->nodename &&
2267 VIR_STRDUP(tmp->nodename, info->nodename) < 0)
2270 if (virHashAddEntry(table, entryname, tmp) < 0)
2278 VIR_FREE(tmp->nodename);
2284 int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
2285 virHashTablePtr table)
2290 virJSONValuePtr devices;
2292 if (!(devices = qemuMonitorJSONQueryBlock(mon)))
2295 for (i = 0; i < virJSONValueArraySize(devices); i++) {
2296 virJSONValuePtr dev;
2297 virJSONValuePtr image;
2298 struct qemuDomainDiskInfo info = { false };
2299 const char *thisdev;
2303 if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
2306 if (!(thisdev = qemuMonitorJSONGetBlockDevDevice(dev)))
2309 thisdev = qemuAliasDiskDriveSkipPrefix(thisdev);
2310 qdev = virJSONValueObjectGetString(dev, "qdev");
2312 if (*thisdev == '\0')
2315 if (!qdev && !thisdev) {
2316 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2317 _("query-block device entry was not in expected format"));
2321 if (virJSONValueObjectGetBoolean(dev, "removable", &info.removable) < 0) {
2322 virReportError(VIR_ERR_INTERNAL_ERROR,
2323 _("cannot read %s value"),
2328 /* 'tray_open' is present only if the device has a tray */
2329 if (virJSONValueObjectGetBoolean(dev, "tray_open", &info.tray_open) == 0)
2332 /* presence of 'inserted' notifies that a medium is in the device */
2333 if ((image = virJSONValueObjectGetObject(dev, "inserted"))) {
2334 info.nodename = (char *) virJSONValueObjectGetString(image, "node-name");
2339 /* Missing io-status indicates no error */
2340 if ((status = virJSONValueObjectGetString(dev, "io-status"))) {
2341 info.io_status = qemuMonitorBlockIOStatusToError(status);
2342 if (info.io_status < 0)
2347 qemuMonitorJSONBlockInfoAdd(table, &info, thisdev) < 0)
2350 if (qdev && STRNEQ_NULLABLE(thisdev, qdev) &&
2351 qemuMonitorJSONBlockInfoAdd(table, &info, qdev) < 0)
2357 virJSONValueFree(devices);
2362 static qemuBlockStatsPtr
2363 qemuMonitorJSONBlockStatsCollectData(virJSONValuePtr dev,
2366 qemuBlockStatsPtr bstats = NULL;
2367 qemuBlockStatsPtr ret = NULL;
2368 virJSONValuePtr parent;
2369 virJSONValuePtr parentstats;
2370 virJSONValuePtr stats;
2372 if ((stats = virJSONValueObjectGetObject(dev, "stats")) == NULL) {
2373 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2374 _("blockstats stats entry was not "
2375 "in expected format"));
2379 if (VIR_ALLOC(bstats) < 0)
2382 #define QEMU_MONITOR_BLOCK_STAT_GET(NAME, VAR, MANDATORY) \
2383 if (MANDATORY || virJSONValueObjectHasKey(stats, NAME)) { \
2385 if (virJSONValueObjectGetNumberLong(stats, NAME, &VAR) < 0) { \
2386 virReportError(VIR_ERR_INTERNAL_ERROR, \
2387 _("cannot read %s statistic"), NAME); \
2391 QEMU_MONITOR_BLOCK_STAT_GET("rd_bytes", bstats->rd_bytes, true);
2392 QEMU_MONITOR_BLOCK_STAT_GET("wr_bytes", bstats->wr_bytes, true);
2393 QEMU_MONITOR_BLOCK_STAT_GET("rd_operations", bstats->rd_req, true);
2394 QEMU_MONITOR_BLOCK_STAT_GET("wr_operations", bstats->wr_req, true);
2395 QEMU_MONITOR_BLOCK_STAT_GET("rd_total_time_ns", bstats->rd_total_times, false);
2396 QEMU_MONITOR_BLOCK_STAT_GET("wr_total_time_ns", bstats->wr_total_times, false);
2397 QEMU_MONITOR_BLOCK_STAT_GET("flush_operations", bstats->flush_req, false);
2398 QEMU_MONITOR_BLOCK_STAT_GET("flush_total_time_ns", bstats->flush_total_times, false);
2399 #undef QEMU_MONITOR_BLOCK_STAT_GET
2401 if ((parent = virJSONValueObjectGetObject(dev, "parent")) &&
2402 (parentstats = virJSONValueObjectGetObject(parent, "stats"))) {
2403 if (virJSONValueObjectGetNumberUlong(parentstats, "wr_highest_offset",
2404 &bstats->wr_highest_offset) == 0)
2405 bstats->wr_highest_offset_valid = true;
2408 VIR_STEAL_PTR(ret, bstats);
2417 qemuMonitorJSONAddOneBlockStatsInfo(qemuBlockStatsPtr bstats,
2419 virHashTablePtr stats)
2421 qemuBlockStatsPtr copy = NULL;
2423 if (VIR_ALLOC(copy) < 0)
2429 if (virHashAddEntry(stats, name, copy) < 0) {
2439 qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
2440 const char *dev_name,
2442 virHashTablePtr hash,
2445 qemuBlockStatsPtr bstats = NULL;
2448 const char *qdevname = NULL;
2449 const char *nodename = NULL;
2450 char *devicename = NULL;
2451 virJSONValuePtr backing;
2454 !(devicename = qemuDomainStorageAlias(dev_name, depth)))
2457 qdevname = virJSONValueObjectGetString(dev, "qdev");
2458 nodename = virJSONValueObjectGetString(dev, "node-name");
2460 if (!devicename && !qdevname && !nodename) {
2461 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2462 _("blockstats device entry was not in expected format"));
2466 if (!(bstats = qemuMonitorJSONBlockStatsCollectData(dev, &nstats)))
2470 qemuMonitorJSONAddOneBlockStatsInfo(bstats, devicename, hash) < 0)
2473 if (qdevname && STRNEQ_NULLABLE(qdevname, devicename) &&
2474 qemuMonitorJSONAddOneBlockStatsInfo(bstats, qdevname, hash) < 0)
2478 qemuMonitorJSONAddOneBlockStatsInfo(bstats, nodename, hash) < 0)
2482 (backing = virJSONValueObjectGetObject(dev, "backing")) &&
2483 qemuMonitorJSONGetOneBlockStatsInfo(backing, dev_name, depth + 1,
2490 VIR_FREE(devicename);
2496 qemuMonitorJSONQueryBlockstats(qemuMonitorPtr mon)
2498 virJSONValuePtr cmd;
2499 virJSONValuePtr reply = NULL;
2500 virJSONValuePtr ret = NULL;
2502 if (!(cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL)))
2505 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2508 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
2511 ret = virJSONValueObjectStealArray(reply, "return");
2514 virJSONValueFree(cmd);
2515 virJSONValueFree(reply);
2521 qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
2522 virHashTablePtr hash,
2529 virJSONValuePtr devices;
2531 if (!(devices = qemuMonitorJSONQueryBlockstats(mon)))
2534 for (i = 0; i < virJSONValueArraySize(devices); i++) {
2535 virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
2536 const char *dev_name;
2538 if (!dev || virJSONValueGetType(dev) != VIR_JSON_TYPE_OBJECT) {
2539 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2540 _("blockstats device entry was not "
2541 "in expected format"));
2545 if (!(dev_name = virJSONValueObjectGetString(dev, "device"))) {
2546 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2547 _("blockstats device entry was not "
2548 "in expected format"));
2552 if (*dev_name == '\0')
2555 rc = qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, 0, hash,
2568 virJSONValueFree(devices);
2574 qemuMonitorJSONBlockStatsUpdateCapacityData(virJSONValuePtr image,
2576 virHashTablePtr stats,
2577 qemuBlockStatsPtr *entry)
2579 qemuBlockStatsPtr bstats;
2581 if (!(bstats = virHashLookup(stats, name))) {
2582 if (VIR_ALLOC(bstats) < 0)
2585 if (virHashAddEntry(stats, name, bstats) < 0) {
2594 /* failures can be ignored after this point */
2595 if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
2596 &bstats->capacity) < 0)
2599 /* if actual-size is missing, image is not thin provisioned */
2600 if (virJSONValueObjectGetNumberUlong(image, "actual-size",
2601 &bstats->physical) < 0)
2602 bstats->physical = bstats->capacity;
2609 qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
2610 const char *dev_name,
2612 virHashTablePtr stats,
2616 char *entry_name = qemuDomainStorageAlias(dev_name, depth);
2617 virJSONValuePtr backing;
2619 if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, entry_name,
2624 (backing = virJSONValueObjectGetObject(image, "backing-image")) &&
2625 qemuMonitorJSONBlockStatsUpdateCapacityOne(backing,
2634 VIR_FREE(entry_name);
2640 qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
2641 virHashTablePtr stats,
2646 virJSONValuePtr devices;
2648 if (!(devices = qemuMonitorJSONQueryBlock(mon)))
2651 for (i = 0; i < virJSONValueArraySize(devices); i++) {
2652 virJSONValuePtr dev;
2653 virJSONValuePtr inserted;
2654 virJSONValuePtr image;
2655 const char *dev_name;
2657 if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
2660 if (!(dev_name = qemuMonitorJSONGetBlockDevDevice(dev)))
2663 /* drive may be empty */
2664 if (!(inserted = virJSONValueObjectGetObject(dev, "inserted")) ||
2665 !(image = virJSONValueObjectGetObject(inserted, "image")))
2668 if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, 0,
2677 virJSONValueFree(devices);
2683 qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker(size_t pos ATTRIBUTE_UNUSED,
2684 virJSONValuePtr val,
2687 virHashTablePtr stats = opaque;
2688 virJSONValuePtr image;
2689 const char *nodename;
2690 qemuBlockStatsPtr entry;
2692 if (!(nodename = virJSONValueObjectGetString(val, "node-name")) ||
2693 !(image = virJSONValueObjectGetObject(val, "image"))) {
2694 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2695 _("query-named-block-nodes entry was not in expected format"));
2699 if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, nodename, stats, &entry) < 0)
2703 ignore_value(virJSONValueObjectGetNumberUlong(val, "write_threshold",
2704 &entry->write_threshold));
2706 return 1; /* we don't want to steal the value from the JSON array */
2711 qemuMonitorJSONBlockStatsUpdateCapacityBlockdev(qemuMonitorPtr mon,
2712 virHashTablePtr stats)
2714 virJSONValuePtr nodes;
2717 if (!(nodes = qemuMonitorJSONQueryNamedBlockNodes(mon)))
2720 if (virJSONValueArrayForeachSteal(nodes,
2721 qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker,
2728 virJSONValueFree(nodes);
2733 int qemuMonitorJSONBlockResize(qemuMonitorPtr mon,
2735 const char *nodename,
2736 unsigned long long size)
2739 virJSONValuePtr cmd;
2740 virJSONValuePtr reply = NULL;
2742 cmd = qemuMonitorJSONMakeCommand("block_resize",
2744 "S:node-name", nodename,
2750 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2753 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2758 virJSONValueFree(cmd);
2759 virJSONValueFree(reply);
2764 int qemuMonitorJSONSetPassword(qemuMonitorPtr mon,
2765 const char *protocol,
2766 const char *password,
2767 const char *action_if_connected)
2770 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("set_password",
2771 "s:protocol", protocol,
2772 "s:password", password,
2773 "s:connected", action_if_connected,
2775 virJSONValuePtr reply = NULL;
2779 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2782 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2787 virJSONValueFree(cmd);
2788 virJSONValueFree(reply);
2792 int qemuMonitorJSONExpirePassword(qemuMonitorPtr mon,
2793 const char *protocol,
2794 const char *expire_time)
2797 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("expire_password",
2798 "s:protocol", protocol,
2799 "s:time", expire_time,
2801 virJSONValuePtr reply = NULL;
2805 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2808 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2813 virJSONValueFree(cmd);
2814 virJSONValueFree(reply);
2820 qemuMonitorJSONSetBalloon(qemuMonitorPtr mon,
2821 unsigned long long newmem)
2824 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("balloon",
2825 "U:value", newmem * 1024,
2827 virJSONValuePtr reply = NULL;
2831 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2834 /* See if balloon soft-failed */
2835 if (qemuMonitorJSONHasError(reply, "DeviceNotActive") ||
2836 qemuMonitorJSONHasError(reply, "KVMMissingCap")) {
2841 /* See if any other fatal error occurred */
2842 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2848 virJSONValueFree(cmd);
2849 virJSONValueFree(reply);
2854 int qemuMonitorJSONSetCPU(qemuMonitorPtr mon,
2855 int cpu, bool online)
2858 virJSONValuePtr cmd = NULL;
2859 virJSONValuePtr reply = NULL;
2862 cmd = qemuMonitorJSONMakeCommand("cpu-add",
2866 /* offlining is not yet implemented in qmp */
2872 if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
2875 if (qemuMonitorJSONHasError(reply, "CommandNotFound"))
2878 ret = qemuMonitorJSONCheckError(cmd, reply);
2881 virJSONValueFree(cmd);
2882 virJSONValueFree(reply);
2886 VIR_DEBUG("no QMP support for cpu_set, trying HMP");
2887 ret = qemuMonitorTextSetCPU(mon, cpu, online);
2893 * Run QMP command to eject a media from ejectable device.
2899 int qemuMonitorJSONEjectMedia(qemuMonitorPtr mon,
2900 const char *dev_name,
2904 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("eject",
2905 "s:device", dev_name,
2906 "b:force", force ? 1 : 0,
2908 virJSONValuePtr reply = NULL;
2912 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2915 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2920 virJSONValueFree(cmd);
2921 virJSONValueFree(reply);
2926 int qemuMonitorJSONChangeMedia(qemuMonitorPtr mon,
2927 const char *dev_name,
2928 const char *newmedia,
2932 virJSONValuePtr cmd;
2933 virJSONValuePtr reply = NULL;
2935 cmd = qemuMonitorJSONMakeCommand("change",
2936 "s:device", dev_name,
2937 "s:target", newmedia,
2944 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2947 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2952 virJSONValueFree(cmd);
2953 virJSONValueFree(reply);
2958 static int qemuMonitorJSONSaveMemory(qemuMonitorPtr mon,
2959 const char *cmdtype,
2960 unsigned long long offset,
2965 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand(cmdtype,
2970 virJSONValuePtr reply = NULL;
2974 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2977 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2982 virJSONValueFree(cmd);
2983 virJSONValueFree(reply);
2988 int qemuMonitorJSONSaveVirtualMemory(qemuMonitorPtr mon,
2989 unsigned long long offset,
2993 return qemuMonitorJSONSaveMemory(mon, "memsave", offset, length, path);
2996 int qemuMonitorJSONSavePhysicalMemory(qemuMonitorPtr mon,
2997 unsigned long long offset,
3001 return qemuMonitorJSONSaveMemory(mon, "pmemsave", offset, length, path);
3005 int qemuMonitorJSONSetMigrationSpeed(qemuMonitorPtr mon,
3006 unsigned long bandwidth)
3009 virJSONValuePtr cmd;
3010 virJSONValuePtr reply = NULL;
3011 cmd = qemuMonitorJSONMakeCommand("migrate_set_speed",
3012 "U:value", bandwidth * 1024ULL * 1024ULL,
3017 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3020 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3025 virJSONValueFree(cmd);
3026 virJSONValueFree(reply);
3031 int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
3032 unsigned long long downtime)
3035 virJSONValuePtr cmd;
3036 virJSONValuePtr reply = NULL;
3038 cmd = qemuMonitorJSONMakeCommand("migrate_set_downtime",
3039 "d:value", downtime / 1000.0,
3044 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3047 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3052 virJSONValueFree(cmd);
3053 virJSONValueFree(reply);
3059 qemuMonitorJSONGetMigrationCacheSize(qemuMonitorPtr mon,
3060 unsigned long long *cacheSize)
3063 virJSONValuePtr cmd;
3064 virJSONValuePtr reply = NULL;
3068 cmd = qemuMonitorJSONMakeCommand("query-migrate-cache-size", NULL);
3072 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3075 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_NUMBER) < 0)
3078 if (virJSONValueObjectGetNumberUlong(reply, "return", cacheSize) < 0) {
3079 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3080 _("invalid cache size in query-migrate-cache-size reply"));
3086 virJSONValueFree(cmd);
3087 virJSONValueFree(reply);
3093 qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon,
3094 unsigned long long cacheSize)
3097 virJSONValuePtr cmd;
3098 virJSONValuePtr reply = NULL;
3100 cmd = qemuMonitorJSONMakeCommand("migrate-set-cache-size",
3101 "U:value", cacheSize,
3106 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3109 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3114 virJSONValueFree(cmd);
3115 virJSONValueFree(reply);
3121 qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon,
3122 virJSONValuePtr *params)
3125 virJSONValuePtr cmd = NULL;
3126 virJSONValuePtr reply = NULL;
3130 if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate-parameters", NULL)))
3133 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3136 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
3141 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3144 *params = virJSONValueObjectStealObject(reply, "return");
3148 virJSONValueFree(cmd);
3149 virJSONValueFree(reply);
3154 qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon,
3155 virJSONValuePtr params)
3158 virJSONValuePtr cmd = NULL;
3159 virJSONValuePtr reply = NULL;
3161 if (!(cmd = virJSONValueNewObject()))
3164 if (virJSONValueObjectAppendString(cmd, "execute",
3165 "migrate-set-parameters") < 0)
3168 if (virJSONValueObjectAppend(cmd, "arguments", params) < 0)
3172 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3175 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3180 virJSONValueFree(cmd);
3181 virJSONValueFree(params);
3182 virJSONValueFree(reply);
3188 qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
3189 qemuMonitorMigrationStatsPtr stats,
3192 virJSONValuePtr ret;
3193 virJSONValuePtr ram;
3194 virJSONValuePtr disk;
3195 virJSONValuePtr comp;
3196 const char *statusstr;
3201 ret = virJSONValueObjectGetObject(reply, "return");
3203 if (!(statusstr = virJSONValueObjectGetString(ret, "status"))) {
3204 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3205 _("info migration reply was missing return status"));
3209 stats->status = qemuMonitorMigrationStatusTypeFromString(statusstr);
3210 if (stats->status < 0) {
3211 virReportError(VIR_ERR_INTERNAL_ERROR,
3212 _("unexpected migration status in %s"), statusstr);
3216 ignore_value(virJSONValueObjectGetNumberUlong(ret, "total-time",
3217 &stats->total_time));
3218 if (stats->status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) {
3219 rc = virJSONValueObjectGetNumberUlong(ret, "downtime",
3222 rc = virJSONValueObjectGetNumberUlong(ret, "expected-downtime",
3226 stats->downtime_set = true;
3228 if (virJSONValueObjectGetNumberUlong(ret, "setup-time",
3229 &stats->setup_time) == 0)
3230 stats->setup_time_set = true;
3232 ignore_value(virJSONValueObjectGetNumberInt(ret, "cpu-throttle-percentage",
3233 &stats->cpu_throttle_percentage));
3235 switch ((qemuMonitorMigrationStatus) stats->status) {
3236 case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
3237 case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
3238 case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
3239 case QEMU_MONITOR_MIGRATION_STATUS_LAST:
3242 case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
3244 tmp = virJSONValueObjectGetString(ret, "error-desc");
3245 if (tmp && VIR_STRDUP(*error, tmp) < 0)
3250 case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
3251 case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY:
3252 case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
3253 case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING:
3254 case QEMU_MONITOR_MIGRATION_STATUS_PRE_SWITCHOVER:
3255 case QEMU_MONITOR_MIGRATION_STATUS_DEVICE:
3256 ram = virJSONValueObjectGetObject(ret, "ram");
3258 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3259 _("migration was active, but no RAM info was set"));
3263 if (virJSONValueObjectGetNumberUlong(ram, "transferred",
3264 &stats->ram_transferred) < 0) {
3265 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3266 _("migration was active, but RAM 'transferred' "
3267 "data was missing"));
3270 if (virJSONValueObjectGetNumberUlong(ram, "remaining",
3271 &stats->ram_remaining) < 0) {
3272 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3273 _("migration was active, but RAM 'remaining' "
3274 "data was missing"));
3277 if (virJSONValueObjectGetNumberUlong(ram, "total",
3278 &stats->ram_total) < 0) {
3279 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3280 _("migration was active, but RAM 'total' "
3281 "data was missing"));
3285 if (virJSONValueObjectGetNumberDouble(ram, "mbps", &mbps) == 0 &&
3287 /* mpbs from QEMU reports Mbits/s (M as in 10^6 not Mi as 2^20) */
3288 stats->ram_bps = mbps * (1000 * 1000 / 8);
3291 if (virJSONValueObjectGetNumberUlong(ram, "duplicate",
3292 &stats->ram_duplicate) == 0)
3293 stats->ram_duplicate_set = true;
3294 ignore_value(virJSONValueObjectGetNumberUlong(ram, "normal",
3295 &stats->ram_normal));
3296 ignore_value(virJSONValueObjectGetNumberUlong(ram, "normal-bytes",
3297 &stats->ram_normal_bytes));
3298 ignore_value(virJSONValueObjectGetNumberUlong(ram, "dirty-pages-rate",
3299 &stats->ram_dirty_rate));
3300 ignore_value(virJSONValueObjectGetNumberUlong(ram, "page-size",
3301 &stats->ram_page_size));
3302 ignore_value(virJSONValueObjectGetNumberUlong(ram, "dirty-sync-count",
3303 &stats->ram_iteration));
3304 ignore_value(virJSONValueObjectGetNumberUlong(ram, "postcopy-requests",
3305 &stats->ram_postcopy_reqs));
3307 disk = virJSONValueObjectGetObject(ret, "disk");
3309 rc = virJSONValueObjectGetNumberUlong(disk, "transferred",
3310 &stats->disk_transferred);
3312 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3313 _("disk migration was active, but "
3314 "'transferred' data was missing"));
3318 rc = virJSONValueObjectGetNumberUlong(disk, "remaining",
3319 &stats->disk_remaining);
3321 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3322 _("disk migration was active, but 'remaining' "
3323 "data was missing"));
3327 rc = virJSONValueObjectGetNumberUlong(disk, "total",
3328 &stats->disk_total);
3330 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3331 _("disk migration was active, but 'total' "
3332 "data was missing"));
3336 if (virJSONValueObjectGetNumberDouble(disk, "mbps", &mbps) == 0 &&
3338 /* mpbs from QEMU reports Mbits/s (M as in 10^6 not Mi as 2^20) */
3339 stats->disk_bps = mbps * (1000 * 1000 / 8);
3343 comp = virJSONValueObjectGetObject(ret, "xbzrle-cache");
3345 stats->xbzrle_set = true;
3346 rc = virJSONValueObjectGetNumberUlong(comp, "cache-size",
3347 &stats->xbzrle_cache_size);
3349 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3350 _("XBZRLE is active, but 'cache-size' data "
3355 rc = virJSONValueObjectGetNumberUlong(comp, "bytes",
3356 &stats->xbzrle_bytes);
3358 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3359 _("XBZRLE is active, but 'bytes' data "
3364 rc = virJSONValueObjectGetNumberUlong(comp, "pages",
3365 &stats->xbzrle_pages);
3367 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3368 _("XBZRLE is active, but 'pages' data "
3373 rc = virJSONValueObjectGetNumberUlong(comp, "cache-miss",
3374 &stats->xbzrle_cache_miss);
3376 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3377 _("XBZRLE is active, but 'cache-miss' data "
3382 rc = virJSONValueObjectGetNumberUlong(comp, "overflow",
3383 &stats->xbzrle_overflow);
3385 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3386 _("XBZRLE is active, but 'overflow' data "
3398 int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
3399 qemuMonitorMigrationStatsPtr stats,
3403 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
3405 virJSONValuePtr reply = NULL;
3407 memset(stats, 0, sizeof(*stats));
3412 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3415 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3418 if (qemuMonitorJSONGetMigrationStatsReply(reply, stats, error) < 0)
3424 memset(stats, 0, sizeof(*stats));
3425 virJSONValueFree(cmd);
3426 virJSONValueFree(reply);
3431 int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
3436 virJSONValuePtr cmd =
3437 qemuMonitorJSONMakeCommand("migrate",
3438 "b:detach", flags & QEMU_MONITOR_MIGRATE_BACKGROUND ? 1 : 0,
3439 "b:blk", flags & QEMU_MONITOR_MIGRATE_NON_SHARED_DISK ? 1 : 0,
3440 "b:inc", flags & QEMU_MONITOR_MIGRATE_NON_SHARED_INC ? 1 : 0,
3443 virJSONValuePtr reply = NULL;
3448 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3451 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3456 virJSONValueFree(cmd);
3457 virJSONValueFree(reply);
3461 int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)
3464 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("migrate_cancel", NULL);
3465 virJSONValuePtr reply = NULL;
3469 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3472 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3477 virJSONValueFree(cmd);
3478 virJSONValueFree(reply);
3483 /* qemuMonitorJSONQueryDump:
3484 * @mon: Monitor pointer
3485 * @stats: Monitor dump stats
3487 * Attempt to make a "query-dump" call, check for errors, and get/return
3488 * the current from the reply
3490 * Returns: 0 on success, -1 on failure
3493 qemuMonitorJSONQueryDump(qemuMonitorPtr mon,
3494 qemuMonitorDumpStatsPtr stats)
3496 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-dump", NULL);
3497 virJSONValuePtr reply = NULL;
3498 virJSONValuePtr result = NULL;
3504 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3507 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3510 result = virJSONValueObjectGetObject(reply, "return");
3512 ret = qemuMonitorJSONExtractDumpStats(result, stats);
3515 virJSONValueFree(cmd);
3516 virJSONValueFree(reply);
3522 qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitorPtr mon,
3523 const char *capability)
3526 virJSONValuePtr cmd;
3527 virJSONValuePtr reply = NULL;
3528 virJSONValuePtr caps;
3529 virJSONValuePtr formats;
3532 if (!(cmd = qemuMonitorJSONMakeCommand("query-dump-guest-memory-capability",
3536 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3539 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
3544 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3547 caps = virJSONValueObjectGetObject(reply, "return");
3549 if (!(formats = virJSONValueObjectGetArray(caps, "formats"))) {
3550 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3551 _("missing supported dump formats"));
3555 for (i = 0; i < virJSONValueArraySize(formats); i++) {
3556 virJSONValuePtr dumpformat = virJSONValueArrayGet(formats, i);
3558 if (!dumpformat || virJSONValueGetType(dumpformat) != VIR_JSON_TYPE_STRING) {
3559 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3560 _("missing entry in supported dump formats"));
3564 if (STREQ(virJSONValueGetString(dumpformat), capability)) {
3572 virJSONValueFree(cmd);
3573 virJSONValueFree(reply);
3578 qemuMonitorJSONDump(qemuMonitorPtr mon,
3579 const char *protocol,
3580 const char *dumpformat,
3584 virJSONValuePtr cmd = NULL;
3585 virJSONValuePtr reply = NULL;
3587 cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
3589 "s:protocol", protocol,
3590 "S:format", dumpformat,
3596 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3599 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3604 virJSONValueFree(cmd);
3605 virJSONValueFree(reply);
3609 int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
3611 const char *hostname,
3614 const char *tlsSubject)
3617 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("client_migrate_info",
3619 (type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc"),
3620 "s:hostname", hostname,
3622 "i:tls-port", tlsPort,
3623 "S:cert-subject", tlsSubject,
3625 virJSONValuePtr reply = NULL;
3629 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3632 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3637 virJSONValueFree(cmd);
3638 virJSONValueFree(reply);
3643 int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
3648 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("getfd",
3651 virJSONValuePtr reply = NULL;
3655 if (qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply) < 0)
3658 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3663 virJSONValueFree(cmd);
3664 virJSONValueFree(reply);
3669 int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
3673 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("closefd",
3676 virJSONValuePtr reply = NULL;
3680 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3683 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3688 virJSONValueFree(cmd);
3689 virJSONValueFree(reply);
3695 qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name)
3698 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("add-fd",
3699 "i:fdset-id", fdset,
3702 virJSONValuePtr reply = NULL;
3706 ret = qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply);
3709 /* qemu 1.2 lacks the functionality we need; but we have to
3710 * probe to find that out. Don't log errors in that case. */
3711 if (STREQ_NULLABLE(name, "/dev/null") &&
3712 qemuMonitorJSONHasError(reply, "GenericError")) {
3716 ret = qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT);
3719 virJSONValuePtr data = virJSONValueObjectGetObject(reply, "return");
3721 if (virJSONValueObjectGetNumberInt(data, "fd", &ret) < 0) {
3722 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3723 _("incomplete return information"));
3729 virJSONValueFree(cmd);
3730 virJSONValueFree(reply);
3734 /* Best effort cleanup - kill the entire fdset (even if it has
3735 * earlier successful fd registrations), since we don't know which
3736 * fd qemu got, and don't want to leave the fd leaked in qemu. */
3737 qemuMonitorJSONRemoveFd(mon, fdset, -1);
3744 qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd)
3747 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("remove-fd",
3748 "i:fdset-id", fdset,
3749 fd < 0 ? NULL : "i:fd",
3751 virJSONValuePtr reply = NULL;
3755 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3758 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3763 virJSONValueFree(cmd);
3764 virJSONValueFree(reply);
3769 int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
3770 const char *netdevstr)
3773 virJSONValuePtr cmd = NULL;
3774 virJSONValuePtr reply = NULL;
3775 virJSONValuePtr args = NULL;
3777 cmd = qemuMonitorJSONMakeCommand("netdev_add", NULL);
3781 args = qemuMonitorJSONKeywordStringToJSON(netdevstr, "type");
3785 if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
3787 args = NULL; /* obj owns reference to args now */
3789 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3792 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3797 virJSONValueFree(args);
3798 virJSONValueFree(cmd);
3799 virJSONValueFree(reply);
3804 int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
3808 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("netdev_del",
3811 virJSONValuePtr reply = NULL;
3815 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3818 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3823 virJSONValueFree(cmd);
3824 virJSONValueFree(reply);
3830 qemuMonitorJSONQueryRxFilterParse(virJSONValuePtr msg,
3831 virNetDevRxFilterPtr *filter)
3835 virJSONValuePtr returnArray, entry, table, element;
3838 virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
3843 returnArray = virJSONValueObjectGetArray(msg, "return");
3845 if (!(entry = virJSONValueArrayGet(returnArray, 0))) {
3846 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3847 _("query -rx-filter return data missing array element"));
3851 if (!(tmp = virJSONValueObjectGetString(entry, "name"))) {
3852 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3853 _("Missing or invalid name "
3854 "in query-rx-filter response"));
3857 if (VIR_STRDUP(fil->name, tmp) < 0)
3859 if ((!(tmp = virJSONValueObjectGetString(entry, "main-mac"))) ||
3860 virMacAddrParse(tmp, &fil->mac) < 0) {
3861 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3862 _("Missing or invalid 'main-mac' "
3863 "in query-rx-filter response"));
3866 if (virJSONValueObjectGetBoolean(entry, "promiscuous",
3867 &fil->promiscuous) < 0) {
3868 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3869 _("Missing or invalid 'promiscuous' "
3870 "in query-rx-filter response"));
3873 if (virJSONValueObjectGetBoolean(entry, "broadcast-allowed",
3874 &fil->broadcastAllowed) < 0) {
3875 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3876 _("Missing or invalid 'broadcast-allowed' "
3877 "in query-rx-filter response"));
3881 if ((!(tmp = virJSONValueObjectGetString(entry, "unicast"))) ||
3883 = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
3884 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3885 _("Missing or invalid 'unicast' "
3886 "in query-rx-filter response"));
3889 if (virJSONValueObjectGetBoolean(entry, "unicast-overflow",
3890 &fil->unicast.overflow) < 0) {
3891 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3892 _("Missing or invalid 'unicast-overflow' "
3893 "in query-rx-filter response"));
3896 if ((!(table = virJSONValueObjectGet(entry, "unicast-table"))) ||
3897 (!virJSONValueIsArray(table))) {
3898 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3899 _("Missing or invalid 'unicast-table' array "
3900 "in query-rx-filter response"));
3903 nTable = virJSONValueArraySize(table);
3904 if (VIR_ALLOC_N(fil->unicast.table, nTable))
3906 for (i = 0; i < nTable; i++) {
3907 if (!(element = virJSONValueArrayGet(table, i)) ||
3908 !(tmp = virJSONValueGetString(element))) {
3909 virReportError(VIR_ERR_INTERNAL_ERROR,
3910 _("Missing or invalid element %zu of 'unicast' "
3911 "list in query-rx-filter response"), i);
3914 if (virMacAddrParse(tmp, &fil->unicast.table[i]) < 0) {
3915 virReportError(VIR_ERR_INTERNAL_ERROR,
3916 _("invalid mac address '%s' in 'unicast-table' "
3917 "array in query-rx-filter response"), tmp);
3921 fil->unicast.nTable = nTable;
3923 if ((!(tmp = virJSONValueObjectGetString(entry, "multicast"))) ||
3924 ((fil->multicast.mode
3925 = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
3926 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3927 _("Missing or invalid 'multicast' "
3928 "in query-rx-filter response"));
3931 if (virJSONValueObjectGetBoolean(entry, "multicast-overflow",
3932 &fil->multicast.overflow) < 0) {
3933 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3934 _("Missing or invalid 'multicast-overflow' "
3935 "in query-rx-filter response"));
3938 if ((!(table = virJSONValueObjectGet(entry, "multicast-table"))) ||
3939 (!virJSONValueIsArray(table))) {
3940 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3941 _("Missing or invalid 'multicast-table' array "
3942 "in query-rx-filter response"));
3945 nTable = virJSONValueArraySize(table);
3946 if (VIR_ALLOC_N(fil->multicast.table, nTable))
3948 for (i = 0; i < nTable; i++) {
3949 if (!(element = virJSONValueArrayGet(table, i)) ||
3950 !(tmp = virJSONValueGetString(element))) {
3951 virReportError(VIR_ERR_INTERNAL_ERROR,
3952 _("Missing or invalid element %zu of 'multicast' "
3953 "list in query-rx-filter response"), i);
3956 if (virMacAddrParse(tmp, &fil->multicast.table[i]) < 0) {
3957 virReportError(VIR_ERR_INTERNAL_ERROR,
3958 _("invalid mac address '%s' in 'multicast-table' "
3959 "array in query-rx-filter response"), tmp);
3963 fil->multicast.nTable = nTable;
3965 if ((!(tmp = virJSONValueObjectGetString(entry, "vlan"))) ||
3967 = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
3968 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3969 _("Missing or invalid 'vlan' "
3970 "in query-rx-filter response"));
3973 if ((!(table = virJSONValueObjectGet(entry, "vlan-table"))) ||
3974 (!virJSONValueIsArray(table))) {
3975 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3976 _("Missing or invalid 'vlan-table' array "
3977 "in query-rx-filter response"));
3980 nTable = virJSONValueArraySize(table);
3981 if (VIR_ALLOC_N(fil->vlan.table, nTable))
3983 for (i = 0; i < nTable; i++) {
3984 if (!(element = virJSONValueArrayGet(table, i)) ||
3985 virJSONValueGetNumberUint(element, &fil->vlan.table[i]) < 0) {
3986 virReportError(VIR_ERR_INTERNAL_ERROR,
3987 _("Missing or invalid element %zu of 'vlan-table' "
3988 "array in query-rx-filter response"), i);
3992 fil->vlan.nTable = nTable;
3997 virNetDevRxFilterFree(fil);
4006 qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
4007 virNetDevRxFilterPtr *filter)
4010 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-rx-filter",
4013 virJSONValuePtr reply = NULL;
4018 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4021 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
4024 if (qemuMonitorJSONQueryRxFilterParse(reply, filter) < 0)
4030 virNetDevRxFilterFree(*filter);
4033 virJSONValueFree(cmd);
4034 virJSONValueFree(reply);
4040 * Example return data
4043 * {"filename": "stdio", "label": "monitor"},
4044 * {"filename": "pty:/dev/pts/6", "label": "serial0", "frontend-open": true},
4045 * {"filename": "pty:/dev/pts/7", "label": "parallel0"}
4050 qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
4051 virHashTablePtr info)
4053 virJSONValuePtr data;
4056 qemuMonitorChardevInfoPtr entry = NULL;
4058 data = virJSONValueObjectGetArray(reply, "return");
4060 for (i = 0; i < virJSONValueArraySize(data); i++) {
4061 virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
4067 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4068 _("character device information was missing array element"));
4072 if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
4073 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4074 _("character device information was missing label"));
4078 if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
4079 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4080 _("character device information was missing filename"));
4084 if (VIR_ALLOC(entry) < 0)
4087 if (STRPREFIX(type, "pty:") &&
4088 VIR_STRDUP(entry->ptyPath, type + strlen("pty:")) < 0)
4091 if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
4093 entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
4095 entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
4098 if (virHashAddEntry(info, alias, entry) < 0) {
4099 virReportError(VIR_ERR_OPERATION_FAILED,
4100 _("failed to add chardev '%s' info"), alias);
4111 VIR_FREE(entry->ptyPath);
4120 qemuMonitorJSONGetChardevInfo(qemuMonitorPtr mon,
4121 virHashTablePtr info)
4125 virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-chardev",
4127 virJSONValuePtr reply = NULL;
4132 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4135 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
4138 ret = qemuMonitorJSONExtractChardevInfo(reply, info);
4140 virJSONValueFree(cmd);
4141 virJSONValueFree(reply);
4146 int qemuMonitorJSONDelDevice(qemuMonitorPtr mon,
4147 const char *devalias)
4150 virJSONValuePtr cmd;
4151 virJSONValuePtr reply = NULL;
4153 cmd = qemuMonitorJSONMakeCommand("device_del",
4159 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4162 if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
4167 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4172 virJSONValueFree(cmd);
4173 virJSONValueFree(reply);
4179 qemuMonitorJSONAddDeviceArgs(qemuMonitorPtr mon,
4180 virJSONValuePtr args)
4183 virJSONValuePtr cmd = NULL;
4184 virJSONValuePtr reply = NULL;
4186 if (!(cmd = qemuMonitorJSONMakeCommand("device_add", NULL)))
4189 if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
4191 args = NULL; /* obj owns reference to args now */
4193 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4196 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4201 virJSONValueFree(args);
4202 virJSONValueFree(cmd);
4203 virJSONValueFree(reply);
4209 qemuMonitorJSONAddDevice(qemuMonitorPtr mon,
4210 const char *devicestr)
4212 virJSONValuePtr args;
4214 if (!(args = qemuMonitorJSONKeywordStringToJSON(devicestr, "driver")))
4217 return qemuMonitorJSONAddDeviceArgs(mon, args);
4222 qemuMonitorJSONAddObject(qemuMonitorPtr mon,
4223 virJSONValuePtr props)
4226 virJSONValuePtr cmd;
4227 virJSONValuePtr reply = NULL;
4229 if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", props)))
4232 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4235 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4240 virJSONValueFree(cmd);
4241 virJSONValueFree(reply);
4246 int qemuMonitorJSONDelObject(qemuMonitorPtr mon,
4247 const char *objalias)
4250 virJSONValuePtr cmd;
4251 virJSONValuePtr reply = NULL;
4253 cmd = qemuMonitorJSONMakeCommand("object-del",
4259 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4262 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4267 virJSONValueFree(cmd);
4268 virJSONValueFree(reply);
4273 /* speed is in bytes/sec */
4275 qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
4276 const char *device, const char *file,
4277 const char *format, unsigned long long speed,
4278 unsigned int granularity,
4279 unsigned long long buf_size,
4283 VIR_AUTOPTR(virJSONValue) cmd = NULL;
4284 VIR_AUTOPTR(virJSONValue) reply = NULL;
4286 cmd = qemuMonitorJSONMakeCommand("drive-mirror",
4290 "z:granularity", granularity,
4291 "P:buf-size", buf_size,
4292 "s:sync", shallow ? "top" : "full",
4293 "s:mode", reuse ? "existing" : "absolute-paths",
4299 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4302 return qemuMonitorJSONCheckError(cmd, reply);
4307 qemuMonitorJSONBlockdevMirror(qemuMonitorPtr mon,
4308 const char *jobname,
4311 unsigned long long speed,
4312 unsigned int granularity,
4313 unsigned long long buf_size,
4316 VIR_AUTOPTR(virJSONValue) cmd = NULL;
4317 VIR_AUTOPTR(virJSONValue) reply = NULL;
4319 cmd = qemuMonitorJSONMakeCommand("blockdev-mirror",
4320 "S:job-id", jobname,
4324 "z:granularity", granularity,
4325 "P:buf-size", buf_size,
4326 "s:sync", shallow ? "top" : "full",
4331 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4334 return qemuMonitorJSONCheckError(cmd, reply);
4339 qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr *actions)
4342 virJSONValuePtr cmd;
4343 virJSONValuePtr reply = NULL;
4345 cmd = qemuMonitorJSONMakeCommand("transaction",
4346 "a:actions", actions,
4351 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4354 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4359 virJSONValueFree(cmd);
4360 virJSONValueFree(reply);
4364 /* Probe if active commit is supported: pass in a bogus device and NULL top
4365 * and base. The probe return is true if active commit is detected or false
4366 * if not supported or on any error */
4368 qemuMonitorJSONSupportsActiveCommit(qemuMonitorPtr mon)
4371 virJSONValuePtr cmd;
4372 virJSONValuePtr reply = NULL;
4374 if (!(cmd = qemuMonitorJSONMakeCommand("block-commit", "s:device",
4378 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4381 if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
4382 VIR_DEBUG("block-commit supports active commit");
4387 /* This is a false negative for qemu 2.0; but probably not
4388 * worth the additional complexity to worry about it */
4389 VIR_DEBUG("block-commit requires 'top' parameter, "
4390 "assuming it lacks active commit");
4392 virJSONValueFree(cmd);
4393 virJSONValueFree(reply);
4398 /* speed is in bytes/sec. Returns 0 on success, -1 with error message
4399 * emitted on failure. */
4401 qemuMonitorJSONBlockCommit(qemuMonitorPtr mon, const char *device,
4402 const char *top, const char *base,
4403 const char *backingName,
4404 unsigned long long speed)
4407 virJSONValuePtr cmd;
4408 virJSONValuePtr reply = NULL;
4410 cmd = qemuMonitorJSONMakeCommand("block-commit",
4415 "S:backing-file", backingName,
4420 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4423 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4428 virJSONValueFree(cmd);
4429 virJSONValueFree(reply);
4435 qemuMonitorJSONDiskNameLookupOne(virJSONValuePtr image,
4436 virStorageSourcePtr top,
4437 virStorageSourcePtr target)
4439 virJSONValuePtr backing;
4442 /* The caller will report a generic message if we return NULL
4443 * without an error; but in some cases we can improve by reporting
4444 * a more specific message. */
4447 if (top != target) {
4448 backing = virJSONValueObjectGetObject(image, "backing-image");
4449 return qemuMonitorJSONDiskNameLookupOne(backing, top->backingStore,
4452 if (VIR_STRDUP(ret, virJSONValueObjectGetString(image, "filename")) < 0)
4454 /* Sanity check - the name qemu gave us should resolve to the same
4455 file tracked by our target description. */
4456 if (virStorageSourceIsLocalStorage(target) &&
4457 STRNEQ(ret, target->path) &&
4458 !virFileLinkPointsTo(ret, target->path)) {
4459 virReportError(VIR_ERR_INTERNAL_ERROR,
4460 _("qemu block name '%s' doesn't match expected '%s'"),
4469 qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon,
4471 virStorageSourcePtr top,
4472 virStorageSourcePtr target)
4475 virJSONValuePtr devices;
4478 if (!(devices = qemuMonitorJSONQueryBlock(mon)))
4481 for (i = 0; i < virJSONValueArraySize(devices); i++) {
4482 virJSONValuePtr dev;
4483 virJSONValuePtr inserted;
4484 virJSONValuePtr image;
4485 const char *thisdev;
4487 if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
4490 if (!(thisdev = qemuMonitorJSONGetBlockDevDevice(dev)))
4493 if (STREQ(thisdev, device)) {
4494 if ((inserted = virJSONValueObjectGetObject(dev, "inserted")) &&
4495 (image = virJSONValueObjectGetObject(inserted, "image"))) {
4496 ret = qemuMonitorJSONDiskNameLookupOne(image, top, target);
4501 /* Guarantee an error when returning NULL, but don't override a
4502 * more specific error if one was already generated. */
4503 if (!ret && virGetLastErrorCode() == VIR_ERR_OK)
4504 virReportError(VIR_ERR_INTERNAL_ERROR,
4505 _("unable to find backing name for device %s"),
4509 virJSONValueFree(devices);
4515 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
4516 const char *cmd_str,
4520 virJSONValuePtr cmd = NULL;
4521 virJSONValuePtr reply = NULL;
4525 return qemuMonitorJSONHumanCommandWithFd(mon, cmd_str, -1, reply_str);
4527 if (!(cmd = virJSONValueFromString(cmd_str)))
4530 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4533 if (!(*reply_str = virJSONValueToString(reply, false)))
4540 virJSONValueFree(cmd);
4541 virJSONValueFree(reply);
4545 int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon)
4548 virJSONValuePtr cmd;
4549 virJSONValuePtr reply = NULL;
4551 cmd = qemuMonitorJSONMakeCommand("inject-nmi", NULL);
4555 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4558 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4563 virJSONValueFree(cmd);
4564 virJSONValueFree(reply);
4568 int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
4569 unsigned int holdtime,
4570 unsigned int *keycodes,
4571 unsigned int nkeycodes)
4574 virJSONValuePtr cmd = NULL;
4575 virJSONValuePtr reply = NULL;
4576 virJSONValuePtr keys = NULL;
4577 virJSONValuePtr key = NULL;
4580 /* create the key data array */
4581 if (!(keys = virJSONValueNewArray()))
4584 for (i = 0; i < nkeycodes; i++) {
4585 if (keycodes[i] > 0xffff) {
4586 virReportError(VIR_ERR_OPERATION_FAILED,
4587 _("keycode %zu is invalid: 0x%X"), i, keycodes[i]);
4591 /* create single key object */
4592 if (!(key = virJSONValueNewObject()))
4595 /* Union KeyValue has two types, use the generic one */
4596 if (virJSONValueObjectAppendString(key, "type", "number") < 0)
4599 /* with the keycode */
4600 if (virJSONValueObjectAppendNumberInt(key, "data", keycodes[i]) < 0)
4603 if (virJSONValueArrayAppend(keys, key) < 0)
4610 cmd = qemuMonitorJSONMakeCommand("send-key",
4612 "p:hold-time", holdtime,
4617 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4620 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4625 virJSONValueFree(cmd);
4626 virJSONValueFree(reply);
4627 virJSONValueFree(keys);
4628 virJSONValueFree(key);
4632 int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
4638 virJSONValuePtr cmd, reply = NULL;
4640 cmd = qemuMonitorJSONMakeCommand("screendump",
4649 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4652 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4657 virJSONValueFree(cmd);
4658 virJSONValueFree(reply);
4664 qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
4665 virJSONValuePtr entry)
4667 qemuMonitorBlockJobInfoPtr info = NULL;
4672 if (!(device = virJSONValueObjectGetString(entry, "device"))) {
4673 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4674 _("entry was missing 'device'"));
4677 device = qemuAliasDiskDriveSkipPrefix(device);
4679 if (VIR_ALLOC(info) < 0 ||
4680 virHashAddEntry(blockJobs, device, info) < 0) {
4685 /* assume we don't know the state */
4688 if (!(type = virJSONValueObjectGetString(entry, "type"))) {
4689 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4690 _("entry was missing 'type'"));
4693 if (STREQ(type, "stream"))
4694 info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
4695 else if (STREQ(type, "commit"))
4696 info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
4697 else if (STREQ(type, "mirror"))
4698 info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
4700 info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
4702 if (virJSONValueObjectGetNumberUlong(entry, "speed", &info->bandwidth) < 0) {
4703 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4704 _("entry was missing 'speed'"));
4708 if (virJSONValueObjectGetNumberUlong(entry, "offset", &info->cur) < 0) {
4709 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4710 _("entry was missing 'offset'"));
4714 if (virJSONValueObjectGetNumberUlong(entry, "len", &info->end) < 0) {
4715 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4716 _("entry was missing 'len'"));
4720 if (virJSONValueObjectGetBoolean(entry, "ready", &ready) == 0)
4721 info->ready = ready;
4727 qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon)
4729 virJSONValuePtr cmd = NULL;
4730 virJSONValuePtr reply = NULL;
4731 virJSONValuePtr data;
4734 virHashTablePtr blockJobs = NULL;
4736 cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL);
4739 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4742 if ((data = virJSONValueObjectGetArray(reply, "return")) == NULL) {
4743 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4744 _("reply was missing return data"));
4748 nr_results = virJSONValueArraySize(data);
4749 if (!(blockJobs = virHashCreate(nr_results, virHashValueFree)))
4752 for (i = 0; i < nr_results; i++) {
4753 virJSONValuePtr entry = virJSONValueArrayGet(data, i);
4755 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4756 _("missing array element"));
4759 if (qemuMonitorJSONParseBlockJobInfo(blockJobs, entry) < 0)
4764 virJSONValueFree(cmd);
4765 virJSONValueFree(reply);
4769 virHashFree(blockJobs);
4776 qemuMonitorJSONBlockJobError(virJSONValuePtr cmd,
4777 virJSONValuePtr reply,
4778 const char *jobname)
4780 virJSONValuePtr error;
4782 if ((error = virJSONValueObjectGet(reply, "error")) &&
4783 (qemuMonitorJSONErrorIsClass(error, "DeviceNotActive"))) {
4784 virReportError(VIR_ERR_OPERATION_INVALID,
4785 _("No active block job '%s'"), jobname);
4789 return qemuMonitorJSONCheckError(cmd, reply);
4793 /* speed is in bytes/sec */
4795 qemuMonitorJSONBlockStream(qemuMonitorPtr mon,
4798 const char *backingName,
4799 unsigned long long speed)
4802 virJSONValuePtr cmd = NULL;
4803 virJSONValuePtr reply = NULL;
4805 if (!(cmd = qemuMonitorJSONMakeCommand("block-stream",
4809 "S:backing-file", backingName,
4813 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4816 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4822 virJSONValueFree(cmd);
4823 virJSONValueFree(reply);
4829 qemuMonitorJSONBlockJobCancel(qemuMonitorPtr mon,
4830 const char *jobname)
4833 virJSONValuePtr cmd = NULL;
4834 virJSONValuePtr reply = NULL;
4836 if (!(cmd = qemuMonitorJSONMakeCommand("block-job-cancel",
4837 "s:device", jobname,
4841 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4844 if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4850 virJSONValueFree(cmd);
4851 virJSONValueFree(reply);
4857 qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon,
4858 const char *jobname,
4859 unsigned long long speed)
4862 virJSONValuePtr cmd;
4863 virJSONValuePtr reply = NULL;
4865 if (!(cmd = qemuMonitorJSONMakeCommand("block-job-set-speed",
4866 "s:device", jobname,
4871 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4874 if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4880 virJSONValueFree(cmd);
4881 virJSONValueFree(reply);
4887 qemuMonitorJSONDrivePivot(qemuMonitorPtr mon,
4888 const char *jobname)
4891 virJSONValuePtr cmd;
4892 virJSONValuePtr reply = NULL;
4894 cmd = qemuMonitorJSONMakeCommand("block-job-complete",
4895 "s:device", jobname,
4900 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4903 if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4908 virJSONValueFree(cmd);
4909 virJSONValueFree(reply);
4914 int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
4915 const char *protocol,
4920 virJSONValuePtr cmd, reply = NULL;
4922 cmd = qemuMonitorJSONMakeCommand("add_client",
4923 "s:protocol", protocol,
4925 "b:skipauth", skipauth,
4931 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4934 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4939 virJSONValueFree(cmd);
4940 virJSONValueFree(reply);
4945 #define GET_THROTTLE_STATS_OPTIONAL(FIELD, STORE) \
4946 if (virJSONValueObjectGetNumberUlong(inserted, \
4948 &reply->STORE) < 0) { \
4951 #define GET_THROTTLE_STATS(FIELD, STORE) \
4952 if (virJSONValueObjectGetNumberUlong(inserted, \
4954 &reply->STORE) < 0) { \
4955 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \
4956 _("block_io_throttle field '%s' missing " \
4957 "in qemu's output"), \
4962 qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr io_throttle,
4963 const char *drivealias,
4965 virDomainBlockIoTuneInfoPtr reply)
4971 for (i = 0; i < virJSONValueArraySize(io_throttle); i++) {
4972 virJSONValuePtr temp_dev = virJSONValueArrayGet(io_throttle, i);
4973 virJSONValuePtr inserted;
4974 const char *current_drive;
4975 const char *current_qdev;
4977 if (!temp_dev || virJSONValueGetType(temp_dev) != VIR_JSON_TYPE_OBJECT) {
4978 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4979 _("block_io_throttle device entry "
4980 "was not in expected format"));
4984 current_qdev = virJSONValueObjectGetString(temp_dev, "qdev");
4985 current_drive = virJSONValueObjectGetString(temp_dev, "device");
4987 if (!current_drive && !current_qdev) {
4988 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4989 _("block_io_throttle device entry "
4990 "was not in expected format"));
4994 if ((drivealias && current_drive && STRNEQ(current_drive, drivealias)) ||
4995 (qdevid && current_qdev && STRNEQ(current_qdev, qdevid)))
4999 if (!(inserted = virJSONValueObjectGetObject(temp_dev, "inserted"))) {
5000 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5001 _("block_io_throttle inserted entry "
5002 "was not in expected format"));
5005 GET_THROTTLE_STATS("bps", total_bytes_sec);
5006 GET_THROTTLE_STATS("bps_rd", read_bytes_sec);
5007 GET_THROTTLE_STATS("bps_wr", write_bytes_sec);
5008 GET_THROTTLE_STATS("iops", total_iops_sec);
5009 GET_THROTTLE_STATS("iops_rd", read_iops_sec);
5010 GET_THROTTLE_STATS("iops_wr", write_iops_sec);
5011 GET_THROTTLE_STATS_OPTIONAL("bps_max", total_bytes_sec_max);
5012 GET_THROTTLE_STATS_OPTIONAL("bps_rd_max", read_bytes_sec_max);
5013 GET_THROTTLE_STATS_OPTIONAL("bps_wr_max", write_bytes_sec_max);
5014 GET_THROTTLE_STATS_OPTIONAL("iops_max", total_iops_sec_max);
5015 GET_THROTTLE_STATS_OPTIONAL("iops_rd_max", read_iops_sec_max);
5016 GET_THROTTLE_STATS_OPTIONAL("iops_wr_max", write_iops_sec_max);
5017 GET_THROTTLE_STATS_OPTIONAL("iops_size", size_iops_sec);
5019 if (VIR_STRDUP(reply->group_name,
5020 virJSONValueObjectGetString(inserted, "group")) < 0)
5023 GET_THROTTLE_STATS_OPTIONAL("bps_max_length", total_bytes_sec_max_length);
5024 GET_THROTTLE_STATS_OPTIONAL("bps_rd_max_length", read_bytes_sec_max_length);
5025 GET_THROTTLE_STATS_OPTIONAL("bps_wr_max_length", write_bytes_sec_max_length);
5026 GET_THROTTLE_STATS_OPTIONAL("iops_max_length", total_iops_sec_max_length);
5027 GET_THROTTLE_STATS_OPTIONAL("iops_rd_max_length", read_iops_sec_max_length);
5028 GET_THROTTLE_STATS_OPTIONAL("iops_wr_max_length", write_iops_sec_max_length);
5034 virReportError(VIR_ERR_INTERNAL_ERROR,
5035 _("cannot find throttling info for device '%s'"),
5036 drivealias ? drivealias : qdevid);
5044 #undef GET_THROTTLE_STATS
5045 #undef GET_THROTTLE_STATS_OPTIONAL
5047 int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
5048 const char *drivealias,
5050 virDomainBlockIoTuneInfoPtr info,
5051 bool supportMaxOptions,
5052 bool supportGroupNameOption,
5053 bool supportMaxLengthOptions)
5056 virJSONValuePtr cmd = NULL;
5057 virJSONValuePtr result = NULL;
5058 virJSONValuePtr args = NULL;
5059 const char *errdev = drivealias;
5064 if (!(cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", NULL)))
5067 if (virJSONValueObjectCreate(&args,
5068 "S:device", drivealias,
5070 "U:bps", info->total_bytes_sec,
5071 "U:bps_rd", info->read_bytes_sec,
5072 "U:bps_wr", info->write_bytes_sec,
5073 "U:iops", info->total_iops_sec,
5074 "U:iops_rd", info->read_iops_sec,
5075 "U:iops_wr", info->write_iops_sec,
5079 if (supportMaxOptions &&
5080 virJSONValueObjectAdd(args,
5081 "U:bps_max", info->total_bytes_sec_max,
5082 "U:bps_rd_max", info->read_bytes_sec_max,
5083 "U:bps_wr_max", info->write_bytes_sec_max,
5084 "U:iops_max", info->total_iops_sec_max,
5085 "U:iops_rd_max", info->read_iops_sec_max,
5086 "U:iops_wr_max", info->write_iops_sec_max,
5087 "U:iops_size", info->size_iops_sec,
5091 if (supportGroupNameOption &&
5092 virJSONValueObjectAdd(args,
5093 "S:group", info->group_name,
5097 if (supportMaxLengthOptions &&
5098 virJSONValueObjectAdd(args,
5100 info->total_bytes_sec_max_length,
5101 "P:bps_rd_max_length",
5102 info->read_bytes_sec_max_length,
5103 "P:bps_wr_max_length",
5104 info->write_bytes_sec_max_length,
5105 "P:iops_max_length",
5106 info->total_iops_sec_max_length,
5107 "P:iops_rd_max_length",
5108 info->read_iops_sec_max_length,
5109 "P:iops_wr_max_length",
5110 info->write_iops_sec_max_length,
5114 if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
5116 args = NULL; /* obj owns reference to args now */
5118 if (qemuMonitorJSONCommand(mon, cmd, &result) < 0)
5121 if (virJSONValueObjectHasKey(result, "error")) {
5122 if (qemuMonitorJSONHasError(result, "DeviceNotActive")) {
5123 virReportError(VIR_ERR_OPERATION_INVALID,
5124 _("No active operation on device: %s"), errdev);
5125 } else if (qemuMonitorJSONHasError(result, "NotSupported")) {
5126 virReportError(VIR_ERR_OPERATION_INVALID,
5127 _("Operation is not supported for device: %s"), errdev);
5129 virJSONValuePtr error = virJSONValueObjectGet(result, "error");
5130 virReportError(VIR_ERR_INTERNAL_ERROR,
5131 _("unable to execute '%s', unexpected error: '%s'"),
5132 qemuMonitorJSONCommandName(cmd),
5133 qemuMonitorJSONStringifyError(error));
5140 virJSONValueFree(cmd);
5141 virJSONValueFree(result);
5142 virJSONValueFree(args);
5146 int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
5147 const char *drivealias,
5149 virDomainBlockIoTuneInfoPtr reply)
5152 virJSONValuePtr devices = NULL;
5154 if (!(devices = qemuMonitorJSONQueryBlock(mon)))
5157 ret = qemuMonitorJSONBlockIoThrottleInfo(devices, drivealias, qdevid, reply);
5158 virJSONValueFree(devices);
5162 int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon)
5165 virJSONValuePtr cmd = NULL;
5166 virJSONValuePtr reply = NULL;
5168 cmd = qemuMonitorJSONMakeCommand("system_wakeup", NULL);
5172 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5175 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
5180 virJSONValueFree(cmd);
5181 virJSONValueFree(reply);
5185 int qemuMonitorJSONGetVersion(qemuMonitorPtr mon,
5192 virJSONValuePtr cmd;
5193 virJSONValuePtr reply = NULL;
5194 virJSONValuePtr data;
5195 virJSONValuePtr qemu;
5197 *major = *minor = *micro = 0;
5201 if (!(cmd = qemuMonitorJSONMakeCommand("query-version", NULL)))
5204 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5207 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5210 data = virJSONValueObjectGetObject(reply, "return");
5212 if (!(qemu = virJSONValueObjectGetObject(data, "qemu"))) {
5213 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5214 _("query-version reply was missing 'qemu' data"));
5218 if (virJSONValueObjectGetNumberInt(qemu, "major", major) < 0) {
5219 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5220 _("query-version reply was missing 'major' version"));
5223 if (virJSONValueObjectGetNumberInt(qemu, "minor", minor) < 0) {
5224 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5225 _("query-version reply was missing 'minor' version"));
5228 if (virJSONValueObjectGetNumberInt(qemu, "micro", micro) < 0) {
5229 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5230 _("query-version reply was missing 'micro' version"));
5236 if (!(tmp = virJSONValueObjectGetString(data, "package"))) {
5237 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5238 _("query-version reply was missing 'package' version"));
5241 if (VIR_STRDUP(*package, tmp) < 0)
5248 virJSONValueFree(cmd);
5249 virJSONValueFree(reply);
5254 int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
5255 qemuMonitorMachineInfoPtr **machines)
5258 virJSONValuePtr cmd;
5259 virJSONValuePtr reply = NULL;
5260 virJSONValuePtr data;
5261 qemuMonitorMachineInfoPtr *infolist = NULL;
5267 if (!(cmd = qemuMonitorJSONMakeCommand("query-machines", NULL)))
5270 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5273 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5276 data = virJSONValueObjectGetArray(reply, "return");
5277 n = virJSONValueArraySize(data);
5279 /* null-terminated list */
5280 if (VIR_ALLOC_N(infolist, n + 1) < 0)
5283 for (i = 0; i < n; i++) {
5284 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5286 qemuMonitorMachineInfoPtr info;
5288 if (VIR_ALLOC(info) < 0)
5293 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5294 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5295 _("query-machines reply data was missing 'name'"));
5299 if (VIR_STRDUP(info->name, tmp) < 0)
5302 if (virJSONValueObjectHasKey(child, "is-default") &&
5303 virJSONValueObjectGetBoolean(child, "is-default", &info->isDefault) < 0) {
5304 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5305 _("query-machines reply has malformed 'is-default' data"));
5309 if (virJSONValueObjectHasKey(child, "alias")) {
5310 if (!(tmp = virJSONValueObjectGetString(child, "alias"))) {
5311 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5312 _("query-machines reply has malformed 'alias' data"));
5315 if (VIR_STRDUP(info->alias, tmp) < 0)
5318 if (virJSONValueObjectHasKey(child, "cpu-max") &&
5319 virJSONValueObjectGetNumberUint(child, "cpu-max", &info->maxCpus) < 0) {
5320 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5321 _("query-machines reply has malformed 'cpu-max' data"));
5325 ignore_value(virJSONValueObjectGetBoolean(child, "hotpluggable-cpus",
5326 &info->hotplugCpus));
5330 *machines = infolist;
5335 for (i = 0; i < n; i++)
5336 qemuMonitorMachineInfoFree(infolist[i]);
5339 virJSONValueFree(cmd);
5340 virJSONValueFree(reply);
5346 qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
5347 qemuMonitorCPUDefInfoPtr **cpus)
5350 virJSONValuePtr cmd;
5351 virJSONValuePtr reply = NULL;
5352 virJSONValuePtr data;
5353 qemuMonitorCPUDefInfoPtr *cpulist = NULL;
5359 if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-definitions", NULL)))
5362 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5365 /* Urgh, some QEMU architectures have the query-cpu-definitions
5366 * command, but return 'GenericError' with string "Not supported",
5367 * instead of simply omitting the command entirely :-(
5369 if (qemuMonitorJSONHasError(reply, "GenericError")) {
5374 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5377 data = virJSONValueObjectGetArray(reply, "return");
5378 n = virJSONValueArraySize(data);
5380 if (VIR_ALLOC_N(cpulist, n) < 0)
5383 for (i = 0; i < n; i++) {
5384 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5386 qemuMonitorCPUDefInfoPtr cpu;
5388 if (VIR_ALLOC(cpu) < 0)
5393 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5394 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5395 _("query-cpu-definitions reply data was missing 'name'"));
5399 if (VIR_STRDUP(cpu->name, tmp) < 0)
5402 if (virJSONValueObjectHasKey(child, "unavailable-features")) {
5403 virJSONValuePtr blockers;
5407 blockers = virJSONValueObjectGetArray(child,
5408 "unavailable-features");
5410 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5411 _("unavailable-features in query-cpu-definitions "
5412 "reply data was not an array"));
5416 len = virJSONValueArraySize(blockers);
5419 cpu->usable = VIR_TRISTATE_BOOL_YES;
5423 cpu->usable = VIR_TRISTATE_BOOL_NO;
5424 if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0)
5427 for (j = 0; j < len; j++) {
5428 virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j);
5430 if (virJSONValueGetType(blocker) != VIR_JSON_TYPE_STRING) {
5431 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5432 _("unexpected value in unavailable-features "
5437 if (VIR_STRDUP(cpu->blockers[j], virJSONValueGetString(blocker)) < 0)
5449 for (i = 0; i < n; i++)
5450 qemuMonitorCPUDefInfoFree(cpulist[i]);
5453 virJSONValueFree(cmd);
5454 virJSONValueFree(reply);
5459 VIR_ENUM_IMPL(qemuMonitorCPUProperty,
5460 QEMU_MONITOR_CPU_PROPERTY_LAST,
5461 "boolean", "string", "number",
5465 qemuMonitorJSONParseCPUModelProperty(const char *key,
5466 virJSONValue *value,
5469 qemuMonitorCPUModelInfoPtr machine_model = opaque;
5470 qemuMonitorCPUPropertyPtr prop;
5472 prop = machine_model->props + machine_model->nprops;
5474 switch ((virJSONType)virJSONValueGetType(value)) {
5475 case VIR_JSON_TYPE_STRING:
5476 if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0)
5478 prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
5481 case VIR_JSON_TYPE_NUMBER:
5482 /* Ignore numbers which cannot be parsed as unsigned long long */
5483 if (virJSONValueGetNumberLong(value, &prop->value.number) < 0)
5485 prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER;
5488 case VIR_JSON_TYPE_BOOLEAN:
5489 virJSONValueGetBoolean(value, &prop->value.boolean);
5490 prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
5493 case VIR_JSON_TYPE_OBJECT:
5494 case VIR_JSON_TYPE_ARRAY:
5495 case VIR_JSON_TYPE_NULL:
5499 machine_model->nprops++;
5500 if (VIR_STRDUP(prop->name, key) < 0)
5507 qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
5508 qemuMonitorCPUModelExpansionType type,
5509 const char *model_name,
5511 qemuMonitorCPUModelInfoPtr *model_info)
5514 virJSONValuePtr model = NULL;
5515 virJSONValuePtr props = NULL;
5516 virJSONValuePtr cmd = NULL;
5517 virJSONValuePtr reply = NULL;
5518 virJSONValuePtr data;
5519 virJSONValuePtr cpu_model;
5520 virJSONValuePtr cpu_props;
5521 qemuMonitorCPUModelInfoPtr machine_model = NULL;
5522 char const *cpu_name;
5523 const char *typeStr = "";
5527 if (!(model = virJSONValueNewObject()))
5530 if (virJSONValueObjectAppendString(model, "name", model_name) < 0)
5534 if (!(props = virJSONValueNewObject()) ||
5535 virJSONValueObjectAppendBoolean(props, "migratable", false) < 0 ||
5536 virJSONValueObjectAppend(model, "props", props) < 0)
5543 case QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC:
5544 case QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL:
5548 case QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL:
5553 if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-model-expansion",
5559 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5562 /* Even though query-cpu-model-expansion is advertised by query-commands it
5563 * may just return GenericError if it is not implemented for the requested
5564 * guest architecture or it is not supported in the host environment.
5566 if (qemuMonitorJSONHasError(reply, "GenericError")) {
5571 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5574 data = virJSONValueObjectGetObject(reply, "return");
5576 if (!(cpu_model = virJSONValueObjectGetObject(data, "model"))) {
5577 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5578 _("query-cpu-model-expansion reply data was missing 'model'"));
5582 /* QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL requests "full" expansion
5583 * on the result of the initial "static" expansion.
5585 if (type == QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL) {
5586 if (!(model = virJSONValueCopy(cpu_model)))
5589 virJSONValueFree(cmd);
5590 virJSONValueFree(reply);
5591 type = QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL;
5595 if (!(cpu_name = virJSONValueObjectGetString(cpu_model, "name"))) {
5596 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5597 _("query-cpu-model-expansion reply data was missing 'name'"));
5601 if (!(cpu_props = virJSONValueObjectGetObject(cpu_model, "props"))) {
5602 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5603 _("query-cpu-model-expansion reply data was missing 'props'"));
5607 if (VIR_ALLOC(machine_model) < 0)
5610 if (VIR_STRDUP(machine_model->name, cpu_name) < 0)
5613 if (VIR_ALLOC_N(machine_model->props, virJSONValueObjectKeysNumber(cpu_props)) < 0)
5616 if (virJSONValueObjectForeachKeyValue(cpu_props,
5617 qemuMonitorJSONParseCPUModelProperty,
5622 *model_info = machine_model;
5623 machine_model = NULL;
5626 qemuMonitorCPUModelInfoFree(machine_model);
5627 virJSONValueFree(cmd);
5628 virJSONValueFree(reply);
5629 virJSONValueFree(model);
5630 virJSONValueFree(props);
5635 int qemuMonitorJSONGetCommands(qemuMonitorPtr mon,
5639 virJSONValuePtr cmd;
5640 virJSONValuePtr reply = NULL;
5641 virJSONValuePtr data;
5642 char **commandlist = NULL;
5648 if (!(cmd = qemuMonitorJSONMakeCommand("query-commands", NULL)))
5651 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5654 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5657 data = virJSONValueObjectGetArray(reply, "return");
5658 n = virJSONValueArraySize(data);
5660 /* null-terminated list */
5661 if (VIR_ALLOC_N(commandlist, n + 1) < 0)
5664 for (i = 0; i < n; i++) {
5665 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5668 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5669 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5670 _("query-commands reply data was missing 'name'"));
5674 if (VIR_STRDUP(commandlist[i], tmp) < 0)
5679 *commands = commandlist;
5684 virStringListFree(commandlist);
5685 virJSONValueFree(cmd);
5686 virJSONValueFree(reply);
5691 int qemuMonitorJSONGetEvents(qemuMonitorPtr mon,
5695 virJSONValuePtr cmd;
5696 virJSONValuePtr reply = NULL;
5697 virJSONValuePtr data;
5698 char **eventlist = NULL;
5704 if (!(cmd = qemuMonitorJSONMakeCommand("query-events", NULL)))
5707 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5710 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5715 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5718 data = virJSONValueObjectGetArray(reply, "return");
5719 n = virJSONValueArraySize(data);
5721 /* null-terminated list */
5722 if (VIR_ALLOC_N(eventlist, n + 1) < 0)
5725 for (i = 0; i < n; i++) {
5726 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5729 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5730 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5731 _("query-events reply data was missing 'name'"));
5735 if (VIR_STRDUP(eventlist[i], tmp) < 0)
5740 *events = eventlist;
5744 virStringListFree(eventlist);
5745 virJSONValueFree(cmd);
5746 virJSONValueFree(reply);
5752 qemuMonitorJSONGetCommandLineOptionParameters(qemuMonitorPtr mon,
5758 virJSONValuePtr cmd = NULL;
5759 virJSONValuePtr reply = NULL;
5760 virJSONValuePtr data = NULL;
5761 virJSONValuePtr array = NULL;
5762 char **paramlist = NULL;
5770 /* query-command-line-options has fixed output for a given qemu
5771 * binary; but since callers want to query parameters for one
5772 * option at a time, we cache the option list from qemu. */
5773 if (!(array = qemuMonitorGetOptions(mon))) {
5774 if (!(cmd = qemuMonitorJSONMakeCommand("query-command-line-options",
5778 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5781 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5786 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
5789 if (virJSONValueObjectRemoveKey(reply, "return", &array) <= 0) {
5790 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5791 _("query-command-line-options reply was missing "
5796 if (!virJSONValueIsArray(array)) {
5797 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5798 _("Malformed query-command-line-options array"));
5802 qemuMonitorSetOptions(mon, array);
5805 for (i = 0; i < virJSONValueArraySize(array); i++) {
5806 virJSONValuePtr child = virJSONValueArrayGet(array, i);
5809 if (!(tmp = virJSONValueObjectGetString(child, "option"))) {
5810 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5811 _("query-command-line-options reply data was "
5812 "missing 'option'"));
5815 if (STREQ(tmp, option)) {
5816 data = virJSONValueObjectGet(child, "parameters");
5822 /* Option not found; return 0 parameters rather than an error. */
5830 if (!virJSONValueIsArray(data)) {
5831 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5832 _("Malformed query-command-line-options parameters array"));
5835 n = virJSONValueArraySize(data);
5837 /* null-terminated list */
5838 if (VIR_ALLOC_N(paramlist, n + 1) < 0)
5841 for (i = 0; i < n; i++) {
5842 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5845 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5846 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5847 _("query-command-line-options parameter data was "
5852 if (VIR_STRDUP(paramlist[i], tmp) < 0)
5857 *params = paramlist;
5861 /* If we failed before getting the JSON array of options, we (try)
5862 * to cache an empty array to speed up the next failure. */
5863 if (!qemuMonitorGetOptions(mon))
5864 qemuMonitorSetOptions(mon, virJSONValueNewArray());
5866 virStringListFree(paramlist);
5867 virJSONValueFree(cmd);
5868 virJSONValueFree(reply);
5873 int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon,
5878 virJSONValuePtr cmd = NULL;
5879 virJSONValuePtr reply = NULL;
5880 virJSONValuePtr data = NULL;
5883 *enabled = *present = false;
5885 if (!(cmd = qemuMonitorJSONMakeCommand("query-kvm", NULL)))
5888 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5891 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5896 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5899 data = virJSONValueObjectGetObject(reply, "return");
5901 if (virJSONValueObjectGetBoolean(data, "enabled", enabled) < 0 ||
5902 virJSONValueObjectGetBoolean(data, "present", present) < 0) {
5903 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5904 _("query-kvm replied unexpected data"));
5911 virJSONValueFree(cmd);
5912 virJSONValueFree(reply);
5917 int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon,
5921 virJSONValuePtr cmd;
5922 virJSONValuePtr reply = NULL;
5923 virJSONValuePtr data;
5924 char **typelist = NULL;
5930 if (!(cmd = qemuMonitorJSONMakeCommand("qom-list-types", NULL)))
5933 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5936 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5939 data = virJSONValueObjectGetArray(reply, "return");
5940 n = virJSONValueArraySize(data);
5942 /* null-terminated list */
5943 if (VIR_ALLOC_N(typelist, n + 1) < 0)
5946 for (i = 0; i < n; i++) {
5947 virJSONValuePtr child = virJSONValueArrayGet(data, i);
5950 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5951 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5952 _("qom-list-types reply data was missing 'name'"));
5956 if (VIR_STRDUP(typelist[i], tmp) < 0)
5965 virStringListFree(typelist);
5966 virJSONValueFree(cmd);
5967 virJSONValueFree(reply);
5972 int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
5974 qemuMonitorJSONListPathPtr **paths)
5977 virJSONValuePtr cmd;
5978 virJSONValuePtr reply = NULL;
5979 virJSONValuePtr data;
5980 qemuMonitorJSONListPathPtr *pathlist = NULL;
5986 if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
5991 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5994 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5997 data = virJSONValueObjectGetArray(reply, "return");
5998 n = virJSONValueArraySize(data);
6000 /* null-terminated list */
6001 if (VIR_ALLOC_N(pathlist, n + 1) < 0)
6004 for (i = 0; i < n; i++) {
6005 virJSONValuePtr child = virJSONValueArrayGet(data, i);
6007 qemuMonitorJSONListPathPtr info;
6009 if (VIR_ALLOC(info) < 0)
6014 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
6015 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6016 _("qom-list reply data was missing 'name'"));
6020 if (VIR_STRDUP(info->name, tmp) < 0)
6023 if (virJSONValueObjectHasKey(child, "type")) {
6024 if (!(tmp = virJSONValueObjectGetString(child, "type"))) {
6025 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6026 _("qom-list reply has malformed 'type' data"));
6029 if (VIR_STRDUP(info->type, tmp) < 0)
6040 for (i = 0; i < n; i++)
6041 qemuMonitorJSONListPathFree(pathlist[i]);
6044 virJSONValueFree(cmd);
6045 virJSONValueFree(reply);
6049 void qemuMonitorJSONListPathFree(qemuMonitorJSONListPathPtr paths)
6053 VIR_FREE(paths->name);
6054 VIR_FREE(paths->type);
6059 int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
6061 const char *property,
6062 qemuMonitorJSONObjectPropertyPtr prop)
6065 virJSONValuePtr cmd;
6066 virJSONValuePtr reply = NULL;
6067 virJSONValuePtr data;
6070 if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
6072 "s:property", property,
6076 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6079 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6082 data = virJSONValueObjectGet(reply, "return");
6084 switch ((qemuMonitorJSONObjectPropertyType) prop->type) {
6085 /* Simple cases of boolean, int, long, uint, ulong, double, and string
6086 * will receive return value as part of {"return": xxx} statement
6088 case QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN:
6089 ret = virJSONValueGetBoolean(data, &prop->val.b);
6091 case QEMU_MONITOR_OBJECT_PROPERTY_INT:
6092 ret = virJSONValueGetNumberInt(data, &prop->val.iv);
6094 case QEMU_MONITOR_OBJECT_PROPERTY_LONG:
6095 ret = virJSONValueGetNumberLong(data, &prop->val.l);
6097 case QEMU_MONITOR_OBJECT_PROPERTY_UINT:
6098 ret = virJSONValueGetNumberUint(data, &prop->val.ui);
6100 case QEMU_MONITOR_OBJECT_PROPERTY_ULONG:
6101 ret = virJSONValueGetNumberUlong(data, &prop->val.ul);
6103 case QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE:
6104 ret = virJSONValueGetNumberDouble(data, &prop->val.d);
6106 case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
6107 tmp = virJSONValueGetString(data);
6108 if (tmp && VIR_STRDUP(prop->val.str, tmp) < 0)
6113 case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
6114 virReportError(VIR_ERR_INTERNAL_ERROR,
6115 _("qom-get invalid object property type %d"),
6122 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6123 _("qom-get reply was missing return data"));
6129 virJSONValueFree(cmd);
6130 virJSONValueFree(reply);
6136 #define MAKE_SET_CMD(STRING, VALUE) \
6137 cmd = qemuMonitorJSONMakeCommand("qom-set", \
6139 "s:property", property, \
6142 int qemuMonitorJSONSetObjectProperty(qemuMonitorPtr mon,
6144 const char *property,
6145 qemuMonitorJSONObjectPropertyPtr prop)
6148 virJSONValuePtr cmd = NULL;
6149 virJSONValuePtr reply = NULL;
6151 switch ((qemuMonitorJSONObjectPropertyType) prop->type) {
6152 /* Simple cases of boolean, int, long, uint, ulong, double, and string
6153 * will receive return value as part of {"return": xxx} statement
6155 case QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN:
6156 MAKE_SET_CMD("b:value", prop->val.b);
6158 case QEMU_MONITOR_OBJECT_PROPERTY_INT:
6159 MAKE_SET_CMD("i:value", prop->val.iv);
6161 case QEMU_MONITOR_OBJECT_PROPERTY_LONG:
6162 MAKE_SET_CMD("I:value", prop->val.l);
6164 case QEMU_MONITOR_OBJECT_PROPERTY_UINT:
6165 MAKE_SET_CMD("u:value", prop->val.ui);
6167 case QEMU_MONITOR_OBJECT_PROPERTY_ULONG:
6168 MAKE_SET_CMD("U:value", prop->val.ul);
6170 case QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE:
6171 MAKE_SET_CMD("d:value", prop->val.d);
6173 case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
6174 MAKE_SET_CMD("s:value", prop->val.str);
6176 case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
6177 virReportError(VIR_ERR_INTERNAL_ERROR,
6178 _("qom-set invalid object property type %d"),
6186 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6189 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6194 virJSONValueFree(cmd);
6195 virJSONValueFree(reply);
6203 qemuMonitorJSONParsePropsList(virJSONValuePtr cmd,
6204 virJSONValuePtr reply,
6207 virJSONValuePtr data;
6208 char **proplist = NULL;
6213 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6216 data = virJSONValueObjectGetArray(reply, "return");
6217 n = virJSONValueArraySize(data);
6219 /* null-terminated list */
6220 if (VIR_ALLOC_N(proplist, n + 1) < 0)
6223 for (i = 0; i < n; i++) {
6224 virJSONValuePtr child = virJSONValueArrayGet(data, i);
6227 if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
6228 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6229 _("reply data was missing 'name'"));
6233 if (VIR_STRDUP(proplist[i], tmp) < 0)
6242 virStringListFree(proplist);
6247 int qemuMonitorJSONGetDeviceProps(qemuMonitorPtr mon,
6252 virJSONValuePtr cmd;
6253 virJSONValuePtr reply = NULL;
6257 if (!(cmd = qemuMonitorJSONMakeCommand("device-list-properties",
6258 "s:typename", device,
6262 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6265 if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
6270 ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
6272 virJSONValueFree(reply);
6273 virJSONValueFree(cmd);
6279 qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
6284 virJSONValuePtr cmd;
6285 virJSONValuePtr reply = NULL;
6289 if (!(cmd = qemuMonitorJSONMakeCommand("qom-list-properties",
6290 "s:typename", object,
6294 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6297 if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
6302 ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
6304 virJSONValueFree(reply);
6305 virJSONValueFree(cmd);
6311 qemuMonitorJSONGetTargetArch(qemuMonitorPtr mon)
6315 virJSONValuePtr cmd;
6316 virJSONValuePtr reply = NULL;
6317 virJSONValuePtr data;
6319 if (!(cmd = qemuMonitorJSONMakeCommand("query-target", NULL)))
6322 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6325 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
6328 data = virJSONValueObjectGetObject(reply, "return");
6330 if (!(arch = virJSONValueObjectGetString(data, "arch"))) {
6331 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6332 _("query-target reply was missing arch data"));
6336 ignore_value(VIR_STRDUP(ret, arch));
6339 virJSONValueFree(cmd);
6340 virJSONValueFree(reply);
6346 qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon,
6347 char ***capabilities)
6350 virJSONValuePtr cmd;
6351 virJSONValuePtr reply = NULL;
6352 virJSONValuePtr caps;
6357 *capabilities = NULL;
6359 if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate-capabilities",
6363 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6366 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6371 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6374 caps = virJSONValueObjectGetArray(reply, "return");
6375 n = virJSONValueArraySize(caps);
6377 if (VIR_ALLOC_N(list, n + 1) < 0)
6380 for (i = 0; i < n; i++) {
6381 virJSONValuePtr cap = virJSONValueArrayGet(caps, i);
6384 if (!cap || virJSONValueGetType(cap) != VIR_JSON_TYPE_OBJECT) {
6385 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6386 _("missing entry in migration capabilities list"));
6390 if (!(name = virJSONValueObjectGetString(cap, "capability"))) {
6391 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6392 _("missing migration capability name"));
6396 if (VIR_STRDUP(list[i], name) < 1)
6401 *capabilities = list;
6405 virStringListFree(list);
6406 virJSONValueFree(cmd);
6407 virJSONValueFree(reply);
6413 qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon,
6414 virJSONValuePtr caps)
6417 virJSONValuePtr cmd = NULL;
6418 virJSONValuePtr reply = NULL;
6420 cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities",
6421 "a:capabilities", &caps,
6426 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6429 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6434 virJSONValueFree(caps);
6435 virJSONValueFree(cmd);
6436 virJSONValueFree(reply);
6442 * qemuMonitorJSONGetGICCapabilities:
6443 * @mon: QEMU JSON monitor
6444 * @capabilities: where to store the GIC capabilities
6446 * Use @mon to obtain information about the GIC capabilities for the
6447 * corresponding QEMU binary, and store them in @capabilities.
6449 * If the QEMU binary has no GIC capabilities, or if GIC capabilities could
6450 * not be determined due to the lack of 'query-gic-capabilities' QMP command,
6451 * a NULL pointer will be returned instead of an empty array.
6453 * Returns: the number of GIC capabilities obtained from the monitor,
6457 qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
6458 virGICCapability **capabilities)
6461 virJSONValuePtr cmd;
6462 virJSONValuePtr reply = NULL;
6463 virJSONValuePtr caps;
6464 virGICCapability *list = NULL;
6468 *capabilities = NULL;
6470 if (!(cmd = qemuMonitorJSONMakeCommand("query-gic-capabilities",
6474 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6477 /* If the 'query-gic-capabilities' QMP command was not available
6478 * we simply successfully return zero capabilities.
6479 * This is the case for QEMU <2.6 and all non-ARM architectures */
6480 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6485 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6488 caps = virJSONValueObjectGetArray(reply, "return");
6489 n = virJSONValueArraySize(caps);
6491 /* If the returned array was empty we have to return successfully */
6497 if (VIR_ALLOC_N(list, n) < 0)
6500 for (i = 0; i < n; i++) {
6501 virJSONValuePtr cap = virJSONValueArrayGet(caps, i);
6506 if (!cap || virJSONValueGetType(cap) != VIR_JSON_TYPE_OBJECT) {
6507 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6508 _("missing entry in GIC capabilities list"));
6512 if (virJSONValueObjectGetNumberInt(cap, "version", &version) < 0) {
6513 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6514 _("missing GIC version"));
6518 if (virJSONValueObjectGetBoolean(cap, "kernel", &kernel) < 0) {
6519 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6520 _("missing in-kernel GIC information"));
6524 if (virJSONValueObjectGetBoolean(cap, "emulated", &emulated) < 0) {
6525 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6526 _("missing emulated GIC information"));
6530 list[i].version = version;
6532 list[i].implementation |= VIR_GIC_IMPLEMENTATION_KERNEL;
6534 list[i].implementation |= VIR_GIC_IMPLEMENTATION_EMULATED;
6538 *capabilities = list;
6543 virJSONValueFree(cmd);
6544 virJSONValueFree(reply);
6551 * qemuMonitorJSONGetSEVCapabilities:
6552 * @mon: qemu monitor object
6553 * @capabilities: pointer to pointer to a SEV capability structure to be filled
6555 * This function queries and fills in AMD's SEV platform-specific data.
6556 * Note that from QEMU's POV both -object sev-guest and query-sev-capabilities
6557 * can be present even if SEV is not available, which basically leaves us with
6558 * checking for JSON "GenericError" in order to differentiate between
6559 * compiled-in support and actual SEV support on the platform.
6561 * Returns -1 on error, 0 if SEV is not supported, and 1 if SEV is supported on
6565 qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
6566 virSEVCapability **capabilities)
6569 virJSONValuePtr cmd;
6570 virJSONValuePtr reply = NULL;
6571 virJSONValuePtr caps;
6572 const char *pdh = NULL;
6573 const char *cert_chain = NULL;
6574 unsigned int cbitpos;
6575 unsigned int reduced_phys_bits;
6576 VIR_AUTOPTR(virSEVCapability) capability = NULL;
6578 *capabilities = NULL;
6580 if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-capabilities",
6584 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6587 /* QEMU has only compiled-in support of SEV */
6588 if (qemuMonitorJSONHasError(reply, "GenericError")) {
6593 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6596 caps = virJSONValueObjectGetObject(reply, "return");
6598 if (virJSONValueObjectGetNumberUint(caps, "cbitpos", &cbitpos) < 0) {
6599 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6600 _("query-sev-capabilities reply was missing"
6601 " 'cbitpos' field"));
6605 if (virJSONValueObjectGetNumberUint(caps, "reduced-phys-bits",
6606 &reduced_phys_bits) < 0) {
6607 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6608 _("query-sev-capabilities reply was missing"
6609 " 'reduced-phys-bits' field"));
6613 if (!(pdh = virJSONValueObjectGetString(caps, "pdh"))) {
6614 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6615 _("query-sev-capabilities reply was missing"
6620 if (!(cert_chain = virJSONValueObjectGetString(caps, "cert-chain"))) {
6621 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6622 _("query-sev-capabilities reply was missing"
6623 " 'cert-chain' field"));
6627 if (VIR_ALLOC(capability) < 0)
6630 if (VIR_STRDUP(capability->pdh, pdh) < 0)
6633 if (VIR_STRDUP(capability->cert_chain, cert_chain) < 0)
6636 capability->cbitpos = cbitpos;
6637 capability->reduced_phys_bits = reduced_phys_bits;
6638 VIR_STEAL_PTR(*capabilities, capability);
6641 virJSONValueFree(cmd);
6642 virJSONValueFree(reply);
6647 static virJSONValuePtr
6648 qemuMonitorJSONBuildInetSocketAddress(const char *host,
6651 virJSONValuePtr addr = NULL;
6652 virJSONValuePtr data = NULL;
6654 if (virJSONValueObjectCreate(&data, "s:host", host,
6655 "s:port", port, NULL) < 0)
6658 if (virJSONValueObjectCreate(&addr, "s:type", "inet",
6659 "a:data", &data, NULL) < 0) {
6660 virJSONValueFree(data);
6667 static virJSONValuePtr
6668 qemuMonitorJSONBuildUnixSocketAddress(const char *path)
6670 virJSONValuePtr addr = NULL;
6671 virJSONValuePtr data = NULL;
6673 if (virJSONValueObjectCreate(&data, "s:path", path, NULL) < 0)
6676 if (virJSONValueObjectCreate(&addr, "s:type", "unix",
6677 "a:data", &data, NULL) < 0) {
6678 virJSONValueFree(data);
6686 qemuMonitorJSONNBDServerStart(qemuMonitorPtr mon,
6689 const char *tls_alias)
6692 virJSONValuePtr cmd = NULL;
6693 virJSONValuePtr reply = NULL;
6694 virJSONValuePtr addr = NULL;
6695 char *port_str = NULL;
6697 if (virAsprintf(&port_str, "%u", port) < 0)
6700 if (!(addr = qemuMonitorJSONBuildInetSocketAddress(host, port_str)))
6703 if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-start",
6705 "S:tls-creds", tls_alias,
6709 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6712 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6719 virJSONValueFree(reply);
6720 virJSONValueFree(cmd);
6721 virJSONValueFree(addr);
6726 qemuMonitorJSONNBDServerAdd(qemuMonitorPtr mon,
6727 const char *deviceID,
6731 virJSONValuePtr cmd;
6732 virJSONValuePtr reply = NULL;
6734 if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-add",
6735 "s:device", deviceID,
6736 "b:writable", writable,
6740 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6743 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6748 virJSONValueFree(cmd);
6749 virJSONValueFree(reply);
6754 qemuMonitorJSONNBDServerStop(qemuMonitorPtr mon)
6757 virJSONValuePtr cmd;
6758 virJSONValuePtr reply = NULL;
6760 if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-stop",
6764 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6767 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6772 virJSONValueFree(cmd);
6773 virJSONValueFree(reply);
6779 qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd,
6783 virJSONValuePtr cmd;
6784 virJSONValuePtr reply = NULL;
6785 virJSONValuePtr data;
6792 if (!(cmd = qemuMonitorJSONMakeCommand(qmpCmd, NULL)))
6795 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6798 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6803 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6806 data = virJSONValueObjectGetArray(reply, "return");
6807 n = virJSONValueArraySize(data);
6809 /* null-terminated list */
6810 if (VIR_ALLOC_N(list, n + 1) < 0)
6813 for (i = 0; i < n; i++) {
6814 virJSONValuePtr child = virJSONValueArrayGet(data, i);
6817 if (!(tmp = virJSONValueGetString(child))) {
6818 virReportError(VIR_ERR_INTERNAL_ERROR,
6819 _("%s array element does not contain data"),
6824 if (VIR_STRDUP(list[i], tmp) < 0)
6833 virStringListFree(list);
6834 virJSONValueFree(cmd);
6835 virJSONValueFree(reply);
6839 int qemuMonitorJSONGetTPMModels(qemuMonitorPtr mon,
6842 return qemuMonitorJSONGetStringArray(mon, "query-tpm-models", tpmmodels);
6846 int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
6849 return qemuMonitorJSONGetStringArray(mon, "query-tpm-types", tpmtypes);
6853 qemuMonitorJSONBuildChrChardevReconnect(virJSONValuePtr object,
6854 const virDomainChrSourceReconnectDef *def)
6856 if (def->enabled != VIR_TRISTATE_BOOL_YES)
6859 return virJSONValueObjectAppendNumberUint(object, "reconnect", def->timeout);
6862 static virJSONValuePtr
6863 qemuMonitorJSONAttachCharDevCommand(const char *chrID,
6864 const virDomainChrSourceDef *chr)
6866 virJSONValuePtr ret = NULL;
6867 virJSONValuePtr backend = NULL;
6868 virJSONValuePtr data = NULL;
6869 virJSONValuePtr addr = NULL;
6870 const char *backend_type = NULL;
6873 char *tlsalias = NULL;
6876 if (!(backend = virJSONValueNewObject()) ||
6877 !(data = virJSONValueNewObject())) {
6881 switch ((virDomainChrType)chr->type) {
6882 case VIR_DOMAIN_CHR_TYPE_NULL:
6883 case VIR_DOMAIN_CHR_TYPE_VC:
6884 backend_type = "null";
6887 case VIR_DOMAIN_CHR_TYPE_PTY:
6888 backend_type = "pty";
6891 case VIR_DOMAIN_CHR_TYPE_FILE:
6892 backend_type = "file";
6893 if (virJSONValueObjectAppendString(data, "out", chr->data.file.path) < 0)
6897 case VIR_DOMAIN_CHR_TYPE_DEV:
6898 backend_type = STRPREFIX(chrID, "parallel") ? "parallel" : "serial";
6899 if (virJSONValueObjectAppendString(data, "device",
6900 chr->data.file.path) < 0)
6904 case VIR_DOMAIN_CHR_TYPE_TCP:
6905 backend_type = "socket";
6906 addr = qemuMonitorJSONBuildInetSocketAddress(chr->data.tcp.host,
6907 chr->data.tcp.service);
6909 virJSONValueObjectAppend(data, "addr", addr) < 0)
6913 telnet = chr->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
6915 if (chr->data.tcp.listen &&
6916 virJSONValueObjectAppendBoolean(data, "wait", false) < 0)
6919 if (virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 ||
6920 virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0)
6922 if (chr->data.tcp.tlscreds) {
6923 if (!(tlsalias = qemuAliasTLSObjFromSrcAlias(chrID)))
6926 if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0)
6930 if (qemuMonitorJSONBuildChrChardevReconnect(data, &chr->data.tcp.reconnect) < 0)
6934 case VIR_DOMAIN_CHR_TYPE_UDP:
6935 backend_type = "udp";
6936 host = chr->data.udp.connectHost;
6939 addr = qemuMonitorJSONBuildInetSocketAddress(host,
6940 chr->data.udp.connectService);
6942 virJSONValueObjectAppend(data, "remote", addr) < 0)
6945 host = chr->data.udp.bindHost;
6946 port = chr->data.udp.bindService;
6952 addr = qemuMonitorJSONBuildInetSocketAddress(host, port);
6954 virJSONValueObjectAppend(data, "local", addr) < 0)
6960 case VIR_DOMAIN_CHR_TYPE_UNIX:
6961 backend_type = "socket";
6962 addr = qemuMonitorJSONBuildUnixSocketAddress(chr->data.nix.path);
6965 virJSONValueObjectAppend(data, "addr", addr) < 0)
6969 if (chr->data.nix.listen &&
6970 virJSONValueObjectAppendBoolean(data, "wait", false) < 0)
6973 if (virJSONValueObjectAppendBoolean(data, "server", chr->data.nix.listen) < 0)
6976 if (qemuMonitorJSONBuildChrChardevReconnect(data, &chr->data.nix.reconnect) < 0)
6980 case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
6981 backend_type = "spicevmc";
6983 if (virJSONValueObjectAppendString(data, "type",
6984 virDomainChrSpicevmcTypeToString(chr->data.spicevmc)) < 0)
6988 case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
6989 case VIR_DOMAIN_CHR_TYPE_PIPE:
6990 case VIR_DOMAIN_CHR_TYPE_STDIO:
6991 case VIR_DOMAIN_CHR_TYPE_NMDM:
6992 case VIR_DOMAIN_CHR_TYPE_LAST:
6993 if (virDomainChrTypeToString(chr->type)) {
6994 virReportError(VIR_ERR_OPERATION_FAILED,
6995 _("Hotplug unsupported for char device type '%s'"),
6996 virDomainChrTypeToString(chr->type));
6998 virReportError(VIR_ERR_OPERATION_FAILED,
6999 _("Hotplug unsupported for char device type '%d'"),
7005 if (virJSONValueObjectAppendString(backend, "type", backend_type) < 0 ||
7006 virJSONValueObjectAppend(backend, "data", data) < 0)
7010 if (!(ret = qemuMonitorJSONMakeCommand("chardev-add",
7012 "a:backend", &backend,
7018 virJSONValueFree(addr);
7019 virJSONValueFree(data);
7020 virJSONValueFree(backend);
7026 qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
7028 virDomainChrSourceDefPtr chr)
7031 virJSONValuePtr cmd;
7032 virJSONValuePtr reply = NULL;
7034 if (!(cmd = qemuMonitorJSONAttachCharDevCommand(chrID, chr)))
7037 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7040 if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
7041 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
7044 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7048 if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
7049 virJSONValuePtr data = virJSONValueObjectGetObject(reply, "return");
7052 if (!(path = virJSONValueObjectGetString(data, "pty"))) {
7053 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7054 _("chardev-add reply was missing pty path"));
7058 if (VIR_STRDUP(chr->data.file.path, path) < 0)
7065 virJSONValueFree(cmd);
7066 virJSONValueFree(reply);
7071 qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon,
7075 virJSONValuePtr cmd;
7076 virJSONValuePtr reply = NULL;
7078 if (!(cmd = qemuMonitorJSONMakeCommand("chardev-remove",
7083 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7086 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7091 virJSONValueFree(cmd);
7092 virJSONValueFree(reply);
7098 qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon,
7101 qemuMonitorJSONListPathPtr *paths = NULL;
7109 n = qemuMonitorJSONGetObjectListPaths(mon, "/machine/peripheral", &paths);
7113 if (VIR_ALLOC_N(*aliases, n + 1) < 0)
7117 for (i = 0; i < n; i++) {
7118 if (STRPREFIX(paths[i]->type, "child<")) {
7119 *alias = paths[i]->name;
7120 paths[i]->name = NULL;
7128 for (i = 0; i < n; i++)
7129 qemuMonitorJSONListPathFree(paths[i]);
7136 qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
7137 virCPUx86CPUID *cpuid)
7140 unsigned long long eax_in;
7141 unsigned long long ecx_in = 0;
7142 unsigned long long features;
7144 memset(cpuid, 0, sizeof(*cpuid));
7146 if (!(reg = virJSONValueObjectGetString(data, "cpuid-register"))) {
7147 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7148 _("missing cpuid-register in CPU data"));
7151 if (virJSONValueObjectGetNumberUlong(data, "cpuid-input-eax", &eax_in) < 0) {
7152 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7153 _("missing or invalid cpuid-input-eax in CPU data"));
7156 ignore_value(virJSONValueObjectGetNumberUlong(data, "cpuid-input-ecx",
7158 if (virJSONValueObjectGetNumberUlong(data, "features", &features) < 0) {
7159 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7160 _("missing or invalid features in CPU data"));
7164 cpuid->eax_in = eax_in;
7165 cpuid->ecx_in = ecx_in;
7166 if (STREQ(reg, "EAX")) {
7167 cpuid->eax = features;
7168 } else if (STREQ(reg, "EBX")) {
7169 cpuid->ebx = features;
7170 } else if (STREQ(reg, "ECX")) {
7171 cpuid->ecx = features;
7172 } else if (STREQ(reg, "EDX")) {
7173 cpuid->edx = features;
7175 virReportError(VIR_ERR_INTERNAL_ERROR,
7176 _("unknown CPU register '%s'"), reg);
7184 static virCPUDataPtr
7185 qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
7187 virCPUDataPtr cpudata = NULL;
7188 virCPUx86DataItem item = { 0 };
7191 if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64)))
7194 item.type = VIR_CPU_X86_DATA_CPUID;
7195 for (i = 0; i < virJSONValueArraySize(data); i++) {
7196 if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
7197 &item.data.cpuid) < 0 ||
7198 virCPUx86DataAdd(cpudata, &item) < 0)
7205 virCPUDataFree(cpudata);
7211 qemuMonitorJSONGetCPUx86Data(qemuMonitorPtr mon,
7212 const char *property,
7213 virCPUDataPtr *cpudata)
7215 virJSONValuePtr cmd = NULL;
7216 virJSONValuePtr reply = NULL;
7217 virJSONValuePtr data;
7220 if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
7221 "s:path", QOM_CPU_PATH,
7222 "s:property", property,
7226 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7229 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7232 data = virJSONValueObjectGetArray(reply, "return");
7233 if (!(*cpudata = qemuMonitorJSONParseCPUx86Features(data)))
7239 virJSONValueFree(cmd);
7240 virJSONValueFree(reply);
7246 * Returns -1 on error, 0 if QEMU does not support reporting CPUID features
7247 * of a guest CPU, and 1 if the feature is supported.
7250 qemuMonitorJSONCheckCPUx86(qemuMonitorPtr mon)
7252 virJSONValuePtr cmd = NULL;
7253 virJSONValuePtr reply = NULL;
7254 virJSONValuePtr data;
7259 if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
7260 "s:path", QOM_CPU_PATH,
7264 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7267 if ((data = virJSONValueObjectGet(reply, "error"))) {
7268 const char *klass = virJSONValueObjectGetString(data, "class");
7269 if (STREQ_NULLABLE(klass, "DeviceNotFound") ||
7270 STREQ_NULLABLE(klass, "CommandNotFound")) {
7276 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7279 data = virJSONValueObjectGetArray(reply, "return");
7280 n = virJSONValueArraySize(data);
7282 for (i = 0; i < n; i++) {
7283 virJSONValuePtr element = virJSONValueArrayGet(data, i);
7284 if (STREQ_NULLABLE(virJSONValueObjectGetString(element, "name"),
7295 virJSONValueFree(cmd);
7296 virJSONValueFree(reply);
7302 * qemuMonitorJSONGetGuestCPU:
7303 * @mon: Pointer to the monitor
7304 * @arch: arch of the guest
7305 * @data: returns the cpu data of the guest
7306 * @disabled: returns the CPU data for features which were disabled by QEMU
7308 * Retrieve the definition of the guest CPU from a running qemu instance.
7310 * Returns 0 on success, -2 if guest doesn't support this feature,
7311 * -1 on other errors.
7314 qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
7316 virCPUDataPtr *data,
7317 virCPUDataPtr *disabled)
7319 virCPUDataPtr cpuEnabled = NULL;
7320 virCPUDataPtr cpuDisabled = NULL;
7323 if (ARCH_IS_X86(arch)) {
7324 if ((rc = qemuMonitorJSONCheckCPUx86(mon)) < 0)
7329 if (qemuMonitorJSONGetCPUx86Data(mon, "feature-words",
7334 qemuMonitorJSONGetCPUx86Data(mon, "filtered-features",
7340 *disabled = cpuDisabled;
7344 virReportError(VIR_ERR_INTERNAL_ERROR,
7345 _("CPU definition retrieval isn't supported for '%s'"),
7346 virArchToString(arch));
7350 virCPUDataFree(cpuEnabled);
7351 virCPUDataFree(cpuDisabled);
7356 qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
7359 virJSONValuePtr cmd;
7360 virJSONValuePtr reply = NULL;
7362 if (!(cmd = qemuMonitorJSONMakeCommand("rtc-reset-reinjection",
7366 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7369 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7374 virJSONValueFree(cmd);
7375 virJSONValueFree(reply);
7380 * Query and parse returned array of data such as:
7382 * {u'return': [{u'id': u'iothread1', u'thread-id': 30992}, \
7383 * {u'id': u'iothread2', u'thread-id': 30993}]}
7386 qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
7387 qemuMonitorIOThreadInfoPtr **iothreads)
7390 virJSONValuePtr cmd;
7391 virJSONValuePtr reply = NULL;
7392 virJSONValuePtr data;
7393 qemuMonitorIOThreadInfoPtr *infolist = NULL;
7399 if (!(cmd = qemuMonitorJSONMakeCommand("query-iothreads", NULL)))
7402 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7405 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7408 data = virJSONValueObjectGetArray(reply, "return");
7409 n = virJSONValueArraySize(data);
7411 /* null-terminated list */
7412 if (VIR_ALLOC_N(infolist, n + 1) < 0)
7415 for (i = 0; i < n; i++) {
7416 virJSONValuePtr child = virJSONValueArrayGet(data, i);
7418 qemuMonitorIOThreadInfoPtr info;
7420 if (!(tmp = virJSONValueObjectGetString(child, "id"))) {
7421 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7422 _("query-iothreads reply data was missing 'id'"));
7426 if (!STRPREFIX(tmp, "iothread"))
7429 if (VIR_ALLOC(info) < 0)
7434 if (virStrToLong_ui(tmp + strlen("iothread"),
7435 NULL, 10, &info->iothread_id) < 0) {
7436 virReportError(VIR_ERR_INTERNAL_ERROR,
7437 _("failed to find iothread id for '%s'"),
7442 if (virJSONValueObjectGetNumberInt(child, "thread-id",
7443 &info->thread_id) < 0) {
7444 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7445 _("query-iothreads reply has malformed "
7446 "'thread-id' data"));
7450 /* Fetch poll values (since QEMU 2.9 ) if available. QEMU
7451 * stores these values as int64_t's; however, the qapi type
7452 * is an int. The qapi/misc.json also mis-describes the grow
7453 * and shrink values as pure add/remove values. The source
7454 * util/aio-posix.c function aio_poll uses them as a factor
7455 * or divisor in it's calculation. We will fetch and store
7456 * them as defined in our structures. */
7457 if (virJSONValueObjectGetNumberUlong(child, "poll-max-ns",
7458 &info->poll_max_ns) == 0 &&
7459 virJSONValueObjectGetNumberUint(child, "poll-grow",
7460 &info->poll_grow) == 0 &&
7461 virJSONValueObjectGetNumberUint(child, "poll-shrink",
7462 &info->poll_shrink) == 0)
7463 info->poll_valid = true;
7467 *iothreads = infolist;
7472 for (i = 0; i < n; i++)
7473 VIR_FREE(infolist[i]);
7476 virJSONValueFree(cmd);
7477 virJSONValueFree(reply);
7483 qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
7484 qemuMonitorIOThreadInfoPtr iothreadInfo)
7488 qemuMonitorJSONObjectProperty prop;
7490 if (virAsprintf(&path, "/objects/iothread%u",
7491 iothreadInfo->iothread_id) < 0)
7494 #define VIR_IOTHREAD_SET_PROP(propName, propVal) \
7495 if (iothreadInfo->set_##propVal) { \
7496 memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty)); \
7497 prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT; \
7498 prop.val.iv = iothreadInfo->propVal; \
7499 if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \
7503 VIR_IOTHREAD_SET_PROP("poll-max-ns", poll_max_ns);
7504 VIR_IOTHREAD_SET_PROP("poll-grow", poll_grow);
7505 VIR_IOTHREAD_SET_PROP("poll-shrink", poll_shrink);
7507 #undef VIR_IOTHREAD_SET_PROP
7518 qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
7519 virHashTablePtr info)
7522 virJSONValuePtr cmd;
7523 virJSONValuePtr reply = NULL;
7524 virJSONValuePtr data = NULL;
7525 qemuMonitorMemoryDeviceInfoPtr meminfo = NULL;
7528 if (!(cmd = qemuMonitorJSONMakeCommand("query-memory-devices", NULL)))
7531 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7534 if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
7539 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7542 data = virJSONValueObjectGetArray(reply, "return");
7544 for (i = 0; i < virJSONValueArraySize(data); i++) {
7545 virJSONValuePtr elem = virJSONValueArrayGet(data, i);
7548 if (!(type = virJSONValueObjectGetString(elem, "type"))) {
7549 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7550 _("query-memory-devices reply data doesn't contain "
7551 "enum type discriminator"));
7555 /* dimm memory devices */
7556 if (STREQ(type, "dimm")) {
7557 virJSONValuePtr dimminfo;
7558 const char *devalias;
7560 if (!(dimminfo = virJSONValueObjectGetObject(elem, "data"))) {
7561 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7562 _("query-memory-devices reply data doesn't "
7563 "contain enum data"));
7567 if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) {
7568 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7569 _("dimm memory info data is missing 'id'"));
7573 if (VIR_ALLOC(meminfo) < 0)
7576 if (virJSONValueObjectGetNumberUlong(dimminfo, "addr",
7577 &meminfo->address) < 0) {
7578 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7579 _("malformed/missing addr in dimm memory info"));
7583 if (virJSONValueObjectGetNumberUint(dimminfo, "slot",
7584 &meminfo->slot) < 0) {
7585 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7586 _("malformed/missing slot in dimm memory info"));
7590 if (virJSONValueObjectGetBoolean(dimminfo, "hotplugged",
7591 &meminfo->hotplugged) < 0) {
7592 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7593 _("malformed/missing hotplugged in dimm memory info"));
7598 if (virJSONValueObjectGetBoolean(dimminfo, "hotpluggable",
7599 &meminfo->hotpluggable) < 0) {
7600 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7601 _("malformed/missing hotpluggable in dimm memory info"));
7606 if (virHashAddEntry(info, devalias, meminfo) < 0)
7617 virJSONValueFree(cmd);
7618 virJSONValueFree(reply);
7624 * Search for a QOM object link by alias and name.
7626 * For @alias and @name, this function tries to find QOM object named @name
7627 * with id @alias in /machine/peripheral.
7631 * -1 - Error - bail out
7635 qemuMonitorJSONFindObjectPathByAlias(qemuMonitorPtr mon,
7640 qemuMonitorJSONListPathPtr *paths = NULL;
7646 npaths = qemuMonitorJSONGetObjectListPaths(mon, "/machine/peripheral", &paths);
7650 if (virAsprintf(&child, "child<%s>", name) < 0)
7653 for (i = 0; i < npaths; i++) {
7654 if (STREQ(paths[i]->name, alias) && STREQ(paths[i]->type, child)) {
7655 if (virAsprintf(path, "/machine/peripheral/%s", alias) < 0)
7666 for (i = 0; i < npaths; i++)
7667 qemuMonitorJSONListPathFree(paths[i]);
7675 * Recursively search for a QOM object link only by name.
7677 * For @name, this function finds the first QOM object
7678 * named @name, recursively going through all the "child<>"
7679 * entries, starting from @curpath.
7683 * -1 - Error - bail out
7687 qemuMonitorJSONFindObjectPathByName(qemuMonitorPtr mon,
7688 const char *curpath,
7692 ssize_t i, npaths = 0;
7694 char *nextpath = NULL;
7695 qemuMonitorJSONListPathPtr *paths = NULL;
7697 VIR_DEBUG("Searching for '%s' Object Path starting at '%s'", name, curpath);
7699 npaths = qemuMonitorJSONGetObjectListPaths(mon, curpath, &paths);
7703 for (i = 0; i < npaths && ret == -2; i++) {
7705 if (STREQ_NULLABLE(paths[i]->type, name)) {
7706 VIR_DEBUG("Path to '%s' is '%s/%s'", name, curpath, paths[i]->name);
7708 if (virAsprintf(path, "%s/%s", curpath, paths[i]->name) < 0) {
7715 /* Type entries that begin with "child<" are a branch that can be
7716 * traversed looking for more entries
7718 if (paths[i]->type && STRPREFIX(paths[i]->type, "child<")) {
7719 if (virAsprintf(&nextpath, "%s/%s", curpath, paths[i]->name) < 0) {
7724 ret = qemuMonitorJSONFindObjectPathByName(mon, nextpath, name, path);
7730 for (i = 0; i < npaths; i++)
7731 qemuMonitorJSONListPathFree(paths[i]);
7739 * Recursively search for a QOM object link.
7741 * For @name and @alias, this function finds the first QOM object.
7742 * The search is done at first by @alias and @name and if nothing was found
7743 * it continues recursively only with @name.
7751 qemuMonitorJSONFindLinkPath(qemuMonitorPtr mon,
7756 char *linkname = NULL;
7760 ret = qemuMonitorJSONFindObjectPathByAlias(mon, name, alias, path);
7761 if (ret == -1 || ret == 0)
7765 if (virAsprintf(&linkname, "link<%s>", name) < 0)
7768 ret = qemuMonitorJSONFindObjectPathByName(mon, "/", linkname, path);
7775 qemuMonitorJSONMigrateIncoming(qemuMonitorPtr mon,
7779 virJSONValuePtr cmd;
7780 virJSONValuePtr reply = NULL;
7782 if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming",
7787 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7790 ret = qemuMonitorJSONCheckError(cmd, reply);
7793 virJSONValueFree(cmd);
7794 virJSONValueFree(reply);
7800 qemuMonitorJSONMigrateStartPostCopy(qemuMonitorPtr mon)
7803 virJSONValuePtr cmd;
7804 virJSONValuePtr reply = NULL;
7806 if (!(cmd = qemuMonitorJSONMakeCommand("migrate-start-postcopy", NULL)))
7809 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7812 ret = qemuMonitorJSONCheckError(cmd, reply);
7815 virJSONValueFree(cmd);
7816 virJSONValueFree(reply);
7822 qemuMonitorJSONMigrateContinue(qemuMonitorPtr mon,
7823 qemuMonitorMigrationStatus status)
7825 const char *statusStr = qemuMonitorMigrationStatusTypeToString(status);
7827 virJSONValuePtr cmd;
7828 virJSONValuePtr reply = NULL;
7830 if (!(cmd = qemuMonitorJSONMakeCommand("migrate-continue",
7831 "s:state", statusStr,
7835 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7838 ret = qemuMonitorJSONCheckError(cmd, reply);
7841 virJSONValueFree(cmd);
7842 virJSONValueFree(reply);
7848 qemuMonitorJSONGetRTCTime(qemuMonitorPtr mon,
7852 virJSONValuePtr cmd;
7853 virJSONValuePtr reply = NULL;
7854 virJSONValuePtr data;
7856 if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
7857 "s:path", "/machine",
7858 "s:property", "rtc-time",
7862 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7865 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
7868 data = virJSONValueObjectGet(reply, "return");
7870 if (virJSONValueObjectGetNumberInt(data, "tm_year", &tm->tm_year) < 0 ||
7871 virJSONValueObjectGetNumberInt(data, "tm_mon", &tm->tm_mon) < 0 ||
7872 virJSONValueObjectGetNumberInt(data, "tm_mday", &tm->tm_mday) < 0 ||
7873 virJSONValueObjectGetNumberInt(data, "tm_hour", &tm->tm_hour) < 0 ||
7874 virJSONValueObjectGetNumberInt(data, "tm_min", &tm->tm_min) < 0 ||
7875 virJSONValueObjectGetNumberInt(data, "tm_sec", &tm->tm_sec) < 0) {
7876 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7877 _("qemu returned malformed time"));
7883 virJSONValueFree(cmd);
7884 virJSONValueFree(reply);
7890 qemuMonitorQueryHotpluggableCpusFree(struct qemuMonitorQueryHotpluggableCpusEntry *entries,
7893 struct qemuMonitorQueryHotpluggableCpusEntry *entry;
7899 for (i = 0; i < nentries; i++) {
7900 entry = entries + i;
7902 VIR_FREE(entry->type);
7903 VIR_FREE(entry->qom_path);
7904 VIR_FREE(entry->alias);
7919 * "qom-path": "/machine/unattached/device[0]",
7920 * "type": "qemu64-x86_64-cpu"
7926 qemuMonitorJSONProcessHotpluggableCpusReply(virJSONValuePtr vcpu,
7927 struct qemuMonitorQueryHotpluggableCpusEntry *entry)
7929 virJSONValuePtr props;
7932 if (!(tmp = virJSONValueObjectGetString(vcpu, "type"))) {
7933 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7934 _("query-hotpluggable-cpus didn't return device type"));
7938 if (VIR_STRDUP(entry->type, tmp) < 0)
7941 if (virJSONValueObjectGetNumberUint(vcpu, "vcpus-count", &entry->vcpus) < 0) {
7942 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7943 _("query-hotpluggable-cpus didn't return vcpus-count"));
7947 if (!(props = virJSONValueObjectGetObject(vcpu, "props"))) {
7948 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7949 _("query-hotpluggable-cpus didn't return device props"));
7953 entry->node_id = -1;
7954 entry->socket_id = -1;
7955 entry->core_id = -1;
7956 entry->thread_id = -1;
7958 ignore_value(virJSONValueObjectGetNumberInt(props, "node-id", &entry->node_id));
7959 ignore_value(virJSONValueObjectGetNumberInt(props, "socket-id", &entry->socket_id));
7960 ignore_value(virJSONValueObjectGetNumberInt(props, "core-id", &entry->core_id));
7961 ignore_value(virJSONValueObjectGetNumberInt(props, "thread-id", &entry->thread_id));
7963 if (entry->node_id == -1 && entry->socket_id == -1 &&
7964 entry->core_id == -1 && entry->thread_id == -1) {
7965 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7966 _("query-hotpluggable-cpus entry doesn't report "
7967 "topology information"));
7971 /* qom path is not present unless the vCPU is online */
7972 if ((tmp = virJSONValueObjectGetString(vcpu, "qom-path"))) {
7973 if (VIR_STRDUP(entry->qom_path, tmp) < 0)
7976 /* alias is the part after last slash having a "vcpu" prefix */
7977 if ((tmp = strrchr(tmp, '/')) && STRPREFIX(tmp + 1, "vcpu")) {
7978 if (VIR_STRDUP(entry->alias, tmp + 1) < 0)
7988 qemuMonitorQueryHotpluggableCpusEntrySort(const void *p1,
7991 const struct qemuMonitorQueryHotpluggableCpusEntry *a = p1;
7992 const struct qemuMonitorQueryHotpluggableCpusEntry *b = p2;
7994 if (a->socket_id != b->socket_id)
7995 return a->socket_id - b->socket_id;
7997 if (a->core_id != b->core_id)
7998 return a->core_id - b->core_id;
8000 return a->thread_id - b->thread_id;
8005 qemuMonitorJSONGetHotpluggableCPUs(qemuMonitorPtr mon,
8006 struct qemuMonitorQueryHotpluggableCpusEntry **entries,
8009 struct qemuMonitorQueryHotpluggableCpusEntry *info = NULL;
8013 virJSONValuePtr data;
8014 virJSONValuePtr cmd;
8015 virJSONValuePtr reply = NULL;
8016 virJSONValuePtr vcpu;
8018 if (!(cmd = qemuMonitorJSONMakeCommand("query-hotpluggable-cpus", NULL)))
8021 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8024 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8027 data = virJSONValueObjectGet(reply, "return");
8028 ninfo = virJSONValueArraySize(data);
8030 if (VIR_ALLOC_N(info, ninfo) < 0)
8033 for (i = 0; i < ninfo; i++) {
8034 vcpu = virJSONValueArrayGet(data, i);
8036 if (qemuMonitorJSONProcessHotpluggableCpusReply(vcpu, info + i) < 0)
8040 qsort(info, ninfo, sizeof(*info), qemuMonitorQueryHotpluggableCpusEntrySort);
8042 VIR_STEAL_PTR(*entries, info);
8047 qemuMonitorQueryHotpluggableCpusFree(info, ninfo);
8048 virJSONValueFree(cmd);
8049 virJSONValueFree(reply);
8055 qemuMonitorJSONQueryQMPSchema(qemuMonitorPtr mon)
8057 virJSONValuePtr cmd;
8058 virJSONValuePtr reply = NULL;
8059 virJSONValuePtr ret = NULL;
8061 if (!(cmd = qemuMonitorJSONMakeCommand("query-qmp-schema", NULL)))
8064 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8067 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8070 ret = virJSONValueObjectStealArray(reply, "return");
8073 virJSONValueFree(cmd);
8074 virJSONValueFree(reply);
8081 qemuMonitorJSONSetBlockThreshold(qemuMonitorPtr mon,
8082 const char *nodename,
8083 unsigned long long threshold)
8085 virJSONValuePtr cmd;
8086 virJSONValuePtr reply = NULL;
8089 if (!(cmd = qemuMonitorJSONMakeCommand("block-set-write-threshold",
8090 "s:node-name", nodename,
8091 "U:write-threshold", threshold,
8095 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8098 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8104 virJSONValueFree(cmd);
8105 virJSONValueFree(reply);
8112 qemuMonitorJSONQueryNamedBlockNodes(qemuMonitorPtr mon)
8114 virJSONValuePtr cmd;
8115 virJSONValuePtr reply = NULL;
8116 virJSONValuePtr ret = NULL;
8118 if (!(cmd = qemuMonitorJSONMakeCommand("query-named-block-nodes", NULL)))
8121 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8124 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8127 ret = virJSONValueObjectStealArray(reply, "return");
8130 virJSONValueFree(cmd);
8131 virJSONValueFree(reply);
8138 qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
8141 virJSONValuePtr cmd;
8142 virJSONValuePtr reply = NULL;
8145 if (!(cmd = qemuMonitorJSONMakeCommand("watchdog-set-action",
8150 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8153 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8159 virJSONValueFree(cmd);
8160 virJSONValueFree(reply);
8166 qemuMonitorJSONBlockdevAdd(qemuMonitorPtr mon,
8167 virJSONValuePtr props)
8169 virJSONValuePtr cmd;
8170 virJSONValuePtr reply = NULL;
8173 if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-add", props)))
8176 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8179 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8185 virJSONValueFree(cmd);
8186 virJSONValueFree(reply);
8192 qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
8193 const char *nodename)
8195 virJSONValuePtr cmd;
8196 virJSONValuePtr reply = NULL;
8199 if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-del",
8200 "s:node-name", nodename,
8204 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8207 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8213 virJSONValueFree(cmd);
8214 virJSONValueFree(reply);
8220 qemuMonitorJSONBlockdevTrayOpen(qemuMonitorPtr mon,
8224 virJSONValuePtr cmd;
8225 virJSONValuePtr reply = NULL;
8228 if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-open-tray",
8230 "b:force", force, NULL)))
8233 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8236 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8242 virJSONValueFree(cmd);
8243 virJSONValueFree(reply);
8249 qemuMonitorJSONBlockdevTrayClose(qemuMonitorPtr mon,
8252 virJSONValuePtr cmd;
8253 virJSONValuePtr reply = NULL;
8256 if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-close-tray",
8260 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8263 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8269 virJSONValueFree(cmd);
8270 virJSONValueFree(reply);
8276 qemuMonitorJSONBlockdevMediumRemove(qemuMonitorPtr mon,
8279 virJSONValuePtr cmd;
8280 virJSONValuePtr reply = NULL;
8283 if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-remove-medium",
8287 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8290 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8296 virJSONValueFree(cmd);
8297 virJSONValueFree(reply);
8303 qemuMonitorJSONBlockdevMediumInsert(qemuMonitorPtr mon,
8305 const char *nodename)
8307 virJSONValuePtr cmd;
8308 virJSONValuePtr reply = NULL;
8311 if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-insert-medium",
8313 "s:node-name", nodename,
8317 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8320 if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8326 virJSONValueFree(cmd);
8327 virJSONValueFree(reply);
8333 * The function is used to retrieve the measurement of a SEV guest.
8334 * The measurement is signature of the memory contents that was encrypted
8335 * through the SEV launch flow.
8337 * A example JSON output:
8339 * { "execute" : "query-sev-launch-measure" }
8340 * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
8343 qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
8346 char *measurement = NULL;
8347 virJSONValuePtr cmd;
8348 virJSONValuePtr reply = NULL;
8349 virJSONValuePtr data;
8351 if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
8354 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8357 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
8360 data = virJSONValueObjectGetObject(reply, "return");
8362 if (!(tmp = virJSONValueObjectGetString(data, "data")))
8365 if (VIR_STRDUP(measurement, tmp) < 0)
8369 virJSONValueFree(cmd);
8370 virJSONValueFree(reply);
8376 * Example return data
8379 * { "connected": true, "id": "pr-helper0" }
8383 qemuMonitorJSONExtractPRManagerInfo(virJSONValuePtr reply,
8384 virHashTablePtr info)
8386 qemuMonitorPRManagerInfoPtr entry = NULL;
8387 virJSONValuePtr data;
8391 data = virJSONValueObjectGetArray(reply, "return");
8393 for (i = 0; i < virJSONValueArraySize(data); i++) {
8394 virJSONValuePtr prManager = virJSONValueArrayGet(data, i);
8397 if (!(alias = virJSONValueObjectGetString(prManager, "id")))
8400 if (VIR_ALLOC(entry) < 0)
8403 if (virJSONValueObjectGetBoolean(prManager,
8405 &entry->connected) < 0) {
8409 if (virHashAddEntry(info, alias, entry) < 0)
8421 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8422 _("malformed prManager reply"));
8428 qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon,
8429 virHashTablePtr info)
8432 virJSONValuePtr cmd;
8433 virJSONValuePtr reply = NULL;
8435 if (!(cmd = qemuMonitorJSONMakeCommand("query-pr-managers",
8439 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8442 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8445 ret = qemuMonitorJSONExtractPRManagerInfo(reply, info);
8447 virJSONValueFree(cmd);
8448 virJSONValueFree(reply);
8455 qemuMonitorJSONExtractCurrentMachineInfo(virJSONValuePtr reply,
8456 qemuMonitorCurrentMachineInfoPtr info)
8458 virJSONValuePtr data;
8460 data = virJSONValueObjectGetObject(reply, "return");
8464 if (virJSONValueObjectGetBoolean(data, "wakeup-suspend-support",
8465 &info->wakeupSuspendSupport) < 0)
8471 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8472 _("malformed qemu-current-machine reply"));
8478 qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon,
8479 qemuMonitorCurrentMachineInfoPtr info)
8482 virJSONValuePtr cmd;
8483 virJSONValuePtr reply = NULL;
8485 if (!(cmd = qemuMonitorJSONMakeCommand("query-current-machine",
8489 if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8492 if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
8495 ret = qemuMonitorJSONExtractCurrentMachineInfo(reply, info);
8498 virJSONValueFree(cmd);
8499 virJSONValueFree(reply);