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