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-common.h" 18 #include "qemu/cutils.h" 19 #include "qemu/option.h" 20 #include "monitor/monitor.h" 21 #include "sysemu/sysemu.h" 22 #include "qemu/config-file.h" 23 #include "qemu/uuid.h" 24 #include "chardev/char.h" 25 #include "ui/qemu-spice.h" 26 #include "ui/vnc.h" 27 #include "sysemu/kvm.h" 28 #include "sysemu/runstate.h" 29 #include "sysemu/arch_init.h" 30 #include "sysemu/blockdev.h" 31 #include "sysemu/block-backend.h" 32 #include "qapi/error.h" 33 #include "qapi/qapi-commands-block.h" 34 #include "qapi/qapi-commands-control.h" 35 #include "qapi/qapi-commands-machine.h" 36 #include "qapi/qapi-commands-misc.h" 37 #include "qapi/qapi-commands-ui.h" 38 #include "qapi/qmp/qerror.h" 39 #include "hw/mem/memory-device.h" 40 #include "hw/acpi/acpi_dev_interface.h" 41 42 NameInfo *qmp_query_name(Error **errp) 43 { 44 NameInfo *info = g_malloc0(sizeof(*info)); 45 46 if (qemu_name) { 47 info->has_name = true; 48 info->name = g_strdup(qemu_name); 49 } 50 51 return info; 52 } 53 54 KvmInfo *qmp_query_kvm(Error **errp) 55 { 56 KvmInfo *info = g_malloc0(sizeof(*info)); 57 58 info->enabled = kvm_enabled(); 59 info->present = kvm_available(); 60 61 return info; 62 } 63 64 UuidInfo *qmp_query_uuid(Error **errp) 65 { 66 UuidInfo *info = g_malloc0(sizeof(*info)); 67 68 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 69 return info; 70 } 71 72 void qmp_quit(Error **errp) 73 { 74 no_shutdown = 0; 75 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); 76 } 77 78 void qmp_stop(Error **errp) 79 { 80 /* if there is a dump in background, we should wait until the dump 81 * finished */ 82 if (dump_in_progress()) { 83 error_setg(errp, "There is a dump in process, please wait."); 84 return; 85 } 86 87 if (runstate_check(RUN_STATE_INMIGRATE)) { 88 autostart = 0; 89 } else { 90 vm_stop(RUN_STATE_PAUSED); 91 } 92 } 93 94 void qmp_system_reset(Error **errp) 95 { 96 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 97 } 98 99 void qmp_system_powerdown(Error **errp) 100 { 101 qemu_system_powerdown_request(); 102 } 103 104 void qmp_x_exit_preconfig(Error **errp) 105 { 106 if (!runstate_check(RUN_STATE_PRECONFIG)) { 107 error_setg(errp, "The command is permitted only in '%s' state", 108 RunState_str(RUN_STATE_PRECONFIG)); 109 return; 110 } 111 qemu_exit_preconfig_request(); 112 } 113 114 void qmp_cont(Error **errp) 115 { 116 BlockBackend *blk; 117 BlockJob *job; 118 Error *local_err = NULL; 119 120 /* if there is a dump in background, we should wait until the dump 121 * finished */ 122 if (dump_in_progress()) { 123 error_setg(errp, "There is a dump in process, please wait."); 124 return; 125 } 126 127 if (runstate_needs_reset()) { 128 error_setg(errp, "Resetting the Virtual Machine is required"); 129 return; 130 } else if (runstate_check(RUN_STATE_SUSPENDED)) { 131 return; 132 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { 133 error_setg(errp, "Migration is not finalized yet"); 134 return; 135 } 136 137 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { 138 blk_iostatus_reset(blk); 139 } 140 141 for (job = block_job_next(NULL); job; job = block_job_next(job)) { 142 block_job_iostatus_reset(job); 143 } 144 145 /* Continuing after completed migration. Images have been inactivated to 146 * allow the destination to take control. Need to get control back now. 147 * 148 * If there are no inactive block nodes (e.g. because the VM was just 149 * paused rather than completing a migration), bdrv_inactivate_all() simply 150 * doesn't do anything. */ 151 bdrv_invalidate_cache_all(&local_err); 152 if (local_err) { 153 error_propagate(errp, local_err); 154 return; 155 } 156 157 if (runstate_check(RUN_STATE_INMIGRATE)) { 158 autostart = 1; 159 } else { 160 vm_start(); 161 } 162 } 163 164 void qmp_system_wakeup(Error **errp) 165 { 166 if (!qemu_wakeup_suspend_enabled()) { 167 error_setg(errp, 168 "wake-up from suspend is not supported by this guest"); 169 return; 170 } 171 172 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 173 } 174 175 void qmp_set_password(const char *protocol, const char *password, 176 bool has_connected, const char *connected, Error **errp) 177 { 178 int disconnect_if_connected = 0; 179 int fail_if_connected = 0; 180 int rc; 181 182 if (has_connected) { 183 if (strcmp(connected, "fail") == 0) { 184 fail_if_connected = 1; 185 } else if (strcmp(connected, "disconnect") == 0) { 186 disconnect_if_connected = 1; 187 } else if (strcmp(connected, "keep") == 0) { 188 /* nothing */ 189 } else { 190 error_setg(errp, QERR_INVALID_PARAMETER, "connected"); 191 return; 192 } 193 } 194 195 if (strcmp(protocol, "spice") == 0) { 196 if (!qemu_using_spice(errp)) { 197 return; 198 } 199 rc = qemu_spice_set_passwd(password, fail_if_connected, 200 disconnect_if_connected); 201 if (rc != 0) { 202 error_setg(errp, QERR_SET_PASSWD_FAILED); 203 } 204 return; 205 } 206 207 if (strcmp(protocol, "vnc") == 0) { 208 if (fail_if_connected || disconnect_if_connected) { 209 /* vnc supports "connected=keep" only */ 210 error_setg(errp, QERR_INVALID_PARAMETER, "connected"); 211 return; 212 } 213 /* Note that setting an empty password will not disable login through 214 * this interface. */ 215 rc = vnc_display_password(NULL, password); 216 if (rc < 0) { 217 error_setg(errp, QERR_SET_PASSWD_FAILED); 218 } 219 return; 220 } 221 222 error_setg(errp, QERR_INVALID_PARAMETER, "protocol"); 223 } 224 225 void qmp_expire_password(const char *protocol, const char *whenstr, 226 Error **errp) 227 { 228 time_t when; 229 int rc; 230 231 if (strcmp(whenstr, "now") == 0) { 232 when = 0; 233 } else if (strcmp(whenstr, "never") == 0) { 234 when = TIME_MAX; 235 } else if (whenstr[0] == '+') { 236 when = time(NULL) + strtoull(whenstr+1, NULL, 10); 237 } else { 238 when = strtoull(whenstr, NULL, 10); 239 } 240 241 if (strcmp(protocol, "spice") == 0) { 242 if (!qemu_using_spice(errp)) { 243 return; 244 } 245 rc = qemu_spice_set_pw_expire(when); 246 if (rc != 0) { 247 error_setg(errp, QERR_SET_PASSWD_FAILED); 248 } 249 return; 250 } 251 252 if (strcmp(protocol, "vnc") == 0) { 253 rc = vnc_display_pw_expire(NULL, when); 254 if (rc != 0) { 255 error_setg(errp, QERR_SET_PASSWD_FAILED); 256 } 257 return; 258 } 259 260 error_setg(errp, QERR_INVALID_PARAMETER, "protocol"); 261 } 262 263 #ifdef CONFIG_VNC 264 void qmp_change_vnc_password(const char *password, Error **errp) 265 { 266 if (vnc_display_password(NULL, password) < 0) { 267 error_setg(errp, QERR_SET_PASSWD_FAILED); 268 } 269 } 270 271 static void qmp_change_vnc_listen(const char *target, Error **errp) 272 { 273 QemuOptsList *olist = qemu_find_opts("vnc"); 274 QemuOpts *opts; 275 276 if (strstr(target, "id=")) { 277 error_setg(errp, "id not supported"); 278 return; 279 } 280 281 opts = qemu_opts_find(olist, "default"); 282 if (opts) { 283 qemu_opts_del(opts); 284 } 285 opts = vnc_parse(target, errp); 286 if (!opts) { 287 return; 288 } 289 290 vnc_display_open("default", errp); 291 } 292 293 static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, 294 Error **errp) 295 { 296 if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { 297 if (!has_arg) { 298 error_setg(errp, QERR_MISSING_PARAMETER, "password"); 299 } else { 300 qmp_change_vnc_password(arg, errp); 301 } 302 } else { 303 qmp_change_vnc_listen(target, errp); 304 } 305 } 306 #endif /* !CONFIG_VNC */ 307 308 void qmp_change(const char *device, const char *target, 309 bool has_arg, const char *arg, Error **errp) 310 { 311 if (strcmp(device, "vnc") == 0) { 312 #ifdef CONFIG_VNC 313 qmp_change_vnc(target, has_arg, arg, errp); 314 #else 315 error_setg(errp, QERR_FEATURE_DISABLED, "vnc"); 316 #endif 317 } else { 318 qmp_blockdev_change_medium(true, device, false, NULL, target, 319 has_arg, arg, false, 0, errp); 320 } 321 } 322 323 void qmp_add_client(const char *protocol, const char *fdname, 324 bool has_skipauth, bool skipauth, bool has_tls, bool tls, 325 Error **errp) 326 { 327 Chardev *s; 328 int fd; 329 330 fd = monitor_get_fd(cur_mon, fdname, errp); 331 if (fd < 0) { 332 return; 333 } 334 335 if (strcmp(protocol, "spice") == 0) { 336 if (!qemu_using_spice(errp)) { 337 close(fd); 338 return; 339 } 340 skipauth = has_skipauth ? skipauth : false; 341 tls = has_tls ? tls : false; 342 if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { 343 error_setg(errp, "spice failed to add client"); 344 close(fd); 345 } 346 return; 347 #ifdef CONFIG_VNC 348 } else if (strcmp(protocol, "vnc") == 0) { 349 skipauth = has_skipauth ? skipauth : false; 350 vnc_display_add_client(NULL, fd, skipauth); 351 return; 352 #endif 353 } else if ((s = qemu_chr_find(protocol)) != NULL) { 354 if (qemu_chr_add_client(s, fd) < 0) { 355 error_setg(errp, "failed to add client"); 356 close(fd); 357 return; 358 } 359 return; 360 } 361 362 error_setg(errp, "protocol '%s' is invalid", protocol); 363 close(fd); 364 } 365 366 367 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 368 { 369 return qmp_memory_device_list(); 370 } 371 372 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) 373 { 374 bool ambig; 375 ACPIOSTInfoList *head = NULL; 376 ACPIOSTInfoList **prev = &head; 377 Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig); 378 379 if (obj) { 380 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); 381 AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj); 382 383 adevc->ospm_status(adev, &prev); 384 } else { 385 error_setg(errp, "command is not supported, missing ACPI device"); 386 } 387 388 return head; 389 } 390 391 MemoryInfo *qmp_query_memory_size_summary(Error **errp) 392 { 393 MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo)); 394 395 mem_info->base_memory = ram_size; 396 397 mem_info->plugged_memory = get_plugged_memory_size(); 398 mem_info->has_plugged_memory = 399 mem_info->plugged_memory != (uint64_t)-1; 400 401 return mem_info; 402 } 403