xref: /openbmc/qemu/monitor/qmp-cmds.c (revision 0d04c4c9)
1 /*
2  * QEMU Management Protocol commands
3  *
4  * Copyright IBM, Corp. 2011
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  * Contributions after 2012-01-13 are licensed under the terms of the
13  * GNU GPL, version 2 or (at your option) any later version.
14  */
15 
16 #include "qemu/osdep.h"
17 #include "qemu-common.h"
18 #include "qemu/cutils.h"
19 #include "qemu/option.h"
20 #include "monitor/monitor.h"
21 #include "sysemu/sysemu.h"
22 #include "qemu/config-file.h"
23 #include "qemu/uuid.h"
24 #include "chardev/char.h"
25 #include "ui/qemu-spice.h"
26 #include "ui/console.h"
27 #include "ui/dbus-display.h"
28 #include "sysemu/kvm.h"
29 #include "sysemu/runstate.h"
30 #include "sysemu/runstate-action.h"
31 #include "sysemu/blockdev.h"
32 #include "sysemu/block-backend.h"
33 #include "qapi/error.h"
34 #include "qapi/qapi-commands-acpi.h"
35 #include "qapi/qapi-commands-block.h"
36 #include "qapi/qapi-commands-control.h"
37 #include "qapi/qapi-commands-machine.h"
38 #include "qapi/qapi-commands-misc.h"
39 #include "qapi/qapi-commands-ui.h"
40 #include "qapi/type-helpers.h"
41 #include "qapi/qmp/qerror.h"
42 #include "exec/ramlist.h"
43 #include "hw/mem/memory-device.h"
44 #include "hw/acpi/acpi_dev_interface.h"
45 #include "hw/intc/intc.h"
46 #include "hw/rdma/rdma.h"
47 
48 NameInfo *qmp_query_name(Error **errp)
49 {
50     NameInfo *info = g_malloc0(sizeof(*info));
51 
52     if (qemu_name) {
53         info->has_name = true;
54         info->name = g_strdup(qemu_name);
55     }
56 
57     return info;
58 }
59 
60 KvmInfo *qmp_query_kvm(Error **errp)
61 {
62     KvmInfo *info = g_malloc0(sizeof(*info));
63 
64     info->enabled = kvm_enabled();
65     info->present = accel_find("kvm");
66 
67     return info;
68 }
69 
70 UuidInfo *qmp_query_uuid(Error **errp)
71 {
72     UuidInfo *info = g_malloc0(sizeof(*info));
73 
74     info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
75     return info;
76 }
77 
78 void qmp_quit(Error **errp)
79 {
80     shutdown_action = SHUTDOWN_ACTION_POWEROFF;
81     qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
82 }
83 
84 void qmp_stop(Error **errp)
85 {
86     /* if there is a dump in background, we should wait until the dump
87      * finished */
88     if (dump_in_progress()) {
89         error_setg(errp, "There is a dump in process, please wait.");
90         return;
91     }
92 
93     if (runstate_check(RUN_STATE_INMIGRATE)) {
94         autostart = 0;
95     } else {
96         vm_stop(RUN_STATE_PAUSED);
97     }
98 }
99 
100 void qmp_system_reset(Error **errp)
101 {
102     qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
103 }
104 
105 void qmp_system_powerdown(Error **errp)
106 {
107     qemu_system_powerdown_request();
108 }
109 
110 void qmp_cont(Error **errp)
111 {
112     BlockBackend *blk;
113     BlockJob *job;
114     Error *local_err = NULL;
115 
116     /* if there is a dump in background, we should wait until the dump
117      * finished */
118     if (dump_in_progress()) {
119         error_setg(errp, "There is a dump in process, please wait.");
120         return;
121     }
122 
123     if (runstate_needs_reset()) {
124         error_setg(errp, "Resetting the Virtual Machine is required");
125         return;
126     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
127         return;
128     } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
129         error_setg(errp, "Migration is not finalized yet");
130         return;
131     }
132 
133     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
134         blk_iostatus_reset(blk);
135     }
136 
137     for (job = block_job_next(NULL); job; job = block_job_next(job)) {
138         block_job_iostatus_reset(job);
139     }
140 
141     /* Continuing after completed migration. Images have been inactivated to
142      * allow the destination to take control. Need to get control back now.
143      *
144      * If there are no inactive block nodes (e.g. because the VM was just
145      * paused rather than completing a migration), bdrv_inactivate_all() simply
146      * doesn't do anything. */
147     bdrv_invalidate_cache_all(&local_err);
148     if (local_err) {
149         error_propagate(errp, local_err);
150         return;
151     }
152 
153     if (runstate_check(RUN_STATE_INMIGRATE)) {
154         autostart = 1;
155     } else {
156         vm_start();
157     }
158 }
159 
160 void qmp_system_wakeup(Error **errp)
161 {
162     if (!qemu_wakeup_suspend_enabled()) {
163         error_setg(errp,
164                    "wake-up from suspend is not supported by this guest");
165         return;
166     }
167 
168     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
169 }
170 
171 void qmp_set_password(const char *protocol, const char *password,
172                       bool has_connected, const char *connected, Error **errp)
173 {
174     int disconnect_if_connected = 0;
175     int fail_if_connected = 0;
176     int rc;
177 
178     if (has_connected) {
179         if (strcmp(connected, "fail") == 0) {
180             fail_if_connected = 1;
181         } else if (strcmp(connected, "disconnect") == 0) {
182             disconnect_if_connected = 1;
183         } else if (strcmp(connected, "keep") == 0) {
184             /* nothing */
185         } else {
186             error_setg(errp, QERR_INVALID_PARAMETER, "connected");
187             return;
188         }
189     }
190 
191     if (strcmp(protocol, "spice") == 0) {
192         if (!qemu_using_spice(errp)) {
193             return;
194         }
195         rc = qemu_spice.set_passwd(password, fail_if_connected,
196                                    disconnect_if_connected);
197     } else if (strcmp(protocol, "vnc") == 0) {
198         if (fail_if_connected || disconnect_if_connected) {
199             /* vnc supports "connected=keep" only */
200             error_setg(errp, QERR_INVALID_PARAMETER, "connected");
201             return;
202         }
203         /* Note that setting an empty password will not disable login through
204          * this interface. */
205         rc = vnc_display_password(NULL, password);
206     } else {
207         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
208                    "'vnc' or 'spice'");
209         return;
210     }
211 
212     if (rc != 0) {
213         error_setg(errp, "Could not set password");
214     }
215 }
216 
217 void qmp_expire_password(const char *protocol, const char *whenstr,
218                          Error **errp)
219 {
220     time_t when;
221     int rc;
222 
223     if (strcmp(whenstr, "now") == 0) {
224         when = 0;
225     } else if (strcmp(whenstr, "never") == 0) {
226         when = TIME_MAX;
227     } else if (whenstr[0] == '+') {
228         when = time(NULL) + strtoull(whenstr+1, NULL, 10);
229     } else {
230         when = strtoull(whenstr, NULL, 10);
231     }
232 
233     if (strcmp(protocol, "spice") == 0) {
234         if (!qemu_using_spice(errp)) {
235             return;
236         }
237         rc = qemu_spice.set_pw_expire(when);
238     } else if (strcmp(protocol, "vnc") == 0) {
239         rc = vnc_display_pw_expire(NULL, when);
240     } else {
241         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
242                    "'vnc' or 'spice'");
243         return;
244     }
245 
246     if (rc != 0) {
247         error_setg(errp, "Could not set password expire time");
248     }
249 }
250 
251 #ifdef CONFIG_VNC
252 void qmp_change_vnc_password(const char *password, Error **errp)
253 {
254     if (vnc_display_password(NULL, password) < 0) {
255         error_setg(errp, "Could not set password");
256     }
257 }
258 #endif
259 
260 void qmp_add_client(const char *protocol, const char *fdname,
261                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
262                     Error **errp)
263 {
264     Chardev *s;
265     int fd;
266 
267     fd = monitor_get_fd(monitor_cur(), fdname, errp);
268     if (fd < 0) {
269         return;
270     }
271 
272     if (strcmp(protocol, "spice") == 0) {
273         if (!qemu_using_spice(errp)) {
274             close(fd);
275             return;
276         }
277         skipauth = has_skipauth ? skipauth : false;
278         tls = has_tls ? tls : false;
279         if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
280             error_setg(errp, "spice failed to add client");
281             close(fd);
282         }
283         return;
284 #ifdef CONFIG_VNC
285     } else if (strcmp(protocol, "vnc") == 0) {
286         skipauth = has_skipauth ? skipauth : false;
287         vnc_display_add_client(NULL, fd, skipauth);
288         return;
289 #endif
290 #ifdef CONFIG_DBUS_DISPLAY
291     } else if (strcmp(protocol, "@dbus-display") == 0) {
292         if (!qemu_using_dbus_display(errp)) {
293             close(fd);
294             return;
295         }
296         if (!qemu_dbus_display.add_client(fd, errp)) {
297             close(fd);
298             return;
299         }
300         return;
301 #endif
302     } else if ((s = qemu_chr_find(protocol)) != NULL) {
303         if (qemu_chr_add_client(s, fd) < 0) {
304             error_setg(errp, "failed to add client");
305             close(fd);
306             return;
307         }
308         return;
309     }
310 
311     error_setg(errp, "protocol '%s' is invalid", protocol);
312     close(fd);
313 }
314 
315 
316 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
317 {
318     return qmp_memory_device_list();
319 }
320 
321 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
322 {
323     bool ambig;
324     ACPIOSTInfoList *head = NULL;
325     ACPIOSTInfoList **prev = &head;
326     Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
327 
328     if (obj) {
329         AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
330         AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
331 
332         adevc->ospm_status(adev, &prev);
333     } else {
334         error_setg(errp, "command is not supported, missing ACPI device");
335     }
336 
337     return head;
338 }
339 
340 MemoryInfo *qmp_query_memory_size_summary(Error **errp)
341 {
342     MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
343     MachineState *ms = MACHINE(qdev_get_machine());
344 
345     mem_info->base_memory = ms->ram_size;
346 
347     mem_info->plugged_memory = get_plugged_memory_size();
348     mem_info->has_plugged_memory =
349         mem_info->plugged_memory != (uint64_t)-1;
350 
351     return mem_info;
352 }
353 
354 void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
355 {
356     switch (arg->type) {
357     case DISPLAY_RELOAD_TYPE_VNC:
358 #ifdef CONFIG_VNC
359         if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
360             vnc_display_reload_certs(NULL, errp);
361         }
362 #else
363         error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
364 #endif
365         break;
366     default:
367         abort();
368     }
369 }
370 
371 static int qmp_x_query_rdma_foreach(Object *obj, void *opaque)
372 {
373     RdmaProvider *rdma;
374     RdmaProviderClass *k;
375     GString *buf = opaque;
376 
377     if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
378         rdma = RDMA_PROVIDER(obj);
379         k = RDMA_PROVIDER_GET_CLASS(obj);
380         if (k->format_statistics) {
381             k->format_statistics(rdma, buf);
382         } else {
383             g_string_append_printf(buf,
384                                    "RDMA statistics not available for %s.\n",
385                                    object_get_typename(obj));
386         }
387     }
388 
389     return 0;
390 }
391 
392 HumanReadableText *qmp_x_query_rdma(Error **errp)
393 {
394     g_autoptr(GString) buf = g_string_new("");
395 
396     object_child_foreach_recursive(object_get_root(),
397                                    qmp_x_query_rdma_foreach, buf);
398 
399     return human_readable_text_from_str(buf);
400 }
401 
402 HumanReadableText *qmp_x_query_ramblock(Error **errp)
403 {
404     g_autoptr(GString) buf = ram_block_format();
405 
406     return human_readable_text_from_str(buf);
407 }
408 
409 static int qmp_x_query_irq_foreach(Object *obj, void *opaque)
410 {
411     InterruptStatsProvider *intc;
412     InterruptStatsProviderClass *k;
413     GString *buf = opaque;
414 
415     if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
416         intc = INTERRUPT_STATS_PROVIDER(obj);
417         k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
418         uint64_t *irq_counts;
419         unsigned int nb_irqs, i;
420         if (k->get_statistics &&
421             k->get_statistics(intc, &irq_counts, &nb_irqs)) {
422             if (nb_irqs > 0) {
423                 g_string_append_printf(buf, "IRQ statistics for %s:\n",
424                                        object_get_typename(obj));
425                 for (i = 0; i < nb_irqs; i++) {
426                     if (irq_counts[i] > 0) {
427                         g_string_append_printf(buf, "%2d: %" PRId64 "\n", i,
428                                                irq_counts[i]);
429                     }
430                 }
431             }
432         } else {
433             g_string_append_printf(buf,
434                                    "IRQ statistics not available for %s.\n",
435                                    object_get_typename(obj));
436         }
437     }
438 
439     return 0;
440 }
441 
442 HumanReadableText *qmp_x_query_irq(Error **errp)
443 {
444     g_autoptr(GString) buf = g_string_new("");
445 
446     object_child_foreach_recursive(object_get_root(),
447                                    qmp_x_query_irq_foreach, buf);
448 
449     return human_readable_text_from_str(buf);
450 }
451