]> git.ipfire.org Git - thirdparty/qemu.git/blame - monitor/qmp-cmds.c
qom: Move QMP command handlers to qom/
[thirdparty/qemu.git] / monitor / qmp-cmds.c
CommitLineData
48a32bed 1/*
f1b3ccfa 2 * QEMU Management Protocol commands
48a32bed
AL
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 *
6b620ca3
PB
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.
48a32bed
AL
14 */
15
d38ea87a 16#include "qemu/osdep.h"
a8d25326 17#include "qemu-common.h"
67a1de0d 18#include "qemu-version.h"
f348b6d1 19#include "qemu/cutils.h"
922a01a0 20#include "qemu/option.h"
a0b1a66e 21#include "monitor/monitor.h"
9c17d615 22#include "sysemu/sysemu.h"
213dcb06 23#include "qemu/config-file.h"
cea25275 24#include "qemu/uuid.h"
8228e353 25#include "chardev/char.h"
fbf796fd
LC
26#include "ui/qemu-spice.h"
27#include "ui/vnc.h"
9c17d615
PB
28#include "sysemu/kvm.h"
29#include "sysemu/arch_init.h"
9c17d615 30#include "sysemu/blockdev.h"
373340b2 31#include "sysemu/block-backend.h"
e688df6b 32#include "qapi/error.h"
112ed241
MA
33#include "qapi/qapi-commands-block-core.h"
34#include "qapi/qapi-commands-misc.h"
35#include "qapi/qapi-commands-ui.h"
cc7a8ea7 36#include "qapi/qmp/qerror.h"
69ca3ea5 37#include "hw/boards.h"
2cc0e2e8 38#include "hw/mem/memory-device.h"
02419bcb 39#include "hw/acpi/acpi_dev_interface.h"
48a32bed
AL
40
41NameInfo *qmp_query_name(Error **errp)
42{
43 NameInfo *info = g_malloc0(sizeof(*info));
44
45 if (qemu_name) {
46 info->has_name = true;
47 info->name = g_strdup(qemu_name);
48 }
49
50 return info;
51}
b9c15f16 52
7daecb30 53VersionInfo *qmp_query_version(Error **errp)
b9c15f16 54{
4752cdbb 55 VersionInfo *info = g_new0(VersionInfo, 1);
b9c15f16 56
4752cdbb 57 info->qemu = g_new0(VersionTriple, 1);
3688d8c7
MAL
58 info->qemu->major = QEMU_VERSION_MAJOR;
59 info->qemu->minor = QEMU_VERSION_MINOR;
60 info->qemu->micro = QEMU_VERSION_MICRO;
b9c15f16
LC
61 info->package = g_strdup(QEMU_PKGVERSION);
62
63 return info;
64}
292a2602
LC
65
66KvmInfo *qmp_query_kvm(Error **errp)
67{
68 KvmInfo *info = g_malloc0(sizeof(*info));
69
70 info->enabled = kvm_enabled();
71 info->present = kvm_available();
72
73 return info;
74}
75
efab767e
LC
76UuidInfo *qmp_query_uuid(Error **errp)
77{
78 UuidInfo *info = g_malloc0(sizeof(*info));
efab767e 79
9c5ce8db 80 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
efab767e
LC
81 return info;
82}
83
7daecb30 84void qmp_quit(Error **errp)
7a7f325e
LC
85{
86 no_shutdown = 0;
92548938 87 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
7a7f325e
LC
88}
89
5f158f21
LC
90void qmp_stop(Error **errp)
91{
65d64f36
PX
92 /* if there is a dump in background, we should wait until the dump
93 * finished */
94 if (dump_in_progress()) {
95 error_setg(errp, "There is a dump in process, please wait.");
96 return;
97 }
98
1e998146
PB
99 if (runstate_check(RUN_STATE_INMIGRATE)) {
100 autostart = 0;
101 } else {
102 vm_stop(RUN_STATE_PAUSED);
103 }
5f158f21
LC
104}
105
38d22653
LC
106void qmp_system_reset(Error **errp)
107{
92548938 108 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
38d22653 109}
5bc465e4
LC
110
111void qmp_system_powerdown(Error **erp)
112{
113 qemu_system_powerdown_request();
114}
755f1968 115
69ca3ea5
IM
116void qmp_cpu_add(int64_t id, Error **errp)
117{
0056ae24
MA
118 MachineClass *mc;
119
120 mc = MACHINE_GET_CLASS(current_machine);
958db90c
MA
121 if (mc->hot_add_cpu) {
122 mc->hot_add_cpu(id, errp);
69ca3ea5
IM
123 } else {
124 error_setg(errp, "Not supported");
125 }
126}
127
361ac948 128void qmp_x_exit_preconfig(Error **errp)
047f7038
IM
129{
130 if (!runstate_check(RUN_STATE_PRECONFIG)) {
131 error_setg(errp, "The command is permitted only in '%s' state",
132 RunState_str(RUN_STATE_PRECONFIG));
133 return;
134 }
135 qemu_exit_preconfig_request();
136}
137
e42e818b
LC
138void qmp_cont(Error **errp)
139{
373340b2 140 BlockBackend *blk;
68d00e42 141 BlockJob *job;
788cf9f8 142 Error *local_err = NULL;
e42e818b 143
65d64f36
PX
144 /* if there is a dump in background, we should wait until the dump
145 * finished */
146 if (dump_in_progress()) {
147 error_setg(errp, "There is a dump in process, please wait.");
148 return;
149 }
150
ede085b3 151 if (runstate_needs_reset()) {
f231b88d 152 error_setg(errp, "Resetting the Virtual Machine is required");
e42e818b 153 return;
ad02b96a
LC
154 } else if (runstate_check(RUN_STATE_SUSPENDED)) {
155 return;
9183dd15
VSO
156 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
157 error_setg(errp, "Migration is not finalized yet");
158 return;
e42e818b
LC
159 }
160
373340b2
HR
161 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
162 blk_iostatus_reset(blk);
ab31979a 163 }
7c8eece4 164
68d00e42
VSO
165 for (job = block_job_next(NULL); job; job = block_job_next(job)) {
166 block_job_iostatus_reset(job);
167 }
168
76b1c7fe 169 /* Continuing after completed migration. Images have been inactivated to
ace21a58
KW
170 * allow the destination to take control. Need to get control back now.
171 *
172 * If there are no inactive block nodes (e.g. because the VM was just
173 * paused rather than completing a migration), bdrv_inactivate_all() simply
174 * doesn't do anything. */
175 bdrv_invalidate_cache_all(&local_err);
176 if (local_err) {
177 error_propagate(errp, local_err);
178 return;
76b1c7fe
KW
179 }
180
1e998146
PB
181 if (runstate_check(RUN_STATE_INMIGRATE)) {
182 autostart = 1;
183 } else {
184 vm_start();
185 }
e42e818b 186}
b4b12c62 187
9b9df25a
GH
188void qmp_system_wakeup(Error **errp)
189{
fb064112
DHB
190 if (!qemu_wakeup_suspend_enabled()) {
191 error_setg(errp,
192 "wake-up from suspend is not supported by this guest");
193 return;
194 }
195
196 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
9b9df25a
GH
197}
198
fbf796fd
LC
199void qmp_set_password(const char *protocol, const char *password,
200 bool has_connected, const char *connected, Error **errp)
201{
202 int disconnect_if_connected = 0;
203 int fail_if_connected = 0;
204 int rc;
205
206 if (has_connected) {
207 if (strcmp(connected, "fail") == 0) {
208 fail_if_connected = 1;
209 } else if (strcmp(connected, "disconnect") == 0) {
210 disconnect_if_connected = 1;
211 } else if (strcmp(connected, "keep") == 0) {
212 /* nothing */
213 } else {
c6bd8c70 214 error_setg(errp, QERR_INVALID_PARAMETER, "connected");
fbf796fd
LC
215 return;
216 }
217 }
218
219 if (strcmp(protocol, "spice") == 0) {
b25d81ba 220 if (!qemu_using_spice(errp)) {
fbf796fd
LC
221 return;
222 }
223 rc = qemu_spice_set_passwd(password, fail_if_connected,
224 disconnect_if_connected);
225 if (rc != 0) {
c6bd8c70 226 error_setg(errp, QERR_SET_PASSWD_FAILED);
fbf796fd
LC
227 }
228 return;
229 }
230
231 if (strcmp(protocol, "vnc") == 0) {
232 if (fail_if_connected || disconnect_if_connected) {
233 /* vnc supports "connected=keep" only */
c6bd8c70 234 error_setg(errp, QERR_INVALID_PARAMETER, "connected");
fbf796fd
LC
235 return;
236 }
237 /* Note that setting an empty password will not disable login through
238 * this interface. */
239 rc = vnc_display_password(NULL, password);
240 if (rc < 0) {
c6bd8c70 241 error_setg(errp, QERR_SET_PASSWD_FAILED);
fbf796fd
LC
242 }
243 return;
244 }
245
c6bd8c70 246 error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
fbf796fd 247}
9ad5372d
LC
248
249void qmp_expire_password(const char *protocol, const char *whenstr,
250 Error **errp)
251{
252 time_t when;
253 int rc;
254
255 if (strcmp(whenstr, "now") == 0) {
256 when = 0;
257 } else if (strcmp(whenstr, "never") == 0) {
258 when = TIME_MAX;
259 } else if (whenstr[0] == '+') {
260 when = time(NULL) + strtoull(whenstr+1, NULL, 10);
261 } else {
262 when = strtoull(whenstr, NULL, 10);
263 }
264
265 if (strcmp(protocol, "spice") == 0) {
b25d81ba 266 if (!qemu_using_spice(errp)) {
9ad5372d
LC
267 return;
268 }
269 rc = qemu_spice_set_pw_expire(when);
270 if (rc != 0) {
c6bd8c70 271 error_setg(errp, QERR_SET_PASSWD_FAILED);
9ad5372d
LC
272 }
273 return;
274 }
275
276 if (strcmp(protocol, "vnc") == 0) {
277 rc = vnc_display_pw_expire(NULL, when);
278 if (rc != 0) {
c6bd8c70 279 error_setg(errp, QERR_SET_PASSWD_FAILED);
9ad5372d
LC
280 }
281 return;
282 }
283
c6bd8c70 284 error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
9ad5372d 285}
270b243f 286
333a96ec 287#ifdef CONFIG_VNC
270b243f
LC
288void qmp_change_vnc_password(const char *password, Error **errp)
289{
290 if (vnc_display_password(NULL, password) < 0) {
c6bd8c70 291 error_setg(errp, QERR_SET_PASSWD_FAILED);
270b243f
LC
292 }
293}
333a96ec 294
007fcd3e 295static void qmp_change_vnc_listen(const char *target, Error **errp)
333a96ec 296{
4db14629
GH
297 QemuOptsList *olist = qemu_find_opts("vnc");
298 QemuOpts *opts;
299
300 if (strstr(target, "id=")) {
301 error_setg(errp, "id not supported");
302 return;
303 }
304
305 opts = qemu_opts_find(olist, "default");
306 if (opts) {
307 qemu_opts_del(opts);
308 }
70b94331 309 opts = vnc_parse(target, errp);
f7801c5c
GA
310 if (!opts) {
311 return;
312 }
313
4db14629 314 vnc_display_open("default", errp);
333a96ec
LC
315}
316
317static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
318 Error **errp)
319{
320 if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
321 if (!has_arg) {
c6bd8c70 322 error_setg(errp, QERR_MISSING_PARAMETER, "password");
333a96ec
LC
323 } else {
324 qmp_change_vnc_password(arg, errp);
325 }
326 } else {
327 qmp_change_vnc_listen(target, errp);
328 }
329}
333a96ec
LC
330#endif /* !CONFIG_VNC */
331
332void qmp_change(const char *device, const char *target,
7daecb30 333 bool has_arg, const char *arg, Error **errp)
333a96ec
LC
334{
335 if (strcmp(device, "vnc") == 0) {
05eb4a25 336#ifdef CONFIG_VNC
7daecb30 337 qmp_change_vnc(target, has_arg, arg, errp);
05eb4a25
MAL
338#else
339 error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
340#endif
333a96ec 341 } else {
70e2cb3b
KW
342 qmp_blockdev_change_medium(true, device, false, NULL, target,
343 has_arg, arg, false, 0, errp);
333a96ec
LC
344 }
345}
5eeee3fa 346
b224e5e2
LC
347void qmp_add_client(const char *protocol, const char *fdname,
348 bool has_skipauth, bool skipauth, bool has_tls, bool tls,
349 Error **errp)
350{
0ec7b3e7 351 Chardev *s;
b224e5e2
LC
352 int fd;
353
354 fd = monitor_get_fd(cur_mon, fdname, errp);
355 if (fd < 0) {
356 return;
357 }
358
359 if (strcmp(protocol, "spice") == 0) {
b25d81ba 360 if (!qemu_using_spice(errp)) {
b224e5e2
LC
361 close(fd);
362 return;
363 }
364 skipauth = has_skipauth ? skipauth : false;
365 tls = has_tls ? tls : false;
366 if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
367 error_setg(errp, "spice failed to add client");
368 close(fd);
369 }
370 return;
371#ifdef CONFIG_VNC
372 } else if (strcmp(protocol, "vnc") == 0) {
373 skipauth = has_skipauth ? skipauth : false;
374 vnc_display_add_client(NULL, fd, skipauth);
375 return;
376#endif
377 } else if ((s = qemu_chr_find(protocol)) != NULL) {
378 if (qemu_chr_add_client(s, fd) < 0) {
379 error_setg(errp, "failed to add client");
380 close(fd);
381 return;
382 }
383 return;
384 }
385
386 error_setg(errp, "protocol '%s' is invalid", protocol);
387 close(fd);
388}
ab2d0531 389
cff8b2c6 390
6f2e2730
IM
391MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
392{
2cc0e2e8 393 return qmp_memory_device_list();
6f2e2730 394}
02419bcb
IM
395
396ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
397{
398 bool ambig;
399 ACPIOSTInfoList *head = NULL;
400 ACPIOSTInfoList **prev = &head;
401 Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
402
403 if (obj) {
404 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
405 AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
406
407 adevc->ospm_status(adev, &prev);
408 } else {
409 error_setg(errp, "command is not supported, missing ACPI device");
410 }
411
412 return head;
413}
9aa3397f
VG
414
415MemoryInfo *qmp_query_memory_size_summary(Error **errp)
416{
417 MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
418
419 mem_info->base_memory = ram_size;
420
421 mem_info->plugged_memory = get_plugged_memory_size();
422 mem_info->has_plugged_memory =
423 mem_info->plugged_memory != (uint64_t)-1;
424
425 return mem_info;
426}