123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /*
- * QEMU Management Protocol commands
- *
- * 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.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
- #include "qemu/osdep.h"
- #include "qemu/sockets.h"
- #include "monitor-internal.h"
- #include "monitor/qdev.h"
- #include "monitor/qmp-helpers.h"
- #include "system/system.h"
- #include "system/kvm.h"
- #include "system/runstate.h"
- #include "system/runstate-action.h"
- #include "system/block-backend.h"
- #include "qapi/error.h"
- #include "qapi/qapi-init-commands.h"
- #include "qapi/qapi-commands-control.h"
- #include "qapi/qapi-commands-misc.h"
- #include "qapi/qmp/qerror.h"
- #include "qapi/type-helpers.h"
- #include "hw/mem/memory-device.h"
- #include "hw/intc/intc.h"
- #include "migration/misc.h"
- NameInfo *qmp_query_name(Error **errp)
- {
- NameInfo *info = g_malloc0(sizeof(*info));
- info->name = g_strdup(qemu_name);
- return info;
- }
- void qmp_quit(Error **errp)
- {
- shutdown_action = SHUTDOWN_ACTION_POWEROFF;
- qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
- }
- void qmp_stop(Error **errp)
- {
- /* if there is a dump in background, we should wait until the dump
- * finished */
- if (qemu_system_dump_in_progress()) {
- error_setg(errp, "There is a dump in process, please wait.");
- return;
- }
- if (runstate_check(RUN_STATE_INMIGRATE)) {
- autostart = 0;
- } else {
- vm_stop(RUN_STATE_PAUSED);
- }
- }
- void qmp_cont(Error **errp)
- {
- BlockBackend *blk;
- BlockJob *job;
- Error *local_err = NULL;
- /* if there is a dump in background, we should wait until the dump
- * finished */
- if (qemu_system_dump_in_progress()) {
- error_setg(errp, "There is a dump in process, please wait.");
- return;
- }
- if (runstate_needs_reset()) {
- error_setg(errp, "Resetting the Virtual Machine is required");
- return;
- } else if (runstate_check(RUN_STATE_SUSPENDED)) {
- return;
- } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
- error_setg(errp, "Migration is not finalized yet");
- return;
- }
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- blk_iostatus_reset(blk);
- }
- WITH_JOB_LOCK_GUARD() {
- for (job = block_job_next_locked(NULL); job;
- job = block_job_next_locked(job)) {
- block_job_iostatus_reset_locked(job);
- }
- }
- if (runstate_check(RUN_STATE_INMIGRATE)) {
- autostart = 1;
- } else {
- /*
- * Continuing after completed migration. Images have been
- * inactivated to allow the destination to take control. Need to
- * get control back now.
- */
- if (!migration_block_activate(&local_err)) {
- error_propagate(errp, local_err);
- return;
- }
- vm_start();
- }
- }
- void qmp_add_client(const char *protocol, const char *fdname,
- bool has_skipauth, bool skipauth, bool has_tls, bool tls,
- Error **errp)
- {
- static const struct {
- 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;
- fd = monitor_get_fd(monitor_cur(), fdname, errp);
- if (fd < 0) {
- return;
- }
- if (!fd_is_socket(fd)) {
- error_setg(errp, "parameter @fdname must name a socket");
- close(fd);
- return;
- }
- 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);
- }
- return;
- }
- }
- if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
- protocol, errp)) {
- close(fd);
- }
- }
- 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);
- }
|