qmp: add query-memory-devices command
[qemu.git] / qmp.c
1 /*
2 * QEMU Management Protocol
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-common.h"
17 #include "sysemu/sysemu.h"
18 #include "qmp-commands.h"
19 #include "sysemu/char.h"
20 #include "ui/qemu-spice.h"
21 #include "ui/vnc.h"
22 #include "sysemu/kvm.h"
23 #include "sysemu/arch_init.h"
24 #include "hw/qdev.h"
25 #include "sysemu/blockdev.h"
26 #include "qom/qom-qobject.h"
27 #include "qapi/qmp/qobject.h"
28 #include "qapi/qmp-input-visitor.h"
29 #include "hw/boards.h"
30 #include "qom/object_interfaces.h"
31 #include "hw/mem/pc-dimm.h"
32
33 NameInfo *qmp_query_name(Error **errp)
34 {
35 NameInfo *info = g_malloc0(sizeof(*info));
36
37 if (qemu_name) {
38 info->has_name = true;
39 info->name = g_strdup(qemu_name);
40 }
41
42 return info;
43 }
44
45 VersionInfo *qmp_query_version(Error **errp)
46 {
47 VersionInfo *info = g_malloc0(sizeof(*info));
48 const char *version = QEMU_VERSION;
49 char *tmp;
50
51 info->qemu.major = strtol(version, &tmp, 10);
52 tmp++;
53 info->qemu.minor = strtol(tmp, &tmp, 10);
54 tmp++;
55 info->qemu.micro = strtol(tmp, &tmp, 10);
56 info->package = g_strdup(QEMU_PKGVERSION);
57
58 return info;
59 }
60
61 KvmInfo *qmp_query_kvm(Error **errp)
62 {
63 KvmInfo *info = g_malloc0(sizeof(*info));
64
65 info->enabled = kvm_enabled();
66 info->present = kvm_available();
67
68 return info;
69 }
70
71 UuidInfo *qmp_query_uuid(Error **errp)
72 {
73 UuidInfo *info = g_malloc0(sizeof(*info));
74 char uuid[64];
75
76 snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
77 qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
78 qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
79 qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
80 qemu_uuid[14], qemu_uuid[15]);
81
82 info->UUID = g_strdup(uuid);
83 return info;
84 }
85
86 void qmp_quit(Error **errp)
87 {
88 no_shutdown = 0;
89 qemu_system_shutdown_request();
90 }
91
92 void qmp_stop(Error **errp)
93 {
94 if (runstate_check(RUN_STATE_INMIGRATE)) {
95 autostart = 0;
96 } else {
97 vm_stop(RUN_STATE_PAUSED);
98 }
99 }
100
101 void qmp_system_reset(Error **errp)
102 {
103 qemu_system_reset_request();
104 }
105
106 void qmp_system_powerdown(Error **erp)
107 {
108 qemu_system_powerdown_request();
109 }
110
111 void qmp_cpu(int64_t index, Error **errp)
112 {
113 /* Just do nothing */
114 }
115
116 void qmp_cpu_add(int64_t id, Error **errp)
117 {
118 MachineClass *mc;
119
120 mc = MACHINE_GET_CLASS(current_machine);
121 if (mc->hot_add_cpu) {
122 mc->hot_add_cpu(id, errp);
123 } else {
124 error_setg(errp, "Not supported");
125 }
126 }
127
128 #ifndef CONFIG_VNC
129 /* If VNC support is enabled, the "true" query-vnc command is
130 defined in the VNC subsystem */
131 VncInfo *qmp_query_vnc(Error **errp)
132 {
133 error_set(errp, QERR_FEATURE_DISABLED, "vnc");
134 return NULL;
135 };
136 #endif
137
138 #ifndef CONFIG_SPICE
139 /* If SPICE support is enabled, the "true" query-spice command is
140 defined in the SPICE subsystem. Also note that we use a small
141 trick to maintain query-spice's original behavior, which is not
142 to be available in the namespace if SPICE is not compiled in */
143 SpiceInfo *qmp_query_spice(Error **errp)
144 {
145 error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice");
146 return NULL;
147 };
148 #endif
149
150 void qmp_cont(Error **errp)
151 {
152 BlockDriverState *bs;
153
154 if (runstate_needs_reset()) {
155 error_setg(errp, "Resetting the Virtual Machine is required");
156 return;
157 } else if (runstate_check(RUN_STATE_SUSPENDED)) {
158 return;
159 }
160
161 for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
162 bdrv_iostatus_reset(bs);
163 }
164 for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
165 if (bdrv_key_required(bs)) {
166 error_set(errp, QERR_DEVICE_ENCRYPTED,
167 bdrv_get_device_name(bs),
168 bdrv_get_encrypted_filename(bs));
169 return;
170 }
171 }
172
173 if (runstate_check(RUN_STATE_INMIGRATE)) {
174 autostart = 1;
175 } else {
176 vm_start();
177 }
178 }
179
180 void qmp_system_wakeup(Error **errp)
181 {
182 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
183 }
184
185 ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
186 {
187 Object *obj;
188 bool ambiguous = false;
189 ObjectPropertyInfoList *props = NULL;
190 ObjectProperty *prop;
191
192 obj = object_resolve_path(path, &ambiguous);
193 if (obj == NULL) {
194 if (ambiguous) {
195 error_setg(errp, "Path '%s' is ambiguous", path);
196 } else {
197 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
198 }
199 return NULL;
200 }
201
202 QTAILQ_FOREACH(prop, &obj->properties, node) {
203 ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
204
205 entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
206 entry->next = props;
207 props = entry;
208
209 entry->value->name = g_strdup(prop->name);
210 entry->value->type = g_strdup(prop->type);
211 }
212
213 return props;
214 }
215
216 /* FIXME: teach qapi about how to pass through Visitors */
217 int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
218 {
219 const char *path = qdict_get_str(qdict, "path");
220 const char *property = qdict_get_str(qdict, "property");
221 QObject *value = qdict_get(qdict, "value");
222 Error *local_err = NULL;
223 Object *obj;
224
225 obj = object_resolve_path(path, NULL);
226 if (!obj) {
227 error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
228 goto out;
229 }
230
231 object_property_set_qobject(obj, value, property, &local_err);
232
233 out:
234 if (local_err) {
235 qerror_report_err(local_err);
236 error_free(local_err);
237 return -1;
238 }
239
240 return 0;
241 }
242
243 int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
244 {
245 const char *path = qdict_get_str(qdict, "path");
246 const char *property = qdict_get_str(qdict, "property");
247 Error *local_err = NULL;
248 Object *obj;
249
250 obj = object_resolve_path(path, NULL);
251 if (!obj) {
252 error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
253 goto out;
254 }
255
256 *ret = object_property_get_qobject(obj, property, &local_err);
257
258 out:
259 if (local_err) {
260 qerror_report_err(local_err);
261 error_free(local_err);
262 return -1;
263 }
264
265 return 0;
266 }
267
268 void qmp_set_password(const char *protocol, const char *password,
269 bool has_connected, const char *connected, Error **errp)
270 {
271 int disconnect_if_connected = 0;
272 int fail_if_connected = 0;
273 int rc;
274
275 if (has_connected) {
276 if (strcmp(connected, "fail") == 0) {
277 fail_if_connected = 1;
278 } else if (strcmp(connected, "disconnect") == 0) {
279 disconnect_if_connected = 1;
280 } else if (strcmp(connected, "keep") == 0) {
281 /* nothing */
282 } else {
283 error_set(errp, QERR_INVALID_PARAMETER, "connected");
284 return;
285 }
286 }
287
288 if (strcmp(protocol, "spice") == 0) {
289 if (!using_spice) {
290 /* correct one? spice isn't a device ,,, */
291 error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
292 return;
293 }
294 rc = qemu_spice_set_passwd(password, fail_if_connected,
295 disconnect_if_connected);
296 if (rc != 0) {
297 error_set(errp, QERR_SET_PASSWD_FAILED);
298 }
299 return;
300 }
301
302 if (strcmp(protocol, "vnc") == 0) {
303 if (fail_if_connected || disconnect_if_connected) {
304 /* vnc supports "connected=keep" only */
305 error_set(errp, QERR_INVALID_PARAMETER, "connected");
306 return;
307 }
308 /* Note that setting an empty password will not disable login through
309 * this interface. */
310 rc = vnc_display_password(NULL, password);
311 if (rc < 0) {
312 error_set(errp, QERR_SET_PASSWD_FAILED);
313 }
314 return;
315 }
316
317 error_set(errp, QERR_INVALID_PARAMETER, "protocol");
318 }
319
320 void qmp_expire_password(const char *protocol, const char *whenstr,
321 Error **errp)
322 {
323 time_t when;
324 int rc;
325
326 if (strcmp(whenstr, "now") == 0) {
327 when = 0;
328 } else if (strcmp(whenstr, "never") == 0) {
329 when = TIME_MAX;
330 } else if (whenstr[0] == '+') {
331 when = time(NULL) + strtoull(whenstr+1, NULL, 10);
332 } else {
333 when = strtoull(whenstr, NULL, 10);
334 }
335
336 if (strcmp(protocol, "spice") == 0) {
337 if (!using_spice) {
338 /* correct one? spice isn't a device ,,, */
339 error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
340 return;
341 }
342 rc = qemu_spice_set_pw_expire(when);
343 if (rc != 0) {
344 error_set(errp, QERR_SET_PASSWD_FAILED);
345 }
346 return;
347 }
348
349 if (strcmp(protocol, "vnc") == 0) {
350 rc = vnc_display_pw_expire(NULL, when);
351 if (rc != 0) {
352 error_set(errp, QERR_SET_PASSWD_FAILED);
353 }
354 return;
355 }
356
357 error_set(errp, QERR_INVALID_PARAMETER, "protocol");
358 }
359
360 #ifdef CONFIG_VNC
361 void qmp_change_vnc_password(const char *password, Error **errp)
362 {
363 if (vnc_display_password(NULL, password) < 0) {
364 error_set(errp, QERR_SET_PASSWD_FAILED);
365 }
366 }
367
368 static void qmp_change_vnc_listen(const char *target, Error **errp)
369 {
370 vnc_display_open(NULL, target, errp);
371 }
372
373 static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
374 Error **errp)
375 {
376 if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
377 if (!has_arg) {
378 error_set(errp, QERR_MISSING_PARAMETER, "password");
379 } else {
380 qmp_change_vnc_password(arg, errp);
381 }
382 } else {
383 qmp_change_vnc_listen(target, errp);
384 }
385 }
386 #else
387 void qmp_change_vnc_password(const char *password, Error **errp)
388 {
389 error_set(errp, QERR_FEATURE_DISABLED, "vnc");
390 }
391 static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
392 Error **errp)
393 {
394 error_set(errp, QERR_FEATURE_DISABLED, "vnc");
395 }
396 #endif /* !CONFIG_VNC */
397
398 void qmp_change(const char *device, const char *target,
399 bool has_arg, const char *arg, Error **errp)
400 {
401 if (strcmp(device, "vnc") == 0) {
402 qmp_change_vnc(target, has_arg, arg, errp);
403 } else {
404 qmp_change_blockdev(device, target, arg, errp);
405 }
406 }
407
408 static void qom_list_types_tramp(ObjectClass *klass, void *data)
409 {
410 ObjectTypeInfoList *e, **pret = data;
411 ObjectTypeInfo *info;
412
413 info = g_malloc0(sizeof(*info));
414 info->name = g_strdup(object_class_get_name(klass));
415
416 e = g_malloc0(sizeof(*e));
417 e->value = info;
418 e->next = *pret;
419 *pret = e;
420 }
421
422 ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
423 const char *implements,
424 bool has_abstract,
425 bool abstract,
426 Error **errp)
427 {
428 ObjectTypeInfoList *ret = NULL;
429
430 object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
431
432 return ret;
433 }
434
435 DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
436 Error **errp)
437 {
438 ObjectClass *klass;
439 Property *prop;
440 DevicePropertyInfoList *prop_list = NULL;
441
442 klass = object_class_by_name(typename);
443 if (klass == NULL) {
444 error_set(errp, QERR_DEVICE_NOT_FOUND, typename);
445 return NULL;
446 }
447
448 klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
449 if (klass == NULL) {
450 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
451 "name", TYPE_DEVICE);
452 return NULL;
453 }
454
455 do {
456 for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
457 DevicePropertyInfoList *entry;
458 DevicePropertyInfo *info;
459
460 /*
461 * TODO Properties without a parser are just for dirty hacks.
462 * qdev_prop_ptr is the only such PropertyInfo. It's marked
463 * for removal. This conditional should be removed along with
464 * it.
465 */
466 if (!prop->info->set) {
467 continue; /* no way to set it, don't show */
468 }
469
470 info = g_malloc0(sizeof(*info));
471 info->name = g_strdup(prop->name);
472 info->type = g_strdup(prop->info->legacy_name ?: prop->info->name);
473
474 entry = g_malloc0(sizeof(*entry));
475 entry->value = info;
476 entry->next = prop_list;
477 prop_list = entry;
478 }
479 klass = object_class_get_parent(klass);
480 } while (klass != object_class_by_name(TYPE_DEVICE));
481
482 return prop_list;
483 }
484
485 CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
486 {
487 return arch_query_cpu_definitions(errp);
488 }
489
490 void qmp_add_client(const char *protocol, const char *fdname,
491 bool has_skipauth, bool skipauth, bool has_tls, bool tls,
492 Error **errp)
493 {
494 CharDriverState *s;
495 int fd;
496
497 fd = monitor_get_fd(cur_mon, fdname, errp);
498 if (fd < 0) {
499 return;
500 }
501
502 if (strcmp(protocol, "spice") == 0) {
503 if (!using_spice) {
504 error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
505 close(fd);
506 return;
507 }
508 skipauth = has_skipauth ? skipauth : false;
509 tls = has_tls ? tls : false;
510 if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
511 error_setg(errp, "spice failed to add client");
512 close(fd);
513 }
514 return;
515 #ifdef CONFIG_VNC
516 } else if (strcmp(protocol, "vnc") == 0) {
517 skipauth = has_skipauth ? skipauth : false;
518 vnc_display_add_client(NULL, fd, skipauth);
519 return;
520 #endif
521 } else if ((s = qemu_chr_find(protocol)) != NULL) {
522 if (qemu_chr_add_client(s, fd) < 0) {
523 error_setg(errp, "failed to add client");
524 close(fd);
525 return;
526 }
527 return;
528 }
529
530 error_setg(errp, "protocol '%s' is invalid", protocol);
531 close(fd);
532 }
533
534 void object_add(const char *type, const char *id, const QDict *qdict,
535 Visitor *v, Error **errp)
536 {
537 Object *obj;
538 ObjectClass *klass;
539 const QDictEntry *e;
540 Error *local_err = NULL;
541
542 klass = object_class_by_name(type);
543 if (!klass) {
544 error_setg(errp, "invalid object type: %s", type);
545 return;
546 }
547
548 if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
549 error_setg(errp, "object type '%s' isn't supported by object-add",
550 type);
551 return;
552 }
553
554 if (object_class_is_abstract(klass)) {
555 error_setg(errp, "object type '%s' is abstract", type);
556 return;
557 }
558
559 obj = object_new(type);
560 if (qdict) {
561 for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
562 object_property_set(obj, v, e->key, &local_err);
563 if (local_err) {
564 goto out;
565 }
566 }
567 }
568
569 object_property_add_child(container_get(object_get_root(), "/objects"),
570 id, obj, &local_err);
571 if (local_err) {
572 goto out;
573 }
574
575 user_creatable_complete(obj, &local_err);
576 if (local_err) {
577 object_property_del(container_get(object_get_root(), "/objects"),
578 id, &error_abort);
579 goto out;
580 }
581 out:
582 if (local_err) {
583 error_propagate(errp, local_err);
584 }
585 object_unref(obj);
586 }
587
588 int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret)
589 {
590 const char *type = qdict_get_str(qdict, "qom-type");
591 const char *id = qdict_get_str(qdict, "id");
592 QObject *props = qdict_get(qdict, "props");
593 const QDict *pdict = NULL;
594 Error *local_err = NULL;
595 QmpInputVisitor *qiv;
596
597 if (props) {
598 pdict = qobject_to_qdict(props);
599 if (!pdict) {
600 error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
601 goto out;
602 }
603 }
604
605 qiv = qmp_input_visitor_new(props);
606 object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err);
607 qmp_input_visitor_cleanup(qiv);
608
609 out:
610 if (local_err) {
611 qerror_report_err(local_err);
612 error_free(local_err);
613 return -1;
614 }
615
616 return 0;
617 }
618
619 void qmp_object_del(const char *id, Error **errp)
620 {
621 Object *container;
622 Object *obj;
623
624 container = container_get(object_get_root(), "/objects");
625 obj = object_resolve_path_component(container, id);
626 if (!obj) {
627 error_setg(errp, "object id not found");
628 return;
629 }
630 object_unparent(obj);
631 }
632
633 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
634 {
635 MemoryDeviceInfoList *head = NULL;
636 MemoryDeviceInfoList **prev = &head;
637
638 qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
639
640 return head;
641 }