]> xenbits.xensource.com Git - libvirt.git/blob
53a7de8b77
[libvirt.git] /
1 /*
2  * qemu_monitor_json.c: interaction with QEMU monitor console
3  *
4  * Copyright (C) 2006-2016 Red Hat, Inc.
5  * Copyright (C) 2006 Daniel P. Berrange
6  *
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.
11  *
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.
16  *
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/>.
20  */
21
22 #include <config.h>
23
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <poll.h>
28 #include <unistd.h>
29 #include <sys/time.h>
30
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"
36 #include "viralloc.h"
37 #include "virlog.h"
38 #include "driver.h"
39 #include "datatypes.h"
40 #include "virerror.h"
41 #include "virjson.h"
42 #include "virprobe.h"
43 #include "virstring.h"
44 #include "cpu/cpu_x86.h"
45 #include "c-strcasestr.h"
46 #include "virenum.h"
47
48 #ifdef WITH_DTRACE_PROBES
49 # include "libvirt_qemu_probes.h"
50 #endif
51
52 #define VIR_FROM_THIS VIR_FROM_QEMU
53
54 VIR_LOG_INIT("qemu.qemu_monitor_json");
55
56 #define QOM_CPU_PATH  "/machine/unattached/device[0]"
57
58 #define LINE_ENDING "\r\n"
59
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);
94
95 typedef struct {
96     const char *type;
97     void (*handler)(qemuMonitorPtr mon, virJSONValuePtr data);
98 } qemuEventHandler;
99
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.  */
136 };
137
138 static int
139 qemuMonitorEventCompare(const void *key, const void *elt)
140 {
141     const char *type = key;
142     const qemuEventHandler *handler = elt;
143     return strcmp(type, handler->type);
144 }
145
146 static int
147 qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
148                               virJSONValuePtr obj)
149 {
150     const char *type;
151     qemuEventHandler *handler;
152     virJSONValuePtr data;
153     char *details = NULL;
154     virJSONValuePtr timestamp;
155     long long seconds = -1;
156     unsigned int micros = 0;
157
158     VIR_DEBUG("mon=%p obj=%p", mon, obj);
159
160     type = virJSONValueObjectGetString(obj, "event");
161     if (!type) {
162         VIR_WARN("missing event type in message");
163         errno = EINVAL;
164         return -1;
165     }
166
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",
172                                                      &seconds));
173         ignore_value(virJSONValueObjectGetNumberUint(timestamp, "microseconds",
174                                                      &micros));
175     }
176     qemuMonitorEmitEvent(mon, type, seconds, micros, details);
177     VIR_FREE(details);
178
179     handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers),
180                       sizeof(eventHandlers[0]), qemuMonitorEventCompare);
181     if (handler) {
182         VIR_DEBUG("handle %s handler=%p data=%p", type,
183                   handler->handler, data);
184         (handler->handler)(mon, data);
185     }
186     return 0;
187 }
188
189 int
190 qemuMonitorJSONIOProcessLine(qemuMonitorPtr mon,
191                              const char *line,
192                              qemuMonitorMessagePtr msg)
193 {
194     virJSONValuePtr obj = NULL;
195     int ret = -1;
196
197     VIR_DEBUG("Line [%s]", line);
198
199     if (!(obj = virJSONValueFromString(line)))
200         goto cleanup;
201
202     if (virJSONValueGetType(obj) != VIR_JSON_TYPE_OBJECT) {
203         virReportError(VIR_ERR_INTERNAL_ERROR,
204                        _("Parsed JSON reply '%s' isn't an object"), line);
205         goto cleanup;
206     }
207
208     if (virJSONValueObjectHasKey(obj, "QMP") == 1) {
209         ret = 0;
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);
218         if (msg) {
219             msg->rxObject = obj;
220             msg->finished = 1;
221             obj = NULL;
222             ret = 0;
223         } else {
224             virReportError(VIR_ERR_INTERNAL_ERROR,
225                            _("Unexpected JSON reply '%s'"), line);
226         }
227     } else {
228         virReportError(VIR_ERR_INTERNAL_ERROR,
229                        _("Unknown JSON reply '%s'"), line);
230     }
231
232  cleanup:
233     virJSONValueFree(obj);
234     return ret;
235 }
236
237 int qemuMonitorJSONIOProcess(qemuMonitorPtr mon,
238                              const char *data,
239                              size_t len,
240                              qemuMonitorMessagePtr msg)
241 {
242     int used = 0;
243     /*VIR_DEBUG("Data %d bytes [%s]", len, data);*/
244
245     while (used < len) {
246         char *nl = strstr(data + used, LINE_ENDING);
247
248         if (nl) {
249             int got = nl - (data + used);
250             char *line;
251             if (VIR_STRNDUP(line, data + used, got) < 0)
252                 return -1;
253             used += got + strlen(LINE_ENDING);
254             line[got] = '\0'; /* kill \n */
255             if (qemuMonitorJSONIOProcessLine(mon, line, msg) < 0) {
256                 VIR_FREE(line);
257                 return -1;
258             }
259
260             VIR_FREE(line);
261         } else {
262             break;
263         }
264     }
265
266 #if DEBUG_IO
267     VIR_DEBUG("Total used %d bytes out of %zd available in buffer", used, len);
268 #endif
269
270     return used;
271 }
272
273 static int
274 qemuMonitorJSONCommandWithFd(qemuMonitorPtr mon,
275                              virJSONValuePtr cmd,
276                              int scm_fd,
277                              virJSONValuePtr *reply)
278 {
279     int ret = -1;
280     qemuMonitorMessage msg;
281     VIR_AUTOCLEAN(virBuffer) cmdbuf = VIR_BUFFER_INITIALIZER;
282     char *id = NULL;
283
284     *reply = NULL;
285
286     memset(&msg, 0, sizeof(msg));
287
288     if (virJSONValueObjectHasKey(cmd, "execute") == 1) {
289         if (!(id = qemuMonitorNextCommandID(mon)))
290             goto cleanup;
291         if (virJSONValueObjectAppendString(cmd, "id", id) < 0) {
292             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
293                            _("Unable to append command 'id' string"));
294             goto cleanup;
295         }
296     }
297
298     if (virJSONValueToBuffer(cmd, &cmdbuf, false) < 0)
299         goto cleanup;
300     virBufferAddLit(&cmdbuf, "\r\n");
301
302     if (virBufferCheckError(&cmdbuf) < 0)
303         goto cleanup;
304
305     msg.txLength = virBufferUse(&cmdbuf);
306     msg.txBuffer = virBufferContentAndReset(&cmdbuf);
307     msg.txFD = scm_fd;
308
309     ret = qemuMonitorSend(mon, &msg);
310
311     if (ret == 0) {
312         if (!msg.rxObject) {
313             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
314                            _("Missing monitor reply object"));
315             ret = -1;
316         } else {
317             *reply = msg.rxObject;
318         }
319     }
320
321  cleanup:
322     VIR_FREE(id);
323     VIR_FREE(msg.txBuffer);
324
325     return ret;
326 }
327
328
329 static int
330 qemuMonitorJSONCommand(qemuMonitorPtr mon,
331                        virJSONValuePtr cmd,
332                        virJSONValuePtr *reply)
333 {
334     return qemuMonitorJSONCommandWithFd(mon, cmd, -1, reply);
335 }
336
337 /* Ignoring OOM in this method, since we're already reporting
338  * a more important error
339  *
340  * XXX see qerror.h for different klasses & fill out useful params
341  */
342 static const char *
343 qemuMonitorJSONStringifyError(virJSONValuePtr error)
344 {
345     const char *klass = virJSONValueObjectGetString(error, "class");
346     const char *detail = NULL;
347
348     /* The QMP 'desc' field is usually sufficient for our generic
349      * error reporting needs.
350      */
351     if (klass)
352         detail = virJSONValueObjectGetString(error, "desc");
353
354
355     if (!detail)
356         detail = "unknown QEMU command error";
357
358     return detail;
359 }
360
361 static const char *
362 qemuMonitorJSONCommandName(virJSONValuePtr cmd)
363 {
364     const char *name = virJSONValueObjectGetString(cmd, "execute");
365     if (name)
366         return name;
367     else
368         return "<unknown>";
369 }
370
371 static int
372 qemuMonitorJSONCheckError(virJSONValuePtr cmd,
373                           virJSONValuePtr reply)
374 {
375     if (virJSONValueObjectHasKey(reply, "error")) {
376         virJSONValuePtr error = virJSONValueObjectGet(reply, "error");
377         char *cmdstr = virJSONValueToString(cmd, false);
378         char *replystr = virJSONValueToString(reply, false);
379
380         /* Log the full JSON formatted command & error */
381         VIR_DEBUG("unable to execute QEMU command %s: %s",
382                   NULLSTR(cmdstr), NULLSTR(replystr));
383
384         /* Only send the user the command name + friendly error */
385         if (!error)
386             virReportError(VIR_ERR_INTERNAL_ERROR,
387                            _("unable to execute QEMU command '%s'"),
388                            qemuMonitorJSONCommandName(cmd));
389         else
390             virReportError(VIR_ERR_INTERNAL_ERROR,
391                            _("unable to execute QEMU command '%s': %s"),
392                            qemuMonitorJSONCommandName(cmd),
393                            qemuMonitorJSONStringifyError(error));
394
395         VIR_FREE(cmdstr);
396         VIR_FREE(replystr);
397         return -1;
398     } else if (!virJSONValueObjectHasKey(reply, "return")) {
399         char *cmdstr = virJSONValueToString(cmd, false);
400         char *replystr = virJSONValueToString(reply, false);
401
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));
407         VIR_FREE(cmdstr);
408         VIR_FREE(replystr);
409         return -1;
410     }
411     return 0;
412 }
413
414
415 static int
416 qemuMonitorJSONCheckReply(virJSONValuePtr cmd,
417                           virJSONValuePtr reply,
418                           virJSONType type)
419 {
420     virJSONValuePtr data;
421
422     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
423         return -1;
424
425     data = virJSONValueObjectGet(reply, "return");
426     if (virJSONValueGetType(data) != type) {
427         char *cmdstr = virJSONValueToString(cmd, false);
428         char *retstr = virJSONValueToString(data, false);
429
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));
435
436         VIR_FREE(cmdstr);
437         VIR_FREE(retstr);
438         return -1;
439     }
440
441     return 0;
442 }
443
444
445 static bool
446 qemuMonitorJSONErrorIsClass(virJSONValuePtr error,
447                             const char *klass)
448 {
449     return STREQ_NULLABLE(virJSONValueObjectGetString(error, "class"), klass);
450 }
451
452
453 static bool
454 qemuMonitorJSONHasError(virJSONValuePtr reply,
455                         const char *klass)
456 {
457     virJSONValuePtr error;
458
459     if (!(error = virJSONValueObjectGet(reply, "error")))
460         return false;
461
462     return qemuMonitorJSONErrorIsClass(error, klass);
463 }
464
465
466 /**
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)
471  *
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.
474  *
475  * Returns 0 on success and -1 on error.
476  */
477 int
478 qemuMonitorJSONTransactionAdd(virJSONValuePtr actions,
479                               const char *cmdname,
480                               ...)
481 {
482     virJSONValuePtr entry = NULL;
483     virJSONValuePtr data = NULL;
484     va_list args;
485     int ret = -1;
486
487     va_start(args, cmdname);
488
489     if (virJSONValueObjectCreateVArgs(&data, args) < 0)
490         goto cleanup;
491
492     if (virJSONValueObjectCreate(&entry,
493                                  "s:type", cmdname,
494                                  "A:data", &data, NULL) < 0)
495         goto cleanup;
496
497     if (virJSONValueArrayAppend(actions, entry) < 0)
498         goto cleanup;
499
500     entry = NULL;
501     ret = 0;
502
503  cleanup:
504     virJSONValueFree(entry);
505     virJSONValueFree(data);
506     va_end(args);
507     return ret;
508 }
509
510
511 /**
512  * qemuMonitorJSONMakeCommandInternal:
513  * @cmdname: QMP command name
514  * @arguments: a JSON object containing command arguments or NULL
515  *
516  * Create a JSON object used on the QMP monitor to call a command.
517  *
518  * Note that @arguments is always consumed and should not be referenced after
519  * the call to this function.
520  */
521 static virJSONValuePtr
522 qemuMonitorJSONMakeCommandInternal(const char *cmdname,
523                                    virJSONValuePtr arguments)
524 {
525     virJSONValuePtr ret = NULL;
526
527     ignore_value(virJSONValueObjectCreate(&ret,
528                                           "s:execute", cmdname,
529                                           "A:arguments", &arguments, NULL));
530
531     virJSONValueFree(arguments);
532     return ret;
533 }
534
535
536 static virJSONValuePtr ATTRIBUTE_SENTINEL
537 qemuMonitorJSONMakeCommand(const char *cmdname,
538                            ...)
539 {
540     virJSONValuePtr obj = NULL;
541     virJSONValuePtr jargs = NULL;
542     va_list args;
543
544     va_start(args, cmdname);
545
546     if (virJSONValueObjectCreateVArgs(&jargs, args) < 0)
547         goto cleanup;
548
549     obj = qemuMonitorJSONMakeCommandInternal(cmdname, jargs);
550
551  cleanup:
552     va_end(args);
553
554     return obj;
555 }
556
557
558 static virJSONValuePtr
559 qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
560 {
561     virJSONValuePtr ret = NULL;
562     char **keywords = NULL;
563     char **values = NULL;
564     int nkeywords = 0;
565     size_t i;
566
567     if (!(ret = virJSONValueNewObject()))
568         return NULL;
569
570     if (qemuParseKeywords(str, &keywords, &values, &nkeywords, 1) < 0)
571         goto error;
572
573     for (i = 0; i < nkeywords; i++) {
574         if (values[i] == NULL) {
575             if (i != 0) {
576                 virReportError(VIR_ERR_INTERNAL_ERROR,
577                                _("unexpected empty keyword in %s"), str);
578                 goto error;
579             } else {
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)
583                     goto error;
584             }
585         } else {
586             if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0)
587                 goto error;
588         }
589     }
590
591     qemuParseKeywordsFree(nkeywords, keywords, values);
592     return ret;
593
594  error:
595     qemuParseKeywordsFree(nkeywords, keywords, values);
596     virJSONValueFree(ret);
597     return NULL;
598 }
599
600
601 static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data)
602 {
603     bool guest = false;
604     virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
605
606     if (data && virJSONValueObjectGetBoolean(data, "guest", &guest) == 0)
607         guest_initiated = guest ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
608
609     qemuMonitorEmitShutdown(mon, guest_initiated);
610 }
611
612 static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
613 {
614     qemuMonitorEmitReset(mon);
615 }
616
617 static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
618 {
619     qemuMonitorEmitPowerdown(mon);
620 }
621
622 static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
623 {
624     qemuMonitorEmitStop(mon);
625 }
626
627 static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
628 {
629     qemuMonitorEmitResume(mon);
630 }
631
632
633 static qemuMonitorEventPanicInfoPtr
634 qemuMonitorJSONGuestPanicExtractInfoHyperv(virJSONValuePtr data)
635 {
636     qemuMonitorEventPanicInfoPtr ret;
637
638     if (VIR_ALLOC(ret) < 0)
639         return NULL;
640
641     ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV;
642
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"));
650         goto error;
651     }
652
653     return ret;
654
655  error:
656     qemuMonitorEventPanicInfoFree(ret);
657     return NULL;
658 }
659
660 static qemuMonitorEventPanicInfoPtr
661 qemuMonitorJSONGuestPanicExtractInfoS390(virJSONValuePtr data)
662 {
663     qemuMonitorEventPanicInfoPtr ret;
664     int core;
665     unsigned long long psw_mask, psw_addr;
666     const char *reason = NULL;
667
668     if (VIR_ALLOC(ret) < 0)
669         return NULL;
670
671     ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390;
672
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"));
678         goto error;
679     }
680
681     ret->data.s390.core = core;
682     ret->data.s390.psw_mask = psw_mask;
683     ret->data.s390.psw_addr = psw_addr;
684
685     if (VIR_STRDUP(ret->data.s390.reason, reason) < 0)
686         goto error;
687
688     return ret;
689
690  error:
691     qemuMonitorEventPanicInfoFree(ret);
692     return NULL;
693 }
694
695 static qemuMonitorEventPanicInfoPtr
696 qemuMonitorJSONGuestPanicExtractInfo(virJSONValuePtr data)
697 {
698     const char *type = virJSONValueObjectGetString(data, "type");
699
700     if (STREQ_NULLABLE(type, "hyper-v"))
701         return qemuMonitorJSONGuestPanicExtractInfoHyperv(data);
702     else if (STREQ_NULLABLE(type, "s390"))
703         return qemuMonitorJSONGuestPanicExtractInfoS390(data);
704
705     virReportError(VIR_ERR_INTERNAL_ERROR,
706                    _("unknown panic info type '%s'"), NULLSTR(type));
707     return NULL;
708 }
709
710
711 static void
712 qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon,
713                                 virJSONValuePtr data)
714 {
715     virJSONValuePtr infojson = virJSONValueObjectGetObject(data, "info");
716     qemuMonitorEventPanicInfoPtr info = NULL;
717
718     if (infojson)
719         info = qemuMonitorJSONGuestPanicExtractInfo(infojson);
720
721     qemuMonitorEmitGuestPanic(mon, info);
722 }
723
724
725 static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data)
726 {
727     long long offset = 0;
728     if (virJSONValueObjectGetNumberLong(data, "offset", &offset) < 0) {
729         VIR_WARN("missing offset in RTC change event");
730         offset = 0;
731     }
732     qemuMonitorEmitRTCChange(mon, offset);
733 }
734
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",
739 );
740
741 static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data)
742 {
743     const char *action;
744     int actionID;
745     if (!(action = virJSONValueObjectGetString(data, "action")))
746         VIR_WARN("missing action in watchdog event");
747     if (action) {
748         if ((actionID = qemuMonitorWatchdogActionTypeFromString(action)) < 0) {
749             VIR_WARN("unknown action %s in watchdog event", action);
750             actionID = VIR_DOMAIN_EVENT_WATCHDOG_NONE;
751         }
752     } else {
753             actionID = VIR_DOMAIN_EVENT_WATCHDOG_NONE;
754     }
755     qemuMonitorEmitWatchdog(mon, actionID);
756 }
757
758 VIR_ENUM_DECL(qemuMonitorIOErrorAction);
759 VIR_ENUM_IMPL(qemuMonitorIOErrorAction,
760               VIR_DOMAIN_EVENT_IO_ERROR_LAST,
761               "ignore", "stop", "report",
762 );
763
764
765 static void
766 qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data)
767 {
768     const char *device;
769     const char *nodename;
770     const char *action;
771     const char *reason = "";
772     bool nospc = false;
773     int actionID;
774
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 */
778
779     if ((action = virJSONValueObjectGetString(data, "action")) == NULL) {
780         VIR_WARN("Missing action in disk io error event");
781         action = "ignore";
782     }
783
784     if ((device = virJSONValueObjectGetString(data, "device")) == NULL)
785         VIR_WARN("missing device in disk io error event");
786
787     nodename = virJSONValueObjectGetString(data, "node-name");
788
789     if (virJSONValueObjectGetBoolean(data, "nospace", &nospc) == 0 && nospc)
790         reason = "enospc";
791
792     if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) {
793         VIR_WARN("unknown disk io error action '%s'", action);
794         actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
795     }
796
797     qemuMonitorEmitIOError(mon, device, nodename, actionID, reason);
798 }
799
800
801 VIR_ENUM_DECL(qemuMonitorGraphicsAddressFamily);
802 VIR_ENUM_IMPL(qemuMonitorGraphicsAddressFamily,
803               VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_LAST,
804               "ipv4", "ipv6", "unix",
805 );
806
807 static void
808 qemuMonitorJSONHandleGraphicsVNC(qemuMonitorPtr mon,
809                                  virJSONValuePtr data,
810                                  int phase)
811 {
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;
818
819     if (!(client = virJSONValueObjectGetObject(data, "client"))) {
820         VIR_WARN("missing client info in VNC event");
821         return;
822     }
823     if (!(server = virJSONValueObjectGetObject(data, "server"))) {
824         VIR_WARN("missing server info in VNC event");
825         return;
826     }
827
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");
831         authScheme = "";
832     }
833
834     if (!(localFamily = virJSONValueObjectGetString(server, "family"))) {
835         VIR_WARN("missing local address family in VNC event");
836         return;
837     }
838     if (!(localNode = virJSONValueObjectGetString(server, "host"))) {
839         VIR_WARN("missing local hostname in VNC event");
840         return;
841     }
842     if (!(localService = virJSONValueObjectGetString(server, "service"))) {
843         VIR_WARN("missing local service in VNC event");
844         return;
845     }
846
847     if (!(remoteFamily = virJSONValueObjectGetString(client, "family"))) {
848         VIR_WARN("missing remote address family in VNC event");
849         return;
850     }
851     if (!(remoteNode = virJSONValueObjectGetString(client, "host"))) {
852         VIR_WARN("missing remote hostname in VNC event");
853         return;
854     }
855     if (!(remoteService = virJSONValueObjectGetString(client, "service"))) {
856         VIR_WARN("missing remote service in VNC event");
857         return;
858     }
859
860     saslUsername = virJSONValueObjectGetString(client, "sasl_username");
861     x509dname = virJSONValueObjectGetString(client, "x509_dname");
862
863     if ((localFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(localFamily)) < 0) {
864         VIR_WARN("unknown address family '%s'", localFamily);
865         localFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
866     }
867     if ((remoteFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(remoteFamily)) < 0) {
868         VIR_WARN("unknown address family '%s'", remoteFamily);
869         remoteFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
870     }
871
872     qemuMonitorEmitGraphics(mon, phase,
873                             localFamilyID, localNode, localService,
874                             remoteFamilyID, remoteNode, remoteService,
875                             authScheme, x509dname, saslUsername);
876 }
877
878 static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data)
879 {
880     qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
881 }
882
883
884 static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data)
885 {
886     qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
887 }
888
889
890 static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data)
891 {
892     qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
893 }
894
895
896 static void
897 qemuMonitorJSONHandleGraphicsSPICE(qemuMonitorPtr mon,
898                                    virJSONValuePtr data,
899                                    int phase)
900 {
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;
907
908     if (!(client = virJSONValueObjectGetObject(data, "client")) ||
909         !(server = virJSONValueObjectGetObject(data, "server"))) {
910         VIR_WARN("missing server or client info in SPICE event");
911         return;
912     }
913
914     if (phase == VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE &&
915         !(auth = virJSONValueObjectGetString(server, "auth"))) {
916         VIR_DEBUG("missing auth scheme in SPICE event");
917         auth = "";
918     }
919
920     if (!(lfamily = virJSONValueObjectGetString(server, "family"))) {
921         VIR_WARN("missing local address family in SPICE event");
922         return;
923     }
924     if (!(lhost = virJSONValueObjectGetString(server, "host"))) {
925         VIR_WARN("missing local hostname in SPICE event");
926         return;
927     }
928     if (!(lport = virJSONValueObjectGetString(server, "port"))) {
929         VIR_WARN("missing local port in SPICE event");
930         return;
931     }
932
933     if (!(rfamily = virJSONValueObjectGetString(client, "family"))) {
934         VIR_WARN("missing remote address family in SPICE event");
935         return;
936     }
937     if (!(rhost = virJSONValueObjectGetString(client, "host"))) {
938         VIR_WARN("missing remote hostname in SPICE event");
939         return;
940     }
941     if (!(rport = virJSONValueObjectGetString(client, "port"))) {
942         VIR_WARN("missing remote service in SPICE event");
943         return;
944     }
945
946     if ((lfamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(lfamily)) < 0) {
947         VIR_WARN("unknown address family '%s'", lfamily);
948         lfamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
949     }
950     if ((rfamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(rfamily)) < 0) {
951         VIR_WARN("unknown address family '%s'", rfamily);
952         rfamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
953     }
954
955     qemuMonitorEmitGraphics(mon, phase, lfamilyID, lhost, lport, rfamilyID,
956                             rhost, rport, auth, NULL, NULL);
957 }
958
959
960 static void qemuMonitorJSONHandleSPICEConnect(qemuMonitorPtr mon, virJSONValuePtr data)
961 {
962     qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
963 }
964
965
966 static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitorPtr mon, virJSONValuePtr data)
967 {
968     qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
969 }
970
971
972 static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitorPtr mon, virJSONValuePtr data)
973 {
974     qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
975 }
976
977 static void
978 qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
979                                   virJSONValuePtr data,
980                                   int event)
981 {
982     const char *device;
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;
987
988     if ((device = virJSONValueObjectGetString(data, "device")) == NULL) {
989         VIR_WARN("missing device in block job event");
990         goto out;
991     }
992
993     if (virJSONValueObjectGetNumberUlong(data, "offset", &offset) < 0) {
994         VIR_WARN("missing offset in block job event");
995         goto out;
996     }
997
998     if (virJSONValueObjectGetNumberUlong(data, "len", &len) < 0) {
999         VIR_WARN("missing len in block job event");
1000         goto out;
1001     }
1002
1003     if ((type_str = virJSONValueObjectGetString(data, "type")) == NULL) {
1004         VIR_WARN("missing type in block job event");
1005         goto out;
1006     }
1007
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;
1014
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;
1021         break;
1022     case VIR_DOMAIN_BLOCK_JOB_CANCELED:
1023     case VIR_DOMAIN_BLOCK_JOB_READY:
1024         break;
1025     case VIR_DOMAIN_BLOCK_JOB_FAILED:
1026     case VIR_DOMAIN_BLOCK_JOB_LAST:
1027         VIR_DEBUG("should not get here");
1028         break;
1029     }
1030
1031  out:
1032     qemuMonitorEmitBlockJob(mon, device, type, event, error);
1033 }
1034
1035 static void
1036 qemuMonitorJSONHandleTrayChange(qemuMonitorPtr mon,
1037                                 virJSONValuePtr data)
1038 {
1039     const char *devAlias = virJSONValueObjectGetString(data, "device");
1040     const char *devid = virJSONValueObjectGetString(data, "id");
1041     bool trayOpened;
1042     int reason;
1043
1044     /* drive alias is always reported but empty for -blockdev */
1045     if (*devAlias == '\0')
1046         devAlias = NULL;
1047
1048     if (!devAlias && !devid) {
1049         VIR_WARN("missing device in tray change event");
1050         return;
1051     }
1052
1053     if (virJSONValueObjectGetBoolean(data, "tray-open", &trayOpened) < 0) {
1054         VIR_WARN("missing tray-open in tray change event");
1055         return;
1056     }
1057
1058     if (trayOpened)
1059         reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN;
1060     else
1061         reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE;
1062
1063     qemuMonitorEmitTrayChange(mon, devAlias, devid, reason);
1064 }
1065
1066 static void
1067 qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon,
1068                               virJSONValuePtr data ATTRIBUTE_UNUSED)
1069 {
1070     qemuMonitorEmitPMWakeup(mon);
1071 }
1072
1073 static void
1074 qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon,
1075                                virJSONValuePtr data ATTRIBUTE_UNUSED)
1076 {
1077     qemuMonitorEmitPMSuspend(mon);
1078 }
1079
1080 static void
1081 qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon,
1082                                        virJSONValuePtr data)
1083 {
1084     qemuMonitorJSONHandleBlockJobImpl(mon, data,
1085                                       VIR_DOMAIN_BLOCK_JOB_COMPLETED);
1086 }
1087
1088 static void
1089 qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon,
1090                                        virJSONValuePtr data)
1091 {
1092     qemuMonitorJSONHandleBlockJobImpl(mon, data,
1093                                       VIR_DOMAIN_BLOCK_JOB_CANCELED);
1094 }
1095
1096 static void
1097 qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon,
1098                                    virJSONValuePtr data)
1099 {
1100     qemuMonitorJSONHandleBlockJobImpl(mon, data,
1101                                       VIR_DOMAIN_BLOCK_JOB_READY);
1102 }
1103
1104 static void
1105 qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon,
1106                                    virJSONValuePtr data)
1107 {
1108     unsigned long long actual = 0;
1109     if (virJSONValueObjectGetNumberUlong(data, "actual", &actual) < 0) {
1110         VIR_WARN("missing actual in balloon change event");
1111         return;
1112     }
1113     actual = VIR_DIV_UP(actual, 1024);
1114     qemuMonitorEmitBalloonChange(mon, actual);
1115 }
1116
1117 static void
1118 qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon,
1119                                    virJSONValuePtr data ATTRIBUTE_UNUSED)
1120 {
1121     qemuMonitorEmitPMSuspendDisk(mon);
1122 }
1123
1124 static void
1125 qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data)
1126 {
1127     const char *device;
1128
1129     if (!(device = virJSONValueObjectGetString(data, "device"))) {
1130         VIR_DEBUG("missing device in device deleted event");
1131         return;
1132     }
1133
1134     qemuMonitorEmitDeviceDeleted(mon, device);
1135 }
1136
1137
1138 static void
1139 qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data)
1140 {
1141     const char *name;
1142
1143     if (!(name = virJSONValueObjectGetString(data, "name"))) {
1144         VIR_WARN("missing device in NIC_RX_FILTER_CHANGED event");
1145         return;
1146     }
1147
1148     qemuMonitorEmitNicRxFilterChanged(mon, name);
1149 }
1150
1151
1152 static void
1153 qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon,
1154                                   virJSONValuePtr data)
1155 {
1156     const char *name;
1157     bool connected;
1158
1159     if (!(name = virJSONValueObjectGetString(data, "id"))) {
1160         VIR_WARN("missing device alias in VSERPORT_CHANGE event");
1161         return;
1162     }
1163
1164     if (virJSONValueObjectGetBoolean(data, "open", &connected) < 0) {
1165         VIR_WARN("missing port state for '%s' in VSERPORT_CHANGE event", name);
1166         return;
1167     }
1168
1169     qemuMonitorEmitSerialChange(mon, name, connected);
1170 }
1171
1172
1173 static void
1174 qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mon,
1175                                    virJSONValuePtr data ATTRIBUTE_UNUSED)
1176 {
1177     qemuMonitorEmitSpiceMigrated(mon);
1178 }
1179
1180
1181 static void
1182 qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon,
1183                                      virJSONValuePtr data)
1184 {
1185     const char *str;
1186     int status;
1187
1188     if (!(str = virJSONValueObjectGetString(data, "status"))) {
1189         VIR_WARN("missing status in migration event");
1190         return;
1191     }
1192
1193     if ((status = qemuMonitorMigrationStatusTypeFromString(str)) == -1) {
1194         VIR_WARN("unknown status '%s' in migration event", str);
1195         return;
1196     }
1197
1198     qemuMonitorEmitMigrationStatus(mon, status);
1199 }
1200
1201
1202 static void
1203 qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon,
1204                                    virJSONValuePtr data)
1205 {
1206     int pass;
1207
1208     if (virJSONValueObjectGetNumberInt(data, "pass", &pass) < 0) {
1209         VIR_WARN("missing dirty-sync-count in migration-pass event");
1210         return;
1211     }
1212
1213     qemuMonitorEmitMigrationPass(mon, pass);
1214 }
1215
1216
1217 static void
1218 qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data)
1219 {
1220     virJSONValuePtr info;
1221     const char *alias;
1222     const char *slotType;
1223     const char *slot;
1224     unsigned int source;
1225     unsigned int status;
1226
1227     if (!(info = virJSONValueObjectGetObject(data, "info")))
1228         goto error;
1229
1230     /* optional */
1231     alias = virJSONValueObjectGetString(info, "device");
1232
1233     if (!(slotType = virJSONValueObjectGetString(info, "slot-type")))
1234         goto error;
1235
1236     if (!(slot = virJSONValueObjectGetString(info, "slot")))
1237         goto error;
1238
1239     if (virJSONValueObjectGetNumberUint(info, "source", &source) < 0)
1240         goto error;
1241
1242     if (virJSONValueObjectGetNumberUint(info, "status", &status) < 0)
1243         goto error;
1244
1245     qemuMonitorEmitAcpiOstInfo(mon, alias, slotType, slot, source, status);
1246     return;
1247
1248  error:
1249     VIR_WARN("malformed ACPI_DEVICE_OST event");
1250     return;
1251 }
1252
1253
1254 static void
1255 qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data)
1256 {
1257     const char *nodename;
1258     unsigned long long threshold;
1259     unsigned long long excess;
1260
1261     if (!(nodename = virJSONValueObjectGetString(data, "node-name")))
1262         goto error;
1263
1264     if (virJSONValueObjectGetNumberUlong(data, "write-threshold", &threshold) < 0)
1265         goto error;
1266
1267     if (virJSONValueObjectGetNumberUlong(data, "amount-exceeded", &excess) < 0)
1268         goto error;
1269
1270     qemuMonitorEmitBlockThreshold(mon, nodename, threshold, excess);
1271     return;
1272
1273  error:
1274     VIR_WARN("malformed 'BLOCK_WRITE_THRESHOLD' event");
1275 }
1276
1277
1278 static int
1279 qemuMonitorJSONExtractDumpStats(virJSONValuePtr result,
1280                                 qemuMonitorDumpStatsPtr ret)
1281 {
1282     const char *statusstr;
1283
1284     if (!(statusstr = virJSONValueObjectGetString(result, "status"))) {
1285         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1286                        _("incomplete result, failed to get status"));
1287         return -1;
1288     }
1289
1290     ret->status = qemuMonitorDumpStatusTypeFromString(statusstr);
1291     if (ret->status < 0) {
1292         virReportError(VIR_ERR_INTERNAL_ERROR,
1293                        _("incomplete result, unknown status string '%s'"),
1294                        statusstr);
1295         return -1;
1296     }
1297
1298     if (virJSONValueObjectGetNumberUlong(result, "completed", &ret->completed) < 0) {
1299         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1300                        _("incomplete result, failed to get completed"));
1301         return -1;
1302     }
1303
1304     if (virJSONValueObjectGetNumberUlong(result, "total", &ret->total) < 0) {
1305         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1306                        _("incomplete result, failed to get total"));
1307         return -1;
1308     }
1309
1310     return 0;
1311 }
1312
1313
1314 static void
1315 qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
1316                                    virJSONValuePtr data)
1317 {
1318     virJSONValuePtr result;
1319     int status;
1320     qemuMonitorDumpStats stats = { 0 };
1321     const char *error = NULL;
1322
1323     if (!(result = virJSONValueObjectGetObject(data, "result"))) {
1324         VIR_WARN("missing result in dump completed event");
1325         return;
1326     }
1327
1328     status = qemuMonitorJSONExtractDumpStats(result, &stats);
1329
1330     error = virJSONValueObjectGetString(data, "error");
1331
1332     qemuMonitorEmitDumpCompleted(mon, status, &stats, error);
1333 }
1334
1335
1336 static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon,
1337                                                         virJSONValuePtr data)
1338 {
1339     const char *name;
1340     bool connected;
1341
1342     if (!(name = virJSONValueObjectGetString(data, "id"))) {
1343         VIR_WARN("missing pr-manager alias in PR_MANAGER_STATUS_CHANGED event");
1344         return;
1345     }
1346
1347     if (virJSONValueObjectGetBoolean(data, "connected", &connected) < 0) {
1348         VIR_WARN("missing connected state for %s "
1349                  "in PR_MANAGER_STATUS_CHANGED event", name);
1350         return;
1351     }
1352
1353     qemuMonitorEmitPRManagerStatusChanged(mon, name, connected);
1354 }
1355
1356
1357 static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon,
1358                                                       virJSONValuePtr data)
1359 {
1360     const char *netdev;
1361     bool gid_status;
1362     unsigned long long subnet_prefix, interface_id;
1363
1364     if (!(netdev = virJSONValueObjectGetString(data, "netdev"))) {
1365         VIR_WARN("missing netdev in GID_STATUS_CHANGED event");
1366         return;
1367     }
1368
1369     if (virJSONValueObjectGetBoolean(data, "gid-status", &gid_status)) {
1370         VIR_WARN("missing gid-status in GID_STATUS_CHANGED event");
1371         return;
1372     }
1373
1374     if (virJSONValueObjectGetNumberUlong(data, "subnet-prefix",
1375                                          &subnet_prefix)) {
1376         VIR_WARN("missing subnet-prefix in GID_STATUS_CHANGED event");
1377         return;
1378     }
1379
1380     if (virJSONValueObjectGetNumberUlong(data, "interface-id",
1381                                          &interface_id)) {
1382         VIR_WARN("missing interface-id in GID_STATUS_CHANGED event");
1383         return;
1384     }
1385
1386     qemuMonitorEmitRdmaGidStatusChanged(mon, netdev, gid_status, subnet_prefix,
1387                                         interface_id);
1388 }
1389
1390
1391 int
1392 qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
1393                                   const char *cmd_str,
1394                                   int scm_fd,
1395                                   char **reply_str)
1396 {
1397     virJSONValuePtr cmd = NULL;
1398     virJSONValuePtr reply = NULL;
1399     virJSONValuePtr obj;
1400     int ret = -1;
1401
1402     cmd = qemuMonitorJSONMakeCommand("human-monitor-command",
1403                                      "s:command-line", cmd_str,
1404                                      NULL);
1405
1406     if (!cmd || qemuMonitorJSONCommandWithFd(mon, cmd, scm_fd, &reply) < 0)
1407         goto cleanup;
1408
1409     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
1410         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1411                        _("Human monitor command is not available to run %s"),
1412                        cmd_str);
1413         goto cleanup;
1414     }
1415
1416     if (qemuMonitorJSONCheckError(cmd, reply))
1417         goto cleanup;
1418
1419     obj = virJSONValueObjectGet(reply, "return");
1420
1421     if (reply_str) {
1422         const char *data;
1423
1424         data = virJSONValueGetString(obj);
1425         if (VIR_STRDUP(*reply_str, NULLSTR_EMPTY(data)) < 0)
1426             goto cleanup;
1427     }
1428
1429     ret = 0;
1430
1431  cleanup:
1432     virJSONValueFree(cmd);
1433     virJSONValueFree(reply);
1434     return ret;
1435 }
1436
1437
1438 int
1439 qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon)
1440 {
1441     int ret = -1;
1442     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("qmp_capabilities", NULL);
1443     virJSONValuePtr reply = NULL;
1444     if (!cmd)
1445         return -1;
1446
1447     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1448         goto cleanup;
1449
1450     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1451         goto cleanup;
1452
1453     ret = 0;
1454  cleanup:
1455     virJSONValueFree(cmd);
1456     virJSONValueFree(reply);
1457     return ret;
1458 }
1459
1460
1461 int
1462 qemuMonitorJSONStartCPUs(qemuMonitorPtr mon)
1463 {
1464     int ret;
1465     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("cont", NULL);
1466     virJSONValuePtr reply = NULL;
1467     size_t i = 0;
1468     int timeout = 3;
1469     if (!cmd)
1470         return -1;
1471
1472     do {
1473         ret = qemuMonitorJSONCommand(mon, cmd, &reply);
1474
1475         if (ret != 0)
1476             break;
1477
1478         /* If no error, we're done */
1479         if ((ret = qemuMonitorJSONCheckError(cmd, reply)) == 0)
1480             break;
1481
1482         /* If error class is not MigrationExpected, we're done.
1483          * Otherwise try 'cont' cmd again */
1484         if (!qemuMonitorJSONHasError(reply, "MigrationExpected"))
1485             break;
1486
1487         virJSONValueFree(reply);
1488         reply = NULL;
1489         usleep(250000);
1490     } while (++i <= timeout);
1491
1492     virJSONValueFree(cmd);
1493     virJSONValueFree(reply);
1494     return ret;
1495 }
1496
1497
1498 int
1499 qemuMonitorJSONStopCPUs(qemuMonitorPtr mon)
1500 {
1501     int ret = -1;
1502     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("stop", NULL);
1503     virJSONValuePtr reply = NULL;
1504     if (!cmd)
1505         return -1;
1506
1507     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1508         goto cleanup;
1509
1510     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1511         goto cleanup;
1512
1513     ret = 0;
1514  cleanup:
1515     virJSONValueFree(cmd);
1516     virJSONValueFree(reply);
1517     return ret;
1518 }
1519
1520
1521 int
1522 qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
1523                          bool *running,
1524                          virDomainPausedReason *reason)
1525 {
1526     int ret = -1;
1527     const char *status;
1528     virJSONValuePtr cmd;
1529     virJSONValuePtr reply = NULL;
1530     virJSONValuePtr data;
1531
1532     if (reason)
1533         *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
1534
1535     if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL)))
1536         return -1;
1537
1538     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1539         goto cleanup;
1540
1541     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
1542         goto cleanup;
1543
1544     data = virJSONValueObjectGetObject(reply, "return");
1545
1546     if (virJSONValueObjectGetBoolean(data, "running", running) < 0) {
1547         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1548                        _("query-status reply was missing running state"));
1549         goto cleanup;
1550     }
1551
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");
1557     }
1558
1559     ret = 0;
1560
1561  cleanup:
1562     virJSONValueFree(cmd);
1563     virJSONValueFree(reply);
1564     return ret;
1565 }
1566
1567
1568 int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon)
1569 {
1570     int ret = -1;
1571     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("system_powerdown", NULL);
1572     virJSONValuePtr reply = NULL;
1573     if (!cmd)
1574         return -1;
1575
1576     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1577         goto cleanup;
1578
1579     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1580         goto cleanup;
1581
1582     ret = 0;
1583  cleanup:
1584     virJSONValueFree(cmd);
1585     virJSONValueFree(reply);
1586     return ret;
1587 }
1588
1589 int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
1590                            const char *name,
1591                            virDomainNetInterfaceLinkState state)
1592 {
1593     int ret = -1;
1594     virJSONValuePtr reply = NULL;
1595     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("set_link",
1596                                                      "s:name", name,
1597                                                      "b:up", state != VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN,
1598                                                      NULL);
1599
1600     if (!cmd)
1601         return -1;
1602
1603     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1604         goto cleanup;
1605
1606     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1607         goto cleanup;
1608
1609     ret = 0;
1610  cleanup:
1611     virJSONValueFree(cmd);
1612     virJSONValueFree(reply);
1613     return ret;
1614 }
1615
1616 int qemuMonitorJSONSystemReset(qemuMonitorPtr mon)
1617 {
1618     int ret = -1;
1619     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("system_reset", NULL);
1620     virJSONValuePtr reply = NULL;
1621     if (!cmd)
1622         return -1;
1623
1624     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1625         goto cleanup;
1626
1627     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
1628         goto cleanup;
1629
1630     ret = 0;
1631  cleanup:
1632     virJSONValueFree(cmd);
1633     virJSONValueFree(reply);
1634     return ret;
1635 }
1636
1637
1638 /**
1639  * qemuMonitorJSONExtractCPUS390Info:
1640  * @jsoncpu: pointer to a single JSON cpu entry
1641  * @cpu: pointer to a single cpu entry
1642  *
1643  * Derive the legacy cpu info 'halted' information
1644  * from the more accurate s390 cpu state. @cpu is
1645  * modified only on success.
1646  *
1647  * Note: the 'uninitialized' s390 cpu state can't be
1648  *       mapped to halted yes/no.
1649  *
1650  * A s390 cpu entry could look like this
1651  *  { "arch": "s390",
1652  *    "cpu-index": 0,
1653  *    "qom-path": "/machine/unattached/device[0]",
1654  *    "thread_id": 3081,
1655  *    "cpu-state": "operating" }
1656  *
1657  */
1658 static void
1659 qemuMonitorJSONExtractCPUS390Info(virJSONValuePtr jsoncpu,
1660                                   struct qemuMonitorQueryCpusEntry *cpu)
1661 {
1662     const char *cpu_state = virJSONValueObjectGetString(jsoncpu, "cpu-state");
1663
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"))
1669         cpu->halted = true;
1670 }
1671
1672
1673 /**
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
1679  *
1680  * The JSON response @data will have the following format
1681  * in case @fast == false
1682  * [{ "arch": "x86",
1683  *    "current": true,
1684  *    "CPU": 0,
1685  *    "qom_path": "/machine/unattached/device[0]",
1686  *    "pc": -2130415978,
1687  *    "halted": true,
1688  *    "thread_id": 2631237,
1689  *    ...},
1690  *    {...}
1691  *  ]
1692  * and for @fast == true
1693  * [{ "arch": "x86",
1694  *    "cpu-index": 0,
1695  *    "props": {
1696  *       "core-id": 0,
1697  *       "thread-id": 0,
1698  *       "socket-id": 0
1699  *    },
1700  *    "qom-path": "/machine/unattached/device[0]",
1701  *    "thread-id": 2631237,
1702  *    ...},
1703  *    {...}
1704  *  ]
1705  * or for s390
1706  * [{ "arch": "s390",
1707  *    "cpu-index": 0,
1708  *    "props": {
1709  *       "core-id": 0
1710  *    },
1711  *    "qom-path": "/machine/unattached/device[0]",
1712  *    "thread-id": 1237,
1713  *    "cpu-state": "operating",
1714  *    ...},
1715  *    {...}
1716  *  ]
1717  *
1718  *  Note that since QEMU 2.13.0 the "arch" output member of the
1719  *  "query-cpus-fast" command is replaced by "target".
1720  */
1721 static int
1722 qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
1723                               struct qemuMonitorQueryCpusEntry **entries,
1724                               size_t *nentries,
1725                               bool fast)
1726 {
1727     const char *arch = NULL;
1728     struct qemuMonitorQueryCpusEntry *cpus = NULL;
1729     int ret = -1;
1730     size_t i;
1731     size_t ncpus;
1732
1733     if ((ncpus = virJSONValueArraySize(data)) == 0)
1734         return -2;
1735
1736     if (VIR_ALLOC_N(cpus, ncpus) < 0)
1737         goto cleanup;
1738
1739     for (i = 0; i < ncpus; i++) {
1740         virJSONValuePtr entry = virJSONValueArrayGet(data, i);
1741         int cpuid = -1;
1742         int thread = 0;
1743         bool halted = false;
1744         const char *qom_path;
1745         if (!entry) {
1746             ret = -2;
1747             goto cleanup;
1748         }
1749
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
1753          */
1754         if (fast) {
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");
1760         } else {
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");
1766         }
1767
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)
1772             goto cleanup;
1773
1774         /* process optional architecture-specific data */
1775         if (STREQ_NULLABLE(arch, "s390") || STREQ_NULLABLE(arch, "s390x"))
1776             qemuMonitorJSONExtractCPUS390Info(entry, cpus + i);
1777     }
1778
1779     VIR_STEAL_PTR(*entries, cpus);
1780     *nentries = ncpus;
1781     ret = 0;
1782
1783  cleanup:
1784     qemuMonitorQueryCpusFree(cpus, ncpus);
1785     return ret;
1786 }
1787
1788
1789 /**
1790  * qemuMonitorJSONQueryCPUs:
1791  *
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
1797  *
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.
1801  *
1802  * Returns 0 on success, -1 on a fatal error (oom ...) and -2 if the
1803  * query failed gracefully.
1804  */
1805 int
1806 qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon,
1807                          struct qemuMonitorQueryCpusEntry **entries,
1808                          size_t *nentries,
1809                          bool force,
1810                          bool fast)
1811 {
1812     int ret = -1;
1813     virJSONValuePtr cmd;
1814     virJSONValuePtr reply = NULL;
1815     virJSONValuePtr data;
1816
1817     if (fast)
1818         cmd = qemuMonitorJSONMakeCommand("query-cpus-fast", NULL);
1819     else
1820         cmd = qemuMonitorJSONMakeCommand("query-cpus", NULL);
1821
1822     if (!cmd)
1823         return -1;
1824
1825     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1826         goto cleanup;
1827
1828     if (force && qemuMonitorJSONCheckError(cmd, reply) < 0)
1829         goto cleanup;
1830
1831     if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
1832         ret = -2;
1833         goto cleanup;
1834     }
1835
1836     ret = qemuMonitorJSONExtractCPUInfo(data, entries, nentries, fast);
1837
1838  cleanup:
1839     virJSONValueFree(cmd);
1840     virJSONValueFree(reply);
1841     return ret;
1842 }
1843
1844
1845 int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
1846                                virDomainVirtType *virtType)
1847 {
1848     int ret = -1;
1849     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-kvm",
1850                                                      NULL);
1851     virJSONValuePtr reply = NULL;
1852     virJSONValuePtr data;
1853     bool val = false;
1854
1855     *virtType = VIR_DOMAIN_VIRT_QEMU;
1856
1857     if (!cmd)
1858         return -1;
1859
1860     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
1861         goto cleanup;
1862
1863     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
1864         goto cleanup;
1865
1866     data = virJSONValueObjectGetObject(reply, "return");
1867
1868     if (virJSONValueObjectGetBoolean(data, "enabled", &val) < 0) {
1869         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1870                        _("info kvm reply missing 'enabled' field"));
1871         goto cleanup;
1872     }
1873
1874     if (val)
1875         *virtType = VIR_DOMAIN_VIRT_KVM;
1876
1877     ret = 0;
1878  cleanup:
1879     virJSONValueFree(cmd);
1880     virJSONValueFree(reply);
1881     return ret;
1882 }
1883
1884
1885 /**
1886  * Loads correct video memory size values from QEMU and update the video
1887  * definition.
1888  *
1889  * Return 0 on success, -1 on failure and set proper error message.
1890  */
1891 int
1892 qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
1893                                      virDomainVideoDefPtr video,
1894                                      char *path)
1895 {
1896     qemuMonitorJSONObjectProperty prop = {
1897         QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
1898         {0}
1899     };
1900
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'"),
1906                            path);
1907             return -1;
1908         }
1909         video->vram = prop.val.ul * 1024;
1910         break;
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'"),
1915                            path);
1916             return -1;
1917         }
1918         video->vram = prop.val.ul / 1024;
1919
1920         if (qemuMonitorJSONGetObjectProperty(mon, path, "ram_size", &prop) < 0) {
1921             virReportError(VIR_ERR_INTERNAL_ERROR,
1922                            _("QOM Object '%s' has no property 'ram_size'"),
1923                            path);
1924             return -1;
1925         }
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'"),
1930                            path);
1931             return -1;
1932         }
1933         video->vgamem = prop.val.ul * 1024;
1934         break;
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'"),
1939                            path);
1940             return -1;
1941         }
1942         video->vram = prop.val.ul * 1024;
1943         break;
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:
1948         break;
1949     }
1950
1951     return 0;
1952 }
1953
1954
1955 /**
1956  * Loads correct video vram64 size value from QEMU and update the video
1957  * definition.
1958  *
1959  * Return 0 on success, -1 on failure and set proper error message.
1960  */
1961 int
1962 qemuMonitorJSONUpdateVideoVram64Size(qemuMonitorPtr mon,
1963                                      virDomainVideoDefPtr video,
1964                                      char *path)
1965 {
1966     qemuMonitorJSONObjectProperty prop = {
1967         QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
1968         {0}
1969     };
1970
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'"),
1978                                path);
1979                 return -1;
1980             }
1981             video->vram64 = prop.val.ul * 1024;
1982         }
1983         break;
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:
1990         break;
1991     }
1992
1993     return 0;
1994 }
1995
1996
1997 int
1998 qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
1999                               unsigned long long *currmem)
2000 {
2001     int ret = -1;
2002     virJSONValuePtr data;
2003     unsigned long long mem;
2004     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-balloon",
2005                                                      NULL);
2006     virJSONValuePtr reply = NULL;
2007
2008     *currmem = 0;
2009
2010     if (!cmd)
2011         return -1;
2012
2013     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2014         goto cleanup;
2015
2016     /* See if balloon soft-failed */
2017     if (qemuMonitorJSONHasError(reply, "DeviceNotActive") ||
2018         qemuMonitorJSONHasError(reply, "KVMMissingCap")) {
2019         ret = 0;
2020         goto cleanup;
2021     }
2022
2023     /* See if any other fatal error occurred */
2024     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
2025         goto cleanup;
2026
2027     data = virJSONValueObjectGetObject(reply, "return");
2028
2029     if (virJSONValueObjectGetNumberUlong(data, "actual", &mem) < 0) {
2030         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2031                        _("info balloon reply was missing balloon data"));
2032         goto cleanup;
2033     }
2034
2035     *currmem = (mem/1024);
2036     ret = 1;
2037  cleanup:
2038     virJSONValueFree(cmd);
2039     virJSONValueFree(reply);
2040     return ret;
2041 }
2042
2043
2044 /* Process the balloon driver statistics.  The request and data returned
2045  * will be as follows (although the 'child[#]' entry will differ based on
2046  * where it's run).
2047  *
2048  * { "execute": "qom-get","arguments": \
2049  *    { "path": "/machine/i440fx/pci.0/child[7]","property": "guest-stats"} }
2050  *
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}}
2059  *
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.
2064  */
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); \
2070         } else { \
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; \
2075                 got++; \
2076             } \
2077         } \
2078     }
2079
2080
2081 int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
2082                                   char *balloonpath,
2083                                   virDomainMemoryStatPtr stats,
2084                                   unsigned int nr_stats)
2085 {
2086     int ret = -1;
2087     virJSONValuePtr cmd = NULL;
2088     virJSONValuePtr reply = NULL;
2089     virJSONValuePtr data;
2090     virJSONValuePtr statsdata;
2091     unsigned long long mem;
2092     int got = 0;
2093
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;
2098         got++;
2099     }
2100
2101     if (!balloonpath)
2102         goto cleanup;
2103
2104     if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
2105                                            "s:path", balloonpath,
2106                                            "s:property", "guest-stats",
2107                                            NULL)))
2108         goto cleanup;
2109
2110     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2111         goto cleanup;
2112
2113     if ((data = virJSONValueObjectGetObject(reply, "error"))) {
2114         const char *klass = virJSONValueObjectGetString(data, "class");
2115         const char *desc = virJSONValueObjectGetString(data, "desc");
2116
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"));
2121             goto cleanup;
2122         }
2123     }
2124
2125     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
2126         goto cleanup;
2127
2128     data = virJSONValueObjectGetObject(reply, "return");
2129
2130     if (!(statsdata = virJSONValueObjectGet(data, "stats"))) {
2131         VIR_DEBUG("data does not include 'stats'");
2132         goto cleanup;
2133     }
2134
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);
2157
2158     ret = got;
2159  cleanup:
2160     virJSONValueFree(cmd);
2161     virJSONValueFree(reply);
2162     return ret;
2163 }
2164 #undef GET_BALLOON_STATS
2165
2166
2167 /*
2168  * Using the provided balloonpath, determine if we need to set the
2169  * collection interval property to enable statistics gathering.
2170  */
2171 int
2172 qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitorPtr mon,
2173                                     char *balloonpath,
2174                                     int period)
2175 {
2176     qemuMonitorJSONObjectProperty prop;
2177
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",
2184                                          &prop) < 0) {
2185         return -1;
2186     }
2187     return 0;
2188 }
2189
2190
2191 /* qemuMonitorJSONQueryBlock:
2192  * @mon: Monitor pointer
2193  *
2194  * This helper will attempt to make a "query-block" call and check for
2195  * errors before returning with the reply.
2196  *
2197  * Returns: NULL on error, reply on success
2198  */
2199 static virJSONValuePtr
2200 qemuMonitorJSONQueryBlock(qemuMonitorPtr mon)
2201 {
2202     virJSONValuePtr cmd;
2203     virJSONValuePtr reply = NULL;
2204     virJSONValuePtr devices = NULL;
2205
2206     if (!(cmd = qemuMonitorJSONMakeCommand("query-block", NULL)))
2207         return NULL;
2208
2209     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0 ||
2210         qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
2211         goto cleanup;
2212
2213     devices = virJSONValueObjectStealArray(reply, "return");
2214
2215  cleanup:
2216     virJSONValueFree(cmd);
2217     virJSONValueFree(reply);
2218     return devices;
2219 }
2220
2221
2222 static virJSONValuePtr
2223 qemuMonitorJSONGetBlockDev(virJSONValuePtr devices,
2224                            size_t idx)
2225 {
2226     virJSONValuePtr dev = virJSONValueArrayGet(devices, idx);
2227
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"));
2231         return NULL;
2232     }
2233     return dev;
2234 }
2235
2236
2237 static const char *
2238 qemuMonitorJSONGetBlockDevDevice(virJSONValuePtr dev)
2239 {
2240     const char *thisdev;
2241
2242     if (!(thisdev = virJSONValueObjectGetString(dev, "device"))) {
2243         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2244                        _("query-block device entry was not in expected format"));
2245         return NULL;
2246     }
2247
2248     return thisdev;
2249 }
2250
2251
2252 static int
2253 qemuMonitorJSONBlockInfoAdd(virHashTablePtr table,
2254                             struct qemuDomainDiskInfo *info,
2255                             const char *entryname)
2256 {
2257     struct qemuDomainDiskInfo *tmp = NULL;
2258     int ret = -1;
2259
2260     if (VIR_ALLOC(tmp) < 0)
2261         goto cleanup;
2262
2263     *tmp = *info;
2264     tmp->nodename = NULL;
2265
2266     if (info->nodename &&
2267         VIR_STRDUP(tmp->nodename, info->nodename) < 0)
2268         goto cleanup;
2269
2270     if (virHashAddEntry(table, entryname, tmp) < 0)
2271         goto cleanup;
2272
2273     tmp = NULL;
2274     ret = 0;
2275
2276  cleanup:
2277     if (tmp)
2278         VIR_FREE(tmp->nodename);
2279     VIR_FREE(tmp);
2280     return ret;
2281 }
2282
2283
2284 int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
2285                                 virHashTablePtr table)
2286 {
2287     int ret = -1;
2288     size_t i;
2289
2290     virJSONValuePtr devices;
2291
2292     if (!(devices = qemuMonitorJSONQueryBlock(mon)))
2293         return -1;
2294
2295     for (i = 0; i < virJSONValueArraySize(devices); i++) {
2296         virJSONValuePtr dev;
2297         virJSONValuePtr image;
2298         struct qemuDomainDiskInfo info = { false };
2299         const char *thisdev;
2300         const char *status;
2301         const char *qdev;
2302
2303         if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
2304             goto cleanup;
2305
2306         if (!(thisdev = qemuMonitorJSONGetBlockDevDevice(dev)))
2307             goto cleanup;
2308
2309         thisdev = qemuAliasDiskDriveSkipPrefix(thisdev);
2310         qdev = virJSONValueObjectGetString(dev, "qdev");
2311
2312         if (*thisdev == '\0')
2313             thisdev = NULL;
2314
2315         if (!qdev && !thisdev) {
2316             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2317                            _("query-block device entry was not in expected format"));
2318             goto cleanup;
2319         }
2320
2321         if (virJSONValueObjectGetBoolean(dev, "removable", &info.removable) < 0) {
2322             virReportError(VIR_ERR_INTERNAL_ERROR,
2323                            _("cannot read %s value"),
2324                            "removable");
2325             goto cleanup;
2326         }
2327
2328         /* 'tray_open' is present only if the device has a tray */
2329         if (virJSONValueObjectGetBoolean(dev, "tray_open", &info.tray_open) == 0)
2330             info.tray = true;
2331
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");
2335         } else {
2336             info.empty = true;
2337         }
2338
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)
2343                 goto cleanup;
2344         }
2345
2346         if (thisdev &&
2347             qemuMonitorJSONBlockInfoAdd(table, &info, thisdev) < 0)
2348             goto cleanup;
2349
2350         if (qdev && STRNEQ_NULLABLE(thisdev, qdev) &&
2351             qemuMonitorJSONBlockInfoAdd(table, &info, qdev) < 0)
2352             goto cleanup;
2353     }
2354
2355     ret = 0;
2356  cleanup:
2357     virJSONValueFree(devices);
2358     return ret;
2359 }
2360
2361
2362 static qemuBlockStatsPtr
2363 qemuMonitorJSONBlockStatsCollectData(virJSONValuePtr dev,
2364                                      int *nstats)
2365 {
2366     qemuBlockStatsPtr bstats = NULL;
2367     qemuBlockStatsPtr ret = NULL;
2368     virJSONValuePtr parent;
2369     virJSONValuePtr parentstats;
2370     virJSONValuePtr stats;
2371
2372     if ((stats = virJSONValueObjectGetObject(dev, "stats")) == NULL) {
2373         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2374                        _("blockstats stats entry was not "
2375                          "in expected format"));
2376         goto cleanup;
2377     }
2378
2379     if (VIR_ALLOC(bstats) < 0)
2380         goto cleanup;
2381
2382 #define QEMU_MONITOR_BLOCK_STAT_GET(NAME, VAR, MANDATORY) \
2383     if (MANDATORY || virJSONValueObjectHasKey(stats, NAME)) { \
2384         (*nstats)++; \
2385         if (virJSONValueObjectGetNumberLong(stats, NAME, &VAR) < 0) { \
2386             virReportError(VIR_ERR_INTERNAL_ERROR, \
2387                            _("cannot read %s statistic"), NAME); \
2388             goto cleanup; \
2389         } \
2390     }
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
2400
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;
2406     }
2407
2408     VIR_STEAL_PTR(ret, bstats);
2409
2410  cleanup:
2411     VIR_FREE(bstats);
2412     return ret;
2413 }
2414
2415
2416 static int
2417 qemuMonitorJSONAddOneBlockStatsInfo(qemuBlockStatsPtr bstats,
2418                                     const char *name,
2419                                     virHashTablePtr stats)
2420 {
2421     qemuBlockStatsPtr copy = NULL;
2422
2423     if (VIR_ALLOC(copy) < 0)
2424         return -1;
2425
2426     if (bstats)
2427         *copy = *bstats;
2428
2429     if (virHashAddEntry(stats, name, copy) < 0) {
2430         VIR_FREE(copy);
2431         return -1;
2432     }
2433
2434     return 0;
2435 }
2436
2437
2438 static int
2439 qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
2440                                     const char *dev_name,
2441                                     int depth,
2442                                     virHashTablePtr hash,
2443                                     bool backingChain)
2444 {
2445     qemuBlockStatsPtr bstats = NULL;
2446     int ret = -1;
2447     int nstats = 0;
2448     const char *qdevname = NULL;
2449     const char *nodename = NULL;
2450     char *devicename = NULL;
2451     virJSONValuePtr backing;
2452
2453     if (dev_name &&
2454         !(devicename = qemuDomainStorageAlias(dev_name, depth)))
2455         goto cleanup;
2456
2457     qdevname = virJSONValueObjectGetString(dev, "qdev");
2458     nodename = virJSONValueObjectGetString(dev, "node-name");
2459
2460     if (!devicename && !qdevname && !nodename) {
2461         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2462                        _("blockstats device entry was not in expected format"));
2463         goto cleanup;
2464     }
2465
2466     if (!(bstats = qemuMonitorJSONBlockStatsCollectData(dev, &nstats)))
2467         goto cleanup;
2468
2469     if (devicename &&
2470         qemuMonitorJSONAddOneBlockStatsInfo(bstats, devicename, hash) < 0)
2471         goto cleanup;
2472
2473     if (qdevname && STRNEQ_NULLABLE(qdevname, devicename) &&
2474         qemuMonitorJSONAddOneBlockStatsInfo(bstats, qdevname, hash) < 0)
2475         goto cleanup;
2476
2477     if (nodename &&
2478         qemuMonitorJSONAddOneBlockStatsInfo(bstats, nodename, hash) < 0)
2479         goto cleanup;
2480
2481     if (backingChain &&
2482         (backing = virJSONValueObjectGetObject(dev, "backing")) &&
2483         qemuMonitorJSONGetOneBlockStatsInfo(backing, dev_name, depth + 1,
2484                                             hash, true) < 0)
2485         goto cleanup;
2486
2487     ret = nstats;
2488  cleanup:
2489     VIR_FREE(bstats);
2490     VIR_FREE(devicename);
2491     return ret;
2492 }
2493
2494
2495 virJSONValuePtr
2496 qemuMonitorJSONQueryBlockstats(qemuMonitorPtr mon)
2497 {
2498     virJSONValuePtr cmd;
2499     virJSONValuePtr reply = NULL;
2500     virJSONValuePtr ret = NULL;
2501
2502     if (!(cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL)))
2503         return NULL;
2504
2505     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2506         goto cleanup;
2507
2508     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
2509         goto cleanup;
2510
2511     ret = virJSONValueObjectStealArray(reply, "return");
2512
2513  cleanup:
2514     virJSONValueFree(cmd);
2515     virJSONValueFree(reply);
2516     return ret;
2517 }
2518
2519
2520 int
2521 qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
2522                                     virHashTablePtr hash,
2523                                     bool backingChain)
2524 {
2525     int ret = -1;
2526     int nstats = 0;
2527     int rc;
2528     size_t i;
2529     virJSONValuePtr devices;
2530
2531     if (!(devices = qemuMonitorJSONQueryBlockstats(mon)))
2532         return -1;
2533
2534     for (i = 0; i < virJSONValueArraySize(devices); i++) {
2535         virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
2536         const char *dev_name;
2537
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"));
2542             goto cleanup;
2543         }
2544
2545         if (!(dev_name = virJSONValueObjectGetString(dev, "device"))) {
2546             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2547                            _("blockstats device entry was not "
2548                              "in expected format"));
2549             goto cleanup;
2550         }
2551
2552         if (*dev_name == '\0')
2553             dev_name = NULL;
2554
2555         rc = qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, 0, hash,
2556                                                  backingChain);
2557
2558         if (rc < 0)
2559             goto cleanup;
2560
2561         if (rc > nstats)
2562             nstats = rc;
2563     }
2564
2565     ret = nstats;
2566
2567  cleanup:
2568     virJSONValueFree(devices);
2569     return ret;
2570 }
2571
2572
2573 static int
2574 qemuMonitorJSONBlockStatsUpdateCapacityData(virJSONValuePtr image,
2575                                             const char *name,
2576                                             virHashTablePtr stats,
2577                                             qemuBlockStatsPtr *entry)
2578 {
2579     qemuBlockStatsPtr bstats;
2580
2581     if (!(bstats = virHashLookup(stats, name))) {
2582         if (VIR_ALLOC(bstats) < 0)
2583             return -1;
2584
2585         if (virHashAddEntry(stats, name, bstats) < 0) {
2586             VIR_FREE(bstats);
2587             return -1;
2588         }
2589     }
2590
2591     if (entry)
2592         *entry = bstats;
2593
2594     /* failures can be ignored after this point */
2595     if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
2596                                          &bstats->capacity) < 0)
2597         return 0;
2598
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;
2603
2604     return 0;
2605 }
2606
2607
2608 static int
2609 qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
2610                                            const char *dev_name,
2611                                            int depth,
2612                                            virHashTablePtr stats,
2613                                            bool backingChain)
2614 {
2615     int ret = -1;
2616     char *entry_name = qemuDomainStorageAlias(dev_name, depth);
2617     virJSONValuePtr backing;
2618
2619     if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, entry_name,
2620                                                     stats, NULL) < 0)
2621         goto cleanup;
2622
2623     if (backingChain &&
2624         (backing = virJSONValueObjectGetObject(image, "backing-image")) &&
2625         qemuMonitorJSONBlockStatsUpdateCapacityOne(backing,
2626                                                    dev_name,
2627                                                    depth + 1,
2628                                                    stats,
2629                                                    true) < 0)
2630         goto cleanup;
2631
2632     ret = 0;
2633  cleanup:
2634     VIR_FREE(entry_name);
2635     return ret;
2636 }
2637
2638
2639 int
2640 qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
2641                                         virHashTablePtr stats,
2642                                         bool backingChain)
2643 {
2644     int ret = -1;
2645     size_t i;
2646     virJSONValuePtr devices;
2647
2648     if (!(devices = qemuMonitorJSONQueryBlock(mon)))
2649         return -1;
2650
2651     for (i = 0; i < virJSONValueArraySize(devices); i++) {
2652         virJSONValuePtr dev;
2653         virJSONValuePtr inserted;
2654         virJSONValuePtr image;
2655         const char *dev_name;
2656
2657         if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
2658             goto cleanup;
2659
2660         if (!(dev_name = qemuMonitorJSONGetBlockDevDevice(dev)))
2661             goto cleanup;
2662
2663         /* drive may be empty */
2664         if (!(inserted = virJSONValueObjectGetObject(dev, "inserted")) ||
2665             !(image = virJSONValueObjectGetObject(inserted, "image")))
2666             continue;
2667
2668         if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, 0,
2669                                                        stats,
2670                                                        backingChain) < 0)
2671             goto cleanup;
2672     }
2673
2674     ret = 0;
2675
2676  cleanup:
2677     virJSONValueFree(devices);
2678     return ret;
2679 }
2680
2681
2682 static int
2683 qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker(size_t pos ATTRIBUTE_UNUSED,
2684                                                       virJSONValuePtr val,
2685                                                       void *opaque)
2686 {
2687     virHashTablePtr stats = opaque;
2688     virJSONValuePtr image;
2689     const char *nodename;
2690     qemuBlockStatsPtr entry;
2691
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"));
2696         return -1;
2697     }
2698
2699     if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, nodename, stats, &entry) < 0)
2700         return -1;
2701
2702     if (entry)
2703         ignore_value(virJSONValueObjectGetNumberUlong(val, "write_threshold",
2704                                                       &entry->write_threshold));
2705
2706     return 1; /* we don't want to steal the value from the JSON array */
2707 }
2708
2709
2710 int
2711 qemuMonitorJSONBlockStatsUpdateCapacityBlockdev(qemuMonitorPtr mon,
2712                                                 virHashTablePtr stats)
2713 {
2714     virJSONValuePtr nodes;
2715     int ret = -1;
2716
2717     if (!(nodes = qemuMonitorJSONQueryNamedBlockNodes(mon)))
2718         return -1;
2719
2720     if (virJSONValueArrayForeachSteal(nodes,
2721                                       qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker,
2722                                       stats) < 0)
2723         goto cleanup;
2724
2725     ret = 0;
2726
2727  cleanup:
2728     virJSONValueFree(nodes);
2729     return ret;
2730 }
2731
2732
2733 int qemuMonitorJSONBlockResize(qemuMonitorPtr mon,
2734                                const char *device,
2735                                const char *nodename,
2736                                unsigned long long size)
2737 {
2738     int ret = -1;
2739     virJSONValuePtr cmd;
2740     virJSONValuePtr reply = NULL;
2741
2742     cmd = qemuMonitorJSONMakeCommand("block_resize",
2743                                      "S:device", device,
2744                                      "S:node-name", nodename,
2745                                      "U:size", size,
2746                                      NULL);
2747     if (!cmd)
2748         return -1;
2749
2750     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2751         goto cleanup;
2752
2753     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2754         goto cleanup;
2755
2756     ret = 0;
2757  cleanup:
2758     virJSONValueFree(cmd);
2759     virJSONValueFree(reply);
2760     return ret;
2761 }
2762
2763
2764 int qemuMonitorJSONSetPassword(qemuMonitorPtr mon,
2765                                const char *protocol,
2766                                const char *password,
2767                                const char *action_if_connected)
2768 {
2769     int ret = -1;
2770     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("set_password",
2771                                                      "s:protocol", protocol,
2772                                                      "s:password", password,
2773                                                      "s:connected", action_if_connected,
2774                                                      NULL);
2775     virJSONValuePtr reply = NULL;
2776     if (!cmd)
2777         return -1;
2778
2779     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2780         goto cleanup;
2781
2782     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2783         goto cleanup;
2784
2785     ret = 0;
2786  cleanup:
2787     virJSONValueFree(cmd);
2788     virJSONValueFree(reply);
2789     return ret;
2790 }
2791
2792 int qemuMonitorJSONExpirePassword(qemuMonitorPtr mon,
2793                                   const char *protocol,
2794                                   const char *expire_time)
2795 {
2796     int ret = -1;
2797     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("expire_password",
2798                                                      "s:protocol", protocol,
2799                                                      "s:time", expire_time,
2800                                                      NULL);
2801     virJSONValuePtr reply = NULL;
2802     if (!cmd)
2803         return -1;
2804
2805     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2806         goto cleanup;
2807
2808     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2809         goto cleanup;
2810
2811     ret = 0;
2812  cleanup:
2813     virJSONValueFree(cmd);
2814     virJSONValueFree(reply);
2815     return ret;
2816 }
2817
2818
2819 int
2820 qemuMonitorJSONSetBalloon(qemuMonitorPtr mon,
2821                           unsigned long long newmem)
2822 {
2823     int ret = -1;
2824     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("balloon",
2825                                                      "U:value", newmem * 1024,
2826                                                      NULL);
2827     virJSONValuePtr reply = NULL;
2828     if (!cmd)
2829         return -1;
2830
2831     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2832         goto cleanup;
2833
2834     /* See if balloon soft-failed */
2835     if (qemuMonitorJSONHasError(reply, "DeviceNotActive") ||
2836         qemuMonitorJSONHasError(reply, "KVMMissingCap")) {
2837         ret = 0;
2838         goto cleanup;
2839     }
2840
2841     /* See if any other fatal error occurred */
2842     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2843         goto cleanup;
2844
2845     /* Real success */
2846     ret = 1;
2847  cleanup:
2848     virJSONValueFree(cmd);
2849     virJSONValueFree(reply);
2850     return ret;
2851 }
2852
2853
2854 int qemuMonitorJSONSetCPU(qemuMonitorPtr mon,
2855                           int cpu, bool online)
2856 {
2857     int ret = -1;
2858     virJSONValuePtr cmd = NULL;
2859     virJSONValuePtr reply = NULL;
2860
2861     if (online) {
2862         cmd = qemuMonitorJSONMakeCommand("cpu-add",
2863                                          "i:id", cpu,
2864                                          NULL);
2865     } else {
2866         /* offlining is not yet implemented in qmp */
2867         goto fallback;
2868     }
2869     if (!cmd)
2870         goto cleanup;
2871
2872     if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
2873         goto cleanup;
2874
2875     if (qemuMonitorJSONHasError(reply, "CommandNotFound"))
2876         goto fallback;
2877     else
2878         ret = qemuMonitorJSONCheckError(cmd, reply);
2879
2880  cleanup:
2881     virJSONValueFree(cmd);
2882     virJSONValueFree(reply);
2883     return ret;
2884
2885  fallback:
2886     VIR_DEBUG("no QMP support for cpu_set, trying HMP");
2887     ret = qemuMonitorTextSetCPU(mon, cpu, online);
2888     goto cleanup;
2889 }
2890
2891
2892 /**
2893  * Run QMP command to eject a media from ejectable device.
2894  *
2895  * Returns:
2896  *      -1 on error
2897  *      0 on success
2898  */
2899 int qemuMonitorJSONEjectMedia(qemuMonitorPtr mon,
2900                               const char *dev_name,
2901                               bool force)
2902 {
2903     int ret = -1;
2904     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("eject",
2905                                                      "s:device", dev_name,
2906                                                      "b:force", force ? 1 : 0,
2907                                                      NULL);
2908     virJSONValuePtr reply = NULL;
2909     if (!cmd)
2910         return -1;
2911
2912     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2913         goto cleanup;
2914
2915     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2916         goto cleanup;
2917
2918     ret = 0;
2919  cleanup:
2920     virJSONValueFree(cmd);
2921     virJSONValueFree(reply);
2922     return ret;
2923 }
2924
2925
2926 int qemuMonitorJSONChangeMedia(qemuMonitorPtr mon,
2927                                const char *dev_name,
2928                                const char *newmedia,
2929                                const char *format)
2930 {
2931     int ret = -1;
2932     virJSONValuePtr cmd;
2933     virJSONValuePtr reply = NULL;
2934
2935     cmd = qemuMonitorJSONMakeCommand("change",
2936                                      "s:device", dev_name,
2937                                      "s:target", newmedia,
2938                                      "S:arg", format,
2939                                      NULL);
2940
2941     if (!cmd)
2942         return -1;
2943
2944     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2945         goto cleanup;
2946
2947     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2948         goto cleanup;
2949
2950     ret = 0;
2951  cleanup:
2952     virJSONValueFree(cmd);
2953     virJSONValueFree(reply);
2954     return ret;
2955 }
2956
2957
2958 static int qemuMonitorJSONSaveMemory(qemuMonitorPtr mon,
2959                                      const char *cmdtype,
2960                                      unsigned long long offset,
2961                                      size_t length,
2962                                      const char *path)
2963 {
2964     int ret = -1;
2965     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand(cmdtype,
2966                                                      "U:val", offset,
2967                                                      "u:size", length,
2968                                                      "s:filename", path,
2969                                                      NULL);
2970     virJSONValuePtr reply = NULL;
2971     if (!cmd)
2972         return -1;
2973
2974     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
2975         goto cleanup;
2976
2977     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
2978         goto cleanup;
2979
2980     ret = 0;
2981  cleanup:
2982     virJSONValueFree(cmd);
2983     virJSONValueFree(reply);
2984     return ret;
2985 }
2986
2987
2988 int qemuMonitorJSONSaveVirtualMemory(qemuMonitorPtr mon,
2989                                      unsigned long long offset,
2990                                      size_t length,
2991                                      const char *path)
2992 {
2993     return qemuMonitorJSONSaveMemory(mon, "memsave", offset, length, path);
2994 }
2995
2996 int qemuMonitorJSONSavePhysicalMemory(qemuMonitorPtr mon,
2997                                       unsigned long long offset,
2998                                       size_t length,
2999                                       const char *path)
3000 {
3001     return qemuMonitorJSONSaveMemory(mon, "pmemsave", offset, length, path);
3002 }
3003
3004
3005 int qemuMonitorJSONSetMigrationSpeed(qemuMonitorPtr mon,
3006                                      unsigned long bandwidth)
3007 {
3008     int ret = -1;
3009     virJSONValuePtr cmd;
3010     virJSONValuePtr reply = NULL;
3011     cmd = qemuMonitorJSONMakeCommand("migrate_set_speed",
3012                                      "U:value", bandwidth * 1024ULL * 1024ULL,
3013                                      NULL);
3014     if (!cmd)
3015         return -1;
3016
3017     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3018         goto cleanup;
3019
3020     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3021         goto cleanup;
3022
3023     ret = 0;
3024  cleanup:
3025     virJSONValueFree(cmd);
3026     virJSONValueFree(reply);
3027     return ret;
3028 }
3029
3030
3031 int qemuMonitorJSONSetMigrationDowntime(qemuMonitorPtr mon,
3032                                         unsigned long long downtime)
3033 {
3034     int ret = -1;
3035     virJSONValuePtr cmd;
3036     virJSONValuePtr reply = NULL;
3037
3038     cmd = qemuMonitorJSONMakeCommand("migrate_set_downtime",
3039                                      "d:value", downtime / 1000.0,
3040                                      NULL);
3041     if (!cmd)
3042         return -1;
3043
3044     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3045         goto cleanup;
3046
3047     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3048         goto cleanup;
3049
3050     ret = 0;
3051  cleanup:
3052     virJSONValueFree(cmd);
3053     virJSONValueFree(reply);
3054     return ret;
3055 }
3056
3057
3058 int
3059 qemuMonitorJSONGetMigrationCacheSize(qemuMonitorPtr mon,
3060                                      unsigned long long *cacheSize)
3061 {
3062     int ret = -1;
3063     virJSONValuePtr cmd;
3064     virJSONValuePtr reply = NULL;
3065
3066     *cacheSize = 0;
3067
3068     cmd = qemuMonitorJSONMakeCommand("query-migrate-cache-size", NULL);
3069     if (!cmd)
3070         return -1;
3071
3072     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3073         goto cleanup;
3074
3075     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_NUMBER) < 0)
3076         goto cleanup;
3077
3078     if (virJSONValueObjectGetNumberUlong(reply, "return", cacheSize) < 0) {
3079         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3080                        _("invalid cache size in query-migrate-cache-size reply"));
3081         goto cleanup;
3082     }
3083
3084     ret = 0;
3085  cleanup:
3086     virJSONValueFree(cmd);
3087     virJSONValueFree(reply);
3088     return ret;
3089 }
3090
3091
3092 int
3093 qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon,
3094                                      unsigned long long cacheSize)
3095 {
3096     int ret = -1;
3097     virJSONValuePtr cmd;
3098     virJSONValuePtr reply = NULL;
3099
3100     cmd = qemuMonitorJSONMakeCommand("migrate-set-cache-size",
3101                                      "U:value", cacheSize,
3102                                      NULL);
3103     if (!cmd)
3104         return -1;
3105
3106     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3107         goto cleanup;
3108
3109     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3110         goto cleanup;
3111
3112     ret = 0;
3113  cleanup:
3114     virJSONValueFree(cmd);
3115     virJSONValueFree(reply);
3116     return ret;
3117 }
3118
3119
3120 int
3121 qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon,
3122                                   virJSONValuePtr *params)
3123 {
3124     int ret = -1;
3125     virJSONValuePtr cmd = NULL;
3126     virJSONValuePtr reply = NULL;
3127
3128     *params = NULL;
3129
3130     if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate-parameters", NULL)))
3131         return -1;
3132
3133     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3134         goto cleanup;
3135
3136     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
3137         ret = 0;
3138         goto cleanup;
3139     }
3140
3141     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3142         goto cleanup;
3143
3144     *params = virJSONValueObjectStealObject(reply, "return");
3145     ret = 0;
3146
3147  cleanup:
3148     virJSONValueFree(cmd);
3149     virJSONValueFree(reply);
3150     return ret;
3151 }
3152
3153 int
3154 qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon,
3155                                   virJSONValuePtr params)
3156 {
3157     int ret = -1;
3158     virJSONValuePtr cmd = NULL;
3159     virJSONValuePtr reply = NULL;
3160
3161     if (!(cmd = virJSONValueNewObject()))
3162         goto cleanup;
3163
3164     if (virJSONValueObjectAppendString(cmd, "execute",
3165                                        "migrate-set-parameters") < 0)
3166         goto cleanup;
3167
3168     if (virJSONValueObjectAppend(cmd, "arguments", params) < 0)
3169         goto cleanup;
3170     params = NULL;
3171
3172     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3173         goto cleanup;
3174
3175     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3176         goto cleanup;
3177
3178     ret = 0;
3179  cleanup:
3180     virJSONValueFree(cmd);
3181     virJSONValueFree(params);
3182     virJSONValueFree(reply);
3183     return ret;
3184 }
3185
3186
3187 static int
3188 qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
3189                                       qemuMonitorMigrationStatsPtr stats,
3190                                       char **error)
3191 {
3192     virJSONValuePtr ret;
3193     virJSONValuePtr ram;
3194     virJSONValuePtr disk;
3195     virJSONValuePtr comp;
3196     const char *statusstr;
3197     int rc;
3198     double mbps;
3199     const char *tmp;
3200
3201     ret = virJSONValueObjectGetObject(reply, "return");
3202
3203     if (!(statusstr = virJSONValueObjectGetString(ret, "status"))) {
3204         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3205                        _("info migration reply was missing return status"));
3206         return -1;
3207     }
3208
3209     stats->status = qemuMonitorMigrationStatusTypeFromString(statusstr);
3210     if (stats->status < 0) {
3211         virReportError(VIR_ERR_INTERNAL_ERROR,
3212                        _("unexpected migration status in %s"), statusstr);
3213         return -1;
3214     }
3215
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",
3220                                               &stats->downtime);
3221     } else {
3222         rc = virJSONValueObjectGetNumberUlong(ret, "expected-downtime",
3223                                               &stats->downtime);
3224     }
3225     if (rc == 0)
3226         stats->downtime_set = true;
3227
3228     if (virJSONValueObjectGetNumberUlong(ret, "setup-time",
3229                                          &stats->setup_time) == 0)
3230         stats->setup_time_set = true;
3231
3232     ignore_value(virJSONValueObjectGetNumberInt(ret, "cpu-throttle-percentage",
3233                                                 &stats->cpu_throttle_percentage));
3234
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:
3240         break;
3241
3242     case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
3243         if (error) {
3244             tmp = virJSONValueObjectGetString(ret, "error-desc");
3245             if (tmp && VIR_STRDUP(*error, tmp) < 0)
3246                 return -1;
3247         }
3248         break;
3249
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");
3257         if (!ram) {
3258             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3259                            _("migration was active, but no RAM info was set"));
3260             return -1;
3261         }
3262
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"));
3268             return -1;
3269         }
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"));
3275             return -1;
3276         }
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"));
3282             return -1;
3283         }
3284
3285         if (virJSONValueObjectGetNumberDouble(ram, "mbps", &mbps) == 0 &&
3286             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);
3289         }
3290
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));
3306
3307         disk = virJSONValueObjectGetObject(ret, "disk");
3308         if (disk) {
3309             rc = virJSONValueObjectGetNumberUlong(disk, "transferred",
3310                                                   &stats->disk_transferred);
3311             if (rc < 0) {
3312                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3313                                _("disk migration was active, but "
3314                                  "'transferred' data was missing"));
3315                 return -1;
3316             }
3317
3318             rc = virJSONValueObjectGetNumberUlong(disk, "remaining",
3319                                                   &stats->disk_remaining);
3320             if (rc < 0) {
3321                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3322                                _("disk migration was active, but 'remaining' "
3323                                  "data was missing"));
3324                 return -1;
3325             }
3326
3327             rc = virJSONValueObjectGetNumberUlong(disk, "total",
3328                                                   &stats->disk_total);
3329             if (rc < 0) {
3330                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3331                                _("disk migration was active, but 'total' "
3332                                  "data was missing"));
3333                 return -1;
3334             }
3335
3336             if (virJSONValueObjectGetNumberDouble(disk, "mbps", &mbps) == 0 &&
3337                 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);
3340             }
3341         }
3342
3343         comp = virJSONValueObjectGetObject(ret, "xbzrle-cache");
3344         if (comp) {
3345             stats->xbzrle_set = true;
3346             rc = virJSONValueObjectGetNumberUlong(comp, "cache-size",
3347                                                   &stats->xbzrle_cache_size);
3348             if (rc < 0) {
3349                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3350                                _("XBZRLE is active, but 'cache-size' data "
3351                                  "was missing"));
3352                 return -1;
3353             }
3354
3355             rc = virJSONValueObjectGetNumberUlong(comp, "bytes",
3356                                                   &stats->xbzrle_bytes);
3357             if (rc < 0) {
3358                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3359                                _("XBZRLE is active, but 'bytes' data "
3360                                  "was missing"));
3361                 return -1;
3362             }
3363
3364             rc = virJSONValueObjectGetNumberUlong(comp, "pages",
3365                                                   &stats->xbzrle_pages);
3366             if (rc < 0) {
3367                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3368                                _("XBZRLE is active, but 'pages' data "
3369                                  "was missing"));
3370                 return -1;
3371             }
3372
3373             rc = virJSONValueObjectGetNumberUlong(comp, "cache-miss",
3374                                                   &stats->xbzrle_cache_miss);
3375             if (rc < 0) {
3376                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3377                                _("XBZRLE is active, but 'cache-miss' data "
3378                                  "was missing"));
3379                 return -1;
3380             }
3381
3382             rc = virJSONValueObjectGetNumberUlong(comp, "overflow",
3383                                                   &stats->xbzrle_overflow);
3384             if (rc < 0) {
3385                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3386                                _("XBZRLE is active, but 'overflow' data "
3387                                  "was missing"));
3388                 return -1;
3389             }
3390         }
3391         break;
3392     }
3393
3394     return 0;
3395 }
3396
3397
3398 int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
3399                                      qemuMonitorMigrationStatsPtr stats,
3400                                      char **error)
3401 {
3402     int ret = -1;
3403     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
3404                                                      NULL);
3405     virJSONValuePtr reply = NULL;
3406
3407     memset(stats, 0, sizeof(*stats));
3408
3409     if (!cmd)
3410         return -1;
3411
3412     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3413         goto cleanup;
3414
3415     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3416         goto cleanup;
3417
3418     if (qemuMonitorJSONGetMigrationStatsReply(reply, stats, error) < 0)
3419         goto cleanup;
3420
3421     ret = 0;
3422  cleanup:
3423     if (ret < 0)
3424         memset(stats, 0, sizeof(*stats));
3425     virJSONValueFree(cmd);
3426     virJSONValueFree(reply);
3427     return ret;
3428 }
3429
3430
3431 int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
3432                            unsigned int flags,
3433                            const char *uri)
3434 {
3435     int ret = -1;
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,
3441                                  "s:uri", uri,
3442                                  NULL);
3443     virJSONValuePtr reply = NULL;
3444
3445     if (!cmd)
3446         return -1;
3447
3448     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3449         goto cleanup;
3450
3451     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3452         goto cleanup;
3453
3454     ret = 0;
3455  cleanup:
3456     virJSONValueFree(cmd);
3457     virJSONValueFree(reply);
3458     return ret;
3459 }
3460
3461 int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)
3462 {
3463     int ret = -1;
3464     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("migrate_cancel", NULL);
3465     virJSONValuePtr reply = NULL;
3466     if (!cmd)
3467         return -1;
3468
3469     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3470         goto cleanup;
3471
3472     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3473         goto cleanup;
3474
3475     ret = 0;
3476  cleanup:
3477     virJSONValueFree(cmd);
3478     virJSONValueFree(reply);
3479     return ret;
3480 }
3481
3482
3483 /* qemuMonitorJSONQueryDump:
3484  * @mon: Monitor pointer
3485  * @stats: Monitor dump stats
3486  *
3487  * Attempt to make a "query-dump" call, check for errors, and get/return
3488  * the current from the reply
3489  *
3490  * Returns: 0 on success, -1 on failure
3491  */
3492 int
3493 qemuMonitorJSONQueryDump(qemuMonitorPtr mon,
3494                          qemuMonitorDumpStatsPtr stats)
3495 {
3496     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-dump", NULL);
3497     virJSONValuePtr reply = NULL;
3498     virJSONValuePtr result = NULL;
3499     int ret = -1;
3500
3501     if (!cmd)
3502         return -1;
3503
3504     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3505         goto cleanup;
3506
3507     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3508         goto cleanup;
3509
3510     result = virJSONValueObjectGetObject(reply, "return");
3511
3512     ret = qemuMonitorJSONExtractDumpStats(result, stats);
3513
3514  cleanup:
3515     virJSONValueFree(cmd);
3516     virJSONValueFree(reply);
3517     return ret;
3518 }
3519
3520
3521 int
3522 qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitorPtr mon,
3523                                             const char *capability)
3524 {
3525     int ret = -1;
3526     virJSONValuePtr cmd;
3527     virJSONValuePtr reply = NULL;
3528     virJSONValuePtr caps;
3529     virJSONValuePtr formats;
3530     size_t i;
3531
3532     if (!(cmd = qemuMonitorJSONMakeCommand("query-dump-guest-memory-capability",
3533                                            NULL)))
3534         return -1;
3535
3536     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3537         goto cleanup;
3538
3539     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
3540         ret = 0;
3541         goto cleanup;
3542     }
3543
3544     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
3545         goto cleanup;
3546
3547     caps = virJSONValueObjectGetObject(reply, "return");
3548
3549     if (!(formats = virJSONValueObjectGetArray(caps, "formats"))) {
3550         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3551                        _("missing supported dump formats"));
3552         goto cleanup;
3553     }
3554
3555     for (i = 0; i < virJSONValueArraySize(formats); i++) {
3556         virJSONValuePtr dumpformat = virJSONValueArrayGet(formats, i);
3557
3558         if (!dumpformat || virJSONValueGetType(dumpformat) != VIR_JSON_TYPE_STRING) {
3559             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3560                            _("missing entry in supported dump formats"));
3561             goto cleanup;
3562         }
3563
3564         if (STREQ(virJSONValueGetString(dumpformat), capability)) {
3565             ret = 1;
3566             goto cleanup;
3567         }
3568     }
3569
3570     ret = 0;
3571  cleanup:
3572     virJSONValueFree(cmd);
3573     virJSONValueFree(reply);
3574     return ret;
3575 }
3576
3577 int
3578 qemuMonitorJSONDump(qemuMonitorPtr mon,
3579                     const char *protocol,
3580                     const char *dumpformat,
3581                     bool detach)
3582 {
3583     int ret = -1;
3584     virJSONValuePtr cmd = NULL;
3585     virJSONValuePtr reply = NULL;
3586
3587     cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
3588                                      "b:paging", false,
3589                                      "s:protocol", protocol,
3590                                      "S:format", dumpformat,
3591                                      "B:detach", detach,
3592                                      NULL);
3593     if (!cmd)
3594         return -1;
3595
3596     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3597         goto cleanup;
3598
3599     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3600         goto cleanup;
3601
3602     ret = 0;
3603  cleanup:
3604     virJSONValueFree(cmd);
3605     virJSONValueFree(reply);
3606     return ret;
3607 }
3608
3609 int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
3610                                     int type,
3611                                     const char *hostname,
3612                                     int port,
3613                                     int tlsPort,
3614                                     const char *tlsSubject)
3615 {
3616     int ret = -1;
3617     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("client_migrate_info",
3618                                                      "s:protocol",
3619                                                      (type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc"),
3620                                                      "s:hostname", hostname,
3621                                                      "i:port", port,
3622                                                      "i:tls-port", tlsPort,
3623                                                      "S:cert-subject", tlsSubject,
3624                                                      NULL);
3625     virJSONValuePtr reply = NULL;
3626     if (!cmd)
3627         return -1;
3628
3629     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3630         goto cleanup;
3631
3632     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3633         goto cleanup;
3634
3635     ret = 0;
3636  cleanup:
3637     virJSONValueFree(cmd);
3638     virJSONValueFree(reply);
3639     return ret;
3640 }
3641
3642
3643 int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
3644                                   const char *fdname,
3645                                   int fd)
3646 {
3647     int ret = -1;
3648     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("getfd",
3649                                                      "s:fdname", fdname,
3650                                                      NULL);
3651     virJSONValuePtr reply = NULL;
3652     if (!cmd)
3653         return -1;
3654
3655     if (qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply) < 0)
3656         goto cleanup;
3657
3658     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3659         goto cleanup;
3660
3661     ret = 0;
3662  cleanup:
3663     virJSONValueFree(cmd);
3664     virJSONValueFree(reply);
3665     return ret;
3666 }
3667
3668
3669 int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
3670                                    const char *fdname)
3671 {
3672     int ret = -1;
3673     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("closefd",
3674                                                      "s:fdname", fdname,
3675                                                      NULL);
3676     virJSONValuePtr reply = NULL;
3677     if (!cmd)
3678         return -1;
3679
3680     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3681         goto cleanup;
3682
3683     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3684         goto cleanup;
3685
3686     ret = 0;
3687  cleanup:
3688     virJSONValueFree(cmd);
3689     virJSONValueFree(reply);
3690     return ret;
3691 }
3692
3693
3694 int
3695 qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name)
3696 {
3697     int ret;
3698     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("add-fd",
3699                                                      "i:fdset-id", fdset,
3700                                                      "S:opaque", name,
3701                                                      NULL);
3702     virJSONValuePtr reply = NULL;
3703     if (!cmd)
3704         return -1;
3705
3706     ret = qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply);
3707
3708     if (ret == 0) {
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")) {
3713             ret = -2;
3714             goto cleanup;
3715         }
3716         ret = qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT);
3717     }
3718     if (ret == 0) {
3719         virJSONValuePtr data = virJSONValueObjectGetObject(reply, "return");
3720
3721         if (virJSONValueObjectGetNumberInt(data, "fd", &ret) < 0) {
3722             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3723                            _("incomplete return information"));
3724             goto error;
3725         }
3726     }
3727
3728  cleanup:
3729     virJSONValueFree(cmd);
3730     virJSONValueFree(reply);
3731     return ret;
3732
3733  error:
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);
3738     ret = -1;
3739     goto cleanup;
3740 }
3741
3742
3743 int
3744 qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd)
3745 {
3746     int ret = -1;
3747     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("remove-fd",
3748                                                      "i:fdset-id", fdset,
3749                                                      fd < 0 ? NULL : "i:fd",
3750                                                      fd, NULL);
3751     virJSONValuePtr reply = NULL;
3752     if (!cmd)
3753         return -1;
3754
3755     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3756         goto cleanup;
3757
3758     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3759         goto cleanup;
3760
3761     ret = 0;
3762  cleanup:
3763     virJSONValueFree(cmd);
3764     virJSONValueFree(reply);
3765     return ret;
3766 }
3767
3768
3769 int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
3770                              const char *netdevstr)
3771 {
3772     int ret = -1;
3773     virJSONValuePtr cmd = NULL;
3774     virJSONValuePtr reply = NULL;
3775     virJSONValuePtr args = NULL;
3776
3777     cmd = qemuMonitorJSONMakeCommand("netdev_add", NULL);
3778     if (!cmd)
3779         return -1;
3780
3781     args = qemuMonitorJSONKeywordStringToJSON(netdevstr, "type");
3782     if (!args)
3783         goto cleanup;
3784
3785     if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
3786         goto cleanup;
3787     args = NULL; /* obj owns reference to args now */
3788
3789     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3790         goto cleanup;
3791
3792     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3793         goto cleanup;
3794
3795     ret = 0;
3796  cleanup:
3797     virJSONValueFree(args);
3798     virJSONValueFree(cmd);
3799     virJSONValueFree(reply);
3800     return ret;
3801 }
3802
3803
3804 int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
3805                                 const char *alias)
3806 {
3807     int ret = -1;
3808     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("netdev_del",
3809                                                      "s:id", alias,
3810                                                      NULL);
3811     virJSONValuePtr reply = NULL;
3812     if (!cmd)
3813         return -1;
3814
3815     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
3816         goto cleanup;
3817
3818     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
3819         goto cleanup;
3820
3821     ret = 0;
3822  cleanup:
3823     virJSONValueFree(cmd);
3824     virJSONValueFree(reply);
3825     return ret;
3826 }
3827
3828
3829 static int
3830 qemuMonitorJSONQueryRxFilterParse(virJSONValuePtr msg,
3831                                   virNetDevRxFilterPtr *filter)
3832 {
3833     int ret = -1;
3834     const char *tmp;
3835     virJSONValuePtr returnArray, entry, table, element;
3836     size_t nTable;
3837     size_t i;
3838     virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
3839
3840     if (!fil)
3841         goto cleanup;
3842
3843     returnArray = virJSONValueObjectGetArray(msg, "return");
3844
3845     if (!(entry = virJSONValueArrayGet(returnArray, 0))) {
3846         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3847                        _("query -rx-filter return data missing array element"));
3848         goto cleanup;
3849     }
3850
3851     if (!(tmp = virJSONValueObjectGetString(entry, "name"))) {
3852         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3853                        _("Missing or invalid name "
3854                          "in query-rx-filter response"));
3855         goto cleanup;
3856     }
3857     if (VIR_STRDUP(fil->name, tmp) < 0)
3858         goto cleanup;
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"));
3864         goto cleanup;
3865     }
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"));
3871         goto cleanup;
3872     }
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"));
3878         goto cleanup;
3879     }
3880
3881     if ((!(tmp = virJSONValueObjectGetString(entry, "unicast"))) ||
3882         ((fil->unicast.mode
3883           = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
3884         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3885                        _("Missing or invalid 'unicast' "
3886                          "in query-rx-filter response"));
3887         goto cleanup;
3888     }
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"));
3894         goto cleanup;
3895     }
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"));
3901         goto cleanup;
3902     }
3903     nTable = virJSONValueArraySize(table);
3904     if (VIR_ALLOC_N(fil->unicast.table, nTable))
3905         goto cleanup;
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);
3912             goto cleanup;
3913         }
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);
3918             goto cleanup;
3919         }
3920     }
3921     fil->unicast.nTable = nTable;
3922
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"));
3929         goto cleanup;
3930     }
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"));
3936         goto cleanup;
3937     }
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"));
3943         goto cleanup;
3944     }
3945     nTable = virJSONValueArraySize(table);
3946     if (VIR_ALLOC_N(fil->multicast.table, nTable))
3947         goto cleanup;
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);
3954             goto cleanup;
3955         }
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);
3960             goto cleanup;
3961         }
3962     }
3963     fil->multicast.nTable = nTable;
3964
3965     if ((!(tmp = virJSONValueObjectGetString(entry, "vlan"))) ||
3966         ((fil->vlan.mode
3967           = virNetDevRxFilterModeTypeFromString(tmp)) < 0)) {
3968         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3969                        _("Missing or invalid 'vlan' "
3970                          "in query-rx-filter response"));
3971         goto cleanup;
3972     }
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"));
3978         goto cleanup;
3979     }
3980     nTable = virJSONValueArraySize(table);
3981     if (VIR_ALLOC_N(fil->vlan.table, nTable))
3982         goto cleanup;
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);
3989             goto cleanup;
3990         }
3991     }
3992     fil->vlan.nTable = nTable;
3993
3994     ret = 0;
3995  cleanup:
3996     if (ret < 0) {
3997         virNetDevRxFilterFree(fil);
3998         fil = NULL;
3999     }
4000     *filter = fil;
4001     return ret;
4002 }
4003
4004
4005 int
4006 qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
4007                              virNetDevRxFilterPtr *filter)
4008 {
4009     int ret = -1;
4010     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-rx-filter",
4011                                                      "s:name", alias,
4012                                                      NULL);
4013     virJSONValuePtr reply = NULL;
4014
4015     if (!cmd)
4016         goto cleanup;
4017
4018     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4019         goto cleanup;
4020
4021     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
4022         goto cleanup;
4023
4024     if (qemuMonitorJSONQueryRxFilterParse(reply, filter) < 0)
4025         goto cleanup;
4026
4027     ret = 0;
4028  cleanup:
4029     if (ret < 0) {
4030         virNetDevRxFilterFree(*filter);
4031         *filter = NULL;
4032     }
4033     virJSONValueFree(cmd);
4034     virJSONValueFree(reply);
4035     return ret;
4036 }
4037
4038
4039 /*
4040  * Example return data
4041  *
4042  * {"return": [
4043  *      {"filename": "stdio", "label": "monitor"},
4044  *      {"filename": "pty:/dev/pts/6", "label": "serial0", "frontend-open": true},
4045  *      {"filename": "pty:/dev/pts/7", "label": "parallel0"}
4046  * ]}
4047  *
4048  */
4049 static int
4050 qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
4051                                   virHashTablePtr info)
4052 {
4053     virJSONValuePtr data;
4054     int ret = -1;
4055     size_t i;
4056     qemuMonitorChardevInfoPtr entry = NULL;
4057
4058     data = virJSONValueObjectGetArray(reply, "return");
4059
4060     for (i = 0; i < virJSONValueArraySize(data); i++) {
4061         virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
4062         const char *type;
4063         const char *alias;
4064         bool connected;
4065
4066         if (!chardev) {
4067             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4068                            _("character device information was missing array element"));
4069             goto cleanup;
4070         }
4071
4072         if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
4073             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4074                            _("character device information was missing label"));
4075             goto cleanup;
4076         }
4077
4078         if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
4079             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4080                            _("character device information was missing filename"));
4081             goto cleanup;
4082         }
4083
4084         if (VIR_ALLOC(entry) < 0)
4085             goto cleanup;
4086
4087         if (STRPREFIX(type, "pty:") &&
4088             VIR_STRDUP(entry->ptyPath, type + strlen("pty:")) < 0)
4089             goto cleanup;
4090
4091         if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
4092             if (connected)
4093                 entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
4094             else
4095                 entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
4096         }
4097
4098         if (virHashAddEntry(info, alias, entry) < 0) {
4099             virReportError(VIR_ERR_OPERATION_FAILED,
4100                            _("failed to add chardev '%s' info"), alias);
4101             goto cleanup;
4102         }
4103
4104         entry = NULL;
4105     }
4106
4107     ret = 0;
4108
4109  cleanup:
4110     if (entry) {
4111         VIR_FREE(entry->ptyPath);
4112         VIR_FREE(entry);
4113     }
4114
4115     return ret;
4116 }
4117
4118
4119 int
4120 qemuMonitorJSONGetChardevInfo(qemuMonitorPtr mon,
4121                               virHashTablePtr info)
4122
4123 {
4124     int ret = -1;
4125     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-chardev",
4126                                                      NULL);
4127     virJSONValuePtr reply = NULL;
4128
4129     if (!cmd)
4130         return -1;
4131
4132     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4133         goto cleanup;
4134
4135     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
4136         goto cleanup;
4137
4138     ret = qemuMonitorJSONExtractChardevInfo(reply, info);
4139  cleanup:
4140     virJSONValueFree(cmd);
4141     virJSONValueFree(reply);
4142     return ret;
4143 }
4144
4145
4146 int qemuMonitorJSONDelDevice(qemuMonitorPtr mon,
4147                              const char *devalias)
4148 {
4149     int ret = -1;
4150     virJSONValuePtr cmd;
4151     virJSONValuePtr reply = NULL;
4152
4153     cmd = qemuMonitorJSONMakeCommand("device_del",
4154                                      "s:id", devalias,
4155                                      NULL);
4156     if (!cmd)
4157         return -1;
4158
4159     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4160         goto cleanup;
4161
4162     if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
4163         ret = -2;
4164         goto cleanup;
4165     }
4166
4167     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4168         goto cleanup;
4169
4170     ret = 0;
4171  cleanup:
4172     virJSONValueFree(cmd);
4173     virJSONValueFree(reply);
4174     return ret;
4175 }
4176
4177
4178 int
4179 qemuMonitorJSONAddDeviceArgs(qemuMonitorPtr mon,
4180                              virJSONValuePtr args)
4181 {
4182     int ret = -1;
4183     virJSONValuePtr cmd = NULL;
4184     virJSONValuePtr reply = NULL;
4185
4186     if (!(cmd = qemuMonitorJSONMakeCommand("device_add", NULL)))
4187         goto cleanup;
4188
4189     if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
4190         goto cleanup;
4191     args = NULL; /* obj owns reference to args now */
4192
4193     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4194         goto cleanup;
4195
4196     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4197         goto cleanup;
4198
4199     ret = 0;
4200  cleanup:
4201     virJSONValueFree(args);
4202     virJSONValueFree(cmd);
4203     virJSONValueFree(reply);
4204     return ret;
4205 }
4206
4207
4208 int
4209 qemuMonitorJSONAddDevice(qemuMonitorPtr mon,
4210                          const char *devicestr)
4211 {
4212     virJSONValuePtr args;
4213
4214     if (!(args = qemuMonitorJSONKeywordStringToJSON(devicestr, "driver")))
4215         return -1;
4216
4217     return qemuMonitorJSONAddDeviceArgs(mon, args);
4218 }
4219
4220
4221 int
4222 qemuMonitorJSONAddObject(qemuMonitorPtr mon,
4223                          virJSONValuePtr props)
4224 {
4225     int ret = -1;
4226     virJSONValuePtr cmd;
4227     virJSONValuePtr reply = NULL;
4228
4229     if (!(cmd = qemuMonitorJSONMakeCommandInternal("object-add", props)))
4230         goto cleanup;
4231
4232     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4233         goto cleanup;
4234
4235     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4236         goto cleanup;
4237
4238     ret = 0;
4239  cleanup:
4240     virJSONValueFree(cmd);
4241     virJSONValueFree(reply);
4242     return ret;
4243 }
4244
4245
4246 int qemuMonitorJSONDelObject(qemuMonitorPtr mon,
4247                              const char *objalias)
4248 {
4249     int ret = -1;
4250     virJSONValuePtr cmd;
4251     virJSONValuePtr reply = NULL;
4252
4253     cmd = qemuMonitorJSONMakeCommand("object-del",
4254                                      "s:id", objalias,
4255                                      NULL);
4256     if (!cmd)
4257         return -1;
4258
4259     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4260         goto cleanup;
4261
4262     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4263         goto cleanup;
4264
4265     ret = 0;
4266  cleanup:
4267     virJSONValueFree(cmd);
4268     virJSONValueFree(reply);
4269     return ret;
4270 }
4271
4272
4273 /* speed is in bytes/sec */
4274 int
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,
4280                            bool shallow,
4281                            bool reuse)
4282 {
4283     VIR_AUTOPTR(virJSONValue) cmd = NULL;
4284     VIR_AUTOPTR(virJSONValue) reply = NULL;
4285
4286     cmd = qemuMonitorJSONMakeCommand("drive-mirror",
4287                                      "s:device", device,
4288                                      "s:target", file,
4289                                      "Y:speed", speed,
4290                                      "z:granularity", granularity,
4291                                      "P:buf-size", buf_size,
4292                                      "s:sync", shallow ? "top" : "full",
4293                                      "s:mode", reuse ? "existing" : "absolute-paths",
4294                                      "S:format", format,
4295                                      NULL);
4296     if (!cmd)
4297         return -1;
4298
4299     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4300         return -1;
4301
4302     return qemuMonitorJSONCheckError(cmd, reply);
4303 }
4304
4305
4306 int
4307 qemuMonitorJSONBlockdevMirror(qemuMonitorPtr mon,
4308                               const char *jobname,
4309                               const char *device,
4310                               const char *target,
4311                               unsigned long long speed,
4312                               unsigned int granularity,
4313                               unsigned long long buf_size,
4314                               bool shallow)
4315 {
4316     VIR_AUTOPTR(virJSONValue) cmd = NULL;
4317     VIR_AUTOPTR(virJSONValue) reply = NULL;
4318
4319     cmd = qemuMonitorJSONMakeCommand("blockdev-mirror",
4320                                      "S:job-id", jobname,
4321                                      "s:device", device,
4322                                      "s:target", target,
4323                                      "Y:speed", speed,
4324                                      "z:granularity", granularity,
4325                                      "P:buf-size", buf_size,
4326                                      "s:sync", shallow ? "top" : "full",
4327                                      NULL);
4328     if (!cmd)
4329         return -1;
4330
4331     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4332         return -1;
4333
4334     return qemuMonitorJSONCheckError(cmd, reply);
4335 }
4336
4337
4338 int
4339 qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr *actions)
4340 {
4341     int ret = -1;
4342     virJSONValuePtr cmd;
4343     virJSONValuePtr reply = NULL;
4344
4345     cmd = qemuMonitorJSONMakeCommand("transaction",
4346                                      "a:actions", actions,
4347                                      NULL);
4348     if (!cmd)
4349         goto cleanup;
4350
4351     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4352         goto cleanup;
4353
4354     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4355         goto cleanup;
4356
4357     ret = 0;
4358  cleanup:
4359     virJSONValueFree(cmd);
4360     virJSONValueFree(reply);
4361     return ret;
4362 }
4363
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 */
4367 bool
4368 qemuMonitorJSONSupportsActiveCommit(qemuMonitorPtr mon)
4369 {
4370     bool ret = false;
4371     virJSONValuePtr cmd;
4372     virJSONValuePtr reply = NULL;
4373
4374     if (!(cmd = qemuMonitorJSONMakeCommand("block-commit", "s:device",
4375                                            "bogus", NULL)))
4376         return false;
4377
4378     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4379         goto cleanup;
4380
4381     if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
4382         VIR_DEBUG("block-commit supports active commit");
4383         ret = true;
4384         goto cleanup;
4385     }
4386
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");
4391  cleanup:
4392     virJSONValueFree(cmd);
4393     virJSONValueFree(reply);
4394     return ret;
4395 }
4396
4397
4398 /* speed is in bytes/sec. Returns 0 on success, -1 with error message
4399  * emitted on failure. */
4400 int
4401 qemuMonitorJSONBlockCommit(qemuMonitorPtr mon, const char *device,
4402                            const char *top, const char *base,
4403                            const char *backingName,
4404                            unsigned long long speed)
4405 {
4406     int ret = -1;
4407     virJSONValuePtr cmd;
4408     virJSONValuePtr reply = NULL;
4409
4410     cmd = qemuMonitorJSONMakeCommand("block-commit",
4411                                      "s:device", device,
4412                                      "Y:speed", speed,
4413                                      "S:top", top,
4414                                      "S:base", base,
4415                                      "S:backing-file", backingName,
4416                                      NULL);
4417     if (!cmd)
4418         return -1;
4419
4420     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4421         goto cleanup;
4422
4423     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4424         goto cleanup;
4425
4426     ret = 0;
4427  cleanup:
4428     virJSONValueFree(cmd);
4429     virJSONValueFree(reply);
4430     return ret;
4431 }
4432
4433
4434 static char *
4435 qemuMonitorJSONDiskNameLookupOne(virJSONValuePtr image,
4436                                  virStorageSourcePtr top,
4437                                  virStorageSourcePtr target)
4438 {
4439     virJSONValuePtr backing;
4440     char *ret;
4441
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.  */
4445     if (!top || !image)
4446         return NULL;
4447     if (top != target) {
4448         backing = virJSONValueObjectGetObject(image, "backing-image");
4449         return qemuMonitorJSONDiskNameLookupOne(backing, top->backingStore,
4450                                                 target);
4451     }
4452     if (VIR_STRDUP(ret, virJSONValueObjectGetString(image, "filename")) < 0)
4453         return NULL;
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'"),
4461                        ret, target->path);
4462         VIR_FREE(ret);
4463     }
4464     return ret;
4465 }
4466
4467
4468 char *
4469 qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon,
4470                               const char *device,
4471                               virStorageSourcePtr top,
4472                               virStorageSourcePtr target)
4473 {
4474     char *ret = NULL;
4475     virJSONValuePtr devices;
4476     size_t i;
4477
4478     if (!(devices = qemuMonitorJSONQueryBlock(mon)))
4479         return NULL;
4480
4481     for (i = 0; i < virJSONValueArraySize(devices); i++) {
4482         virJSONValuePtr dev;
4483         virJSONValuePtr inserted;
4484         virJSONValuePtr image;
4485         const char *thisdev;
4486
4487         if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
4488             goto cleanup;
4489
4490         if (!(thisdev = qemuMonitorJSONGetBlockDevDevice(dev)))
4491             goto cleanup;
4492
4493         if (STREQ(thisdev, device)) {
4494             if ((inserted = virJSONValueObjectGetObject(dev, "inserted")) &&
4495                 (image = virJSONValueObjectGetObject(inserted, "image"))) {
4496                 ret = qemuMonitorJSONDiskNameLookupOne(image, top, target);
4497             }
4498             break;
4499         }
4500     }
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"),
4506                        device);
4507
4508  cleanup:
4509     virJSONValueFree(devices);
4510
4511     return ret;
4512 }
4513
4514
4515 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
4516                                     const char *cmd_str,
4517                                     char **reply_str,
4518                                     bool hmp)
4519 {
4520     virJSONValuePtr cmd = NULL;
4521     virJSONValuePtr reply = NULL;
4522     int ret = -1;
4523
4524     if (hmp) {
4525         return qemuMonitorJSONHumanCommandWithFd(mon, cmd_str, -1, reply_str);
4526     } else {
4527         if (!(cmd = virJSONValueFromString(cmd_str)))
4528             goto cleanup;
4529
4530         if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4531             goto cleanup;
4532
4533         if (!(*reply_str = virJSONValueToString(reply, false)))
4534             goto cleanup;
4535     }
4536
4537     ret = 0;
4538
4539  cleanup:
4540     virJSONValueFree(cmd);
4541     virJSONValueFree(reply);
4542     return ret;
4543 }
4544
4545 int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon)
4546 {
4547     int ret = -1;
4548     virJSONValuePtr cmd;
4549     virJSONValuePtr reply = NULL;
4550
4551     cmd = qemuMonitorJSONMakeCommand("inject-nmi", NULL);
4552     if (!cmd)
4553         return -1;
4554
4555     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4556         goto cleanup;
4557
4558     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4559         goto cleanup;
4560
4561     ret = 0;
4562  cleanup:
4563     virJSONValueFree(cmd);
4564     virJSONValueFree(reply);
4565     return ret;
4566 }
4567
4568 int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
4569                            unsigned int holdtime,
4570                            unsigned int *keycodes,
4571                            unsigned int nkeycodes)
4572 {
4573     int ret = -1;
4574     virJSONValuePtr cmd = NULL;
4575     virJSONValuePtr reply = NULL;
4576     virJSONValuePtr keys = NULL;
4577     virJSONValuePtr key = NULL;
4578     size_t i;
4579
4580     /* create the key data array */
4581     if (!(keys = virJSONValueNewArray()))
4582         goto cleanup;
4583
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]);
4588             goto cleanup;
4589         }
4590
4591         /* create single key object */
4592         if (!(key = virJSONValueNewObject()))
4593             goto cleanup;
4594
4595         /* Union KeyValue has two types, use the generic one */
4596         if (virJSONValueObjectAppendString(key, "type", "number") < 0)
4597             goto cleanup;
4598
4599         /* with the keycode */
4600         if (virJSONValueObjectAppendNumberInt(key, "data", keycodes[i]) < 0)
4601             goto cleanup;
4602
4603         if (virJSONValueArrayAppend(keys, key) < 0)
4604             goto cleanup;
4605
4606         key = NULL;
4607
4608     }
4609
4610     cmd = qemuMonitorJSONMakeCommand("send-key",
4611                                      "a:keys", &keys,
4612                                      "p:hold-time", holdtime,
4613                                      NULL);
4614     if (!cmd)
4615         goto cleanup;
4616
4617     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4618         goto cleanup;
4619
4620     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4621         goto cleanup;
4622
4623     ret = 0;
4624  cleanup:
4625     virJSONValueFree(cmd);
4626     virJSONValueFree(reply);
4627     virJSONValueFree(keys);
4628     virJSONValueFree(key);
4629     return ret;
4630 }
4631
4632 int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
4633                               const char *device,
4634                               unsigned int head,
4635                               const char *file)
4636 {
4637     int ret = -1;
4638     virJSONValuePtr cmd, reply = NULL;
4639
4640     cmd = qemuMonitorJSONMakeCommand("screendump",
4641                                      "s:filename", file,
4642                                      "S:device", device,
4643                                      "p:head", head,
4644                                      NULL);
4645
4646     if (!cmd)
4647         return -1;
4648
4649     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4650         goto cleanup;
4651
4652     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4653         goto cleanup;
4654
4655     ret = 0;
4656  cleanup:
4657     virJSONValueFree(cmd);
4658     virJSONValueFree(reply);
4659     return ret;
4660 }
4661
4662
4663 static int
4664 qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
4665                                  virJSONValuePtr entry)
4666 {
4667     qemuMonitorBlockJobInfoPtr info = NULL;
4668     const char *device;
4669     const char *type;
4670     bool ready;
4671
4672     if (!(device = virJSONValueObjectGetString(entry, "device"))) {
4673         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4674                        _("entry was missing 'device'"));
4675         return -1;
4676     }
4677     device = qemuAliasDiskDriveSkipPrefix(device);
4678
4679     if (VIR_ALLOC(info) < 0 ||
4680         virHashAddEntry(blockJobs, device, info) < 0) {
4681         VIR_FREE(info);
4682         return -1;
4683     }
4684
4685     /* assume we don't know the state */
4686     info->ready = -1;
4687
4688     if (!(type = virJSONValueObjectGetString(entry, "type"))) {
4689         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4690                        _("entry was missing 'type'"));
4691         return -1;
4692     }
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;
4699     else
4700         info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
4701
4702     if (virJSONValueObjectGetNumberUlong(entry, "speed", &info->bandwidth) < 0) {
4703         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4704                        _("entry was missing 'speed'"));
4705         return -1;
4706     }
4707
4708     if (virJSONValueObjectGetNumberUlong(entry, "offset", &info->cur) < 0) {
4709         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4710                        _("entry was missing 'offset'"));
4711         return -1;
4712     }
4713
4714     if (virJSONValueObjectGetNumberUlong(entry, "len", &info->end) < 0) {
4715         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4716                        _("entry was missing 'len'"));
4717         return -1;
4718     }
4719
4720     if (virJSONValueObjectGetBoolean(entry, "ready", &ready) == 0)
4721         info->ready = ready;
4722
4723     return 0;
4724 }
4725
4726 virHashTablePtr
4727 qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon)
4728 {
4729     virJSONValuePtr cmd = NULL;
4730     virJSONValuePtr reply = NULL;
4731     virJSONValuePtr data;
4732     size_t nr_results;
4733     size_t i;
4734     virHashTablePtr blockJobs = NULL;
4735
4736     cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL);
4737     if (!cmd)
4738         return NULL;
4739     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4740         goto cleanup;
4741
4742     if ((data = virJSONValueObjectGetArray(reply, "return")) == NULL) {
4743         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4744                        _("reply was missing return data"));
4745         goto cleanup;
4746     }
4747
4748     nr_results = virJSONValueArraySize(data);
4749     if (!(blockJobs = virHashCreate(nr_results, virHashValueFree)))
4750         goto cleanup;
4751
4752     for (i = 0; i < nr_results; i++) {
4753         virJSONValuePtr entry = virJSONValueArrayGet(data, i);
4754         if (!entry) {
4755             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4756                            _("missing array element"));
4757             goto error;
4758         }
4759         if (qemuMonitorJSONParseBlockJobInfo(blockJobs, entry) < 0)
4760             goto error;
4761     }
4762
4763  cleanup:
4764     virJSONValueFree(cmd);
4765     virJSONValueFree(reply);
4766     return blockJobs;
4767
4768  error:
4769     virHashFree(blockJobs);
4770     blockJobs = NULL;
4771     goto cleanup;
4772 }
4773
4774
4775 static int
4776 qemuMonitorJSONBlockJobError(virJSONValuePtr cmd,
4777                              virJSONValuePtr reply,
4778                              const char *jobname)
4779 {
4780     virJSONValuePtr error;
4781
4782     if ((error = virJSONValueObjectGet(reply, "error")) &&
4783         (qemuMonitorJSONErrorIsClass(error, "DeviceNotActive"))) {
4784         virReportError(VIR_ERR_OPERATION_INVALID,
4785                        _("No active block job '%s'"), jobname);
4786         return -1;
4787     }
4788
4789     return qemuMonitorJSONCheckError(cmd, reply);
4790 }
4791
4792
4793 /* speed is in bytes/sec */
4794 int
4795 qemuMonitorJSONBlockStream(qemuMonitorPtr mon,
4796                            const char *device,
4797                            const char *base,
4798                            const char *backingName,
4799                            unsigned long long speed)
4800 {
4801     int ret = -1;
4802     virJSONValuePtr cmd = NULL;
4803     virJSONValuePtr reply = NULL;
4804
4805     if (!(cmd = qemuMonitorJSONMakeCommand("block-stream",
4806                                            "s:device", device,
4807                                            "Y:speed", speed,
4808                                            "S:base", base,
4809                                            "S:backing-file", backingName,
4810                                            NULL)))
4811         return -1;
4812
4813     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4814         goto cleanup;
4815
4816     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4817         goto cleanup;
4818
4819     ret = 0;
4820
4821  cleanup:
4822     virJSONValueFree(cmd);
4823     virJSONValueFree(reply);
4824     return ret;
4825 }
4826
4827
4828 int
4829 qemuMonitorJSONBlockJobCancel(qemuMonitorPtr mon,
4830                               const char *jobname)
4831 {
4832     int ret = -1;
4833     virJSONValuePtr cmd = NULL;
4834     virJSONValuePtr reply = NULL;
4835
4836     if (!(cmd = qemuMonitorJSONMakeCommand("block-job-cancel",
4837                                            "s:device", jobname,
4838                                            NULL)))
4839         return -1;
4840
4841     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4842         goto cleanup;
4843
4844     if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4845         goto cleanup;
4846
4847     ret = 0;
4848
4849  cleanup:
4850     virJSONValueFree(cmd);
4851     virJSONValueFree(reply);
4852     return ret;
4853 }
4854
4855
4856 int
4857 qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon,
4858                                 const char *jobname,
4859                                 unsigned long long speed)
4860 {
4861     int ret = -1;
4862     virJSONValuePtr cmd;
4863     virJSONValuePtr reply = NULL;
4864
4865     if (!(cmd = qemuMonitorJSONMakeCommand("block-job-set-speed",
4866                                            "s:device", jobname,
4867                                            "J:speed", speed,
4868                                            NULL)))
4869         return -1;
4870
4871     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4872         goto cleanup;
4873
4874     if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4875         goto cleanup;
4876
4877     ret = 0;
4878
4879  cleanup:
4880     virJSONValueFree(cmd);
4881     virJSONValueFree(reply);
4882     return ret;
4883 }
4884
4885
4886 int
4887 qemuMonitorJSONDrivePivot(qemuMonitorPtr mon,
4888                           const char *jobname)
4889 {
4890     int ret = -1;
4891     virJSONValuePtr cmd;
4892     virJSONValuePtr reply = NULL;
4893
4894     cmd = qemuMonitorJSONMakeCommand("block-job-complete",
4895                                      "s:device", jobname,
4896                                      NULL);
4897     if (!cmd)
4898         return -1;
4899
4900     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4901         goto cleanup;
4902
4903     if (qemuMonitorJSONBlockJobError(cmd, reply, jobname) < 0)
4904         goto cleanup;
4905
4906     ret = 0;
4907  cleanup:
4908     virJSONValueFree(cmd);
4909     virJSONValueFree(reply);
4910     return ret;
4911 }
4912
4913
4914 int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
4915                                 const char *protocol,
4916                                 const char *fdname,
4917                                 bool skipauth)
4918 {
4919     int ret = -1;
4920     virJSONValuePtr cmd, reply = NULL;
4921
4922     cmd = qemuMonitorJSONMakeCommand("add_client",
4923                                      "s:protocol", protocol,
4924                                      "s:fdname", fdname,
4925                                      "b:skipauth", skipauth,
4926                                      NULL);
4927
4928     if (!cmd)
4929         return -1;
4930
4931     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
4932         goto cleanup;
4933
4934     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
4935         goto cleanup;
4936
4937     ret = 0;
4938  cleanup:
4939     virJSONValueFree(cmd);
4940     virJSONValueFree(reply);
4941     return ret;
4942 }
4943
4944
4945 #define GET_THROTTLE_STATS_OPTIONAL(FIELD, STORE) \
4946     if (virJSONValueObjectGetNumberUlong(inserted, \
4947                                          FIELD, \
4948                                          &reply->STORE) < 0) { \
4949         reply->STORE = 0; \
4950     }
4951 #define GET_THROTTLE_STATS(FIELD, STORE) \
4952     if (virJSONValueObjectGetNumberUlong(inserted, \
4953                                          FIELD, \
4954                                          &reply->STORE) < 0) { \
4955         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \
4956                        _("block_io_throttle field '%s' missing " \
4957                          "in qemu's output"), \
4958                        #STORE); \
4959         goto cleanup; \
4960     }
4961 static int
4962 qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr io_throttle,
4963                                    const char *drivealias,
4964                                    const char *qdevid,
4965                                    virDomainBlockIoTuneInfoPtr reply)
4966 {
4967     int ret = -1;
4968     size_t i;
4969     bool found = false;
4970
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;
4976
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"));
4981             goto cleanup;
4982         }
4983
4984         current_qdev = virJSONValueObjectGetString(temp_dev, "qdev");
4985         current_drive = virJSONValueObjectGetString(temp_dev, "device");
4986
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"));
4991             goto cleanup;
4992         }
4993
4994         if ((drivealias && current_drive && STRNEQ(current_drive, drivealias)) ||
4995             (qdevid && current_qdev && STRNEQ(current_qdev, qdevid)))
4996             continue;
4997
4998         found = true;
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"));
5003             goto cleanup;
5004         }
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);
5018
5019         if (VIR_STRDUP(reply->group_name,
5020                        virJSONValueObjectGetString(inserted, "group")) < 0)
5021             goto cleanup;
5022
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);
5029
5030         break;
5031     }
5032
5033     if (!found) {
5034         virReportError(VIR_ERR_INTERNAL_ERROR,
5035                        _("cannot find throttling info for device '%s'"),
5036                        drivealias ? drivealias : qdevid);
5037         goto cleanup;
5038     }
5039     ret = 0;
5040
5041  cleanup:
5042     return ret;
5043 }
5044 #undef GET_THROTTLE_STATS
5045 #undef GET_THROTTLE_STATS_OPTIONAL
5046
5047 int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
5048                                       const char *drivealias,
5049                                       const char *qomid,
5050                                       virDomainBlockIoTuneInfoPtr info,
5051                                       bool supportMaxOptions,
5052                                       bool supportGroupNameOption,
5053                                       bool supportMaxLengthOptions)
5054 {
5055     int ret = -1;
5056     virJSONValuePtr cmd = NULL;
5057     virJSONValuePtr result = NULL;
5058     virJSONValuePtr args = NULL;
5059     const char *errdev = drivealias;
5060
5061     if (!errdev)
5062         errdev = qomid;
5063
5064     if (!(cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle", NULL)))
5065         return -1;
5066
5067     if (virJSONValueObjectCreate(&args,
5068                                  "S:device", drivealias,
5069                                  "S:id", qomid,
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,
5076                                  NULL) < 0)
5077         goto cleanup;
5078
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,
5088                               NULL) < 0)
5089         goto cleanup;
5090
5091     if (supportGroupNameOption &&
5092         virJSONValueObjectAdd(args,
5093                               "S:group", info->group_name,
5094                               NULL) < 0)
5095         goto cleanup;
5096
5097     if (supportMaxLengthOptions &&
5098         virJSONValueObjectAdd(args,
5099                               "P:bps_max_length",
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,
5111                               NULL) < 0)
5112         goto cleanup;
5113
5114     if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
5115         goto cleanup;
5116     args = NULL; /* obj owns reference to args now */
5117
5118     if (qemuMonitorJSONCommand(mon, cmd, &result) < 0)
5119         goto cleanup;
5120
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);
5128         } else {
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));
5134         }
5135         goto cleanup;
5136     }
5137
5138     ret = 0;
5139  cleanup:
5140     virJSONValueFree(cmd);
5141     virJSONValueFree(result);
5142     virJSONValueFree(args);
5143     return ret;
5144 }
5145
5146 int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
5147                                       const char *drivealias,
5148                                       const char *qdevid,
5149                                       virDomainBlockIoTuneInfoPtr reply)
5150 {
5151     int ret = -1;
5152     virJSONValuePtr devices = NULL;
5153
5154     if (!(devices = qemuMonitorJSONQueryBlock(mon)))
5155         return -1;
5156
5157     ret = qemuMonitorJSONBlockIoThrottleInfo(devices, drivealias, qdevid, reply);
5158     virJSONValueFree(devices);
5159     return ret;
5160 }
5161
5162 int qemuMonitorJSONSystemWakeup(qemuMonitorPtr mon)
5163 {
5164     int ret = -1;
5165     virJSONValuePtr cmd = NULL;
5166     virJSONValuePtr reply = NULL;
5167
5168     cmd = qemuMonitorJSONMakeCommand("system_wakeup", NULL);
5169     if (!cmd)
5170         return -1;
5171
5172     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5173         goto cleanup;
5174
5175     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
5176         goto cleanup;
5177
5178     ret = 0;
5179  cleanup:
5180     virJSONValueFree(cmd);
5181     virJSONValueFree(reply);
5182     return ret;
5183 }
5184
5185 int qemuMonitorJSONGetVersion(qemuMonitorPtr mon,
5186                               int *major,
5187                               int *minor,
5188                               int *micro,
5189                               char **package)
5190 {
5191     int ret = -1;
5192     virJSONValuePtr cmd;
5193     virJSONValuePtr reply = NULL;
5194     virJSONValuePtr data;
5195     virJSONValuePtr qemu;
5196
5197     *major = *minor = *micro = 0;
5198     if (package)
5199         *package = NULL;
5200
5201     if (!(cmd = qemuMonitorJSONMakeCommand("query-version", NULL)))
5202         return -1;
5203
5204     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5205         goto cleanup;
5206
5207     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5208         goto cleanup;
5209
5210     data = virJSONValueObjectGetObject(reply, "return");
5211
5212     if (!(qemu = virJSONValueObjectGetObject(data, "qemu"))) {
5213         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5214                        _("query-version reply was missing 'qemu' data"));
5215         goto cleanup;
5216     }
5217
5218     if (virJSONValueObjectGetNumberInt(qemu, "major", major) < 0) {
5219         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5220                        _("query-version reply was missing 'major' version"));
5221         goto cleanup;
5222     }
5223     if (virJSONValueObjectGetNumberInt(qemu, "minor", minor) < 0) {
5224         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5225                        _("query-version reply was missing 'minor' version"));
5226         goto cleanup;
5227     }
5228     if (virJSONValueObjectGetNumberInt(qemu, "micro", micro) < 0) {
5229         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5230                        _("query-version reply was missing 'micro' version"));
5231         goto cleanup;
5232     }
5233
5234     if (package) {
5235         const char *tmp;
5236         if (!(tmp = virJSONValueObjectGetString(data, "package"))) {
5237             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5238                            _("query-version reply was missing 'package' version"));
5239             goto cleanup;
5240         }
5241         if (VIR_STRDUP(*package, tmp) < 0)
5242             goto cleanup;
5243     }
5244
5245     ret = 0;
5246
5247  cleanup:
5248     virJSONValueFree(cmd);
5249     virJSONValueFree(reply);
5250     return ret;
5251 }
5252
5253
5254 int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
5255                                qemuMonitorMachineInfoPtr **machines)
5256 {
5257     int ret = -1;
5258     virJSONValuePtr cmd;
5259     virJSONValuePtr reply = NULL;
5260     virJSONValuePtr data;
5261     qemuMonitorMachineInfoPtr *infolist = NULL;
5262     size_t n = 0;
5263     size_t i;
5264
5265     *machines = NULL;
5266
5267     if (!(cmd = qemuMonitorJSONMakeCommand("query-machines", NULL)))
5268         return -1;
5269
5270     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5271         goto cleanup;
5272
5273     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5274         goto cleanup;
5275
5276     data = virJSONValueObjectGetArray(reply, "return");
5277     n = virJSONValueArraySize(data);
5278
5279     /* null-terminated list */
5280     if (VIR_ALLOC_N(infolist, n + 1) < 0)
5281         goto cleanup;
5282
5283     for (i = 0; i < n; i++) {
5284         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5285         const char *tmp;
5286         qemuMonitorMachineInfoPtr info;
5287
5288         if (VIR_ALLOC(info) < 0)
5289             goto cleanup;
5290
5291         infolist[i] = info;
5292
5293         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5294             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5295                            _("query-machines reply data was missing 'name'"));
5296             goto cleanup;
5297         }
5298
5299         if (VIR_STRDUP(info->name, tmp) < 0)
5300             goto cleanup;
5301
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"));
5306             goto cleanup;
5307         }
5308
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"));
5313                 goto cleanup;
5314             }
5315             if (VIR_STRDUP(info->alias, tmp) < 0)
5316                 goto cleanup;
5317         }
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"));
5322             goto cleanup;
5323         }
5324
5325         ignore_value(virJSONValueObjectGetBoolean(child, "hotpluggable-cpus",
5326                                                   &info->hotplugCpus));
5327     }
5328
5329     ret = n;
5330     *machines = infolist;
5331     infolist = NULL;
5332
5333  cleanup:
5334     if (infolist) {
5335         for (i = 0; i < n; i++)
5336             qemuMonitorMachineInfoFree(infolist[i]);
5337         VIR_FREE(infolist);
5338     }
5339     virJSONValueFree(cmd);
5340     virJSONValueFree(reply);
5341     return ret;
5342 }
5343
5344
5345 int
5346 qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
5347                                  qemuMonitorCPUDefInfoPtr **cpus)
5348 {
5349     int ret = -1;
5350     virJSONValuePtr cmd;
5351     virJSONValuePtr reply = NULL;
5352     virJSONValuePtr data;
5353     qemuMonitorCPUDefInfoPtr *cpulist = NULL;
5354     size_t n = 0;
5355     size_t i;
5356
5357     *cpus = NULL;
5358
5359     if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-definitions", NULL)))
5360         return -1;
5361
5362     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5363         goto cleanup;
5364
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 :-(
5368      */
5369     if (qemuMonitorJSONHasError(reply, "GenericError")) {
5370         ret = 0;
5371         goto cleanup;
5372     }
5373
5374     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5375         goto cleanup;
5376
5377     data = virJSONValueObjectGetArray(reply, "return");
5378     n = virJSONValueArraySize(data);
5379
5380     if (VIR_ALLOC_N(cpulist, n) < 0)
5381         goto cleanup;
5382
5383     for (i = 0; i < n; i++) {
5384         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5385         const char *tmp;
5386         qemuMonitorCPUDefInfoPtr cpu;
5387
5388         if (VIR_ALLOC(cpu) < 0)
5389             goto cleanup;
5390
5391         cpulist[i] = cpu;
5392
5393         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5394             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5395                            _("query-cpu-definitions reply data was missing 'name'"));
5396             goto cleanup;
5397         }
5398
5399         if (VIR_STRDUP(cpu->name, tmp) < 0)
5400             goto cleanup;
5401
5402         if (virJSONValueObjectHasKey(child, "unavailable-features")) {
5403             virJSONValuePtr blockers;
5404             size_t j;
5405             size_t len;
5406
5407             blockers = virJSONValueObjectGetArray(child,
5408                                                   "unavailable-features");
5409             if (!blockers) {
5410                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5411                                _("unavailable-features in query-cpu-definitions "
5412                                  "reply data was not an array"));
5413                 goto cleanup;
5414             }
5415
5416             len = virJSONValueArraySize(blockers);
5417
5418             if (len == 0) {
5419                 cpu->usable = VIR_TRISTATE_BOOL_YES;
5420                 continue;
5421             }
5422
5423             cpu->usable = VIR_TRISTATE_BOOL_NO;
5424             if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0)
5425                 goto cleanup;
5426
5427             for (j = 0; j < len; j++) {
5428                 virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j);
5429
5430                 if (virJSONValueGetType(blocker) != VIR_JSON_TYPE_STRING) {
5431                     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5432                                    _("unexpected value in unavailable-features "
5433                                      "array"));
5434                     goto cleanup;
5435                 }
5436
5437                 if (VIR_STRDUP(cpu->blockers[j], virJSONValueGetString(blocker)) < 0)
5438                     goto cleanup;
5439             }
5440         }
5441     }
5442
5443     ret = n;
5444     *cpus = cpulist;
5445     cpulist = NULL;
5446
5447  cleanup:
5448     if (cpulist) {
5449         for (i = 0; i < n; i++)
5450             qemuMonitorCPUDefInfoFree(cpulist[i]);
5451         VIR_FREE(cpulist);
5452     }
5453     virJSONValueFree(cmd);
5454     virJSONValueFree(reply);
5455     return ret;
5456 }
5457
5458
5459 VIR_ENUM_IMPL(qemuMonitorCPUProperty,
5460               QEMU_MONITOR_CPU_PROPERTY_LAST,
5461               "boolean", "string", "number",
5462 );
5463
5464 static int
5465 qemuMonitorJSONParseCPUModelProperty(const char *key,
5466                                      virJSONValue *value,
5467                                      void *opaque)
5468 {
5469     qemuMonitorCPUModelInfoPtr machine_model = opaque;
5470     qemuMonitorCPUPropertyPtr prop;
5471
5472     prop = machine_model->props + machine_model->nprops;
5473
5474     switch ((virJSONType)virJSONValueGetType(value)) {
5475     case VIR_JSON_TYPE_STRING:
5476         if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0)
5477             return -1;
5478         prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
5479         break;
5480
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)
5484             return 0;
5485         prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER;
5486         break;
5487
5488     case VIR_JSON_TYPE_BOOLEAN:
5489         virJSONValueGetBoolean(value, &prop->value.boolean);
5490         prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
5491         break;
5492
5493     case VIR_JSON_TYPE_OBJECT:
5494     case VIR_JSON_TYPE_ARRAY:
5495     case VIR_JSON_TYPE_NULL:
5496         return 0;
5497     }
5498
5499     machine_model->nprops++;
5500     if (VIR_STRDUP(prop->name, key) < 0)
5501         return -1;
5502
5503     return 0;
5504 }
5505
5506 int
5507 qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
5508                                     qemuMonitorCPUModelExpansionType type,
5509                                     const char *model_name,
5510                                     bool migratable,
5511                                     qemuMonitorCPUModelInfoPtr *model_info)
5512 {
5513     int ret = -1;
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 = "";
5524
5525     *model_info = NULL;
5526
5527     if (!(model = virJSONValueNewObject()))
5528         goto cleanup;
5529
5530     if (virJSONValueObjectAppendString(model, "name", model_name) < 0)
5531         goto cleanup;
5532
5533     if (!migratable) {
5534         if (!(props = virJSONValueNewObject()) ||
5535             virJSONValueObjectAppendBoolean(props, "migratable", false) < 0 ||
5536             virJSONValueObjectAppend(model, "props", props) < 0)
5537             goto cleanup;
5538         props = NULL;
5539     }
5540
5541  retry:
5542     switch (type) {
5543     case QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC:
5544     case QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL:
5545         typeStr = "static";
5546         break;
5547
5548     case QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL:
5549         typeStr = "full";
5550         break;
5551     }
5552
5553     if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-model-expansion",
5554                                            "s:type", typeStr,
5555                                            "a:model", &model,
5556                                            NULL)))
5557         goto cleanup;
5558
5559     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5560         goto cleanup;
5561
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.
5565      */
5566     if (qemuMonitorJSONHasError(reply, "GenericError")) {
5567         ret = 0;
5568         goto cleanup;
5569     }
5570
5571     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5572         goto cleanup;
5573
5574     data = virJSONValueObjectGetObject(reply, "return");
5575
5576     if (!(cpu_model = virJSONValueObjectGetObject(data, "model"))) {
5577         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5578                        _("query-cpu-model-expansion reply data was missing 'model'"));
5579         goto cleanup;
5580     }
5581
5582     /* QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL requests "full" expansion
5583      * on the result of the initial "static" expansion.
5584      */
5585     if (type == QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL) {
5586         if (!(model = virJSONValueCopy(cpu_model)))
5587             goto cleanup;
5588
5589         virJSONValueFree(cmd);
5590         virJSONValueFree(reply);
5591         type = QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL;
5592         goto retry;
5593     }
5594
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'"));
5598         goto cleanup;
5599     }
5600
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'"));
5604         goto cleanup;
5605     }
5606
5607     if (VIR_ALLOC(machine_model) < 0)
5608         goto cleanup;
5609
5610     if (VIR_STRDUP(machine_model->name, cpu_name) < 0)
5611         goto cleanup;
5612
5613     if (VIR_ALLOC_N(machine_model->props, virJSONValueObjectKeysNumber(cpu_props)) < 0)
5614         goto cleanup;
5615
5616     if (virJSONValueObjectForeachKeyValue(cpu_props,
5617                                           qemuMonitorJSONParseCPUModelProperty,
5618                                           machine_model) < 0)
5619         goto cleanup;
5620
5621     ret = 0;
5622     *model_info = machine_model;
5623     machine_model = NULL;
5624
5625  cleanup:
5626     qemuMonitorCPUModelInfoFree(machine_model);
5627     virJSONValueFree(cmd);
5628     virJSONValueFree(reply);
5629     virJSONValueFree(model);
5630     virJSONValueFree(props);
5631     return ret;
5632 }
5633
5634
5635 int qemuMonitorJSONGetCommands(qemuMonitorPtr mon,
5636                                char ***commands)
5637 {
5638     int ret = -1;
5639     virJSONValuePtr cmd;
5640     virJSONValuePtr reply = NULL;
5641     virJSONValuePtr data;
5642     char **commandlist = NULL;
5643     size_t n = 0;
5644     size_t i;
5645
5646     *commands = NULL;
5647
5648     if (!(cmd = qemuMonitorJSONMakeCommand("query-commands", NULL)))
5649         return -1;
5650
5651     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5652         goto cleanup;
5653
5654     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5655         goto cleanup;
5656
5657     data = virJSONValueObjectGetArray(reply, "return");
5658     n = virJSONValueArraySize(data);
5659
5660     /* null-terminated list */
5661     if (VIR_ALLOC_N(commandlist, n + 1) < 0)
5662         goto cleanup;
5663
5664     for (i = 0; i < n; i++) {
5665         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5666         const char *tmp;
5667
5668         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5669             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5670                            _("query-commands reply data was missing 'name'"));
5671             goto cleanup;
5672         }
5673
5674         if (VIR_STRDUP(commandlist[i], tmp) < 0)
5675             goto cleanup;
5676     }
5677
5678     ret = n;
5679     *commands = commandlist;
5680     commandlist = NULL;
5681
5682
5683  cleanup:
5684     virStringListFree(commandlist);
5685     virJSONValueFree(cmd);
5686     virJSONValueFree(reply);
5687     return ret;
5688 }
5689
5690
5691 int qemuMonitorJSONGetEvents(qemuMonitorPtr mon,
5692                              char ***events)
5693 {
5694     int ret = -1;
5695     virJSONValuePtr cmd;
5696     virJSONValuePtr reply = NULL;
5697     virJSONValuePtr data;
5698     char **eventlist = NULL;
5699     size_t n = 0;
5700     size_t i;
5701
5702     *events = NULL;
5703
5704     if (!(cmd = qemuMonitorJSONMakeCommand("query-events", NULL)))
5705         return -1;
5706
5707     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5708         goto cleanup;
5709
5710     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5711         ret = 0;
5712         goto cleanup;
5713     }
5714
5715     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5716         goto cleanup;
5717
5718     data = virJSONValueObjectGetArray(reply, "return");
5719     n = virJSONValueArraySize(data);
5720
5721     /* null-terminated list */
5722     if (VIR_ALLOC_N(eventlist, n + 1) < 0)
5723         goto cleanup;
5724
5725     for (i = 0; i < n; i++) {
5726         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5727         const char *tmp;
5728
5729         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5730             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5731                            _("query-events reply data was missing 'name'"));
5732             goto cleanup;
5733         }
5734
5735         if (VIR_STRDUP(eventlist[i], tmp) < 0)
5736             goto cleanup;
5737     }
5738
5739     ret = n;
5740     *events = eventlist;
5741     eventlist = NULL;
5742
5743  cleanup:
5744     virStringListFree(eventlist);
5745     virJSONValueFree(cmd);
5746     virJSONValueFree(reply);
5747     return ret;
5748 }
5749
5750
5751 int
5752 qemuMonitorJSONGetCommandLineOptionParameters(qemuMonitorPtr mon,
5753                                               const char *option,
5754                                               char ***params,
5755                                               bool *found)
5756 {
5757     int ret = -1;
5758     virJSONValuePtr cmd = NULL;
5759     virJSONValuePtr reply = NULL;
5760     virJSONValuePtr data = NULL;
5761     virJSONValuePtr array = NULL;
5762     char **paramlist = NULL;
5763     size_t n = 0;
5764     size_t i;
5765
5766     *params = NULL;
5767     if (found)
5768         *found = false;
5769
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",
5775                                                NULL)))
5776             return -1;
5777
5778         if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5779             goto cleanup;
5780
5781         if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5782             ret = 0;
5783             goto cleanup;
5784         }
5785
5786         if (qemuMonitorJSONCheckError(cmd, reply) < 0)
5787             goto cleanup;
5788
5789         if (virJSONValueObjectRemoveKey(reply, "return", &array) <= 0) {
5790             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5791                            _("query-command-line-options reply was missing "
5792                              "return data"));
5793             goto cleanup;
5794         }
5795
5796         if (!virJSONValueIsArray(array)) {
5797             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5798                            _("Malformed query-command-line-options array"));
5799             goto cleanup;
5800         }
5801
5802         qemuMonitorSetOptions(mon, array);
5803     }
5804
5805     for (i = 0; i < virJSONValueArraySize(array); i++) {
5806         virJSONValuePtr child = virJSONValueArrayGet(array, i);
5807         const char *tmp;
5808
5809         if (!(tmp = virJSONValueObjectGetString(child, "option"))) {
5810             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5811                            _("query-command-line-options reply data was "
5812                              "missing 'option'"));
5813             goto cleanup;
5814         }
5815         if (STREQ(tmp, option)) {
5816             data = virJSONValueObjectGet(child, "parameters");
5817             break;
5818         }
5819     }
5820
5821     if (!data) {
5822         /* Option not found; return 0 parameters rather than an error.  */
5823         ret = 0;
5824         goto cleanup;
5825     }
5826
5827     if (found)
5828         *found = true;
5829
5830     if (!virJSONValueIsArray(data)) {
5831         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5832                        _("Malformed query-command-line-options parameters array"));
5833         goto cleanup;
5834     }
5835     n = virJSONValueArraySize(data);
5836
5837     /* null-terminated list */
5838     if (VIR_ALLOC_N(paramlist, n + 1) < 0)
5839         goto cleanup;
5840
5841     for (i = 0; i < n; i++) {
5842         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5843         const char *tmp;
5844
5845         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5846             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5847                            _("query-command-line-options parameter data was "
5848                              "missing 'name'"));
5849             goto cleanup;
5850         }
5851
5852         if (VIR_STRDUP(paramlist[i], tmp) < 0)
5853             goto cleanup;
5854     }
5855
5856     ret = n;
5857     *params = paramlist;
5858     paramlist = NULL;
5859
5860  cleanup:
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());
5865
5866     virStringListFree(paramlist);
5867     virJSONValueFree(cmd);
5868     virJSONValueFree(reply);
5869     return ret;
5870 }
5871
5872
5873 int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon,
5874                                bool *enabled,
5875                                bool *present)
5876 {
5877     int ret = -1;
5878     virJSONValuePtr cmd = NULL;
5879     virJSONValuePtr reply = NULL;
5880     virJSONValuePtr data = NULL;
5881
5882     /* Safe defaults */
5883     *enabled = *present = false;
5884
5885     if (!(cmd = qemuMonitorJSONMakeCommand("query-kvm", NULL)))
5886         return -1;
5887
5888     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5889         goto cleanup;
5890
5891     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
5892         ret = 0;
5893         goto cleanup;
5894     }
5895
5896     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
5897         goto cleanup;
5898
5899     data = virJSONValueObjectGetObject(reply, "return");
5900
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"));
5905         goto cleanup;
5906     }
5907
5908     ret = 0;
5909
5910  cleanup:
5911     virJSONValueFree(cmd);
5912     virJSONValueFree(reply);
5913     return ret;
5914 }
5915
5916
5917 int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon,
5918                                   char ***types)
5919 {
5920     int ret = -1;
5921     virJSONValuePtr cmd;
5922     virJSONValuePtr reply = NULL;
5923     virJSONValuePtr data;
5924     char **typelist = NULL;
5925     size_t n = 0;
5926     size_t i;
5927
5928     *types = NULL;
5929
5930     if (!(cmd = qemuMonitorJSONMakeCommand("qom-list-types", NULL)))
5931         return -1;
5932
5933     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5934         goto cleanup;
5935
5936     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5937         goto cleanup;
5938
5939     data = virJSONValueObjectGetArray(reply, "return");
5940     n = virJSONValueArraySize(data);
5941
5942     /* null-terminated list */
5943     if (VIR_ALLOC_N(typelist, n + 1) < 0)
5944         goto cleanup;
5945
5946     for (i = 0; i < n; i++) {
5947         virJSONValuePtr child = virJSONValueArrayGet(data, i);
5948         const char *tmp;
5949
5950         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
5951             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5952                            _("qom-list-types reply data was missing 'name'"));
5953             goto cleanup;
5954         }
5955
5956         if (VIR_STRDUP(typelist[i], tmp) < 0)
5957             goto cleanup;
5958     }
5959
5960     ret = n;
5961     *types = typelist;
5962     typelist = NULL;
5963
5964  cleanup:
5965     virStringListFree(typelist);
5966     virJSONValueFree(cmd);
5967     virJSONValueFree(reply);
5968     return ret;
5969 }
5970
5971
5972 int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
5973                                       const char *path,
5974                                       qemuMonitorJSONListPathPtr **paths)
5975 {
5976     int ret = -1;
5977     virJSONValuePtr cmd;
5978     virJSONValuePtr reply = NULL;
5979     virJSONValuePtr data;
5980     qemuMonitorJSONListPathPtr *pathlist = NULL;
5981     size_t n = 0;
5982     size_t i;
5983
5984     *paths = NULL;
5985
5986     if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
5987                                            "s:path", path,
5988                                            NULL)))
5989         return -1;
5990
5991     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
5992         goto cleanup;
5993
5994     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
5995         goto cleanup;
5996
5997     data = virJSONValueObjectGetArray(reply, "return");
5998     n = virJSONValueArraySize(data);
5999
6000     /* null-terminated list */
6001     if (VIR_ALLOC_N(pathlist, n + 1) < 0)
6002         goto cleanup;
6003
6004     for (i = 0; i < n; i++) {
6005         virJSONValuePtr child = virJSONValueArrayGet(data, i);
6006         const char *tmp;
6007         qemuMonitorJSONListPathPtr info;
6008
6009         if (VIR_ALLOC(info) < 0)
6010             goto cleanup;
6011
6012         pathlist[i] = info;
6013
6014         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
6015             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6016                            _("qom-list reply data was missing 'name'"));
6017             goto cleanup;
6018         }
6019
6020         if (VIR_STRDUP(info->name, tmp) < 0)
6021             goto cleanup;
6022
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"));
6027                 goto cleanup;
6028             }
6029             if (VIR_STRDUP(info->type, tmp) < 0)
6030                 goto cleanup;
6031         }
6032     }
6033
6034     ret = n;
6035     *paths = pathlist;
6036     pathlist = NULL;
6037
6038  cleanup:
6039     if (pathlist) {
6040         for (i = 0; i < n; i++)
6041             qemuMonitorJSONListPathFree(pathlist[i]);
6042         VIR_FREE(pathlist);
6043     }
6044     virJSONValueFree(cmd);
6045     virJSONValueFree(reply);
6046     return ret;
6047 }
6048
6049 void qemuMonitorJSONListPathFree(qemuMonitorJSONListPathPtr paths)
6050 {
6051     if (!paths)
6052         return;
6053     VIR_FREE(paths->name);
6054     VIR_FREE(paths->type);
6055     VIR_FREE(paths);
6056 }
6057
6058
6059 int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
6060                                      const char *path,
6061                                      const char *property,
6062                                      qemuMonitorJSONObjectPropertyPtr prop)
6063 {
6064     int ret = -1;
6065     virJSONValuePtr cmd;
6066     virJSONValuePtr reply = NULL;
6067     virJSONValuePtr data;
6068     const char *tmp;
6069
6070     if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
6071                                            "s:path", path,
6072                                            "s:property", property,
6073                                            NULL)))
6074         return -1;
6075
6076     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6077         goto cleanup;
6078
6079     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6080         goto cleanup;
6081
6082     data = virJSONValueObjectGet(reply, "return");
6083
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
6087      */
6088     case QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN:
6089         ret = virJSONValueGetBoolean(data, &prop->val.b);
6090         break;
6091     case QEMU_MONITOR_OBJECT_PROPERTY_INT:
6092         ret = virJSONValueGetNumberInt(data, &prop->val.iv);
6093         break;
6094     case QEMU_MONITOR_OBJECT_PROPERTY_LONG:
6095         ret = virJSONValueGetNumberLong(data, &prop->val.l);
6096         break;
6097     case QEMU_MONITOR_OBJECT_PROPERTY_UINT:
6098         ret = virJSONValueGetNumberUint(data, &prop->val.ui);
6099         break;
6100     case QEMU_MONITOR_OBJECT_PROPERTY_ULONG:
6101         ret = virJSONValueGetNumberUlong(data, &prop->val.ul);
6102         break;
6103     case QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE:
6104         ret = virJSONValueGetNumberDouble(data, &prop->val.d);
6105         break;
6106     case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
6107         tmp = virJSONValueGetString(data);
6108         if (tmp && VIR_STRDUP(prop->val.str, tmp) < 0)
6109             goto cleanup;
6110         if (tmp)
6111             ret = 0;
6112         break;
6113     case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
6114         virReportError(VIR_ERR_INTERNAL_ERROR,
6115                        _("qom-get invalid object property type %d"),
6116                        prop->type);
6117         goto cleanup;
6118         break;
6119     }
6120
6121     if (ret == -1) {
6122         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6123                        _("qom-get reply was missing return data"));
6124         goto cleanup;
6125     }
6126
6127     ret = 0;
6128  cleanup:
6129     virJSONValueFree(cmd);
6130     virJSONValueFree(reply);
6131
6132     return ret;
6133 }
6134
6135
6136 #define MAKE_SET_CMD(STRING, VALUE) \
6137     cmd = qemuMonitorJSONMakeCommand("qom-set", \
6138                                       "s:path", path, \
6139                                       "s:property", property, \
6140                                       STRING, VALUE, \
6141                                       NULL)
6142 int qemuMonitorJSONSetObjectProperty(qemuMonitorPtr mon,
6143                                      const char *path,
6144                                      const char *property,
6145                                      qemuMonitorJSONObjectPropertyPtr prop)
6146 {
6147     int ret = -1;
6148     virJSONValuePtr cmd = NULL;
6149     virJSONValuePtr reply = NULL;
6150
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
6154      */
6155     case QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN:
6156         MAKE_SET_CMD("b:value", prop->val.b);
6157         break;
6158     case QEMU_MONITOR_OBJECT_PROPERTY_INT:
6159         MAKE_SET_CMD("i:value", prop->val.iv);
6160         break;
6161     case QEMU_MONITOR_OBJECT_PROPERTY_LONG:
6162         MAKE_SET_CMD("I:value", prop->val.l);
6163         break;
6164     case QEMU_MONITOR_OBJECT_PROPERTY_UINT:
6165         MAKE_SET_CMD("u:value", prop->val.ui);
6166         break;
6167     case QEMU_MONITOR_OBJECT_PROPERTY_ULONG:
6168         MAKE_SET_CMD("U:value", prop->val.ul);
6169         break;
6170     case QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE:
6171         MAKE_SET_CMD("d:value", prop->val.d);
6172         break;
6173     case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
6174         MAKE_SET_CMD("s:value", prop->val.str);
6175         break;
6176     case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
6177         virReportError(VIR_ERR_INTERNAL_ERROR,
6178                        _("qom-set invalid object property type %d"),
6179                        prop->type);
6180         goto cleanup;
6181
6182     }
6183     if (!cmd)
6184         return -1;
6185
6186     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6187         goto cleanup;
6188
6189     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6190         goto cleanup;
6191
6192     ret = 0;
6193  cleanup:
6194     virJSONValueFree(cmd);
6195     virJSONValueFree(reply);
6196
6197     return ret;
6198 }
6199 #undef MAKE_SET_CMD
6200
6201
6202 static int
6203 qemuMonitorJSONParsePropsList(virJSONValuePtr cmd,
6204                               virJSONValuePtr reply,
6205                               char ***props)
6206 {
6207     virJSONValuePtr data;
6208     char **proplist = NULL;
6209     size_t n = 0;
6210     size_t i;
6211     int ret = -1;
6212
6213     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6214         goto cleanup;
6215
6216     data = virJSONValueObjectGetArray(reply, "return");
6217     n = virJSONValueArraySize(data);
6218
6219     /* null-terminated list */
6220     if (VIR_ALLOC_N(proplist, n + 1) < 0)
6221         goto cleanup;
6222
6223     for (i = 0; i < n; i++) {
6224         virJSONValuePtr child = virJSONValueArrayGet(data, i);
6225         const char *tmp;
6226
6227         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
6228             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6229                            _("reply data was missing 'name'"));
6230             goto cleanup;
6231         }
6232
6233         if (VIR_STRDUP(proplist[i], tmp) < 0)
6234             goto cleanup;
6235     }
6236
6237     ret = n;
6238     *props = proplist;
6239     proplist = NULL;
6240
6241  cleanup:
6242     virStringListFree(proplist);
6243     return ret;
6244 }
6245
6246
6247 int qemuMonitorJSONGetDeviceProps(qemuMonitorPtr mon,
6248                                   const char *device,
6249                                   char ***props)
6250 {
6251     int ret = -1;
6252     virJSONValuePtr cmd;
6253     virJSONValuePtr reply = NULL;
6254
6255     *props = NULL;
6256
6257     if (!(cmd = qemuMonitorJSONMakeCommand("device-list-properties",
6258                                            "s:typename", device,
6259                                            NULL)))
6260         return -1;
6261
6262     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6263         goto cleanup;
6264
6265     if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
6266         ret = 0;
6267         goto cleanup;
6268     }
6269
6270     ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
6271  cleanup:
6272     virJSONValueFree(reply);
6273     virJSONValueFree(cmd);
6274     return ret;
6275 }
6276
6277
6278 int
6279 qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
6280                               const char *object,
6281                               char ***props)
6282 {
6283     int ret = -1;
6284     virJSONValuePtr cmd;
6285     virJSONValuePtr reply = NULL;
6286
6287     *props = NULL;
6288
6289     if (!(cmd = qemuMonitorJSONMakeCommand("qom-list-properties",
6290                                            "s:typename", object,
6291                                            NULL)))
6292         return -1;
6293
6294     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6295         goto cleanup;
6296
6297     if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
6298         ret = 0;
6299         goto cleanup;
6300     }
6301
6302     ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
6303  cleanup:
6304     virJSONValueFree(reply);
6305     virJSONValueFree(cmd);
6306     return ret;
6307 }
6308
6309
6310 char *
6311 qemuMonitorJSONGetTargetArch(qemuMonitorPtr mon)
6312 {
6313     char *ret = NULL;
6314     const char *arch;
6315     virJSONValuePtr cmd;
6316     virJSONValuePtr reply = NULL;
6317     virJSONValuePtr data;
6318
6319     if (!(cmd = qemuMonitorJSONMakeCommand("query-target", NULL)))
6320         return NULL;
6321
6322     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6323         goto cleanup;
6324
6325     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
6326         goto cleanup;
6327
6328     data = virJSONValueObjectGetObject(reply, "return");
6329
6330     if (!(arch = virJSONValueObjectGetString(data, "arch"))) {
6331         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6332                        _("query-target reply was missing arch data"));
6333         goto cleanup;
6334     }
6335
6336     ignore_value(VIR_STRDUP(ret, arch));
6337
6338  cleanup:
6339     virJSONValueFree(cmd);
6340     virJSONValueFree(reply);
6341     return ret;
6342 }
6343
6344
6345 int
6346 qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon,
6347                                         char ***capabilities)
6348 {
6349     int ret = -1;
6350     virJSONValuePtr cmd;
6351     virJSONValuePtr reply = NULL;
6352     virJSONValuePtr caps;
6353     char **list = NULL;
6354     size_t i;
6355     size_t n;
6356
6357     *capabilities = NULL;
6358
6359     if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate-capabilities",
6360                                            NULL)))
6361         return -1;
6362
6363     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6364         goto cleanup;
6365
6366     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6367         ret = 0;
6368         goto cleanup;
6369     }
6370
6371     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6372         goto cleanup;
6373
6374     caps = virJSONValueObjectGetArray(reply, "return");
6375     n = virJSONValueArraySize(caps);
6376
6377     if (VIR_ALLOC_N(list, n + 1) < 0)
6378         goto cleanup;
6379
6380     for (i = 0; i < n; i++) {
6381         virJSONValuePtr cap = virJSONValueArrayGet(caps, i);
6382         const char *name;
6383
6384         if (!cap || virJSONValueGetType(cap) != VIR_JSON_TYPE_OBJECT) {
6385             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6386                            _("missing entry in migration capabilities list"));
6387             goto cleanup;
6388         }
6389
6390         if (!(name = virJSONValueObjectGetString(cap, "capability"))) {
6391             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6392                            _("missing migration capability name"));
6393             goto cleanup;
6394         }
6395
6396         if (VIR_STRDUP(list[i], name) < 1)
6397             goto cleanup;
6398     }
6399
6400     ret = n;
6401     *capabilities = list;
6402     list = NULL;
6403
6404  cleanup:
6405     virStringListFree(list);
6406     virJSONValueFree(cmd);
6407     virJSONValueFree(reply);
6408     return ret;
6409 }
6410
6411
6412 int
6413 qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon,
6414                                         virJSONValuePtr caps)
6415 {
6416     int ret = -1;
6417     virJSONValuePtr cmd = NULL;
6418     virJSONValuePtr reply = NULL;
6419
6420     cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities",
6421                                      "a:capabilities", &caps,
6422                                      NULL);
6423     if (!cmd)
6424         goto cleanup;
6425
6426     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6427         goto cleanup;
6428
6429     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6430         goto cleanup;
6431
6432     ret = 0;
6433  cleanup:
6434     virJSONValueFree(caps);
6435     virJSONValueFree(cmd);
6436     virJSONValueFree(reply);
6437     return ret;
6438 }
6439
6440
6441 /**
6442  * qemuMonitorJSONGetGICCapabilities:
6443  * @mon: QEMU JSON monitor
6444  * @capabilities: where to store the GIC capabilities
6445  *
6446  * Use @mon to obtain information about the GIC capabilities for the
6447  * corresponding QEMU binary, and store them in @capabilities.
6448  *
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.
6452  *
6453  * Returns: the number of GIC capabilities obtained from the monitor,
6454  *          <0 on failure
6455  */
6456 int
6457 qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
6458                                   virGICCapability **capabilities)
6459 {
6460     int ret = -1;
6461     virJSONValuePtr cmd;
6462     virJSONValuePtr reply = NULL;
6463     virJSONValuePtr caps;
6464     virGICCapability *list = NULL;
6465     size_t i;
6466     size_t n;
6467
6468     *capabilities = NULL;
6469
6470     if (!(cmd = qemuMonitorJSONMakeCommand("query-gic-capabilities",
6471                                            NULL)))
6472         return -1;
6473
6474     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6475         goto cleanup;
6476
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")) {
6481         ret = 0;
6482         goto cleanup;
6483     }
6484
6485     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6486         goto cleanup;
6487
6488     caps = virJSONValueObjectGetArray(reply, "return");
6489     n = virJSONValueArraySize(caps);
6490
6491     /* If the returned array was empty we have to return successfully */
6492     if (n == 0) {
6493         ret = 0;
6494         goto cleanup;
6495     }
6496
6497     if (VIR_ALLOC_N(list, n) < 0)
6498         goto cleanup;
6499
6500     for (i = 0; i < n; i++) {
6501         virJSONValuePtr cap = virJSONValueArrayGet(caps, i);
6502         int version;
6503         bool kernel;
6504         bool emulated;
6505
6506         if (!cap || virJSONValueGetType(cap) != VIR_JSON_TYPE_OBJECT) {
6507             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6508                            _("missing entry in GIC capabilities list"));
6509             goto cleanup;
6510         }
6511
6512         if (virJSONValueObjectGetNumberInt(cap, "version", &version) < 0) {
6513             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6514                            _("missing GIC version"));
6515             goto cleanup;
6516         }
6517
6518         if (virJSONValueObjectGetBoolean(cap, "kernel", &kernel) < 0) {
6519             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6520                            _("missing in-kernel GIC information"));
6521             goto cleanup;
6522         }
6523
6524         if (virJSONValueObjectGetBoolean(cap, "emulated", &emulated) < 0) {
6525             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6526                            _("missing emulated GIC information"));
6527             goto cleanup;
6528         }
6529
6530         list[i].version = version;
6531         if (kernel)
6532             list[i].implementation |= VIR_GIC_IMPLEMENTATION_KERNEL;
6533         if (emulated)
6534             list[i].implementation |= VIR_GIC_IMPLEMENTATION_EMULATED;
6535     }
6536
6537     ret = n;
6538     *capabilities = list;
6539     list = NULL;
6540
6541  cleanup:
6542     VIR_FREE(list);
6543     virJSONValueFree(cmd);
6544     virJSONValueFree(reply);
6545
6546     return ret;
6547 }
6548
6549
6550 /**
6551  * qemuMonitorJSONGetSEVCapabilities:
6552  * @mon: qemu monitor object
6553  * @capabilities: pointer to pointer to a SEV capability structure to be filled
6554  *
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.
6560  *
6561  * Returns -1 on error, 0 if SEV is not supported, and 1 if SEV is supported on
6562  * the platform.
6563  */
6564 int
6565 qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
6566                                   virSEVCapability **capabilities)
6567 {
6568     int ret = -1;
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;
6577
6578     *capabilities = NULL;
6579
6580     if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-capabilities",
6581                                            NULL)))
6582         return -1;
6583
6584     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6585         goto cleanup;
6586
6587     /* QEMU has only compiled-in support of SEV */
6588     if (qemuMonitorJSONHasError(reply, "GenericError")) {
6589         ret = 0;
6590         goto cleanup;
6591     }
6592
6593     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6594         goto cleanup;
6595
6596     caps = virJSONValueObjectGetObject(reply, "return");
6597
6598     if (virJSONValueObjectGetNumberUint(caps, "cbitpos", &cbitpos) < 0) {
6599         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6600                        _("query-sev-capabilities reply was missing"
6601                          " 'cbitpos' field"));
6602         goto cleanup;
6603     }
6604
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"));
6610         goto cleanup;
6611     }
6612
6613     if (!(pdh = virJSONValueObjectGetString(caps, "pdh"))) {
6614         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6615                        _("query-sev-capabilities reply was missing"
6616                          " 'pdh' field"));
6617         goto cleanup;
6618     }
6619
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"));
6624         goto cleanup;
6625     }
6626
6627     if (VIR_ALLOC(capability) < 0)
6628         goto cleanup;
6629
6630     if (VIR_STRDUP(capability->pdh, pdh) < 0)
6631         goto cleanup;
6632
6633     if (VIR_STRDUP(capability->cert_chain, cert_chain) < 0)
6634         goto cleanup;
6635
6636     capability->cbitpos = cbitpos;
6637     capability->reduced_phys_bits = reduced_phys_bits;
6638     VIR_STEAL_PTR(*capabilities, capability);
6639     ret = 1;
6640  cleanup:
6641     virJSONValueFree(cmd);
6642     virJSONValueFree(reply);
6643
6644     return ret;
6645 }
6646
6647 static virJSONValuePtr
6648 qemuMonitorJSONBuildInetSocketAddress(const char *host,
6649                                       const char *port)
6650 {
6651     virJSONValuePtr addr = NULL;
6652     virJSONValuePtr data = NULL;
6653
6654     if (virJSONValueObjectCreate(&data, "s:host", host,
6655                                         "s:port", port, NULL) < 0)
6656         return NULL;
6657
6658     if (virJSONValueObjectCreate(&addr, "s:type", "inet",
6659                                         "a:data", &data, NULL) < 0) {
6660         virJSONValueFree(data);
6661         return NULL;
6662     }
6663
6664     return addr;
6665 }
6666
6667 static virJSONValuePtr
6668 qemuMonitorJSONBuildUnixSocketAddress(const char *path)
6669 {
6670     virJSONValuePtr addr = NULL;
6671     virJSONValuePtr data = NULL;
6672
6673     if (virJSONValueObjectCreate(&data, "s:path", path, NULL) < 0)
6674         return NULL;
6675
6676     if (virJSONValueObjectCreate(&addr, "s:type", "unix",
6677                                         "a:data", &data, NULL) < 0) {
6678         virJSONValueFree(data);
6679         return NULL;
6680     }
6681
6682     return addr;
6683 }
6684
6685 int
6686 qemuMonitorJSONNBDServerStart(qemuMonitorPtr mon,
6687                               const char *host,
6688                               unsigned int port,
6689                               const char *tls_alias)
6690 {
6691     int ret = -1;
6692     virJSONValuePtr cmd = NULL;
6693     virJSONValuePtr reply = NULL;
6694     virJSONValuePtr addr = NULL;
6695     char *port_str = NULL;
6696
6697     if (virAsprintf(&port_str, "%u", port) < 0)
6698         return ret;
6699
6700     if (!(addr = qemuMonitorJSONBuildInetSocketAddress(host, port_str)))
6701         goto cleanup;
6702
6703     if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-start",
6704                                            "a:addr", &addr,
6705                                            "S:tls-creds", tls_alias,
6706                                            NULL)))
6707         goto cleanup;
6708
6709     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6710         goto cleanup;
6711
6712     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6713         goto cleanup;
6714
6715     ret = 0;
6716
6717  cleanup:
6718     VIR_FREE(port_str);
6719     virJSONValueFree(reply);
6720     virJSONValueFree(cmd);
6721     virJSONValueFree(addr);
6722     return ret;
6723 }
6724
6725 int
6726 qemuMonitorJSONNBDServerAdd(qemuMonitorPtr mon,
6727                             const char *deviceID,
6728                             bool writable)
6729 {
6730     int ret = -1;
6731     virJSONValuePtr cmd;
6732     virJSONValuePtr reply = NULL;
6733
6734     if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-add",
6735                                            "s:device", deviceID,
6736                                            "b:writable", writable,
6737                                            NULL)))
6738         return ret;
6739
6740     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6741         goto cleanup;
6742
6743     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6744         goto cleanup;
6745
6746     ret = 0;
6747  cleanup:
6748     virJSONValueFree(cmd);
6749     virJSONValueFree(reply);
6750     return ret;
6751 }
6752
6753 int
6754 qemuMonitorJSONNBDServerStop(qemuMonitorPtr mon)
6755 {
6756     int ret = -1;
6757     virJSONValuePtr cmd;
6758     virJSONValuePtr reply = NULL;
6759
6760     if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-stop",
6761                                            NULL)))
6762         return ret;
6763
6764     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6765         goto cleanup;
6766
6767     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
6768         goto cleanup;
6769
6770     ret = 0;
6771  cleanup:
6772     virJSONValueFree(cmd);
6773     virJSONValueFree(reply);
6774     return ret;
6775 }
6776
6777
6778 static int
6779 qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd,
6780                               char ***array)
6781 {
6782     int ret = -1;
6783     virJSONValuePtr cmd;
6784     virJSONValuePtr reply = NULL;
6785     virJSONValuePtr data;
6786     char **list = NULL;
6787     size_t n = 0;
6788     size_t i;
6789
6790     *array = NULL;
6791
6792     if (!(cmd = qemuMonitorJSONMakeCommand(qmpCmd, NULL)))
6793         return -1;
6794
6795     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
6796         goto cleanup;
6797
6798     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6799         ret = 0;
6800         goto cleanup;
6801     }
6802
6803     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
6804         goto cleanup;
6805
6806     data = virJSONValueObjectGetArray(reply, "return");
6807     n = virJSONValueArraySize(data);
6808
6809     /* null-terminated list */
6810     if (VIR_ALLOC_N(list, n + 1) < 0)
6811         goto cleanup;
6812
6813     for (i = 0; i < n; i++) {
6814         virJSONValuePtr child = virJSONValueArrayGet(data, i);
6815         const char *tmp;
6816
6817         if (!(tmp = virJSONValueGetString(child))) {
6818             virReportError(VIR_ERR_INTERNAL_ERROR,
6819                            _("%s array element does not contain data"),
6820                            qmpCmd);
6821             goto cleanup;
6822         }
6823
6824         if (VIR_STRDUP(list[i], tmp) < 0)
6825             goto cleanup;
6826     }
6827
6828     ret = n;
6829     *array = list;
6830     list = NULL;
6831
6832  cleanup:
6833     virStringListFree(list);
6834     virJSONValueFree(cmd);
6835     virJSONValueFree(reply);
6836     return ret;
6837 }
6838
6839 int qemuMonitorJSONGetTPMModels(qemuMonitorPtr mon,
6840                                 char ***tpmmodels)
6841 {
6842     return qemuMonitorJSONGetStringArray(mon, "query-tpm-models", tpmmodels);
6843 }
6844
6845
6846 int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
6847                                char ***tpmtypes)
6848 {
6849     return qemuMonitorJSONGetStringArray(mon, "query-tpm-types", tpmtypes);
6850 }
6851
6852 static int
6853 qemuMonitorJSONBuildChrChardevReconnect(virJSONValuePtr object,
6854                                         const virDomainChrSourceReconnectDef *def)
6855 {
6856     if (def->enabled != VIR_TRISTATE_BOOL_YES)
6857         return 0;
6858
6859     return virJSONValueObjectAppendNumberUint(object, "reconnect", def->timeout);
6860 }
6861
6862 static virJSONValuePtr
6863 qemuMonitorJSONAttachCharDevCommand(const char *chrID,
6864                                     const virDomainChrSourceDef *chr)
6865 {
6866     virJSONValuePtr ret = NULL;
6867     virJSONValuePtr backend = NULL;
6868     virJSONValuePtr data = NULL;
6869     virJSONValuePtr addr = NULL;
6870     const char *backend_type = NULL;
6871     const char *host;
6872     const char *port;
6873     char *tlsalias = NULL;
6874     bool telnet;
6875
6876     if (!(backend = virJSONValueNewObject()) ||
6877         !(data = virJSONValueNewObject())) {
6878         goto cleanup;
6879     }
6880
6881     switch ((virDomainChrType)chr->type) {
6882     case VIR_DOMAIN_CHR_TYPE_NULL:
6883     case VIR_DOMAIN_CHR_TYPE_VC:
6884         backend_type = "null";
6885         break;
6886
6887     case VIR_DOMAIN_CHR_TYPE_PTY:
6888         backend_type = "pty";
6889         break;
6890
6891     case VIR_DOMAIN_CHR_TYPE_FILE:
6892         backend_type = "file";
6893         if (virJSONValueObjectAppendString(data, "out", chr->data.file.path) < 0)
6894             goto cleanup;
6895         break;
6896
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)
6901             goto cleanup;
6902         break;
6903
6904     case VIR_DOMAIN_CHR_TYPE_TCP:
6905         backend_type = "socket";
6906         addr = qemuMonitorJSONBuildInetSocketAddress(chr->data.tcp.host,
6907                                                      chr->data.tcp.service);
6908         if (!addr ||
6909             virJSONValueObjectAppend(data, "addr", addr) < 0)
6910             goto cleanup;
6911         addr = NULL;
6912
6913         telnet = chr->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
6914
6915         if (chr->data.tcp.listen &&
6916             virJSONValueObjectAppendBoolean(data, "wait", false) < 0)
6917             goto cleanup;
6918
6919         if (virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 ||
6920             virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0)
6921             goto cleanup;
6922         if (chr->data.tcp.tlscreds) {
6923             if (!(tlsalias = qemuAliasTLSObjFromSrcAlias(chrID)))
6924                 goto cleanup;
6925
6926             if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0)
6927                 goto cleanup;
6928         }
6929
6930         if (qemuMonitorJSONBuildChrChardevReconnect(data, &chr->data.tcp.reconnect) < 0)
6931             goto cleanup;
6932         break;
6933
6934     case VIR_DOMAIN_CHR_TYPE_UDP:
6935         backend_type = "udp";
6936         host = chr->data.udp.connectHost;
6937         if (!host)
6938             host = "";
6939         addr = qemuMonitorJSONBuildInetSocketAddress(host,
6940                                                      chr->data.udp.connectService);
6941         if (!addr ||
6942             virJSONValueObjectAppend(data, "remote", addr) < 0)
6943             goto cleanup;
6944
6945         host = chr->data.udp.bindHost;
6946         port = chr->data.udp.bindService;
6947         if (host || port) {
6948             if (!host)
6949                 host = "";
6950             if (!port)
6951                 port = "";
6952             addr = qemuMonitorJSONBuildInetSocketAddress(host, port);
6953             if (!addr ||
6954                 virJSONValueObjectAppend(data, "local", addr) < 0)
6955                 goto cleanup;
6956         }
6957         addr = NULL;
6958         break;
6959
6960     case VIR_DOMAIN_CHR_TYPE_UNIX:
6961         backend_type = "socket";
6962         addr = qemuMonitorJSONBuildUnixSocketAddress(chr->data.nix.path);
6963
6964         if (!addr ||
6965             virJSONValueObjectAppend(data, "addr", addr) < 0)
6966             goto cleanup;
6967         addr = NULL;
6968
6969         if (chr->data.nix.listen &&
6970             virJSONValueObjectAppendBoolean(data, "wait", false) < 0)
6971             goto cleanup;
6972
6973         if (virJSONValueObjectAppendBoolean(data, "server", chr->data.nix.listen) < 0)
6974             goto cleanup;
6975
6976         if (qemuMonitorJSONBuildChrChardevReconnect(data, &chr->data.nix.reconnect) < 0)
6977             goto cleanup;
6978         break;
6979
6980     case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
6981         backend_type = "spicevmc";
6982
6983         if (virJSONValueObjectAppendString(data, "type",
6984                                            virDomainChrSpicevmcTypeToString(chr->data.spicevmc)) < 0)
6985             goto cleanup;
6986         break;
6987
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));
6997         } else {
6998             virReportError(VIR_ERR_OPERATION_FAILED,
6999                            _("Hotplug unsupported for char device type '%d'"),
7000                            chr->type);
7001         }
7002         goto cleanup;
7003     }
7004
7005     if (virJSONValueObjectAppendString(backend, "type", backend_type) < 0 ||
7006         virJSONValueObjectAppend(backend, "data", data) < 0)
7007         goto cleanup;
7008     data = NULL;
7009
7010     if (!(ret = qemuMonitorJSONMakeCommand("chardev-add",
7011                                            "s:id", chrID,
7012                                            "a:backend", &backend,
7013                                            NULL)))
7014         goto cleanup;
7015
7016  cleanup:
7017     VIR_FREE(tlsalias);
7018     virJSONValueFree(addr);
7019     virJSONValueFree(data);
7020     virJSONValueFree(backend);
7021     return ret;
7022 }
7023
7024
7025 int
7026 qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
7027                              const char *chrID,
7028                              virDomainChrSourceDefPtr chr)
7029 {
7030     int ret = -1;
7031     virJSONValuePtr cmd;
7032     virJSONValuePtr reply = NULL;
7033
7034     if (!(cmd = qemuMonitorJSONAttachCharDevCommand(chrID, chr)))
7035         return ret;
7036
7037     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7038         goto cleanup;
7039
7040     if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
7041         if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
7042             goto cleanup;
7043     } else {
7044         if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7045             goto cleanup;
7046     }
7047
7048     if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
7049         virJSONValuePtr data = virJSONValueObjectGetObject(reply, "return");
7050         const char *path;
7051
7052         if (!(path = virJSONValueObjectGetString(data, "pty"))) {
7053             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7054                            _("chardev-add reply was missing pty path"));
7055             goto cleanup;
7056         }
7057
7058         if (VIR_STRDUP(chr->data.file.path, path) < 0)
7059             goto cleanup;
7060     }
7061
7062     ret = 0;
7063
7064  cleanup:
7065     virJSONValueFree(cmd);
7066     virJSONValueFree(reply);
7067     return ret;
7068 }
7069
7070 int
7071 qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon,
7072                              const char *chrID)
7073 {
7074     int ret = -1;
7075     virJSONValuePtr cmd;
7076     virJSONValuePtr reply = NULL;
7077
7078     if (!(cmd = qemuMonitorJSONMakeCommand("chardev-remove",
7079                                            "s:id", chrID,
7080                                            NULL)))
7081         return ret;
7082
7083     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7084         goto cleanup;
7085
7086     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7087         goto cleanup;
7088
7089     ret = 0;
7090  cleanup:
7091     virJSONValueFree(cmd);
7092     virJSONValueFree(reply);
7093     return ret;
7094 }
7095
7096
7097 int
7098 qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon,
7099                                 char ***aliases)
7100 {
7101     qemuMonitorJSONListPathPtr *paths = NULL;
7102     char **alias;
7103     int ret = -1;
7104     size_t i;
7105     int n;
7106
7107     *aliases = NULL;
7108
7109     n = qemuMonitorJSONGetObjectListPaths(mon, "/machine/peripheral", &paths);
7110     if (n < 0)
7111         return -1;
7112
7113     if (VIR_ALLOC_N(*aliases, n + 1) < 0)
7114         goto cleanup;
7115
7116     alias = *aliases;
7117     for (i = 0; i < n; i++) {
7118         if (STRPREFIX(paths[i]->type, "child<")) {
7119             *alias = paths[i]->name;
7120             paths[i]->name = NULL;
7121             alias++;
7122         }
7123     }
7124
7125     ret = 0;
7126
7127  cleanup:
7128     for (i = 0; i < n; i++)
7129         qemuMonitorJSONListPathFree(paths[i]);
7130     VIR_FREE(paths);
7131     return ret;
7132 }
7133
7134
7135 static int
7136 qemuMonitorJSONParseCPUx86FeatureWord(virJSONValuePtr data,
7137                                       virCPUx86CPUID *cpuid)
7138 {
7139     const char *reg;
7140     unsigned long long eax_in;
7141     unsigned long long ecx_in = 0;
7142     unsigned long long features;
7143
7144     memset(cpuid, 0, sizeof(*cpuid));
7145
7146     if (!(reg = virJSONValueObjectGetString(data, "cpuid-register"))) {
7147         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7148                        _("missing cpuid-register in CPU data"));
7149         return -1;
7150     }
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"));
7154         return -1;
7155     }
7156     ignore_value(virJSONValueObjectGetNumberUlong(data, "cpuid-input-ecx",
7157                                                   &ecx_in));
7158     if (virJSONValueObjectGetNumberUlong(data, "features", &features) < 0) {
7159         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7160                        _("missing or invalid features in CPU data"));
7161         return -1;
7162     }
7163
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;
7174     } else {
7175         virReportError(VIR_ERR_INTERNAL_ERROR,
7176                        _("unknown CPU register '%s'"), reg);
7177         return -1;
7178     }
7179
7180     return 0;
7181 }
7182
7183
7184 static virCPUDataPtr
7185 qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
7186 {
7187     virCPUDataPtr cpudata = NULL;
7188     virCPUx86DataItem item = { 0 };
7189     size_t i;
7190
7191     if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64)))
7192         goto error;
7193
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)
7199             goto error;
7200     }
7201
7202     return cpudata;
7203
7204  error:
7205     virCPUDataFree(cpudata);
7206     return NULL;
7207 }
7208
7209
7210 int
7211 qemuMonitorJSONGetCPUx86Data(qemuMonitorPtr mon,
7212                              const char *property,
7213                              virCPUDataPtr *cpudata)
7214 {
7215     virJSONValuePtr cmd = NULL;
7216     virJSONValuePtr reply = NULL;
7217     virJSONValuePtr data;
7218     int ret = -1;
7219
7220     if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
7221                                            "s:path", QOM_CPU_PATH,
7222                                            "s:property", property,
7223                                            NULL)))
7224         goto cleanup;
7225
7226     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7227         goto cleanup;
7228
7229     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7230         goto cleanup;
7231
7232     data = virJSONValueObjectGetArray(reply, "return");
7233     if (!(*cpudata = qemuMonitorJSONParseCPUx86Features(data)))
7234         goto cleanup;
7235
7236     ret = 0;
7237
7238  cleanup:
7239     virJSONValueFree(cmd);
7240     virJSONValueFree(reply);
7241     return ret;
7242 }
7243
7244
7245 /*
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.
7248  */
7249 static int
7250 qemuMonitorJSONCheckCPUx86(qemuMonitorPtr mon)
7251 {
7252     virJSONValuePtr cmd = NULL;
7253     virJSONValuePtr reply = NULL;
7254     virJSONValuePtr data;
7255     size_t i;
7256     size_t n;
7257     int ret = -1;
7258
7259     if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
7260                                            "s:path", QOM_CPU_PATH,
7261                                            NULL)))
7262         goto cleanup;
7263
7264     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7265         goto cleanup;
7266
7267     if ((data = virJSONValueObjectGet(reply, "error"))) {
7268         const char *klass = virJSONValueObjectGetString(data, "class");
7269         if (STREQ_NULLABLE(klass, "DeviceNotFound") ||
7270             STREQ_NULLABLE(klass, "CommandNotFound")) {
7271             ret = 0;
7272             goto cleanup;
7273         }
7274     }
7275
7276     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7277         goto cleanup;
7278
7279     data = virJSONValueObjectGetArray(reply, "return");
7280     n = virJSONValueArraySize(data);
7281
7282     for (i = 0; i < n; i++) {
7283         virJSONValuePtr element = virJSONValueArrayGet(data, i);
7284         if (STREQ_NULLABLE(virJSONValueObjectGetString(element, "name"),
7285                            "feature-words"))
7286             break;
7287     }
7288
7289     if (i == n)
7290         ret = 0;
7291     else
7292         ret = 1;
7293
7294  cleanup:
7295     virJSONValueFree(cmd);
7296     virJSONValueFree(reply);
7297     return ret;
7298 }
7299
7300
7301 /**
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
7307  *
7308  * Retrieve the definition of the guest CPU from a running qemu instance.
7309  *
7310  * Returns 0 on success, -2 if guest doesn't support this feature,
7311  * -1 on other errors.
7312  */
7313 int
7314 qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
7315                            virArch arch,
7316                            virCPUDataPtr *data,
7317                            virCPUDataPtr *disabled)
7318 {
7319     virCPUDataPtr cpuEnabled = NULL;
7320     virCPUDataPtr cpuDisabled = NULL;
7321     int rc;
7322
7323     if (ARCH_IS_X86(arch)) {
7324         if ((rc = qemuMonitorJSONCheckCPUx86(mon)) < 0)
7325             return -1;
7326         else if (!rc)
7327             return -2;
7328
7329         if (qemuMonitorJSONGetCPUx86Data(mon, "feature-words",
7330                                          &cpuEnabled) < 0)
7331             goto error;
7332
7333         if (disabled &&
7334             qemuMonitorJSONGetCPUx86Data(mon, "filtered-features",
7335                                          &cpuDisabled) < 0)
7336             goto error;
7337
7338         *data = cpuEnabled;
7339         if (disabled)
7340             *disabled = cpuDisabled;
7341         return 0;
7342     }
7343
7344     virReportError(VIR_ERR_INTERNAL_ERROR,
7345                    _("CPU definition retrieval isn't supported for '%s'"),
7346                    virArchToString(arch));
7347     return -1;
7348
7349  error:
7350     virCPUDataFree(cpuEnabled);
7351     virCPUDataFree(cpuDisabled);
7352     return -1;
7353 }
7354
7355 int
7356 qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
7357 {
7358     int ret = -1;
7359     virJSONValuePtr cmd;
7360     virJSONValuePtr reply = NULL;
7361
7362     if (!(cmd = qemuMonitorJSONMakeCommand("rtc-reset-reinjection",
7363                                            NULL)))
7364         return ret;
7365
7366     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7367         goto cleanup;
7368
7369     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
7370         goto cleanup;
7371
7372     ret = 0;
7373  cleanup:
7374     virJSONValueFree(cmd);
7375     virJSONValueFree(reply);
7376     return ret;
7377 }
7378
7379 /**
7380  * Query and parse returned array of data such as:
7381  *
7382  *  {u'return': [{u'id': u'iothread1', u'thread-id': 30992}, \
7383  *               {u'id': u'iothread2', u'thread-id': 30993}]}
7384  */
7385 int
7386 qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
7387                             qemuMonitorIOThreadInfoPtr **iothreads)
7388 {
7389     int ret = -1;
7390     virJSONValuePtr cmd;
7391     virJSONValuePtr reply = NULL;
7392     virJSONValuePtr data;
7393     qemuMonitorIOThreadInfoPtr *infolist = NULL;
7394     size_t n = 0;
7395     size_t i;
7396
7397     *iothreads = NULL;
7398
7399     if (!(cmd = qemuMonitorJSONMakeCommand("query-iothreads", NULL)))
7400         return ret;
7401
7402     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7403         goto cleanup;
7404
7405     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7406         goto cleanup;
7407
7408     data = virJSONValueObjectGetArray(reply, "return");
7409     n = virJSONValueArraySize(data);
7410
7411     /* null-terminated list */
7412     if (VIR_ALLOC_N(infolist, n + 1) < 0)
7413         goto cleanup;
7414
7415     for (i = 0; i < n; i++) {
7416         virJSONValuePtr child = virJSONValueArrayGet(data, i);
7417         const char *tmp;
7418         qemuMonitorIOThreadInfoPtr info;
7419
7420         if (!(tmp = virJSONValueObjectGetString(child, "id"))) {
7421             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7422                            _("query-iothreads reply data was missing 'id'"));
7423             goto cleanup;
7424         }
7425
7426         if (!STRPREFIX(tmp, "iothread"))
7427             continue;
7428
7429         if (VIR_ALLOC(info) < 0)
7430             goto cleanup;
7431
7432         infolist[i] = info;
7433
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'"),
7438                            tmp);
7439             goto cleanup;
7440         }
7441
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"));
7447             goto cleanup;
7448         }
7449
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;
7464     }
7465
7466     ret = n;
7467     *iothreads = infolist;
7468     infolist = NULL;
7469
7470  cleanup:
7471     if (infolist) {
7472         for (i = 0; i < n; i++)
7473             VIR_FREE(infolist[i]);
7474         VIR_FREE(infolist);
7475     }
7476     virJSONValueFree(cmd);
7477     virJSONValueFree(reply);
7478     return ret;
7479 }
7480
7481
7482 int
7483 qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
7484                            qemuMonitorIOThreadInfoPtr iothreadInfo)
7485 {
7486     int ret = -1;
7487     char *path = NULL;
7488     qemuMonitorJSONObjectProperty prop;
7489
7490     if (virAsprintf(&path, "/objects/iothread%u",
7491                     iothreadInfo->iothread_id) < 0)
7492         goto cleanup;
7493
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) \
7500             goto cleanup; \
7501     }
7502
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);
7506
7507 #undef VIR_IOTHREAD_SET_PROP
7508
7509     ret = 0;
7510
7511  cleanup:
7512     VIR_FREE(path);
7513     return ret;
7514 }
7515
7516
7517 int
7518 qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
7519                                    virHashTablePtr info)
7520 {
7521     int ret = -1;
7522     virJSONValuePtr cmd;
7523     virJSONValuePtr reply = NULL;
7524     virJSONValuePtr data = NULL;
7525     qemuMonitorMemoryDeviceInfoPtr meminfo = NULL;
7526     size_t i;
7527
7528     if (!(cmd = qemuMonitorJSONMakeCommand("query-memory-devices", NULL)))
7529         return -1;
7530
7531     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7532         goto cleanup;
7533
7534     if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
7535         ret = -2;
7536         goto cleanup;
7537     }
7538
7539     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
7540         goto cleanup;
7541
7542     data = virJSONValueObjectGetArray(reply, "return");
7543
7544     for (i = 0; i < virJSONValueArraySize(data); i++) {
7545         virJSONValuePtr elem = virJSONValueArrayGet(data, i);
7546         const char *type;
7547
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"));
7552             goto cleanup;
7553         }
7554
7555         /* dimm memory devices */
7556         if (STREQ(type, "dimm")) {
7557             virJSONValuePtr dimminfo;
7558             const char *devalias;
7559
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"));
7564                 goto cleanup;
7565             }
7566
7567             if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) {
7568                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7569                                _("dimm memory info data is missing 'id'"));
7570                 goto cleanup;
7571             }
7572
7573             if (VIR_ALLOC(meminfo) < 0)
7574                 goto cleanup;
7575
7576             if (virJSONValueObjectGetNumberUlong(dimminfo, "addr",
7577                                                  &meminfo->address) < 0) {
7578                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7579                                _("malformed/missing addr in dimm memory info"));
7580                 goto cleanup;
7581             }
7582
7583             if (virJSONValueObjectGetNumberUint(dimminfo, "slot",
7584                                                 &meminfo->slot) < 0) {
7585                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7586                                _("malformed/missing slot in dimm memory info"));
7587                 goto cleanup;
7588             }
7589
7590             if (virJSONValueObjectGetBoolean(dimminfo, "hotplugged",
7591                                              &meminfo->hotplugged) < 0) {
7592                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7593                                _("malformed/missing hotplugged in dimm memory info"));
7594                 goto cleanup;
7595
7596             }
7597
7598             if (virJSONValueObjectGetBoolean(dimminfo, "hotpluggable",
7599                                              &meminfo->hotpluggable) < 0) {
7600                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7601                                _("malformed/missing hotpluggable in dimm memory info"));
7602                 goto cleanup;
7603
7604             }
7605
7606             if (virHashAddEntry(info, devalias, meminfo) < 0)
7607                 goto cleanup;
7608
7609             meminfo = NULL;
7610         }
7611     }
7612
7613     ret = 0;
7614
7615  cleanup:
7616     VIR_FREE(meminfo);
7617     virJSONValueFree(cmd);
7618     virJSONValueFree(reply);
7619     return ret;
7620 }
7621
7622
7623 /**
7624  * Search for a QOM object link by alias and name.
7625  *
7626  * For @alias and @name, this function tries to find QOM object named @name
7627  * with id @alias in /machine/peripheral.
7628  *
7629  * Returns:
7630  *   0  - Found
7631  *  -1  - Error - bail out
7632  *  -2  - Not found
7633  */
7634 static int
7635 qemuMonitorJSONFindObjectPathByAlias(qemuMonitorPtr mon,
7636                                      const char *name,
7637                                      const char *alias,
7638                                      char **path)
7639 {
7640     qemuMonitorJSONListPathPtr *paths = NULL;
7641     char *child = NULL;
7642     int npaths;
7643     int ret = -1;
7644     size_t i;
7645
7646     npaths = qemuMonitorJSONGetObjectListPaths(mon, "/machine/peripheral", &paths);
7647     if (npaths < 0)
7648         return -1;
7649
7650     if (virAsprintf(&child, "child<%s>", name) < 0)
7651         goto cleanup;
7652
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)
7656                 goto cleanup;
7657
7658             ret = 0;
7659             goto cleanup;
7660         }
7661     }
7662
7663     ret = -2;
7664
7665  cleanup:
7666     for (i = 0; i < npaths; i++)
7667         qemuMonitorJSONListPathFree(paths[i]);
7668     VIR_FREE(paths);
7669     VIR_FREE(child);
7670     return ret;
7671 }
7672
7673
7674 /**
7675  * Recursively search for a QOM object link only by name.
7676  *
7677  * For @name, this function finds the first QOM object
7678  * named @name, recursively going through all the "child<>"
7679  * entries, starting from @curpath.
7680  *
7681  * Returns:
7682  *   0  - Found
7683  *  -1  - Error - bail out
7684  *  -2  - Not found
7685  */
7686 static int
7687 qemuMonitorJSONFindObjectPathByName(qemuMonitorPtr mon,
7688                                     const char *curpath,
7689                                     const char *name,
7690                                     char **path)
7691 {
7692     ssize_t i, npaths = 0;
7693     int ret = -2;
7694     char *nextpath = NULL;
7695     qemuMonitorJSONListPathPtr *paths = NULL;
7696
7697     VIR_DEBUG("Searching for '%s' Object Path starting at '%s'", name, curpath);
7698
7699     npaths = qemuMonitorJSONGetObjectListPaths(mon, curpath, &paths);
7700     if (npaths < 0)
7701         goto cleanup;
7702
7703     for (i = 0; i < npaths && ret == -2; i++) {
7704
7705         if (STREQ_NULLABLE(paths[i]->type, name)) {
7706             VIR_DEBUG("Path to '%s' is '%s/%s'", name, curpath, paths[i]->name);
7707             ret = 0;
7708             if (virAsprintf(path, "%s/%s", curpath, paths[i]->name) < 0) {
7709                 *path = NULL;
7710                 ret = -1;
7711             }
7712             goto cleanup;
7713         }
7714
7715         /* Type entries that begin with "child<" are a branch that can be
7716          * traversed looking for more entries
7717          */
7718         if (paths[i]->type && STRPREFIX(paths[i]->type, "child<")) {
7719             if (virAsprintf(&nextpath, "%s/%s", curpath, paths[i]->name) < 0) {
7720                 ret = -1;
7721                 goto cleanup;
7722             }
7723
7724             ret = qemuMonitorJSONFindObjectPathByName(mon, nextpath, name, path);
7725             VIR_FREE(nextpath);
7726         }
7727     }
7728
7729  cleanup:
7730     for (i = 0; i < npaths; i++)
7731         qemuMonitorJSONListPathFree(paths[i]);
7732     VIR_FREE(paths);
7733     VIR_FREE(nextpath);
7734     return ret;
7735 }
7736
7737
7738 /**
7739  * Recursively search for a QOM object link.
7740  *
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.
7744  *
7745  * Returns:
7746  *   0  - Found
7747  *  -1  - Error
7748  *  -2  - Not found
7749  */
7750 int
7751 qemuMonitorJSONFindLinkPath(qemuMonitorPtr mon,
7752                             const char *name,
7753                             const char *alias,
7754                             char **path)
7755 {
7756     char *linkname = NULL;
7757     int ret = -1;
7758
7759     if (alias) {
7760         ret = qemuMonitorJSONFindObjectPathByAlias(mon, name, alias, path);
7761         if (ret == -1 || ret == 0)
7762             return ret;
7763     }
7764
7765     if (virAsprintf(&linkname, "link<%s>", name) < 0)
7766         return -1;
7767
7768     ret = qemuMonitorJSONFindObjectPathByName(mon, "/", linkname, path);
7769     VIR_FREE(linkname);
7770     return ret;
7771 }
7772
7773
7774 int
7775 qemuMonitorJSONMigrateIncoming(qemuMonitorPtr mon,
7776                                const char *uri)
7777 {
7778     int ret = -1;
7779     virJSONValuePtr cmd;
7780     virJSONValuePtr reply = NULL;
7781
7782     if (!(cmd = qemuMonitorJSONMakeCommand("migrate-incoming",
7783                                            "s:uri", uri,
7784                                            NULL)))
7785         return -1;
7786
7787     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7788         goto cleanup;
7789
7790     ret = qemuMonitorJSONCheckError(cmd, reply);
7791
7792  cleanup:
7793     virJSONValueFree(cmd);
7794     virJSONValueFree(reply);
7795     return ret;
7796 }
7797
7798
7799 int
7800 qemuMonitorJSONMigrateStartPostCopy(qemuMonitorPtr mon)
7801 {
7802     int ret = -1;
7803     virJSONValuePtr cmd;
7804     virJSONValuePtr reply = NULL;
7805
7806     if (!(cmd = qemuMonitorJSONMakeCommand("migrate-start-postcopy", NULL)))
7807         return -1;
7808
7809     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7810         goto cleanup;
7811
7812     ret = qemuMonitorJSONCheckError(cmd, reply);
7813
7814  cleanup:
7815     virJSONValueFree(cmd);
7816     virJSONValueFree(reply);
7817     return ret;
7818 }
7819
7820
7821 int
7822 qemuMonitorJSONMigrateContinue(qemuMonitorPtr mon,
7823                                qemuMonitorMigrationStatus status)
7824 {
7825     const char *statusStr = qemuMonitorMigrationStatusTypeToString(status);
7826     int ret = -1;
7827     virJSONValuePtr cmd;
7828     virJSONValuePtr reply = NULL;
7829
7830     if (!(cmd = qemuMonitorJSONMakeCommand("migrate-continue",
7831                                            "s:state", statusStr,
7832                                            NULL)))
7833         return -1;
7834
7835     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7836         goto cleanup;
7837
7838     ret = qemuMonitorJSONCheckError(cmd, reply);
7839
7840  cleanup:
7841     virJSONValueFree(cmd);
7842     virJSONValueFree(reply);
7843     return ret;
7844 }
7845
7846
7847 int
7848 qemuMonitorJSONGetRTCTime(qemuMonitorPtr mon,
7849                           struct tm *tm)
7850 {
7851     int ret = -1;
7852     virJSONValuePtr cmd;
7853     virJSONValuePtr reply = NULL;
7854     virJSONValuePtr data;
7855
7856     if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
7857                                            "s:path", "/machine",
7858                                            "s:property", "rtc-time",
7859                                            NULL)))
7860         return -1;
7861
7862     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
7863         goto cleanup;
7864
7865     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
7866         goto cleanup;
7867
7868     data = virJSONValueObjectGet(reply, "return");
7869
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"));
7878         goto cleanup;
7879     }
7880
7881     ret = 0;
7882  cleanup:
7883     virJSONValueFree(cmd);
7884     virJSONValueFree(reply);
7885     return ret;
7886 }
7887
7888
7889 void
7890 qemuMonitorQueryHotpluggableCpusFree(struct qemuMonitorQueryHotpluggableCpusEntry *entries,
7891                                      size_t nentries)
7892 {
7893     struct qemuMonitorQueryHotpluggableCpusEntry *entry;
7894     size_t i;
7895
7896     if (!entries)
7897         return;
7898
7899     for (i = 0; i < nentries; i++) {
7900         entry = entries + i;
7901
7902         VIR_FREE(entry->type);
7903         VIR_FREE(entry->qom_path);
7904         VIR_FREE(entry->alias);
7905     }
7906
7907     VIR_FREE(entries);
7908 }
7909
7910
7911 /**
7912  * [{
7913  *    "props": {
7914  *      "core-id": 0,
7915  *      "thread-id": 0,
7916  *      "socket-id": 0
7917  *    },
7918  *    "vcpus-count": 1,
7919  *    "qom-path": "/machine/unattached/device[0]",
7920  *    "type": "qemu64-x86_64-cpu"
7921  *  },
7922  *  {...}
7923  * ]
7924  */
7925 static int
7926 qemuMonitorJSONProcessHotpluggableCpusReply(virJSONValuePtr vcpu,
7927                                             struct qemuMonitorQueryHotpluggableCpusEntry *entry)
7928 {
7929     virJSONValuePtr props;
7930     const char *tmp;
7931
7932     if (!(tmp = virJSONValueObjectGetString(vcpu, "type"))) {
7933         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7934                        _("query-hotpluggable-cpus didn't return device type"));
7935         return -1;
7936     }
7937
7938     if (VIR_STRDUP(entry->type, tmp) < 0)
7939         return -1;
7940
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"));
7944         return -1;
7945     }
7946
7947     if (!(props = virJSONValueObjectGetObject(vcpu, "props"))) {
7948         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7949                        _("query-hotpluggable-cpus didn't return device props"));
7950         return -1;
7951     }
7952
7953     entry->node_id = -1;
7954     entry->socket_id = -1;
7955     entry->core_id = -1;
7956     entry->thread_id = -1;
7957
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));
7962
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"));
7968         return -1;
7969     }
7970
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)
7974             return -1;
7975
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)
7979                 return -1;
7980         }
7981     }
7982
7983     return 0;
7984 }
7985
7986
7987 static int
7988 qemuMonitorQueryHotpluggableCpusEntrySort(const void *p1,
7989                                           const void *p2)
7990 {
7991     const struct qemuMonitorQueryHotpluggableCpusEntry *a = p1;
7992     const struct qemuMonitorQueryHotpluggableCpusEntry *b = p2;
7993
7994     if (a->socket_id != b->socket_id)
7995         return a->socket_id - b->socket_id;
7996
7997     if (a->core_id != b->core_id)
7998         return a->core_id - b->core_id;
7999
8000     return a->thread_id - b->thread_id;
8001 }
8002
8003
8004 int
8005 qemuMonitorJSONGetHotpluggableCPUs(qemuMonitorPtr mon,
8006                                    struct qemuMonitorQueryHotpluggableCpusEntry **entries,
8007                                    size_t *nentries)
8008 {
8009     struct qemuMonitorQueryHotpluggableCpusEntry *info = NULL;
8010     size_t ninfo = 0;
8011     int ret = -1;
8012     size_t i;
8013     virJSONValuePtr data;
8014     virJSONValuePtr cmd;
8015     virJSONValuePtr reply = NULL;
8016     virJSONValuePtr vcpu;
8017
8018     if (!(cmd = qemuMonitorJSONMakeCommand("query-hotpluggable-cpus", NULL)))
8019         return -1;
8020
8021     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8022         goto cleanup;
8023
8024     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8025         goto cleanup;
8026
8027     data = virJSONValueObjectGet(reply, "return");
8028     ninfo = virJSONValueArraySize(data);
8029
8030     if (VIR_ALLOC_N(info, ninfo) < 0)
8031         goto cleanup;
8032
8033     for (i = 0; i < ninfo; i++) {
8034         vcpu = virJSONValueArrayGet(data, i);
8035
8036         if (qemuMonitorJSONProcessHotpluggableCpusReply(vcpu, info + i) < 0)
8037             goto cleanup;
8038     }
8039
8040     qsort(info, ninfo, sizeof(*info), qemuMonitorQueryHotpluggableCpusEntrySort);
8041
8042     VIR_STEAL_PTR(*entries, info);
8043     *nentries = ninfo;
8044     ret = 0;
8045
8046  cleanup:
8047     qemuMonitorQueryHotpluggableCpusFree(info, ninfo);
8048     virJSONValueFree(cmd);
8049     virJSONValueFree(reply);
8050     return ret;
8051 }
8052
8053
8054 virJSONValuePtr
8055 qemuMonitorJSONQueryQMPSchema(qemuMonitorPtr mon)
8056 {
8057     virJSONValuePtr cmd;
8058     virJSONValuePtr reply = NULL;
8059     virJSONValuePtr ret = NULL;
8060
8061     if (!(cmd = qemuMonitorJSONMakeCommand("query-qmp-schema", NULL)))
8062         return NULL;
8063
8064     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8065         goto cleanup;
8066
8067     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8068         goto cleanup;
8069
8070     ret = virJSONValueObjectStealArray(reply, "return");
8071
8072  cleanup:
8073     virJSONValueFree(cmd);
8074     virJSONValueFree(reply);
8075
8076     return ret;
8077 }
8078
8079
8080 int
8081 qemuMonitorJSONSetBlockThreshold(qemuMonitorPtr mon,
8082                                  const char *nodename,
8083                                  unsigned long long threshold)
8084 {
8085     virJSONValuePtr cmd;
8086     virJSONValuePtr reply = NULL;
8087     int ret = -1;
8088
8089     if (!(cmd = qemuMonitorJSONMakeCommand("block-set-write-threshold",
8090                                            "s:node-name", nodename,
8091                                            "U:write-threshold", threshold,
8092                                            NULL)))
8093         return -1;
8094
8095     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8096         goto cleanup;
8097
8098     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8099         goto cleanup;
8100
8101     ret = 0;
8102
8103  cleanup:
8104     virJSONValueFree(cmd);
8105     virJSONValueFree(reply);
8106
8107     return ret;
8108 }
8109
8110
8111 virJSONValuePtr
8112 qemuMonitorJSONQueryNamedBlockNodes(qemuMonitorPtr mon)
8113 {
8114     virJSONValuePtr cmd;
8115     virJSONValuePtr reply = NULL;
8116     virJSONValuePtr ret = NULL;
8117
8118     if (!(cmd = qemuMonitorJSONMakeCommand("query-named-block-nodes", NULL)))
8119         return NULL;
8120
8121     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8122         goto cleanup;
8123
8124     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8125         goto cleanup;
8126
8127     ret = virJSONValueObjectStealArray(reply, "return");
8128
8129  cleanup:
8130     virJSONValueFree(cmd);
8131     virJSONValueFree(reply);
8132
8133     return ret;
8134 }
8135
8136
8137 int
8138 qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
8139                                  const char *action)
8140 {
8141     virJSONValuePtr cmd;
8142     virJSONValuePtr reply = NULL;
8143     int ret = -1;
8144
8145     if (!(cmd = qemuMonitorJSONMakeCommand("watchdog-set-action",
8146                                            "s:action", action,
8147                                            NULL)))
8148         return -1;
8149
8150     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8151         goto cleanup;
8152
8153     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8154         goto cleanup;
8155
8156     ret = 0;
8157
8158  cleanup:
8159     virJSONValueFree(cmd);
8160     virJSONValueFree(reply);
8161     return ret;
8162 }
8163
8164
8165 int
8166 qemuMonitorJSONBlockdevAdd(qemuMonitorPtr mon,
8167                            virJSONValuePtr props)
8168 {
8169     virJSONValuePtr cmd;
8170     virJSONValuePtr reply = NULL;
8171     int ret = -1;
8172
8173     if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-add", props)))
8174         return -1;
8175
8176     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8177         goto cleanup;
8178
8179     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8180         goto cleanup;
8181
8182     ret = 0;
8183
8184  cleanup:
8185     virJSONValueFree(cmd);
8186     virJSONValueFree(reply);
8187     return ret;
8188 }
8189
8190
8191 int
8192 qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
8193                            const char *nodename)
8194 {
8195     virJSONValuePtr cmd;
8196     virJSONValuePtr reply = NULL;
8197     int ret = -1;
8198
8199     if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-del",
8200                                            "s:node-name", nodename,
8201                                            NULL)))
8202         return -1;
8203
8204     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8205         goto cleanup;
8206
8207     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8208         goto cleanup;
8209
8210     ret = 0;
8211
8212  cleanup:
8213     virJSONValueFree(cmd);
8214     virJSONValueFree(reply);
8215     return ret;
8216 }
8217
8218
8219 int
8220 qemuMonitorJSONBlockdevTrayOpen(qemuMonitorPtr mon,
8221                                 const char *id,
8222                                 bool force)
8223 {
8224     virJSONValuePtr cmd;
8225     virJSONValuePtr reply = NULL;
8226     int ret = -1;
8227
8228     if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-open-tray",
8229                                            "s:id", id,
8230                                            "b:force", force, NULL)))
8231         return -1;
8232
8233     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8234         goto cleanup;
8235
8236     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8237         goto cleanup;
8238
8239     ret = 0;
8240
8241  cleanup:
8242     virJSONValueFree(cmd);
8243     virJSONValueFree(reply);
8244     return ret;
8245 }
8246
8247
8248 int
8249 qemuMonitorJSONBlockdevTrayClose(qemuMonitorPtr mon,
8250                                  const char *id)
8251 {
8252     virJSONValuePtr cmd;
8253     virJSONValuePtr reply = NULL;
8254     int ret = -1;
8255
8256     if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-close-tray",
8257                                            "s:id", id, NULL)))
8258         return -1;
8259
8260     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8261         goto cleanup;
8262
8263     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8264         goto cleanup;
8265
8266     ret = 0;
8267
8268  cleanup:
8269     virJSONValueFree(cmd);
8270     virJSONValueFree(reply);
8271     return ret;
8272 }
8273
8274
8275 int
8276 qemuMonitorJSONBlockdevMediumRemove(qemuMonitorPtr mon,
8277                                     const char *id)
8278 {
8279     virJSONValuePtr cmd;
8280     virJSONValuePtr reply = NULL;
8281     int ret = -1;
8282
8283     if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-remove-medium",
8284                                            "s:id", id, NULL)))
8285         return -1;
8286
8287     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8288         goto cleanup;
8289
8290     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8291         goto cleanup;
8292
8293     ret = 0;
8294
8295  cleanup:
8296     virJSONValueFree(cmd);
8297     virJSONValueFree(reply);
8298     return ret;
8299 }
8300
8301
8302 int
8303 qemuMonitorJSONBlockdevMediumInsert(qemuMonitorPtr mon,
8304                                     const char *id,
8305                                     const char *nodename)
8306 {
8307     virJSONValuePtr cmd;
8308     virJSONValuePtr reply = NULL;
8309     int ret = -1;
8310
8311     if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-insert-medium",
8312                                            "s:id", id,
8313                                            "s:node-name", nodename,
8314                                            NULL)))
8315         return -1;
8316
8317     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8318         goto cleanup;
8319
8320     if (qemuMonitorJSONCheckError(cmd, reply) < 0)
8321         goto cleanup;
8322
8323     ret = 0;
8324
8325  cleanup:
8326     virJSONValueFree(cmd);
8327     virJSONValueFree(reply);
8328     return ret;
8329 }
8330
8331
8332 /**
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.
8336  *
8337  * A example JSON output:
8338  *
8339  * { "execute" : "query-sev-launch-measure" }
8340  * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
8341  */
8342 char *
8343 qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
8344 {
8345     const char *tmp;
8346     char *measurement = NULL;
8347     virJSONValuePtr cmd;
8348     virJSONValuePtr reply = NULL;
8349     virJSONValuePtr data;
8350
8351     if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
8352          return NULL;
8353
8354     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8355         goto cleanup;
8356
8357     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
8358         goto cleanup;
8359
8360     data = virJSONValueObjectGetObject(reply, "return");
8361
8362     if (!(tmp = virJSONValueObjectGetString(data, "data")))
8363         goto cleanup;
8364
8365     if (VIR_STRDUP(measurement, tmp) < 0)
8366         goto cleanup;
8367
8368  cleanup:
8369     virJSONValueFree(cmd);
8370     virJSONValueFree(reply);
8371     return measurement;
8372 }
8373
8374
8375 /*
8376  * Example return data
8377  *
8378  * "return": [
8379  *   { "connected": true, "id": "pr-helper0" }
8380  *  ]
8381  */
8382 static int
8383 qemuMonitorJSONExtractPRManagerInfo(virJSONValuePtr reply,
8384                                     virHashTablePtr info)
8385 {
8386     qemuMonitorPRManagerInfoPtr entry = NULL;
8387     virJSONValuePtr data;
8388     int ret = -1;
8389     size_t i;
8390
8391     data = virJSONValueObjectGetArray(reply, "return");
8392
8393     for (i = 0; i < virJSONValueArraySize(data); i++) {
8394         virJSONValuePtr prManager = virJSONValueArrayGet(data, i);
8395         const char *alias;
8396
8397         if (!(alias = virJSONValueObjectGetString(prManager, "id")))
8398             goto malformed;
8399
8400         if (VIR_ALLOC(entry) < 0)
8401             goto cleanup;
8402
8403         if (virJSONValueObjectGetBoolean(prManager,
8404                                          "connected",
8405                                          &entry->connected) < 0) {
8406             goto malformed;
8407         }
8408
8409         if (virHashAddEntry(info, alias, entry) < 0)
8410             goto cleanup;
8411
8412         entry = NULL;
8413     }
8414
8415     ret = 0;
8416  cleanup:
8417     VIR_FREE(entry);
8418     return ret;
8419
8420  malformed:
8421     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8422                    _("malformed prManager reply"));
8423     goto cleanup;
8424 }
8425
8426
8427 int
8428 qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon,
8429                                 virHashTablePtr info)
8430 {
8431     int ret = -1;
8432     virJSONValuePtr cmd;
8433     virJSONValuePtr reply = NULL;
8434
8435     if (!(cmd = qemuMonitorJSONMakeCommand("query-pr-managers",
8436                                            NULL)))
8437         return -1;
8438
8439     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8440         goto cleanup;
8441
8442     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
8443         goto cleanup;
8444
8445     ret = qemuMonitorJSONExtractPRManagerInfo(reply, info);
8446  cleanup:
8447     virJSONValueFree(cmd);
8448     virJSONValueFree(reply);
8449     return ret;
8450
8451 }
8452
8453
8454 static int
8455 qemuMonitorJSONExtractCurrentMachineInfo(virJSONValuePtr reply,
8456                                          qemuMonitorCurrentMachineInfoPtr info)
8457 {
8458     virJSONValuePtr data;
8459
8460     data = virJSONValueObjectGetObject(reply, "return");
8461     if (!data)
8462         goto malformed;
8463
8464     if (virJSONValueObjectGetBoolean(data, "wakeup-suspend-support",
8465                                      &info->wakeupSuspendSupport) < 0)
8466         goto malformed;
8467
8468     return 0;
8469
8470  malformed:
8471     virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8472                    _("malformed qemu-current-machine reply"));
8473     return -1;
8474 }
8475
8476
8477 int
8478 qemuMonitorJSONGetCurrentMachineInfo(qemuMonitorPtr mon,
8479                                      qemuMonitorCurrentMachineInfoPtr info)
8480 {
8481     int ret = -1;
8482     virJSONValuePtr cmd;
8483     virJSONValuePtr reply = NULL;
8484
8485     if (!(cmd = qemuMonitorJSONMakeCommand("query-current-machine",
8486                                            NULL)))
8487         return -1;
8488
8489     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
8490         goto cleanup;
8491
8492     if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
8493         goto cleanup;
8494
8495     ret = qemuMonitorJSONExtractCurrentMachineInfo(reply, info);
8496
8497  cleanup:
8498     virJSONValueFree(cmd);
8499     virJSONValueFree(reply);
8500     return ret;
8501 }