root / qmp.c @ 19bf7c87
History | View | Annotate | Download (5.8 kB)
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 |
*/
|
13 |
|
14 |
#include "qemu-common.h" |
15 |
#include "sysemu.h" |
16 |
#include "qmp-commands.h" |
17 |
#include "kvm.h" |
18 |
#include "arch_init.h" |
19 |
#include "hw/qdev.h" |
20 |
#include "qapi/qmp-input-visitor.h" |
21 |
#include "qapi/qmp-output-visitor.h" |
22 |
|
23 |
NameInfo *qmp_query_name(Error **errp) |
24 |
{ |
25 |
NameInfo *info = g_malloc0(sizeof(*info));
|
26 |
|
27 |
if (qemu_name) {
|
28 |
info->has_name = true;
|
29 |
info->name = g_strdup(qemu_name); |
30 |
} |
31 |
|
32 |
return info;
|
33 |
} |
34 |
|
35 |
VersionInfo *qmp_query_version(Error **err) |
36 |
{ |
37 |
VersionInfo *info = g_malloc0(sizeof(*info));
|
38 |
const char *version = QEMU_VERSION; |
39 |
char *tmp;
|
40 |
|
41 |
info->qemu.major = strtol(version, &tmp, 10);
|
42 |
tmp++; |
43 |
info->qemu.minor = strtol(tmp, &tmp, 10);
|
44 |
tmp++; |
45 |
info->qemu.micro = strtol(tmp, &tmp, 10);
|
46 |
info->package = g_strdup(QEMU_PKGVERSION); |
47 |
|
48 |
return info;
|
49 |
} |
50 |
|
51 |
KvmInfo *qmp_query_kvm(Error **errp) |
52 |
{ |
53 |
KvmInfo *info = g_malloc0(sizeof(*info));
|
54 |
|
55 |
info->enabled = kvm_enabled(); |
56 |
info->present = kvm_available(); |
57 |
|
58 |
return info;
|
59 |
} |
60 |
|
61 |
UuidInfo *qmp_query_uuid(Error **errp) |
62 |
{ |
63 |
UuidInfo *info = g_malloc0(sizeof(*info));
|
64 |
char uuid[64]; |
65 |
|
66 |
snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1], |
67 |
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], |
68 |
qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], |
69 |
qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], |
70 |
qemu_uuid[14], qemu_uuid[15]); |
71 |
|
72 |
info->UUID = g_strdup(uuid); |
73 |
return info;
|
74 |
} |
75 |
|
76 |
void qmp_quit(Error **err)
|
77 |
{ |
78 |
no_shutdown = 0;
|
79 |
qemu_system_shutdown_request(); |
80 |
} |
81 |
|
82 |
void qmp_stop(Error **errp)
|
83 |
{ |
84 |
vm_stop(RUN_STATE_PAUSED); |
85 |
} |
86 |
|
87 |
void qmp_system_reset(Error **errp)
|
88 |
{ |
89 |
qemu_system_reset_request(); |
90 |
} |
91 |
|
92 |
void qmp_system_powerdown(Error **erp)
|
93 |
{ |
94 |
qemu_system_powerdown_request(); |
95 |
} |
96 |
|
97 |
void qmp_cpu(int64_t index, Error **errp)
|
98 |
{ |
99 |
/* Just do nothing */
|
100 |
} |
101 |
|
102 |
#ifndef CONFIG_VNC
|
103 |
/* If VNC support is enabled, the "true" query-vnc command is
|
104 |
defined in the VNC subsystem */
|
105 |
VncInfo *qmp_query_vnc(Error **errp) |
106 |
{ |
107 |
error_set(errp, QERR_FEATURE_DISABLED, "vnc");
|
108 |
return NULL; |
109 |
}; |
110 |
#endif
|
111 |
|
112 |
#ifndef CONFIG_SPICE
|
113 |
/* If SPICE support is enabled, the "true" query-spice command is
|
114 |
defined in the SPICE subsystem. Also note that we use a small
|
115 |
trick to maintain query-spice's original behavior, which is not
|
116 |
to be available in the namespace if SPICE is not compiled in */
|
117 |
SpiceInfo *qmp_query_spice(Error **errp) |
118 |
{ |
119 |
error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice");
|
120 |
return NULL; |
121 |
}; |
122 |
#endif
|
123 |
|
124 |
static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs) |
125 |
{ |
126 |
bdrv_iostatus_reset(bs); |
127 |
} |
128 |
|
129 |
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) |
130 |
{ |
131 |
Error **err = opaque; |
132 |
|
133 |
if (!error_is_set(err) && bdrv_key_required(bs)) {
|
134 |
error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs)); |
135 |
} |
136 |
} |
137 |
|
138 |
void qmp_cont(Error **errp)
|
139 |
{ |
140 |
Error *local_err = NULL;
|
141 |
|
142 |
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
143 |
error_set(errp, QERR_MIGRATION_EXPECTED); |
144 |
return;
|
145 |
} else if (runstate_check(RUN_STATE_INTERNAL_ERROR) || |
146 |
runstate_check(RUN_STATE_SHUTDOWN)) { |
147 |
error_set(errp, QERR_RESET_REQUIRED); |
148 |
return;
|
149 |
} |
150 |
|
151 |
bdrv_iterate(iostatus_bdrv_it, NULL);
|
152 |
bdrv_iterate(encrypted_bdrv_it, &local_err); |
153 |
if (local_err) {
|
154 |
error_propagate(errp, local_err); |
155 |
return;
|
156 |
} |
157 |
|
158 |
vm_start(); |
159 |
} |
160 |
|
161 |
DevicePropertyInfoList *qmp_qom_list(const char *path, Error **errp) |
162 |
{ |
163 |
DeviceState *dev; |
164 |
bool ambiguous = false; |
165 |
DevicePropertyInfoList *props = NULL;
|
166 |
DeviceProperty *prop; |
167 |
|
168 |
dev = qdev_resolve_path(path, &ambiguous); |
169 |
if (dev == NULL) { |
170 |
error_set(errp, QERR_DEVICE_NOT_FOUND, path); |
171 |
return NULL; |
172 |
} |
173 |
|
174 |
QTAILQ_FOREACH(prop, &dev->properties, node) { |
175 |
DevicePropertyInfoList *entry = g_malloc0(sizeof(*entry));
|
176 |
|
177 |
entry->value = g_malloc0(sizeof(DevicePropertyInfo));
|
178 |
entry->next = props; |
179 |
props = entry; |
180 |
|
181 |
entry->value->name = g_strdup(prop->name); |
182 |
entry->value->type = g_strdup(prop->type); |
183 |
} |
184 |
|
185 |
return props;
|
186 |
} |
187 |
|
188 |
/* FIXME: teach qapi about how to pass through Visitors */
|
189 |
int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret) |
190 |
{ |
191 |
const char *path = qdict_get_str(qdict, "path"); |
192 |
const char *property = qdict_get_str(qdict, "property"); |
193 |
QObject *value = qdict_get(qdict, "value");
|
194 |
Error *local_err = NULL;
|
195 |
QmpInputVisitor *mi; |
196 |
DeviceState *dev; |
197 |
|
198 |
dev = qdev_resolve_path(path, NULL);
|
199 |
if (!dev) {
|
200 |
error_set(&local_err, QERR_DEVICE_NOT_FOUND, path); |
201 |
goto out;
|
202 |
} |
203 |
|
204 |
mi = qmp_input_visitor_new(value); |
205 |
qdev_property_set(dev, qmp_input_get_visitor(mi), property, &local_err); |
206 |
|
207 |
qmp_input_visitor_cleanup(mi); |
208 |
|
209 |
out:
|
210 |
if (local_err) {
|
211 |
qerror_report_err(local_err); |
212 |
error_free(local_err); |
213 |
return -1; |
214 |
} |
215 |
|
216 |
return 0; |
217 |
} |
218 |
|
219 |
int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret) |
220 |
{ |
221 |
const char *path = qdict_get_str(qdict, "path"); |
222 |
const char *property = qdict_get_str(qdict, "property"); |
223 |
Error *local_err = NULL;
|
224 |
QmpOutputVisitor *mo; |
225 |
DeviceState *dev; |
226 |
|
227 |
dev = qdev_resolve_path(path, NULL);
|
228 |
if (!dev) {
|
229 |
error_set(&local_err, QERR_DEVICE_NOT_FOUND, path); |
230 |
goto out;
|
231 |
} |
232 |
|
233 |
mo = qmp_output_visitor_new(); |
234 |
qdev_property_get(dev, qmp_output_get_visitor(mo), property, &local_err); |
235 |
if (!local_err) {
|
236 |
*ret = qmp_output_get_qobject(mo); |
237 |
} |
238 |
|
239 |
qmp_output_visitor_cleanup(mo); |
240 |
|
241 |
out:
|
242 |
if (local_err) {
|
243 |
qerror_report_err(local_err); |
244 |
error_free(local_err); |
245 |
return -1; |
246 |
} |
247 |
|
248 |
return 0; |
249 |
} |