qemu/qmp.c
<<
>>
Prefs
   1/*
   2 * QEMU Management Protocol
   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-version.h"
  18#include "qemu/cutils.h"
  19#include "monitor/monitor.h"
  20#include "sysemu/sysemu.h"
  21#include "qemu/uuid.h"
  22#include "qmp-commands.h"
  23#include "sysemu/char.h"
  24#include "ui/qemu-spice.h"
  25#include "ui/vnc.h"
  26#include "sysemu/kvm.h"
  27#include "sysemu/arch_init.h"
  28#include "hw/qdev.h"
  29#include "sysemu/blockdev.h"
  30#include "sysemu/block-backend.h"
  31#include "qom/qom-qobject.h"
  32#include "qapi/qmp/qerror.h"
  33#include "qapi/qmp/qobject.h"
  34#include "qapi/qobject-input-visitor.h"
  35#include "hw/boards.h"
  36#include "qom/object_interfaces.h"
  37#include "hw/mem/pc-dimm.h"
  38#include "hw/acpi/acpi_dev_interface.h"
  39
  40NameInfo *qmp_query_name(Error **errp)
  41{
  42    NameInfo *info = g_malloc0(sizeof(*info));
  43
  44    if (qemu_name) {
  45        info->has_name = true;
  46        info->name = g_strdup(qemu_name);
  47    }
  48
  49    return info;
  50}
  51
  52VersionInfo *qmp_query_version(Error **errp)
  53{
  54    VersionInfo *info = g_new0(VersionInfo, 1);
  55
  56    info->qemu = g_new0(VersionTriple, 1);
  57    info->qemu->major = QEMU_VERSION_MAJOR;
  58    info->qemu->minor = QEMU_VERSION_MINOR;
  59    info->qemu->micro = QEMU_VERSION_MICRO;
  60    info->package = g_strdup(QEMU_PKGVERSION);
  61
  62    return info;
  63}
  64
  65KvmInfo *qmp_query_kvm(Error **errp)
  66{
  67    KvmInfo *info = g_malloc0(sizeof(*info));
  68
  69    info->enabled = kvm_enabled();
  70    info->present = kvm_available();
  71
  72    return info;
  73}
  74
  75UuidInfo *qmp_query_uuid(Error **errp)
  76{
  77    UuidInfo *info = g_malloc0(sizeof(*info));
  78
  79    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
  80    return info;
  81}
  82
  83void qmp_quit(Error **errp)
  84{
  85    no_shutdown = 0;
  86    qemu_system_shutdown_request();
  87}
  88
  89void qmp_stop(Error **errp)
  90{
  91    /* if there is a dump in background, we should wait until the dump
  92     * finished */
  93    if (dump_in_progress()) {
  94        error_setg(errp, "There is a dump in process, please wait.");
  95        return;
  96    }
  97
  98    if (runstate_check(RUN_STATE_INMIGRATE)) {
  99        autostart = 0;
 100    } else {
 101        vm_stop(RUN_STATE_PAUSED);
 102    }
 103}
 104
 105void qmp_system_reset(Error **errp)
 106{
 107    qemu_system_reset_request();
 108}
 109
 110void qmp_system_powerdown(Error **erp)
 111{
 112    qemu_system_powerdown_request();
 113}
 114
 115void qmp_cpu(int64_t index, Error **errp)
 116{
 117    /* Just do nothing */
 118}
 119
 120void qmp_cpu_add(int64_t id, Error **errp)
 121{
 122    MachineClass *mc;
 123
 124    mc = MACHINE_GET_CLASS(current_machine);
 125    if (mc->hot_add_cpu) {
 126        mc->hot_add_cpu(id, errp);
 127    } else {
 128        error_setg(errp, "Not supported");
 129    }
 130}
 131
 132#ifndef CONFIG_VNC
 133/* If VNC support is enabled, the "true" query-vnc command is
 134   defined in the VNC subsystem */
 135VncInfo *qmp_query_vnc(Error **errp)
 136{
 137    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 138    return NULL;
 139};
 140
 141VncInfo2List *qmp_query_vnc_servers(Error **errp)
 142{
 143    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 144    return NULL;
 145};
 146#endif
 147
 148#ifndef CONFIG_SPICE
 149/*
 150 * qmp-commands.hx ensures that QMP command query-spice exists only
 151 * #ifdef CONFIG_SPICE.  Necessary for an accurate query-commands
 152 * result.  However, the QAPI schema is blissfully unaware of that,
 153 * and the QAPI code generator happily generates a dead
 154 * qmp_marshal_query_spice() that calls qmp_query_spice().  Provide it
 155 * one, or else linking fails.  FIXME Educate the QAPI schema on
 156 * CONFIG_SPICE.
 157 */
 158SpiceInfo *qmp_query_spice(Error **errp)
 159{
 160    abort();
 161};
 162#endif
 163
 164void qmp_cont(Error **errp)
 165{
 166    Error *local_err = NULL;
 167    BlockBackend *blk;
 168    BlockDriverState *bs;
 169    BdrvNextIterator it;
 170
 171    /* if there is a dump in background, we should wait until the dump
 172     * finished */
 173    if (dump_in_progress()) {
 174        error_setg(errp, "There is a dump in process, please wait.");
 175        return;
 176    }
 177
 178    if (runstate_needs_reset()) {
 179        error_setg(errp, "Resetting the Virtual Machine is required");
 180        return;
 181    } else if (runstate_check(RUN_STATE_SUSPENDED)) {
 182        return;
 183    }
 184
 185    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
 186        blk_iostatus_reset(blk);
 187    }
 188
 189    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 190        bdrv_add_key(bs, NULL, &local_err);
 191        if (local_err) {
 192            error_propagate(errp, local_err);
 193            return;
 194        }
 195    }
 196
 197    /* Continuing after completed migration. Images have been inactivated to
 198     * allow the destination to take control. Need to get control back now. */
 199    if (runstate_check(RUN_STATE_FINISH_MIGRATE) ||
 200        runstate_check(RUN_STATE_POSTMIGRATE))
 201    {
 202        bdrv_invalidate_cache_all(&local_err);
 203        if (local_err) {
 204            error_propagate(errp, local_err);
 205            return;
 206        }
 207    }
 208
 209    if (runstate_check(RUN_STATE_INMIGRATE)) {
 210        autostart = 1;
 211    } else {
 212        vm_start();
 213    }
 214}
 215
 216void qmp_system_wakeup(Error **errp)
 217{
 218    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
 219}
 220
 221ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
 222{
 223    Object *obj;
 224    bool ambiguous = false;
 225    ObjectPropertyInfoList *props = NULL;
 226    ObjectProperty *prop;
 227    ObjectPropertyIterator iter;
 228
 229    obj = object_resolve_path(path, &ambiguous);
 230    if (obj == NULL) {
 231        if (ambiguous) {
 232            error_setg(errp, "Path '%s' is ambiguous", path);
 233        } else {
 234            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 235                      "Device '%s' not found", path);
 236        }
 237        return NULL;
 238    }
 239
 240    object_property_iter_init(&iter, obj);
 241    while ((prop = object_property_iter_next(&iter))) {
 242        ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
 243
 244        entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
 245        entry->next = props;
 246        props = entry;
 247
 248        entry->value->name = g_strdup(prop->name);
 249        entry->value->type = g_strdup(prop->type);
 250    }
 251
 252    return props;
 253}
 254
 255void qmp_qom_set(const char *path, const char *property, QObject *value,
 256                 Error **errp)
 257{
 258    Object *obj;
 259
 260    obj = object_resolve_path(path, NULL);
 261    if (!obj) {
 262        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 263                  "Device '%s' not found", path);
 264        return;
 265    }
 266
 267    object_property_set_qobject(obj, value, property, errp);
 268}
 269
 270QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
 271{
 272    Object *obj;
 273
 274    obj = object_resolve_path(path, NULL);
 275    if (!obj) {
 276        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 277                  "Device '%s' not found", path);
 278        return NULL;
 279    }
 280
 281    return object_property_get_qobject(obj, property, errp);
 282}
 283
 284void qmp_set_password(const char *protocol, const char *password,
 285                      bool has_connected, const char *connected, Error **errp)
 286{
 287    int disconnect_if_connected = 0;
 288    int fail_if_connected = 0;
 289    int rc;
 290
 291    if (has_connected) {
 292        if (strcmp(connected, "fail") == 0) {
 293            fail_if_connected = 1;
 294        } else if (strcmp(connected, "disconnect") == 0) {
 295            disconnect_if_connected = 1;
 296        } else if (strcmp(connected, "keep") == 0) {
 297            /* nothing */
 298        } else {
 299            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
 300            return;
 301        }
 302    }
 303
 304    if (strcmp(protocol, "spice") == 0) {
 305        if (!qemu_using_spice(errp)) {
 306            return;
 307        }
 308        rc = qemu_spice_set_passwd(password, fail_if_connected,
 309                                   disconnect_if_connected);
 310        if (rc != 0) {
 311            error_setg(errp, QERR_SET_PASSWD_FAILED);
 312        }
 313        return;
 314    }
 315
 316    if (strcmp(protocol, "vnc") == 0) {
 317        if (fail_if_connected || disconnect_if_connected) {
 318            /* vnc supports "connected=keep" only */
 319            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
 320            return;
 321        }
 322        /* Note that setting an empty password will not disable login through
 323         * this interface. */
 324        rc = vnc_display_password(NULL, password);
 325        if (rc < 0) {
 326            error_setg(errp, QERR_SET_PASSWD_FAILED);
 327        }
 328        return;
 329    }
 330
 331    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
 332}
 333
 334void qmp_expire_password(const char *protocol, const char *whenstr,
 335                         Error **errp)
 336{
 337    time_t when;
 338    int rc;
 339
 340    if (strcmp(whenstr, "now") == 0) {
 341        when = 0;
 342    } else if (strcmp(whenstr, "never") == 0) {
 343        when = TIME_MAX;
 344    } else if (whenstr[0] == '+') {
 345        when = time(NULL) + strtoull(whenstr+1, NULL, 10);
 346    } else {
 347        when = strtoull(whenstr, NULL, 10);
 348    }
 349
 350    if (strcmp(protocol, "spice") == 0) {
 351        if (!qemu_using_spice(errp)) {
 352            return;
 353        }
 354        rc = qemu_spice_set_pw_expire(when);
 355        if (rc != 0) {
 356            error_setg(errp, QERR_SET_PASSWD_FAILED);
 357        }
 358        return;
 359    }
 360
 361    if (strcmp(protocol, "vnc") == 0) {
 362        rc = vnc_display_pw_expire(NULL, when);
 363        if (rc != 0) {
 364            error_setg(errp, QERR_SET_PASSWD_FAILED);
 365        }
 366        return;
 367    }
 368
 369    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
 370}
 371
 372#ifdef CONFIG_VNC
 373void qmp_change_vnc_password(const char *password, Error **errp)
 374{
 375    if (vnc_display_password(NULL, password) < 0) {
 376        error_setg(errp, QERR_SET_PASSWD_FAILED);
 377    }
 378}
 379
 380static void qmp_change_vnc_listen(const char *target, Error **errp)
 381{
 382    QemuOptsList *olist = qemu_find_opts("vnc");
 383    QemuOpts *opts;
 384
 385    if (strstr(target, "id=")) {
 386        error_setg(errp, "id not supported");
 387        return;
 388    }
 389
 390    opts = qemu_opts_find(olist, "default");
 391    if (opts) {
 392        qemu_opts_del(opts);
 393    }
 394    opts = vnc_parse(target, errp);
 395    if (!opts) {
 396        return;
 397    }
 398
 399    vnc_display_open("default", errp);
 400}
 401
 402static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
 403                           Error **errp)
 404{
 405    if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
 406        if (!has_arg) {
 407            error_setg(errp, QERR_MISSING_PARAMETER, "password");
 408        } else {
 409            qmp_change_vnc_password(arg, errp);
 410        }
 411    } else {
 412        qmp_change_vnc_listen(target, errp);
 413    }
 414}
 415#else
 416void qmp_change_vnc_password(const char *password, Error **errp)
 417{
 418    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 419}
 420static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
 421                           Error **errp)
 422{
 423    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 424}
 425#endif /* !CONFIG_VNC */
 426
 427void qmp_change(const char *device, const char *target,
 428                bool has_arg, const char *arg, Error **errp)
 429{
 430    if (strcmp(device, "vnc") == 0) {
 431        qmp_change_vnc(target, has_arg, arg, errp);
 432    } else {
 433        qmp_blockdev_change_medium(true, device, false, NULL, target,
 434                                   has_arg, arg, false, 0, errp);
 435    }
 436}
 437
 438static void qom_list_types_tramp(ObjectClass *klass, void *data)
 439{
 440    ObjectTypeInfoList *e, **pret = data;
 441    ObjectTypeInfo *info;
 442
 443    info = g_malloc0(sizeof(*info));
 444    info->name = g_strdup(object_class_get_name(klass));
 445
 446    e = g_malloc0(sizeof(*e));
 447    e->value = info;
 448    e->next = *pret;
 449    *pret = e;
 450}
 451
 452ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
 453                                       const char *implements,
 454                                       bool has_abstract,
 455                                       bool abstract,
 456                                       Error **errp)
 457{
 458    ObjectTypeInfoList *ret = NULL;
 459
 460    object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
 461
 462    return ret;
 463}
 464
 465/* Return a DevicePropertyInfo for a qdev property.
 466 *
 467 * If a qdev property with the given name does not exist, use the given default
 468 * type.  If the qdev property info should not be shown, return NULL.
 469 *
 470 * The caller must free the return value.
 471 */
 472static DevicePropertyInfo *make_device_property_info(ObjectClass *klass,
 473                                                     const char *name,
 474                                                     const char *default_type,
 475                                                     const char *description)
 476{
 477    DevicePropertyInfo *info;
 478    Property *prop;
 479
 480    do {
 481        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
 482            if (strcmp(name, prop->name) != 0) {
 483                continue;
 484            }
 485
 486            /*
 487             * TODO Properties without a parser are just for dirty hacks.
 488             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
 489             * for removal.  This conditional should be removed along with
 490             * it.
 491             */
 492            if (!prop->info->set) {
 493                return NULL;           /* no way to set it, don't show */
 494            }
 495
 496            info = g_malloc0(sizeof(*info));
 497            info->name = g_strdup(prop->name);
 498            info->type = g_strdup(prop->info->name);
 499            info->has_description = !!prop->info->description;
 500            info->description = g_strdup(prop->info->description);
 501            return info;
 502        }
 503        klass = object_class_get_parent(klass);
 504    } while (klass != object_class_by_name(TYPE_DEVICE));
 505
 506    /* Not a qdev property, use the default type */
 507    info = g_malloc0(sizeof(*info));
 508    info->name = g_strdup(name);
 509    info->type = g_strdup(default_type);
 510    info->has_description = !!description;
 511    info->description = g_strdup(description);
 512
 513    return info;
 514}
 515
 516DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
 517                                                   Error **errp)
 518{
 519    ObjectClass *klass;
 520    Object *obj;
 521    ObjectProperty *prop;
 522    ObjectPropertyIterator iter;
 523    DevicePropertyInfoList *prop_list = NULL;
 524
 525    klass = object_class_by_name(typename);
 526    if (klass == NULL) {
 527        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 528                  "Device '%s' not found", typename);
 529        return NULL;
 530    }
 531
 532    klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
 533    if (klass == NULL) {
 534        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name", TYPE_DEVICE);
 535        return NULL;
 536    }
 537
 538    if (object_class_is_abstract(klass)) {
 539        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
 540                   "non-abstract device type");
 541        return NULL;
 542    }
 543
 544    if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
 545        error_setg(errp, "Can't list properties of device '%s'", typename);
 546        return NULL;
 547    }
 548
 549    obj = object_new(typename);
 550
 551    object_property_iter_init(&iter, obj);
 552    while ((prop = object_property_iter_next(&iter))) {
 553        DevicePropertyInfo *info;
 554        DevicePropertyInfoList *entry;
 555
 556        /* Skip Object and DeviceState properties */
 557        if (strcmp(prop->name, "type") == 0 ||
 558            strcmp(prop->name, "realized") == 0 ||
 559            strcmp(prop->name, "hotpluggable") == 0 ||
 560            strcmp(prop->name, "hotplugged") == 0 ||
 561            strcmp(prop->name, "parent_bus") == 0) {
 562            continue;
 563        }
 564
 565        /* Skip legacy properties since they are just string versions of
 566         * properties that we already list.
 567         */
 568        if (strstart(prop->name, "legacy-", NULL)) {
 569            continue;
 570        }
 571
 572        info = make_device_property_info(klass, prop->name, prop->type,
 573                                         prop->description);
 574        if (!info) {
 575            continue;
 576        }
 577
 578        entry = g_malloc0(sizeof(*entry));
 579        entry->value = info;
 580        entry->next = prop_list;
 581        prop_list = entry;
 582    }
 583
 584    object_unref(obj);
 585
 586    return prop_list;
 587}
 588
 589CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 590{
 591    return arch_query_cpu_definitions(errp);
 592}
 593
 594CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 595                                                     CpuModelInfo *model,
 596                                                     Error **errp)
 597{
 598    return arch_query_cpu_model_expansion(type, model, errp);
 599}
 600
 601CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
 602                                                    CpuModelInfo *modelb,
 603                                                    Error **errp)
 604{
 605    return arch_query_cpu_model_comparison(modela, modelb, errp);
 606}
 607
 608CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
 609                                                   CpuModelInfo *modelb,
 610                                                   Error **errp)
 611{
 612    return arch_query_cpu_model_baseline(modela, modelb, errp);
 613}
 614
 615void qmp_add_client(const char *protocol, const char *fdname,
 616                    bool has_skipauth, bool skipauth, bool has_tls, bool tls,
 617                    Error **errp)
 618{
 619    CharDriverState *s;
 620    int fd;
 621
 622    fd = monitor_get_fd(cur_mon, fdname, errp);
 623    if (fd < 0) {
 624        return;
 625    }
 626
 627    if (strcmp(protocol, "spice") == 0) {
 628        if (!qemu_using_spice(errp)) {
 629            close(fd);
 630            return;
 631        }
 632        skipauth = has_skipauth ? skipauth : false;
 633        tls = has_tls ? tls : false;
 634        if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
 635            error_setg(errp, "spice failed to add client");
 636            close(fd);
 637        }
 638        return;
 639#ifdef CONFIG_VNC
 640    } else if (strcmp(protocol, "vnc") == 0) {
 641        skipauth = has_skipauth ? skipauth : false;
 642        vnc_display_add_client(NULL, fd, skipauth);
 643        return;
 644#endif
 645    } else if ((s = qemu_chr_find(protocol)) != NULL) {
 646        if (qemu_chr_add_client(s, fd) < 0) {
 647            error_setg(errp, "failed to add client");
 648            close(fd);
 649            return;
 650        }
 651        return;
 652    }
 653
 654    error_setg(errp, "protocol '%s' is invalid", protocol);
 655    close(fd);
 656}
 657
 658
 659void qmp_object_add(const char *type, const char *id,
 660                    bool has_props, QObject *props, Error **errp)
 661{
 662    QDict *pdict;
 663    Visitor *v;
 664    Object *obj;
 665
 666    if (props) {
 667        pdict = qobject_to_qdict(props);
 668        if (!pdict) {
 669            error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
 670            return;
 671        }
 672        QINCREF(pdict);
 673    } else {
 674        pdict = qdict_new();
 675    }
 676
 677    v = qobject_input_visitor_new(QOBJECT(pdict), true);
 678    obj = user_creatable_add_type(type, id, pdict, v, errp);
 679    visit_free(v);
 680    if (obj) {
 681        object_unref(obj);
 682    }
 683    QDECREF(pdict);
 684}
 685
 686void qmp_object_del(const char *id, Error **errp)
 687{
 688    user_creatable_del(id, errp);
 689}
 690
 691MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
 692{
 693    MemoryDeviceInfoList *head = NULL;
 694    MemoryDeviceInfoList **prev = &head;
 695
 696    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
 697
 698    return head;
 699}
 700
 701ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
 702{
 703    bool ambig;
 704    ACPIOSTInfoList *head = NULL;
 705    ACPIOSTInfoList **prev = &head;
 706    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
 707
 708    if (obj) {
 709        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
 710        AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
 711
 712        adevc->ospm_status(adev, &prev);
 713    } else {
 714        error_setg(errp, "command is not supported, missing ACPI device");
 715    }
 716
 717    return head;
 718}
 719