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-common.h"
  17#include "monitor/monitor.h"
  18#include "sysemu/sysemu.h"
  19#include "qmp-commands.h"
  20#include "sysemu/char.h"
  21#include "ui/qemu-spice.h"
  22#include "ui/vnc.h"
  23#include "sysemu/kvm.h"
  24#include "sysemu/arch_init.h"
  25#include "hw/qdev.h"
  26#include "sysemu/blockdev.h"
  27#include "qom/qom-qobject.h"
  28#include "qapi/qmp/qerror.h"
  29#include "qapi/qmp/qobject.h"
  30#include "qapi/qmp-input-visitor.h"
  31#include "hw/boards.h"
  32#include "qom/object_interfaces.h"
  33#include "hw/mem/pc-dimm.h"
  34#include "hw/acpi/acpi_dev_interface.h"
  35
  36NameInfo *qmp_query_name(Error **errp)
  37{
  38    NameInfo *info = g_malloc0(sizeof(*info));
  39
  40    if (qemu_name) {
  41        info->has_name = true;
  42        info->name = g_strdup(qemu_name);
  43    }
  44
  45    return info;
  46}
  47
  48VersionInfo *qmp_query_version(Error **errp)
  49{
  50    VersionInfo *info = g_new0(VersionInfo, 1);
  51    const char *version = QEMU_VERSION;
  52    char *tmp;
  53
  54    info->qemu = g_new0(VersionTriple, 1);
  55    info->qemu->major = strtol(version, &tmp, 10);
  56    tmp++;
  57    info->qemu->minor = strtol(tmp, &tmp, 10);
  58    tmp++;
  59    info->qemu->micro = strtol(tmp, &tmp, 10);
  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    char uuid[64];
  79
  80    snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
  81                   qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
  82                   qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
  83                   qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
  84                   qemu_uuid[14], qemu_uuid[15]);
  85
  86    info->UUID = g_strdup(uuid);
  87    return info;
  88}
  89
  90void qmp_quit(Error **errp)
  91{
  92    no_shutdown = 0;
  93    qemu_system_shutdown_request();
  94}
  95
  96void qmp_stop(Error **errp)
  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_input_query_spice() that calls qmp_query_spice().
 155 * Provide it one, or else linking fails.
 156 * FIXME Educate the QAPI schema on 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    BlockDriverState *bs;
 168
 169    if (runstate_needs_reset()) {
 170        error_setg(errp, "Resetting the Virtual Machine is required");
 171        return;
 172    } else if (runstate_check(RUN_STATE_SUSPENDED)) {
 173        return;
 174    }
 175
 176    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
 177        bdrv_iostatus_reset(bs);
 178    }
 179    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
 180        bdrv_add_key(bs, NULL, &local_err);
 181        if (local_err) {
 182            error_propagate(errp, local_err);
 183            return;
 184        }
 185    }
 186
 187    if (runstate_check(RUN_STATE_INMIGRATE)) {
 188        autostart = 1;
 189    } else {
 190        vm_start();
 191    }
 192}
 193
 194void qmp_system_wakeup(Error **errp)
 195{
 196    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
 197}
 198
 199ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
 200{
 201    Object *obj;
 202    bool ambiguous = false;
 203    ObjectPropertyInfoList *props = NULL;
 204    ObjectProperty *prop;
 205
 206    obj = object_resolve_path(path, &ambiguous);
 207    if (obj == NULL) {
 208        if (ambiguous) {
 209            error_setg(errp, "Path '%s' is ambiguous", path);
 210        } else {
 211            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 212                      "Device '%s' not found", path);
 213        }
 214        return NULL;
 215    }
 216
 217    QTAILQ_FOREACH(prop, &obj->properties, node) {
 218        ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
 219
 220        entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
 221        entry->next = props;
 222        props = entry;
 223
 224        entry->value->name = g_strdup(prop->name);
 225        entry->value->type = g_strdup(prop->type);
 226    }
 227
 228    return props;
 229}
 230
 231/* FIXME: teach qapi about how to pass through Visitors */
 232void qmp_qom_set(QDict *qdict, QObject **ret, Error **errp)
 233{
 234    const char *path = qdict_get_str(qdict, "path");
 235    const char *property = qdict_get_str(qdict, "property");
 236    QObject *value = qdict_get(qdict, "value");
 237    Object *obj;
 238
 239    obj = object_resolve_path(path, NULL);
 240    if (!obj) {
 241        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 242                  "Device '%s' not found", path);
 243        return;
 244    }
 245
 246    object_property_set_qobject(obj, value, property, errp);
 247}
 248
 249void qmp_qom_get(QDict *qdict, QObject **ret, Error **errp)
 250{
 251    const char *path = qdict_get_str(qdict, "path");
 252    const char *property = qdict_get_str(qdict, "property");
 253    Object *obj;
 254
 255    obj = object_resolve_path(path, NULL);
 256    if (!obj) {
 257        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 258                  "Device '%s' not found", path);
 259        return;
 260    }
 261
 262    *ret = object_property_get_qobject(obj, property, errp);
 263}
 264
 265void qmp_set_password(const char *protocol, const char *password,
 266                      bool has_connected, const char *connected, Error **errp)
 267{
 268    int disconnect_if_connected = 0;
 269    int fail_if_connected = 0;
 270    int rc;
 271
 272    if (has_connected) {
 273        if (strcmp(connected, "fail") == 0) {
 274            fail_if_connected = 1;
 275        } else if (strcmp(connected, "disconnect") == 0) {
 276            disconnect_if_connected = 1;
 277        } else if (strcmp(connected, "keep") == 0) {
 278            /* nothing */
 279        } else {
 280            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
 281            return;
 282        }
 283    }
 284
 285    if (strcmp(protocol, "spice") == 0) {
 286        if (!qemu_using_spice(errp)) {
 287            return;
 288        }
 289        rc = qemu_spice_set_passwd(password, fail_if_connected,
 290                                   disconnect_if_connected);
 291        if (rc != 0) {
 292            error_setg(errp, QERR_SET_PASSWD_FAILED);
 293        }
 294        return;
 295    }
 296
 297    if (strcmp(protocol, "vnc") == 0) {
 298        if (fail_if_connected || disconnect_if_connected) {
 299            /* vnc supports "connected=keep" only */
 300            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
 301            return;
 302        }
 303        /* Note that setting an empty password will not disable login through
 304         * this interface. */
 305        rc = vnc_display_password(NULL, password);
 306        if (rc < 0) {
 307            error_setg(errp, QERR_SET_PASSWD_FAILED);
 308        }
 309        return;
 310    }
 311
 312    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
 313}
 314
 315void qmp_expire_password(const char *protocol, const char *whenstr,
 316                         Error **errp)
 317{
 318    time_t when;
 319    int rc;
 320
 321    if (strcmp(whenstr, "now") == 0) {
 322        when = 0;
 323    } else if (strcmp(whenstr, "never") == 0) {
 324        when = TIME_MAX;
 325    } else if (whenstr[0] == '+') {
 326        when = time(NULL) + strtoull(whenstr+1, NULL, 10);
 327    } else {
 328        when = strtoull(whenstr, NULL, 10);
 329    }
 330
 331    if (strcmp(protocol, "spice") == 0) {
 332        if (!qemu_using_spice(errp)) {
 333            return;
 334        }
 335        rc = qemu_spice_set_pw_expire(when);
 336        if (rc != 0) {
 337            error_setg(errp, QERR_SET_PASSWD_FAILED);
 338        }
 339        return;
 340    }
 341
 342    if (strcmp(protocol, "vnc") == 0) {
 343        rc = vnc_display_pw_expire(NULL, when);
 344        if (rc != 0) {
 345            error_setg(errp, QERR_SET_PASSWD_FAILED);
 346        }
 347        return;
 348    }
 349
 350    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
 351}
 352
 353#ifdef CONFIG_VNC
 354void qmp_change_vnc_password(const char *password, Error **errp)
 355{
 356    if (vnc_display_password(NULL, password) < 0) {
 357        error_setg(errp, QERR_SET_PASSWD_FAILED);
 358    }
 359}
 360
 361static void qmp_change_vnc_listen(const char *target, Error **errp)
 362{
 363    QemuOptsList *olist = qemu_find_opts("vnc");
 364    QemuOpts *opts;
 365
 366    if (strstr(target, "id=")) {
 367        error_setg(errp, "id not supported");
 368        return;
 369    }
 370
 371    opts = qemu_opts_find(olist, "default");
 372    if (opts) {
 373        qemu_opts_del(opts);
 374    }
 375    opts = vnc_parse(target, errp);
 376    if (!opts) {
 377        return;
 378    }
 379
 380    vnc_display_open("default", errp);
 381}
 382
 383static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
 384                           Error **errp)
 385{
 386    if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
 387        if (!has_arg) {
 388            error_setg(errp, QERR_MISSING_PARAMETER, "password");
 389        } else {
 390            qmp_change_vnc_password(arg, errp);
 391        }
 392    } else {
 393        qmp_change_vnc_listen(target, errp);
 394    }
 395}
 396#else
 397void qmp_change_vnc_password(const char *password, Error **errp)
 398{
 399    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 400}
 401static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
 402                           Error **errp)
 403{
 404    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
 405}
 406#endif /* !CONFIG_VNC */
 407
 408void qmp_change(const char *device, const char *target,
 409                bool has_arg, const char *arg, Error **errp)
 410{
 411    if (strcmp(device, "vnc") == 0) {
 412        qmp_change_vnc(target, has_arg, arg, errp);
 413    } else {
 414        qmp_change_blockdev(device, target, arg, errp);
 415    }
 416}
 417
 418static void qom_list_types_tramp(ObjectClass *klass, void *data)
 419{
 420    ObjectTypeInfoList *e, **pret = data;
 421    ObjectTypeInfo *info;
 422
 423    info = g_malloc0(sizeof(*info));
 424    info->name = g_strdup(object_class_get_name(klass));
 425
 426    e = g_malloc0(sizeof(*e));
 427    e->value = info;
 428    e->next = *pret;
 429    *pret = e;
 430}
 431
 432ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
 433                                       const char *implements,
 434                                       bool has_abstract,
 435                                       bool abstract,
 436                                       Error **errp)
 437{
 438    ObjectTypeInfoList *ret = NULL;
 439
 440    object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
 441
 442    return ret;
 443}
 444
 445/* Return a DevicePropertyInfo for a qdev property.
 446 *
 447 * If a qdev property with the given name does not exist, use the given default
 448 * type.  If the qdev property info should not be shown, return NULL.
 449 *
 450 * The caller must free the return value.
 451 */
 452static DevicePropertyInfo *make_device_property_info(ObjectClass *klass,
 453                                                     const char *name,
 454                                                     const char *default_type,
 455                                                     const char *description)
 456{
 457    DevicePropertyInfo *info;
 458    Property *prop;
 459
 460    do {
 461        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
 462            if (strcmp(name, prop->name) != 0) {
 463                continue;
 464            }
 465
 466            /*
 467             * TODO Properties without a parser are just for dirty hacks.
 468             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
 469             * for removal.  This conditional should be removed along with
 470             * it.
 471             */
 472            if (!prop->info->set) {
 473                return NULL;           /* no way to set it, don't show */
 474            }
 475
 476            info = g_malloc0(sizeof(*info));
 477            info->name = g_strdup(prop->name);
 478            info->type = g_strdup(prop->info->name);
 479            info->has_description = !!prop->info->description;
 480            info->description = g_strdup(prop->info->description);
 481            return info;
 482        }
 483        klass = object_class_get_parent(klass);
 484    } while (klass != object_class_by_name(TYPE_DEVICE));
 485
 486    /* Not a qdev property, use the default type */
 487    info = g_malloc0(sizeof(*info));
 488    info->name = g_strdup(name);
 489    info->type = g_strdup(default_type);
 490    info->has_description = !!description;
 491    info->description = g_strdup(description);
 492
 493    return info;
 494}
 495
 496DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
 497                                                   Error **errp)
 498{
 499    ObjectClass *klass;
 500    Object *obj;
 501    ObjectProperty *prop;
 502    DevicePropertyInfoList *prop_list = NULL;
 503
 504    klass = object_class_by_name(typename);
 505    if (klass == NULL) {
 506        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 507                  "Device '%s' not found", typename);
 508        return NULL;
 509    }
 510
 511    klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
 512    if (klass == NULL) {
 513        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name", TYPE_DEVICE);
 514        return NULL;
 515    }
 516
 517    obj = object_new(typename);
 518
 519    QTAILQ_FOREACH(prop, &obj->properties, node) {
 520        DevicePropertyInfo *info;
 521        DevicePropertyInfoList *entry;
 522
 523        /* Skip Object and DeviceState properties */
 524        if (strcmp(prop->name, "type") == 0 ||
 525            strcmp(prop->name, "realized") == 0 ||
 526            strcmp(prop->name, "hotpluggable") == 0 ||
 527            strcmp(prop->name, "hotplugged") == 0 ||
 528            strcmp(prop->name, "parent_bus") == 0) {
 529            continue;
 530        }
 531
 532        /* Skip legacy properties since they are just string versions of
 533         * properties that we already list.
 534         */
 535        if (strstart(prop->name, "legacy-", NULL)) {
 536            continue;
 537        }
 538
 539        info = make_device_property_info(klass, prop->name, prop->type,
 540                                         prop->description);
 541        if (!info) {
 542            continue;
 543        }
 544
 545        entry = g_malloc0(sizeof(*entry));
 546        entry->value = info;
 547        entry->next = prop_list;
 548        prop_list = entry;
 549    }
 550
 551    object_unref(obj);
 552
 553    return prop_list;
 554}
 555
 556CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 557{
 558    return arch_query_cpu_definitions(errp);
 559}
 560
 561void qmp_add_client(const char *protocol, const char *fdname,
 562                    bool has_skipauth, bool skipauth, bool has_tls, bool tls,
 563                    Error **errp)
 564{
 565    CharDriverState *s;
 566    int fd;
 567
 568    fd = monitor_get_fd(cur_mon, fdname, errp);
 569    if (fd < 0) {
 570        return;
 571    }
 572
 573    if (strcmp(protocol, "spice") == 0) {
 574        if (!qemu_using_spice(errp)) {
 575            close(fd);
 576            return;
 577        }
 578        skipauth = has_skipauth ? skipauth : false;
 579        tls = has_tls ? tls : false;
 580        if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
 581            error_setg(errp, "spice failed to add client");
 582            close(fd);
 583        }
 584        return;
 585#ifdef CONFIG_VNC
 586    } else if (strcmp(protocol, "vnc") == 0) {
 587        skipauth = has_skipauth ? skipauth : false;
 588        vnc_display_add_client(NULL, fd, skipauth);
 589        return;
 590#endif
 591    } else if ((s = qemu_chr_find(protocol)) != NULL) {
 592        if (qemu_chr_add_client(s, fd) < 0) {
 593            error_setg(errp, "failed to add client");
 594            close(fd);
 595            return;
 596        }
 597        return;
 598    }
 599
 600    error_setg(errp, "protocol '%s' is invalid", protocol);
 601    close(fd);
 602}
 603
 604void object_add(const char *type, const char *id, const QDict *qdict,
 605                Visitor *v, Error **errp)
 606{
 607    Object *obj;
 608    ObjectClass *klass;
 609    const QDictEntry *e;
 610    Error *local_err = NULL;
 611
 612    klass = object_class_by_name(type);
 613    if (!klass) {
 614        error_setg(errp, "invalid object type: %s", type);
 615        return;
 616    }
 617
 618    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
 619        error_setg(errp, "object type '%s' isn't supported by object-add",
 620                   type);
 621        return;
 622    }
 623
 624    if (object_class_is_abstract(klass)) {
 625        error_setg(errp, "object type '%s' is abstract", type);
 626        return;
 627    }
 628
 629    obj = object_new(type);
 630    if (qdict) {
 631        for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
 632            object_property_set(obj, v, e->key, &local_err);
 633            if (local_err) {
 634                goto out;
 635            }
 636        }
 637    }
 638
 639    object_property_add_child(object_get_objects_root(),
 640                              id, obj, &local_err);
 641    if (local_err) {
 642        goto out;
 643    }
 644
 645    user_creatable_complete(obj, &local_err);
 646    if (local_err) {
 647        object_property_del(object_get_objects_root(),
 648                            id, &error_abort);
 649        goto out;
 650    }
 651out:
 652    if (local_err) {
 653        error_propagate(errp, local_err);
 654    }
 655    object_unref(obj);
 656}
 657
 658void qmp_object_add(QDict *qdict, QObject **ret, Error **errp)
 659{
 660    const char *type = qdict_get_str(qdict, "qom-type");
 661    const char *id = qdict_get_str(qdict, "id");
 662    QObject *props = qdict_get(qdict, "props");
 663    const QDict *pdict = NULL;
 664    QmpInputVisitor *qiv;
 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    }
 673
 674    qiv = qmp_input_visitor_new(props);
 675    object_add(type, id, pdict, qmp_input_get_visitor(qiv), errp);
 676    qmp_input_visitor_cleanup(qiv);
 677}
 678
 679void qmp_object_del(const char *id, Error **errp)
 680{
 681    Object *container;
 682    Object *obj;
 683
 684    container = object_get_objects_root();
 685    obj = object_resolve_path_component(container, id);
 686    if (!obj) {
 687        error_setg(errp, "object id not found");
 688        return;
 689    }
 690
 691    if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) {
 692        error_setg(errp, "%s is in use, can not be deleted", id);
 693        return;
 694    }
 695    object_unparent(obj);
 696}
 697
 698MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
 699{
 700    MemoryDeviceInfoList *head = NULL;
 701    MemoryDeviceInfoList **prev = &head;
 702
 703    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
 704
 705    return head;
 706}
 707
 708ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
 709{
 710    bool ambig;
 711    ACPIOSTInfoList *head = NULL;
 712    ACPIOSTInfoList **prev = &head;
 713    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
 714
 715    if (obj) {
 716        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
 717        AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
 718
 719        adevc->ospm_status(adev, &prev);
 720    } else {
 721        error_setg(errp, "command is not supported, missing ACPI device");
 722    }
 723
 724    return head;
 725}
 726