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/cutils.h" 18 #include "qemu/option.h" 19 #include "monitor/monitor.h" 20 #include "sysemu/sysemu.h" 21 #include "qemu/config-file.h" 22 #include "qemu/uuid.h" 23 #include "chardev/char.h" 24 #include "ui/qemu-spice.h" 25 #include "ui/console.h" 26 #include "ui/dbus-display.h" 27 #include "sysemu/kvm.h" 28 #include "sysemu/runstate.h" 29 #include "sysemu/runstate-action.h" 30 #include "sysemu/blockdev.h" 31 #include "sysemu/block-backend.h" 32 #include "qapi/error.h" 33 #include "qapi/qapi-commands-acpi.h" 34 #include "qapi/qapi-commands-block.h" 35 #include "qapi/qapi-commands-control.h" 36 #include "qapi/qapi-commands-machine.h" 37 #include "qapi/qapi-commands-misc.h" 38 #include "qapi/qapi-commands-stats.h" 39 #include "qapi/qapi-commands-ui.h" 40 #include "qapi/type-helpers.h" 41 #include "qapi/qmp/qerror.h" 42 #include "exec/ramlist.h" 43 #include "hw/mem/memory-device.h" 44 #include "hw/acpi/acpi_dev_interface.h" 45 #include "hw/intc/intc.h" 46 #include "hw/rdma/rdma.h" 47 #include "monitor/stats.h" 48 49 NameInfo *qmp_query_name(Error **errp) 50 { 51 NameInfo *info = g_malloc0(sizeof(*info)); 52 53 info->name = g_strdup(qemu_name); 54 return info; 55 } 56 57 KvmInfo *qmp_query_kvm(Error **errp) 58 { 59 KvmInfo *info = g_malloc0(sizeof(*info)); 60 61 info->enabled = kvm_enabled(); 62 info->present = accel_find("kvm"); 63 64 return info; 65 } 66 67 UuidInfo *qmp_query_uuid(Error **errp) 68 { 69 UuidInfo *info = g_malloc0(sizeof(*info)); 70 71 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 72 return info; 73 } 74 75 void qmp_quit(Error **errp) 76 { 77 shutdown_action = SHUTDOWN_ACTION_POWEROFF; 78 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); 79 } 80 81 void qmp_stop(Error **errp) 82 { 83 /* if there is a dump in background, we should wait until the dump 84 * finished */ 85 if (qemu_system_dump_in_progress()) { 86 error_setg(errp, "There is a dump in process, please wait."); 87 return; 88 } 89 90 if (runstate_check(RUN_STATE_INMIGRATE)) { 91 autostart = 0; 92 } else { 93 vm_stop(RUN_STATE_PAUSED); 94 } 95 } 96 97 void qmp_system_reset(Error **errp) 98 { 99 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 100 } 101 102 void qmp_system_powerdown(Error **errp) 103 { 104 qemu_system_powerdown_request(); 105 } 106 107 void qmp_cont(Error **errp) 108 { 109 BlockBackend *blk; 110 BlockJob *job; 111 Error *local_err = NULL; 112 113 /* if there is a dump in background, we should wait until the dump 114 * finished */ 115 if (qemu_system_dump_in_progress()) { 116 error_setg(errp, "There is a dump in process, please wait."); 117 return; 118 } 119 120 if (runstate_needs_reset()) { 121 error_setg(errp, "Resetting the Virtual Machine is required"); 122 return; 123 } else if (runstate_check(RUN_STATE_SUSPENDED)) { 124 return; 125 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { 126 error_setg(errp, "Migration is not finalized yet"); 127 return; 128 } 129 130 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { 131 blk_iostatus_reset(blk); 132 } 133 134 WITH_JOB_LOCK_GUARD() { 135 for (job = block_job_next_locked(NULL); job; 136 job = block_job_next_locked(job)) { 137 block_job_iostatus_reset_locked(job); 138 } 139 } 140 141 /* Continuing after completed migration. Images have been inactivated to 142 * allow the destination to take control. Need to get control back now. 143 * 144 * If there are no inactive block nodes (e.g. because the VM was just 145 * paused rather than completing a migration), bdrv_inactivate_all() simply 146 * doesn't do anything. */ 147 bdrv_activate_all(&local_err); 148 if (local_err) { 149 error_propagate(errp, local_err); 150 return; 151 } 152 153 if (runstate_check(RUN_STATE_INMIGRATE)) { 154 autostart = 1; 155 } else { 156 vm_start(); 157 } 158 } 159 160 void qmp_system_wakeup(Error **errp) 161 { 162 if (!qemu_wakeup_suspend_enabled()) { 163 error_setg(errp, 164 "wake-up from suspend is not supported by this guest"); 165 return; 166 } 167 168 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 169 } 170 171 void qmp_set_password(SetPasswordOptions *opts, Error **errp) 172 { 173 int rc; 174 175 if (opts->protocol == DISPLAY_PROTOCOL_SPICE) { 176 if (!qemu_using_spice(errp)) { 177 return; 178 } 179 rc = qemu_spice.set_passwd(opts->password, 180 opts->connected == SET_PASSWORD_ACTION_FAIL, 181 opts->connected == SET_PASSWORD_ACTION_DISCONNECT); 182 } else { 183 assert(opts->protocol == DISPLAY_PROTOCOL_VNC); 184 if (opts->connected != SET_PASSWORD_ACTION_KEEP) { 185 /* vnc supports "connected=keep" only */ 186 error_setg(errp, QERR_INVALID_PARAMETER, "connected"); 187 return; 188 } 189 /* Note that setting an empty password will not disable login through 190 * this interface. */ 191 rc = vnc_display_password(opts->u.vnc.display, opts->password); 192 } 193 194 if (rc != 0) { 195 error_setg(errp, "Could not set password"); 196 } 197 } 198 199 void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp) 200 { 201 time_t when; 202 int rc; 203 const char *whenstr = opts->time; 204 const char *numstr = NULL; 205 uint64_t num; 206 207 if (strcmp(whenstr, "now") == 0) { 208 when = 0; 209 } else if (strcmp(whenstr, "never") == 0) { 210 when = TIME_MAX; 211 } else if (whenstr[0] == '+') { 212 when = time(NULL); 213 numstr = whenstr + 1; 214 } else { 215 when = 0; 216 numstr = whenstr; 217 } 218 219 if (numstr) { 220 if (qemu_strtou64(numstr, NULL, 10, &num) < 0) { 221 error_setg(errp, "Parameter 'time' doesn't take value '%s'", 222 whenstr); 223 return; 224 } 225 when += num; 226 } 227 228 if (opts->protocol == DISPLAY_PROTOCOL_SPICE) { 229 if (!qemu_using_spice(errp)) { 230 return; 231 } 232 rc = qemu_spice.set_pw_expire(when); 233 } else { 234 assert(opts->protocol == DISPLAY_PROTOCOL_VNC); 235 rc = vnc_display_pw_expire(opts->u.vnc.display, when); 236 } 237 238 if (rc != 0) { 239 error_setg(errp, "Could not set password expire time"); 240 } 241 } 242 243 #ifdef CONFIG_VNC 244 void qmp_change_vnc_password(const char *password, Error **errp) 245 { 246 if (vnc_display_password(NULL, password) < 0) { 247 error_setg(errp, "Could not set password"); 248 } 249 } 250 #endif 251 252 void qmp_add_client(const char *protocol, const char *fdname, 253 bool has_skipauth, bool skipauth, bool has_tls, bool tls, 254 Error **errp) 255 { 256 Chardev *s; 257 int fd; 258 259 fd = monitor_get_fd(monitor_cur(), fdname, errp); 260 if (fd < 0) { 261 return; 262 } 263 264 if (strcmp(protocol, "spice") == 0) { 265 if (!qemu_using_spice(errp)) { 266 close(fd); 267 return; 268 } 269 skipauth = has_skipauth ? skipauth : false; 270 tls = has_tls ? tls : false; 271 if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) { 272 error_setg(errp, "spice failed to add client"); 273 close(fd); 274 } 275 return; 276 #ifdef CONFIG_VNC 277 } else if (strcmp(protocol, "vnc") == 0) { 278 skipauth = has_skipauth ? skipauth : false; 279 vnc_display_add_client(NULL, fd, skipauth); 280 return; 281 #endif 282 #ifdef CONFIG_DBUS_DISPLAY 283 } else if (strcmp(protocol, "@dbus-display") == 0) { 284 if (!qemu_using_dbus_display(errp)) { 285 close(fd); 286 return; 287 } 288 if (!qemu_dbus_display.add_client(fd, errp)) { 289 close(fd); 290 return; 291 } 292 return; 293 #endif 294 } else if ((s = qemu_chr_find(protocol)) != NULL) { 295 if (qemu_chr_add_client(s, fd) < 0) { 296 error_setg(errp, "failed to add client"); 297 close(fd); 298 return; 299 } 300 return; 301 } 302 303 error_setg(errp, "protocol '%s' is invalid", protocol); 304 close(fd); 305 } 306 307 308 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 309 { 310 return qmp_memory_device_list(); 311 } 312 313 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) 314 { 315 bool ambig; 316 ACPIOSTInfoList *head = NULL; 317 ACPIOSTInfoList **prev = &head; 318 Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig); 319 320 if (obj) { 321 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); 322 AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj); 323 324 adevc->ospm_status(adev, &prev); 325 } else { 326 error_setg(errp, "command is not supported, missing ACPI device"); 327 } 328 329 return head; 330 } 331 332 MemoryInfo *qmp_query_memory_size_summary(Error **errp) 333 { 334 MemoryInfo *mem_info = g_new0(MemoryInfo, 1); 335 MachineState *ms = MACHINE(qdev_get_machine()); 336 337 mem_info->base_memory = ms->ram_size; 338 339 mem_info->plugged_memory = get_plugged_memory_size(); 340 mem_info->has_plugged_memory = 341 mem_info->plugged_memory != (uint64_t)-1; 342 343 return mem_info; 344 } 345 346 void qmp_display_reload(DisplayReloadOptions *arg, Error **errp) 347 { 348 switch (arg->type) { 349 case DISPLAY_RELOAD_TYPE_VNC: 350 #ifdef CONFIG_VNC 351 if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) { 352 vnc_display_reload_certs(NULL, errp); 353 } 354 #else 355 error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'"); 356 #endif 357 break; 358 default: 359 abort(); 360 } 361 } 362 363 void qmp_display_update(DisplayUpdateOptions *arg, Error **errp) 364 { 365 switch (arg->type) { 366 case DISPLAY_UPDATE_TYPE_VNC: 367 #ifdef CONFIG_VNC 368 vnc_display_update(&arg->u.vnc, errp); 369 #else 370 error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'"); 371 #endif 372 break; 373 default: 374 abort(); 375 } 376 } 377 378 static int qmp_x_query_rdma_foreach(Object *obj, void *opaque) 379 { 380 RdmaProvider *rdma; 381 RdmaProviderClass *k; 382 GString *buf = opaque; 383 384 if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) { 385 rdma = RDMA_PROVIDER(obj); 386 k = RDMA_PROVIDER_GET_CLASS(obj); 387 if (k->format_statistics) { 388 k->format_statistics(rdma, buf); 389 } else { 390 g_string_append_printf(buf, 391 "RDMA statistics not available for %s.\n", 392 object_get_typename(obj)); 393 } 394 } 395 396 return 0; 397 } 398 399 HumanReadableText *qmp_x_query_rdma(Error **errp) 400 { 401 g_autoptr(GString) buf = g_string_new(""); 402 403 object_child_foreach_recursive(object_get_root(), 404 qmp_x_query_rdma_foreach, buf); 405 406 return human_readable_text_from_str(buf); 407 } 408 409 HumanReadableText *qmp_x_query_ramblock(Error **errp) 410 { 411 g_autoptr(GString) buf = ram_block_format(); 412 413 return human_readable_text_from_str(buf); 414 } 415 416 static int qmp_x_query_irq_foreach(Object *obj, void *opaque) 417 { 418 InterruptStatsProvider *intc; 419 InterruptStatsProviderClass *k; 420 GString *buf = opaque; 421 422 if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { 423 intc = INTERRUPT_STATS_PROVIDER(obj); 424 k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); 425 uint64_t *irq_counts; 426 unsigned int nb_irqs, i; 427 if (k->get_statistics && 428 k->get_statistics(intc, &irq_counts, &nb_irqs)) { 429 if (nb_irqs > 0) { 430 g_string_append_printf(buf, "IRQ statistics for %s:\n", 431 object_get_typename(obj)); 432 for (i = 0; i < nb_irqs; i++) { 433 if (irq_counts[i] > 0) { 434 g_string_append_printf(buf, "%2d: %" PRId64 "\n", i, 435 irq_counts[i]); 436 } 437 } 438 } 439 } else { 440 g_string_append_printf(buf, 441 "IRQ statistics not available for %s.\n", 442 object_get_typename(obj)); 443 } 444 } 445 446 return 0; 447 } 448 449 HumanReadableText *qmp_x_query_irq(Error **errp) 450 { 451 g_autoptr(GString) buf = g_string_new(""); 452 453 object_child_foreach_recursive(object_get_root(), 454 qmp_x_query_irq_foreach, buf); 455 456 return human_readable_text_from_str(buf); 457 } 458 459 typedef struct StatsCallbacks { 460 StatsProvider provider; 461 StatRetrieveFunc *stats_cb; 462 SchemaRetrieveFunc *schemas_cb; 463 QTAILQ_ENTRY(StatsCallbacks) next; 464 } StatsCallbacks; 465 466 static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks = 467 QTAILQ_HEAD_INITIALIZER(stats_callbacks); 468 469 void add_stats_callbacks(StatsProvider provider, 470 StatRetrieveFunc *stats_fn, 471 SchemaRetrieveFunc *schemas_fn) 472 { 473 StatsCallbacks *entry = g_new(StatsCallbacks, 1); 474 entry->provider = provider; 475 entry->stats_cb = stats_fn; 476 entry->schemas_cb = schemas_fn; 477 478 QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next); 479 } 480 481 static bool invoke_stats_cb(StatsCallbacks *entry, 482 StatsResultList **stats_results, 483 StatsFilter *filter, StatsRequest *request, 484 Error **errp) 485 { 486 ERRP_GUARD(); 487 strList *targets = NULL; 488 strList *names = NULL; 489 490 if (request) { 491 if (request->provider != entry->provider) { 492 return true; 493 } 494 if (request->has_names && !request->names) { 495 return true; 496 } 497 names = request->has_names ? request->names : NULL; 498 } 499 500 switch (filter->target) { 501 case STATS_TARGET_VM: 502 break; 503 case STATS_TARGET_VCPU: 504 if (filter->u.vcpu.has_vcpus) { 505 if (!filter->u.vcpu.vcpus) { 506 /* No targets allowed? Return no statistics. */ 507 return true; 508 } 509 targets = filter->u.vcpu.vcpus; 510 } 511 break; 512 default: 513 abort(); 514 } 515 516 entry->stats_cb(stats_results, filter->target, names, targets, errp); 517 if (*errp) { 518 qapi_free_StatsResultList(*stats_results); 519 *stats_results = NULL; 520 return false; 521 } 522 return true; 523 } 524 525 StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp) 526 { 527 StatsResultList *stats_results = NULL; 528 StatsCallbacks *entry; 529 StatsRequestList *request; 530 531 QTAILQ_FOREACH(entry, &stats_callbacks, next) { 532 if (filter->has_providers) { 533 for (request = filter->providers; request; request = request->next) { 534 if (!invoke_stats_cb(entry, &stats_results, filter, 535 request->value, errp)) { 536 break; 537 } 538 } 539 } else { 540 if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) { 541 break; 542 } 543 } 544 } 545 546 return stats_results; 547 } 548 549 StatsSchemaList *qmp_query_stats_schemas(bool has_provider, 550 StatsProvider provider, 551 Error **errp) 552 { 553 ERRP_GUARD(); 554 StatsSchemaList *stats_results = NULL; 555 StatsCallbacks *entry; 556 557 QTAILQ_FOREACH(entry, &stats_callbacks, next) { 558 if (!has_provider || provider == entry->provider) { 559 entry->schemas_cb(&stats_results, errp); 560 if (*errp) { 561 qapi_free_StatsSchemaList(stats_results); 562 return NULL; 563 } 564 } 565 } 566 567 return stats_results; 568 } 569 570 void add_stats_entry(StatsResultList **stats_results, StatsProvider provider, 571 const char *qom_path, StatsList *stats_list) 572 { 573 StatsResult *entry = g_new0(StatsResult, 1); 574 575 entry->provider = provider; 576 entry->qom_path = g_strdup(qom_path); 577 entry->stats = stats_list; 578 579 QAPI_LIST_PREPEND(*stats_results, entry); 580 } 581 582 void add_stats_schema(StatsSchemaList **schema_results, 583 StatsProvider provider, StatsTarget target, 584 StatsSchemaValueList *stats_list) 585 { 586 StatsSchema *entry = g_new0(StatsSchema, 1); 587 588 entry->provider = provider; 589 entry->target = target; 590 entry->stats = stats_list; 591 QAPI_LIST_PREPEND(*schema_results, entry); 592 } 593 594 bool apply_str_list_filter(const char *string, strList *list) 595 { 596 strList *str_list = NULL; 597 598 if (!list) { 599 return true; 600 } 601 for (str_list = list; str_list; str_list = str_list->next) { 602 if (g_str_equal(string, str_list->value)) { 603 return true; 604 } 605 } 606 return false; 607 } 608