master
c 212 lines 5.78 KB
Raw
1 /*
2 * QEMU Management Protocol commands
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/osdep.h"
17 #include "qemu/sockets.h"
18 #include "monitor-internal.h"
19 #include "monitor-hmp-internal.h"
20 #include "monitor/qdev.h"
21 #include "monitor/qmp-helpers.h"
22 #include "system/system.h"
23 #include "system/kvm.h"
24 #include "system/runstate.h"
25 #include "system/runstate-action.h"
26 #include "system/block-backend.h"
27 #include "qapi/error.h"
28 #include "qapi/qapi-init-commands.h"
29 #include "qapi/qapi-commands-control.h"
30 #include "qapi/qapi-commands-misc.h"
31 #include "qapi/qmp/qerror.h"
32 #include "qapi/type-helpers.h"
33 #include "hw/mem/memory-device.h"
34 #include "hw/intc/intc.h"
35 #include "migration/misc.h"
36
37 NameInfo *qmp_query_name(Error **errp)
38 {
39 NameInfo *info = g_malloc0(sizeof(*info));
40
41 info->name = g_strdup(qemu_name);
42 return info;
43 }
44
45 void qmp_quit(Error **errp)
46 {
47 shutdown_action = SHUTDOWN_ACTION_POWEROFF;
48 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
49 }
50
51 void qmp_stop(Error **errp)
52 {
53 /* if there is a dump in background, we should wait until the dump
54 * finished */
55 if (qemu_system_dump_in_progress()) {
56 error_setg(errp, "There is a dump in process, please wait.");
57 return;
58 }
59
60 if (runstate_check(RUN_STATE_INMIGRATE)) {
61 autostart = 0;
62 } else {
63 vm_stop(RUN_STATE_PAUSED);
64 }
65 }
66
67 void qmp_cont(Error **errp)
68 {
69 BlockBackend *blk;
70 BlockJob *job;
71 Error *local_err = NULL;
72
73 /* if there is a dump in background, we should wait until the dump
74 * finished */
75 if (qemu_system_dump_in_progress()) {
76 error_setg(errp, "There is a dump in process, please wait.");
77 return;
78 }
79
80 if (runstate_needs_reset()) {
81 error_setg(errp, "Resetting the Virtual Machine is required");
82 return;
83 } else if (runstate_check(RUN_STATE_SUSPENDED)) {
84 return;
85 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
86 error_setg(errp, "Migration is not finalized yet");
87 return;
88 } else if (runstate_check(RUN_STATE_COLO)) {
89 error_setg(errp, "COLO checkpoint in progress");
90 return;
91 }
92
93 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
94 blk_iostatus_reset(blk);
95 }
96
97 WITH_JOB_LOCK_GUARD() {
98 for (job = block_job_next_locked(NULL); job;
99 job = block_job_next_locked(job)) {
100 block_job_iostatus_reset_locked(job);
101 }
102 }
103
104 if (runstate_check(RUN_STATE_INMIGRATE)) {
105 autostart = 1;
106 } else {
107 /*
108 * Continuing after completed migration. Images have been
109 * inactivated to allow the destination to take control. Need to
110 * get control back now.
111 */
112 if (!migration_block_activate(&local_err)) {
113 error_propagate(errp, local_err);
114 return;
115 }
116 vm_start();
117 }
118 }
119
120 void qmp_add_client(const char *protocol, const char *fdname,
121 bool has_skipauth, bool skipauth, bool has_tls, bool tls,
122 Error **errp)
123 {
124 static const struct {
125 const char *name;
126 bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
127 bool has_tls, bool tls, Error **errp);
128 } protocol_table[] = {
129 { "spice", qmp_add_client_spice },
130 #ifdef CONFIG_VNC
131 { "vnc", qmp_add_client_vnc },
132 #endif
133 #ifdef CONFIG_DBUS_DISPLAY
134 { "@dbus-display", qmp_add_client_dbus_display },
135 #endif
136 };
137 int fd, i;
138
139 fd = monitor_get_fd(monitor_cur(), fdname, errp);
140 if (fd < 0) {
141 return;
142 }
143
144 if (!fd_is_socket(fd)) {
145 error_setg(errp, "parameter @fdname must name a socket");
146 close(fd);
147 return;
148 }
149
150 for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
151 if (!strcmp(protocol, protocol_table[i].name)) {
152 if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
153 has_tls, tls, errp)) {
154 close(fd);
155 }
156 return;
157 }
158 }
159
160 if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
161 protocol, errp)) {
162 close(fd);
163 }
164 }
165
166 #ifdef CONFIG_HMP
167 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
168 int64_t cpu_index, Error **errp)
169 {
170 char *output = NULL;
171 MonitorHMP *hmp = MONITOR_HMP(object_new(TYPE_MONITOR_HMP));
172
173 if (has_cpu_index) {
174 int ret = monitor_hmp_set_cpu(hmp, cpu_index);
175 if (ret < 0) {
176 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
177 "a CPU number");
178 goto out;
179 }
180 }
181
182 handle_hmp_command(hmp, command_line);
183
184 WITH_QEMU_LOCK_GUARD(&hmp->parent_obj.mon_lock) {
185 output = g_strdup(hmp->parent_obj.outbuf->str);
186 }
187
188 out:
189 object_unref(hmp);
190 return output;
191 }
192 #endif /* CONFIG_HMP */
193
194 static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
195 {
196 /*
197 * Two command lists:
198 * - qmp_commands contains all QMP commands
199 * - qmp_cap_negotiation_commands contains just
200 * "qmp_capabilities", to enforce capability negotiation
201 */
202
203 qmp_init_marshal(&qmp_commands);
204
205 qmp_register_command(&qmp_commands, "device_add",
206 qmp_device_add, 0, 0);
207
208 QTAILQ_INIT(&qmp_cap_negotiation_commands);
209 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
210 qmp_marshal_qmp_capabilities,
211 QCO_ALLOW_PRECONFIG, 0);
212 }