2011-09-02 19:34:48 +02:00
|
|
|
/*
|
2019-06-13 17:33:58 +02:00
|
|
|
* QEMU Management Protocol commands
|
2011-09-02 19:34:48 +02:00
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
2012-01-13 17:44:23 +01:00
|
|
|
* Contributions after 2012-01-13 are licensed under the terms of the
|
|
|
|
* GNU GPL, version 2 or (at your option) any later version.
|
2011-09-02 19:34:48 +02:00
|
|
|
*/
|
|
|
|
|
2016-01-29 18:50:05 +01:00
|
|
|
#include "qemu/osdep.h"
|
2023-03-06 13:27:45 +01:00
|
|
|
#include "qemu/sockets.h"
|
2023-01-24 13:19:44 +01:00
|
|
|
#include "monitor-internal.h"
|
|
|
|
#include "monitor/qdev.h"
|
2023-01-09 20:03:14 +01:00
|
|
|
#include "monitor/qmp-helpers.h"
|
2012-12-17 18:20:04 +01:00
|
|
|
#include "sysemu/sysemu.h"
|
|
|
|
#include "sysemu/kvm.h"
|
2019-08-12 07:23:59 +02:00
|
|
|
#include "sysemu/runstate.h"
|
2020-12-11 17:52:43 +01:00
|
|
|
#include "sysemu/runstate-action.h"
|
2015-10-19 17:53:22 +02:00
|
|
|
#include "sysemu/block-backend.h"
|
2018-02-01 12:18:31 +01:00
|
|
|
#include "qapi/error.h"
|
2023-01-24 13:19:44 +01:00
|
|
|
#include "qapi/qapi-init-commands.h"
|
2020-01-29 11:22:37 +01:00
|
|
|
#include "qapi/qapi-commands-control.h"
|
2018-02-27 00:13:27 +01:00
|
|
|
#include "qapi/qapi-commands-misc.h"
|
2023-01-24 13:19:44 +01:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2021-09-08 11:35:43 +02:00
|
|
|
#include "qapi/type-helpers.h"
|
2018-04-23 18:51:16 +02:00
|
|
|
#include "hw/mem/memory-device.h"
|
2021-09-08 11:35:43 +02:00
|
|
|
#include "hw/intc/intc.h"
|
2021-09-08 11:35:43 +02:00
|
|
|
#include "hw/rdma/rdma.h"
|
2011-09-02 19:34:48 +02:00
|
|
|
|
|
|
|
NameInfo *qmp_query_name(Error **errp)
|
|
|
|
{
|
|
|
|
NameInfo *info = g_malloc0(sizeof(*info));
|
|
|
|
|
2022-11-04 17:06:59 +01:00
|
|
|
info->name = g_strdup(qemu_name);
|
2011-09-02 19:34:48 +02:00
|
|
|
return info;
|
|
|
|
}
|
2011-08-26 22:38:13 +02:00
|
|
|
|
2014-05-02 13:26:31 +02:00
|
|
|
void qmp_quit(Error **errp)
|
2011-09-15 19:20:28 +02:00
|
|
|
{
|
2020-12-11 17:52:43 +01:00
|
|
|
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
2018-12-05 12:01:31 +01:00
|
|
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
|
2011-09-15 19:20:28 +02:00
|
|
|
}
|
|
|
|
|
2011-09-15 19:34:39 +02:00
|
|
|
void qmp_stop(Error **errp)
|
|
|
|
{
|
2016-02-18 06:16:49 +01:00
|
|
|
/* if there is a dump in background, we should wait until the dump
|
|
|
|
* finished */
|
2022-03-23 16:57:31 +01:00
|
|
|
if (qemu_system_dump_in_progress()) {
|
2016-02-18 06:16:49 +01:00
|
|
|
error_setg(errp, "There is a dump in process, please wait.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-23 14:54:21 +02:00
|
|
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
|
|
|
autostart = 0;
|
|
|
|
} else {
|
|
|
|
vm_stop(RUN_STATE_PAUSED);
|
|
|
|
}
|
2011-09-15 19:34:39 +02:00
|
|
|
}
|
|
|
|
|
2011-11-22 20:58:31 +01:00
|
|
|
void qmp_cont(Error **errp)
|
|
|
|
{
|
2015-10-19 17:53:22 +02:00
|
|
|
BlockBackend *blk;
|
2019-06-06 17:41:30 +02:00
|
|
|
BlockJob *job;
|
2017-06-23 18:24:15 +02:00
|
|
|
Error *local_err = NULL;
|
2011-11-22 20:58:31 +01:00
|
|
|
|
2016-02-18 06:16:49 +01:00
|
|
|
/* if there is a dump in background, we should wait until the dump
|
|
|
|
* finished */
|
2022-03-23 16:57:31 +01:00
|
|
|
if (qemu_system_dump_in_progress()) {
|
2016-02-18 06:16:49 +01:00
|
|
|
error_setg(errp, "There is a dump in process, please wait.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-26 05:24:40 +02:00
|
|
|
if (runstate_needs_reset()) {
|
2014-03-22 00:42:26 +01:00
|
|
|
error_setg(errp, "Resetting the Virtual Machine is required");
|
2011-11-22 20:58:31 +01:00
|
|
|
return;
|
2012-04-27 18:33:36 +02:00
|
|
|
} else if (runstate_check(RUN_STATE_SUSPENDED)) {
|
|
|
|
return;
|
2019-01-24 13:25:24 +01:00
|
|
|
} else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
|
|
|
|
error_setg(errp, "Migration is not finalized yet");
|
|
|
|
return;
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
|
|
|
|
2015-10-19 17:53:22 +02:00
|
|
|
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
|
|
blk_iostatus_reset(blk);
|
2014-05-02 13:26:42 +02:00
|
|
|
}
|
2016-03-22 18:58:50 +01:00
|
|
|
|
2022-09-26 11:32:04 +02:00
|
|
|
WITH_JOB_LOCK_GUARD() {
|
|
|
|
for (job = block_job_next_locked(NULL); job;
|
|
|
|
job = block_job_next_locked(job)) {
|
|
|
|
block_job_iostatus_reset_locked(job);
|
|
|
|
}
|
2019-06-06 17:41:30 +02:00
|
|
|
}
|
|
|
|
|
2015-12-22 14:07:08 +01:00
|
|
|
/* Continuing after completed migration. Images have been inactivated to
|
2017-05-04 18:52:36 +02:00
|
|
|
* allow the destination to take control. Need to get control back now.
|
|
|
|
*
|
|
|
|
* If there are no inactive block nodes (e.g. because the VM was just
|
|
|
|
* paused rather than completing a migration), bdrv_inactivate_all() simply
|
|
|
|
* doesn't do anything. */
|
2022-02-09 11:54:51 +01:00
|
|
|
bdrv_activate_all(&local_err);
|
2017-05-04 18:52:36 +02:00
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
2015-12-22 14:07:08 +01:00
|
|
|
}
|
|
|
|
|
2012-10-23 14:54:21 +02:00
|
|
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
|
|
|
autostart = 1;
|
|
|
|
} else {
|
|
|
|
vm_start();
|
|
|
|
}
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
2011-12-12 21:29:34 +01:00
|
|
|
|
2012-09-13 21:52:20 +02:00
|
|
|
void qmp_add_client(const char *protocol, const char *fdname,
|
|
|
|
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
|
|
|
|
Error **errp)
|
|
|
|
{
|
2023-01-09 20:03:17 +01:00
|
|
|
static const struct {
|
2023-01-09 20:03:14 +01:00
|
|
|
const char *name;
|
|
|
|
bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
|
|
|
|
bool has_tls, bool tls, Error **errp);
|
|
|
|
} protocol_table[] = {
|
|
|
|
{ "spice", qmp_add_client_spice },
|
|
|
|
#ifdef CONFIG_VNC
|
|
|
|
{ "vnc", qmp_add_client_vnc },
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_DBUS_DISPLAY
|
|
|
|
{ "@dbus-display", qmp_add_client_dbus_display },
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
int fd, i;
|
2012-09-13 21:52:20 +02:00
|
|
|
|
2020-10-05 17:58:44 +02:00
|
|
|
fd = monitor_get_fd(monitor_cur(), fdname, errp);
|
2012-09-13 21:52:20 +02:00
|
|
|
if (fd < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-06 13:27:45 +01:00
|
|
|
if (!fd_is_socket(fd)) {
|
|
|
|
error_setg(errp, "parameter @fdname must name a socket");
|
|
|
|
close(fd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-09 20:03:14 +01:00
|
|
|
for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
|
|
|
|
if (!strcmp(protocol, protocol_table[i].name)) {
|
|
|
|
if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
|
|
|
|
has_tls, tls, errp)) {
|
|
|
|
close(fd);
|
|
|
|
}
|
2012-09-13 21:52:20 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-01-09 20:03:14 +01:00
|
|
|
|
2023-01-24 13:19:18 +01:00
|
|
|
if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
|
|
|
|
protocol, errp)) {
|
2023-01-09 20:03:14 +01:00
|
|
|
close(fd);
|
|
|
|
}
|
2012-09-13 21:52:20 +02:00
|
|
|
}
|
2023-01-24 13:19:44 +01:00
|
|
|
|
|
|
|
char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
|
|
|
int64_t cpu_index, Error **errp)
|
|
|
|
{
|
|
|
|
char *output = NULL;
|
|
|
|
MonitorHMP hmp = {};
|
|
|
|
|
|
|
|
monitor_data_init(&hmp.common, false, true, false);
|
|
|
|
|
|
|
|
if (has_cpu_index) {
|
|
|
|
int ret = monitor_set_cpu(&hmp.common, cpu_index);
|
|
|
|
if (ret < 0) {
|
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
|
|
|
|
"a CPU number");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handle_hmp_command(&hmp, command_line);
|
|
|
|
|
|
|
|
WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
|
|
|
|
output = g_strdup(hmp.common.outbuf->str);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
monitor_data_destroy(&hmp.common);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Two command lists:
|
|
|
|
* - qmp_commands contains all QMP commands
|
|
|
|
* - qmp_cap_negotiation_commands contains just
|
|
|
|
* "qmp_capabilities", to enforce capability negotiation
|
|
|
|
*/
|
|
|
|
|
|
|
|
qmp_init_marshal(&qmp_commands);
|
|
|
|
|
|
|
|
qmp_register_command(&qmp_commands, "device_add",
|
|
|
|
qmp_device_add, 0, 0);
|
|
|
|
|
|
|
|
QTAILQ_INIT(&qmp_cap_negotiation_commands);
|
|
|
|
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
|
|
|
|
qmp_marshal_qmp_capabilities,
|
|
|
|
QCO_ALLOW_PRECONFIG, 0);
|
|
|
|
}
|