xref: /qemu/monitor/qmp-cmds.c (revision 0572f558)
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/vnc.h"
27 #include "sysemu/kvm.h"
28 #include "sysemu/runstate.h"
29 #include "sysemu/arch_init.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 = kvm_available();
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     no_shutdown = 0;
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 
254 static void qmp_change_vnc_listen(const char *target, Error **errp)
255 {
256     QemuOptsList *olist = qemu_find_opts("vnc");
257     QemuOpts *opts;
258 
259     if (strstr(target, "id=")) {
260         error_setg(errp, "id not supported");
261         return;
262     }
263 
264     opts = qemu_opts_find(olist, "default");
265     if (opts) {
266         qemu_opts_del(opts);
267     }
268     opts = vnc_parse(target, errp);
269     if (!opts) {
270         return;
271     }
272 
273     vnc_display_open("default", errp);
274 }
275 
276 static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
277                            Error **errp)
278 {
279     if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
280         if (!has_arg) {
281             error_setg(errp, QERR_MISSING_PARAMETER, "password");
282         } else {
283             qmp_change_vnc_password(arg, errp);
284         }
285     } else {
286         qmp_change_vnc_listen(target, errp);
287     }
288 }
289 #endif /* !CONFIG_VNC */
290 
291 void qmp_change(const char *device, const char *target,
292                 bool has_arg, const char *arg, Error **errp)
293 {
294     if (strcmp(device, "vnc") == 0) {
295 #ifdef CONFIG_VNC
296         qmp_change_vnc(target, has_arg, arg, errp);
297 #else
298         error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
299 #endif
300     } else {
301         qmp_blockdev_change_medium(true, device, false, NULL, target,
302                                    has_arg, arg, false, 0, errp);
303     }
304 }
305 
306 void qmp_add_client(const char *protocol, const char *fdname,
307                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
308                     Error **errp)
309 {
310     Chardev *s;
311     int fd;
312 
313     fd = monitor_get_fd(monitor_cur(), fdname, errp);
314     if (fd < 0) {
315         return;
316     }
317 
318     if (strcmp(protocol, "spice") == 0) {
319         if (!qemu_using_spice(errp)) {
320             close(fd);
321             return;
322         }
323         skipauth = has_skipauth ? skipauth : false;
324         tls = has_tls ? tls : false;
325         if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
326             error_setg(errp, "spice failed to add client");
327             close(fd);
328         }
329         return;
330 #ifdef CONFIG_VNC
331     } else if (strcmp(protocol, "vnc") == 0) {
332         skipauth = has_skipauth ? skipauth : false;
333         vnc_display_add_client(NULL, fd, skipauth);
334         return;
335 #endif
336     } else if ((s = qemu_chr_find(protocol)) != NULL) {
337         if (qemu_chr_add_client(s, fd) < 0) {
338             error_setg(errp, "failed to add client");
339             close(fd);
340             return;
341         }
342         return;
343     }
344 
345     error_setg(errp, "protocol '%s' is invalid", protocol);
346     close(fd);
347 }
348 
349 
350 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
351 {
352     return qmp_memory_device_list();
353 }
354 
355 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
356 {
357     bool ambig;
358     ACPIOSTInfoList *head = NULL;
359     ACPIOSTInfoList **prev = &head;
360     Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
361 
362     if (obj) {
363         AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
364         AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
365 
366         adevc->ospm_status(adev, &prev);
367     } else {
368         error_setg(errp, "command is not supported, missing ACPI device");
369     }
370 
371     return head;
372 }
373 
374 MemoryInfo *qmp_query_memory_size_summary(Error **errp)
375 {
376     MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
377     MachineState *ms = MACHINE(qdev_get_machine());
378 
379     mem_info->base_memory = ms->ram_size;
380 
381     mem_info->plugged_memory = get_plugged_memory_size();
382     mem_info->has_plugged_memory =
383         mem_info->plugged_memory != (uint64_t)-1;
384 
385     return mem_info;
386 }
387