2 * QEMU Management Protocol commands
4 * Copyright IBM, Corp. 2011
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
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.
16 #include "qemu/osdep.h"
17 #include "monitor/monitor.h"
18 #include "monitor/qmp-helpers.h"
19 #include "sysemu/sysemu.h"
20 #include "sysemu/kvm.h"
21 #include "sysemu/runstate.h"
22 #include "sysemu/runstate-action.h"
23 #include "sysemu/block-backend.h"
24 #include "qapi/error.h"
25 #include "qapi/qapi-commands-acpi.h"
26 #include "qapi/qapi-commands-control.h"
27 #include "qapi/qapi-commands-misc.h"
28 #include "qapi/qapi-commands-stats.h"
29 #include "qapi/type-helpers.h"
30 #include "hw/mem/memory-device.h"
31 #include "hw/acpi/acpi_dev_interface.h"
32 #include "hw/intc/intc.h"
33 #include "hw/rdma/rdma.h"
34 #include "monitor/stats.h"
36 NameInfo
*qmp_query_name(Error
**errp
)
38 NameInfo
*info
= g_malloc0(sizeof(*info
));
40 info
->name
= g_strdup(qemu_name
);
44 void qmp_quit(Error
**errp
)
46 shutdown_action
= SHUTDOWN_ACTION_POWEROFF
;
47 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT
);
50 void qmp_stop(Error
**errp
)
52 /* if there is a dump in background, we should wait until the dump
54 if (qemu_system_dump_in_progress()) {
55 error_setg(errp
, "There is a dump in process, please wait.");
59 if (runstate_check(RUN_STATE_INMIGRATE
)) {
62 vm_stop(RUN_STATE_PAUSED
);
66 void qmp_cont(Error
**errp
)
70 Error
*local_err
= NULL
;
72 /* if there is a dump in background, we should wait until the dump
74 if (qemu_system_dump_in_progress()) {
75 error_setg(errp
, "There is a dump in process, please wait.");
79 if (runstate_needs_reset()) {
80 error_setg(errp
, "Resetting the Virtual Machine is required");
82 } else if (runstate_check(RUN_STATE_SUSPENDED
)) {
84 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE
)) {
85 error_setg(errp
, "Migration is not finalized yet");
89 for (blk
= blk_next(NULL
); blk
; blk
= blk_next(blk
)) {
90 blk_iostatus_reset(blk
);
93 WITH_JOB_LOCK_GUARD() {
94 for (job
= block_job_next_locked(NULL
); job
;
95 job
= block_job_next_locked(job
)) {
96 block_job_iostatus_reset_locked(job
);
100 /* Continuing after completed migration. Images have been inactivated to
101 * allow the destination to take control. Need to get control back now.
103 * If there are no inactive block nodes (e.g. because the VM was just
104 * paused rather than completing a migration), bdrv_inactivate_all() simply
105 * doesn't do anything. */
106 bdrv_activate_all(&local_err
);
108 error_propagate(errp
, local_err
);
112 if (runstate_check(RUN_STATE_INMIGRATE
)) {
119 void qmp_add_client(const char *protocol
, const char *fdname
,
120 bool has_skipauth
, bool skipauth
, bool has_tls
, bool tls
,
123 static const struct {
125 bool (*add_client
)(int fd
, bool has_skipauth
, bool skipauth
,
126 bool has_tls
, bool tls
, Error
**errp
);
127 } protocol_table
[] = {
128 { "spice", qmp_add_client_spice
},
130 { "vnc", qmp_add_client_vnc
},
132 #ifdef CONFIG_DBUS_DISPLAY
133 { "@dbus-display", qmp_add_client_dbus_display
},
138 fd
= monitor_get_fd(monitor_cur(), fdname
, errp
);
143 for (i
= 0; i
< ARRAY_SIZE(protocol_table
); i
++) {
144 if (!strcmp(protocol
, protocol_table
[i
].name
)) {
145 if (!protocol_table
[i
].add_client(fd
, has_skipauth
, skipauth
,
146 has_tls
, tls
, errp
)) {
153 if (!qmp_add_client_char(fd
, has_skipauth
, skipauth
, has_tls
, tls
,
159 ACPIOSTInfoList
*qmp_query_acpi_ospm_status(Error
**errp
)
162 ACPIOSTInfoList
*head
= NULL
;
163 ACPIOSTInfoList
**prev
= &head
;
164 Object
*obj
= object_resolve_path_type("", TYPE_ACPI_DEVICE_IF
, &ambig
);
167 AcpiDeviceIfClass
*adevc
= ACPI_DEVICE_IF_GET_CLASS(obj
);
168 AcpiDeviceIf
*adev
= ACPI_DEVICE_IF(obj
);
170 adevc
->ospm_status(adev
, &prev
);
172 error_setg(errp
, "command is not supported, missing ACPI device");
178 typedef struct StatsCallbacks
{
179 StatsProvider provider
;
180 StatRetrieveFunc
*stats_cb
;
181 SchemaRetrieveFunc
*schemas_cb
;
182 QTAILQ_ENTRY(StatsCallbacks
) next
;
185 static QTAILQ_HEAD(, StatsCallbacks
) stats_callbacks
=
186 QTAILQ_HEAD_INITIALIZER(stats_callbacks
);
188 void add_stats_callbacks(StatsProvider provider
,
189 StatRetrieveFunc
*stats_fn
,
190 SchemaRetrieveFunc
*schemas_fn
)
192 StatsCallbacks
*entry
= g_new(StatsCallbacks
, 1);
193 entry
->provider
= provider
;
194 entry
->stats_cb
= stats_fn
;
195 entry
->schemas_cb
= schemas_fn
;
197 QTAILQ_INSERT_TAIL(&stats_callbacks
, entry
, next
);
200 static bool invoke_stats_cb(StatsCallbacks
*entry
,
201 StatsResultList
**stats_results
,
202 StatsFilter
*filter
, StatsRequest
*request
,
206 strList
*targets
= NULL
;
207 strList
*names
= NULL
;
210 if (request
->provider
!= entry
->provider
) {
213 if (request
->has_names
&& !request
->names
) {
216 names
= request
->has_names
? request
->names
: NULL
;
219 switch (filter
->target
) {
220 case STATS_TARGET_VM
:
222 case STATS_TARGET_VCPU
:
223 if (filter
->u
.vcpu
.has_vcpus
) {
224 if (!filter
->u
.vcpu
.vcpus
) {
225 /* No targets allowed? Return no statistics. */
228 targets
= filter
->u
.vcpu
.vcpus
;
235 entry
->stats_cb(stats_results
, filter
->target
, names
, targets
, errp
);
237 qapi_free_StatsResultList(*stats_results
);
238 *stats_results
= NULL
;
244 StatsResultList
*qmp_query_stats(StatsFilter
*filter
, Error
**errp
)
246 StatsResultList
*stats_results
= NULL
;
247 StatsCallbacks
*entry
;
248 StatsRequestList
*request
;
250 QTAILQ_FOREACH(entry
, &stats_callbacks
, next
) {
251 if (filter
->has_providers
) {
252 for (request
= filter
->providers
; request
; request
= request
->next
) {
253 if (!invoke_stats_cb(entry
, &stats_results
, filter
,
254 request
->value
, errp
)) {
259 if (!invoke_stats_cb(entry
, &stats_results
, filter
, NULL
, errp
)) {
265 return stats_results
;
268 StatsSchemaList
*qmp_query_stats_schemas(bool has_provider
,
269 StatsProvider provider
,
273 StatsSchemaList
*stats_results
= NULL
;
274 StatsCallbacks
*entry
;
276 QTAILQ_FOREACH(entry
, &stats_callbacks
, next
) {
277 if (!has_provider
|| provider
== entry
->provider
) {
278 entry
->schemas_cb(&stats_results
, errp
);
280 qapi_free_StatsSchemaList(stats_results
);
286 return stats_results
;
289 void add_stats_entry(StatsResultList
**stats_results
, StatsProvider provider
,
290 const char *qom_path
, StatsList
*stats_list
)
292 StatsResult
*entry
= g_new0(StatsResult
, 1);
294 entry
->provider
= provider
;
295 entry
->qom_path
= g_strdup(qom_path
);
296 entry
->stats
= stats_list
;
298 QAPI_LIST_PREPEND(*stats_results
, entry
);
301 void add_stats_schema(StatsSchemaList
**schema_results
,
302 StatsProvider provider
, StatsTarget target
,
303 StatsSchemaValueList
*stats_list
)
305 StatsSchema
*entry
= g_new0(StatsSchema
, 1);
307 entry
->provider
= provider
;
308 entry
->target
= target
;
309 entry
->stats
= stats_list
;
310 QAPI_LIST_PREPEND(*schema_results
, entry
);
313 bool apply_str_list_filter(const char *string
, strList
*list
)
315 strList
*str_list
= NULL
;
320 for (str_list
= list
; str_list
; str_list
= str_list
->next
) {
321 if (g_str_equal(string
, str_list
->value
)) {