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