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