xref: /openbmc/qemu/monitor/qmp-cmds.c (revision e2f948a8)
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 "sysemu/kvm.h"
28 #include "sysemu/runstate.h"
29 #include "sysemu/runstate-action.h"
30 #include "sysemu/blockdev.h"
31 #include "sysemu/block-backend.h"
32 #include "qapi/error.h"
33 #include "qapi/qapi-commands-acpi.h"
34 #include "qapi/qapi-commands-block.h"
35 #include "qapi/qapi-commands-control.h"
36 #include "qapi/qapi-commands-machine.h"
37 #include "qapi/qapi-commands-misc.h"
38 #include "qapi/qapi-commands-ui.h"
39 #include "qapi/qmp/qerror.h"
40 #include "hw/mem/memory-device.h"
41 #include "hw/acpi/acpi_dev_interface.h"
42 
43 NameInfo *qmp_query_name(Error **errp)
44 {
45     NameInfo *info = g_malloc0(sizeof(*info));
46 
47     if (qemu_name) {
48         info->has_name = true;
49         info->name = g_strdup(qemu_name);
50     }
51 
52     return info;
53 }
54 
55 KvmInfo *qmp_query_kvm(Error **errp)
56 {
57     KvmInfo *info = g_malloc0(sizeof(*info));
58 
59     info->enabled = kvm_enabled();
60     info->present = accel_find("kvm");
61 
62     return info;
63 }
64 
65 UuidInfo *qmp_query_uuid(Error **errp)
66 {
67     UuidInfo *info = g_malloc0(sizeof(*info));
68 
69     info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
70     return info;
71 }
72 
73 void qmp_quit(Error **errp)
74 {
75     shutdown_action = SHUTDOWN_ACTION_POWEROFF;
76     qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
77 }
78 
79 void qmp_stop(Error **errp)
80 {
81     /* if there is a dump in background, we should wait until the dump
82      * finished */
83     if (dump_in_progress()) {
84         error_setg(errp, "There is a dump in process, please wait.");
85         return;
86     }
87 
88     if (runstate_check(RUN_STATE_INMIGRATE)) {
89         autostart = 0;
90     } else {
91         vm_stop(RUN_STATE_PAUSED);
92     }
93 }
94 
95 void qmp_system_reset(Error **errp)
96 {
97     qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
98 }
99 
100 void qmp_system_powerdown(Error **errp)
101 {
102     qemu_system_powerdown_request();
103 }
104 
105 void qmp_cont(Error **errp)
106 {
107     BlockBackend *blk;
108     BlockJob *job;
109     Error *local_err = NULL;
110 
111     /* if there is a dump in background, we should wait until the dump
112      * finished */
113     if (dump_in_progress()) {
114         error_setg(errp, "There is a dump in process, please wait.");
115         return;
116     }
117 
118     if (runstate_needs_reset()) {
119         error_setg(errp, "Resetting the Virtual Machine is required");
120         return;
121     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
122         return;
123     } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
124         error_setg(errp, "Migration is not finalized yet");
125         return;
126     }
127 
128     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
129         blk_iostatus_reset(blk);
130     }
131 
132     for (job = block_job_next(NULL); job; job = block_job_next(job)) {
133         block_job_iostatus_reset(job);
134     }
135 
136     /* Continuing after completed migration. Images have been inactivated to
137      * allow the destination to take control. Need to get control back now.
138      *
139      * If there are no inactive block nodes (e.g. because the VM was just
140      * paused rather than completing a migration), bdrv_inactivate_all() simply
141      * doesn't do anything. */
142     bdrv_invalidate_cache_all(&local_err);
143     if (local_err) {
144         error_propagate(errp, local_err);
145         return;
146     }
147 
148     if (runstate_check(RUN_STATE_INMIGRATE)) {
149         autostart = 1;
150     } else {
151         vm_start();
152     }
153 }
154 
155 void qmp_system_wakeup(Error **errp)
156 {
157     if (!qemu_wakeup_suspend_enabled()) {
158         error_setg(errp,
159                    "wake-up from suspend is not supported by this guest");
160         return;
161     }
162 
163     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
164 }
165 
166 void qmp_set_password(const char *protocol, const char *password,
167                       bool has_connected, const char *connected, Error **errp)
168 {
169     int disconnect_if_connected = 0;
170     int fail_if_connected = 0;
171     int rc;
172 
173     if (has_connected) {
174         if (strcmp(connected, "fail") == 0) {
175             fail_if_connected = 1;
176         } else if (strcmp(connected, "disconnect") == 0) {
177             disconnect_if_connected = 1;
178         } else if (strcmp(connected, "keep") == 0) {
179             /* nothing */
180         } else {
181             error_setg(errp, QERR_INVALID_PARAMETER, "connected");
182             return;
183         }
184     }
185 
186     if (strcmp(protocol, "spice") == 0) {
187         if (!qemu_using_spice(errp)) {
188             return;
189         }
190         rc = qemu_spice.set_passwd(password, fail_if_connected,
191                                    disconnect_if_connected);
192     } else if (strcmp(protocol, "vnc") == 0) {
193         if (fail_if_connected || disconnect_if_connected) {
194             /* vnc supports "connected=keep" only */
195             error_setg(errp, QERR_INVALID_PARAMETER, "connected");
196             return;
197         }
198         /* Note that setting an empty password will not disable login through
199          * this interface. */
200         rc = vnc_display_password(NULL, password);
201     } else {
202         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
203                    "'vnc' or 'spice'");
204         return;
205     }
206 
207     if (rc != 0) {
208         error_setg(errp, "Could not set password");
209     }
210 }
211 
212 void qmp_expire_password(const char *protocol, const char *whenstr,
213                          Error **errp)
214 {
215     time_t when;
216     int rc;
217 
218     if (strcmp(whenstr, "now") == 0) {
219         when = 0;
220     } else if (strcmp(whenstr, "never") == 0) {
221         when = TIME_MAX;
222     } else if (whenstr[0] == '+') {
223         when = time(NULL) + strtoull(whenstr+1, NULL, 10);
224     } else {
225         when = strtoull(whenstr, NULL, 10);
226     }
227 
228     if (strcmp(protocol, "spice") == 0) {
229         if (!qemu_using_spice(errp)) {
230             return;
231         }
232         rc = qemu_spice.set_pw_expire(when);
233     } else if (strcmp(protocol, "vnc") == 0) {
234         rc = vnc_display_pw_expire(NULL, when);
235     } else {
236         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
237                    "'vnc' or 'spice'");
238         return;
239     }
240 
241     if (rc != 0) {
242         error_setg(errp, "Could not set password expire time");
243     }
244 }
245 
246 #ifdef CONFIG_VNC
247 void qmp_change_vnc_password(const char *password, Error **errp)
248 {
249     if (vnc_display_password(NULL, password) < 0) {
250         error_setg(errp, "Could not set password");
251     }
252 }
253 #endif
254 
255 void qmp_add_client(const char *protocol, const char *fdname,
256                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
257                     Error **errp)
258 {
259     Chardev *s;
260     int fd;
261 
262     fd = monitor_get_fd(monitor_cur(), fdname, errp);
263     if (fd < 0) {
264         return;
265     }
266 
267     if (strcmp(protocol, "spice") == 0) {
268         if (!qemu_using_spice(errp)) {
269             close(fd);
270             return;
271         }
272         skipauth = has_skipauth ? skipauth : false;
273         tls = has_tls ? tls : false;
274         if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
275             error_setg(errp, "spice failed to add client");
276             close(fd);
277         }
278         return;
279 #ifdef CONFIG_VNC
280     } else if (strcmp(protocol, "vnc") == 0) {
281         skipauth = has_skipauth ? skipauth : false;
282         vnc_display_add_client(NULL, fd, skipauth);
283         return;
284 #endif
285     } else if ((s = qemu_chr_find(protocol)) != NULL) {
286         if (qemu_chr_add_client(s, fd) < 0) {
287             error_setg(errp, "failed to add client");
288             close(fd);
289             return;
290         }
291         return;
292     }
293 
294     error_setg(errp, "protocol '%s' is invalid", protocol);
295     close(fd);
296 }
297 
298 
299 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
300 {
301     return qmp_memory_device_list();
302 }
303 
304 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
305 {
306     bool ambig;
307     ACPIOSTInfoList *head = NULL;
308     ACPIOSTInfoList **prev = &head;
309     Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
310 
311     if (obj) {
312         AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
313         AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
314 
315         adevc->ospm_status(adev, &prev);
316     } else {
317         error_setg(errp, "command is not supported, missing ACPI device");
318     }
319 
320     return head;
321 }
322 
323 MemoryInfo *qmp_query_memory_size_summary(Error **errp)
324 {
325     MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
326     MachineState *ms = MACHINE(qdev_get_machine());
327 
328     mem_info->base_memory = ms->ram_size;
329 
330     mem_info->plugged_memory = get_plugged_memory_size();
331     mem_info->has_plugged_memory =
332         mem_info->plugged_memory != (uint64_t)-1;
333 
334     return mem_info;
335 }
336 
337 void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
338 {
339     switch (arg->type) {
340     case DISPLAY_RELOAD_TYPE_VNC:
341 #ifdef CONFIG_VNC
342         if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
343             vnc_display_reload_certs(NULL, errp);
344         }
345 #else
346         error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
347 #endif
348         break;
349     default:
350         abort();
351     }
352 }
353