xref: /openbmc/qemu/monitor/qmp-cmds.c (revision 5bd26d78)
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 "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-control.h"
26 #include "qapi/qapi-commands-misc.h"
27 #include "qapi/type-helpers.h"
28 #include "hw/mem/memory-device.h"
29 #include "hw/intc/intc.h"
30 #include "hw/rdma/rdma.h"
31 
32 NameInfo *qmp_query_name(Error **errp)
33 {
34     NameInfo *info = g_malloc0(sizeof(*info));
35 
36     info->name = g_strdup(qemu_name);
37     return info;
38 }
39 
40 void qmp_quit(Error **errp)
41 {
42     shutdown_action = SHUTDOWN_ACTION_POWEROFF;
43     qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
44 }
45 
46 void qmp_stop(Error **errp)
47 {
48     /* if there is a dump in background, we should wait until the dump
49      * finished */
50     if (qemu_system_dump_in_progress()) {
51         error_setg(errp, "There is a dump in process, please wait.");
52         return;
53     }
54 
55     if (runstate_check(RUN_STATE_INMIGRATE)) {
56         autostart = 0;
57     } else {
58         vm_stop(RUN_STATE_PAUSED);
59     }
60 }
61 
62 void qmp_cont(Error **errp)
63 {
64     BlockBackend *blk;
65     BlockJob *job;
66     Error *local_err = NULL;
67 
68     /* if there is a dump in background, we should wait until the dump
69      * finished */
70     if (qemu_system_dump_in_progress()) {
71         error_setg(errp, "There is a dump in process, please wait.");
72         return;
73     }
74 
75     if (runstate_needs_reset()) {
76         error_setg(errp, "Resetting the Virtual Machine is required");
77         return;
78     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
79         return;
80     } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
81         error_setg(errp, "Migration is not finalized yet");
82         return;
83     }
84 
85     for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
86         blk_iostatus_reset(blk);
87     }
88 
89     WITH_JOB_LOCK_GUARD() {
90         for (job = block_job_next_locked(NULL); job;
91              job = block_job_next_locked(job)) {
92             block_job_iostatus_reset_locked(job);
93         }
94     }
95 
96     /* Continuing after completed migration. Images have been inactivated to
97      * allow the destination to take control. Need to get control back now.
98      *
99      * If there are no inactive block nodes (e.g. because the VM was just
100      * paused rather than completing a migration), bdrv_inactivate_all() simply
101      * doesn't do anything. */
102     bdrv_activate_all(&local_err);
103     if (local_err) {
104         error_propagate(errp, local_err);
105         return;
106     }
107 
108     if (runstate_check(RUN_STATE_INMIGRATE)) {
109         autostart = 1;
110     } else {
111         vm_start();
112     }
113 }
114 
115 void qmp_add_client(const char *protocol, const char *fdname,
116                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
117                     Error **errp)
118 {
119     static const struct {
120         const char *name;
121         bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
122                            bool has_tls, bool tls, Error **errp);
123     } protocol_table[] = {
124         { "spice", qmp_add_client_spice },
125 #ifdef CONFIG_VNC
126         { "vnc", qmp_add_client_vnc },
127 #endif
128 #ifdef CONFIG_DBUS_DISPLAY
129         { "@dbus-display", qmp_add_client_dbus_display },
130 #endif
131     };
132     int fd, i;
133 
134     fd = monitor_get_fd(monitor_cur(), fdname, errp);
135     if (fd < 0) {
136         return;
137     }
138 
139     for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
140         if (!strcmp(protocol, protocol_table[i].name)) {
141             if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
142                                               has_tls, tls, errp)) {
143                 close(fd);
144             }
145             return;
146         }
147     }
148 
149     if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
150                              protocol, errp)) {
151         close(fd);
152     }
153 }
154