qemu/monitor/qmp-cmds.c
<<
>>
Prefs
   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/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/console.h"
  27#include "ui/dbus-display.h"
  28#include "sysemu/kvm.h"
  29#include "sysemu/runstate.h"
  30#include "sysemu/runstate-action.h"
  31#include "sysemu/blockdev.h"
  32#include "sysemu/block-backend.h"
  33#include "qapi/error.h"
  34#include "qapi/qapi-commands-acpi.h"
  35#include "qapi/qapi-commands-block.h"
  36#include "qapi/qapi-commands-control.h"
  37#include "qapi/qapi-commands-machine.h"
  38#include "qapi/qapi-commands-misc.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
  48NameInfo *qmp_query_name(Error **errp)
  49{
  50    NameInfo *info = g_malloc0(sizeof(*info));
  51
  52    if (qemu_name) {
  53        info->has_name = true;
  54        info->name = g_strdup(qemu_name);
  55    }
  56
  57    return info;
  58}
  59
  60KvmInfo *qmp_query_kvm(Error **errp)
  61{
  62    KvmInfo *info = g_malloc0(sizeof(*info));
  63
  64    info->enabled = kvm_enabled();
  65    info->present = accel_find("kvm");
  66
  67    return info;
  68}
  69
  70UuidInfo *qmp_query_uuid(Error **errp)
  71{
  72    UuidInfo *info = g_malloc0(sizeof(*info));
  73
  74    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
  75    return info;
  76}
  77
  78void qmp_quit(Error **errp)
  79{
  80    shutdown_action = SHUTDOWN_ACTION_POWEROFF;
  81    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
  82}
  83
  84void qmp_stop(Error **errp)
  85{
  86    /* if there is a dump in background, we should wait until the dump
  87     * finished */
  88    if (dump_in_progress()) {
  89        error_setg(errp, "There is a dump in process, please wait.");
  90        return;
  91    }
  92
  93    if (runstate_check(RUN_STATE_INMIGRATE)) {
  94        autostart = 0;
  95    } else {
  96        vm_stop(RUN_STATE_PAUSED);
  97    }
  98}
  99
 100void qmp_system_reset(Error **errp)
 101{
 102    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
 103}
 104
 105void qmp_system_powerdown(Error **errp)
 106{
 107    qemu_system_powerdown_request();
 108}
 109
 110void qmp_cont(Error **errp)
 111{
 112    BlockBackend *blk;
 113    BlockJob *job;
 114    Error *local_err = NULL;
 115
 116    /* if there is a dump in background, we should wait until the dump
 117     * finished */
 118    if (dump_in_progress()) {
 119        error_setg(errp, "There is a dump in process, please wait.");
 120        return;
 121    }
 122
 123    if (runstate_needs_reset()) {
 124        error_setg(errp, "Resetting the Virtual Machine is required");
 125        return;
 126    } else if (runstate_check(RUN_STATE_SUSPENDED)) {
 127        return;
 128    } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
 129        error_setg(errp, "Migration is not finalized yet");
 130        return;
 131    }
 132
 133    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
 134        blk_iostatus_reset(blk);
 135    }
 136
 137    for (job = block_job_next(NULL); job; job = block_job_next(job)) {
 138        block_job_iostatus_reset(job);
 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
 160void 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
 171void 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
 199void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp)
 200{
 201    time_t when;
 202    int rc;
 203    const char *whenstr = opts->time;
 204
 205    if (strcmp(whenstr, "now") == 0) {
 206        when = 0;
 207    } else if (strcmp(whenstr, "never") == 0) {
 208        when = TIME_MAX;
 209    } else if (whenstr[0] == '+') {
 210        when = time(NULL) + strtoull(whenstr+1, NULL, 10);
 211    } else {
 212        when = strtoull(whenstr, NULL, 10);
 213    }
 214
 215    if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
 216        if (!qemu_using_spice(errp)) {
 217            return;
 218        }
 219        rc = qemu_spice.set_pw_expire(when);
 220    } else {
 221        assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
 222        rc = vnc_display_pw_expire(opts->u.vnc.display, when);
 223    }
 224
 225    if (rc != 0) {
 226        error_setg(errp, "Could not set password expire time");
 227    }
 228}
 229
 230#ifdef CONFIG_VNC
 231void qmp_change_vnc_password(const char *password, Error **errp)
 232{
 233    if (vnc_display_password(NULL, password) < 0) {
 234        error_setg(errp, "Could not set password");
 235    }
 236}
 237#endif
 238
 239void qmp_add_client(const char *protocol, const char *fdname,
 240                    bool has_skipauth, bool skipauth, bool has_tls, bool tls,
 241                    Error **errp)
 242{
 243    Chardev *s;
 244    int fd;
 245
 246    fd = monitor_get_fd(monitor_cur(), fdname, errp);
 247    if (fd < 0) {
 248        return;
 249    }
 250
 251    if (strcmp(protocol, "spice") == 0) {
 252        if (!qemu_using_spice(errp)) {
 253            close(fd);
 254            return;
 255        }
 256        skipauth = has_skipauth ? skipauth : false;
 257        tls = has_tls ? tls : false;
 258        if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
 259            error_setg(errp, "spice failed to add client");
 260            close(fd);
 261        }
 262        return;
 263#ifdef CONFIG_VNC
 264    } else if (strcmp(protocol, "vnc") == 0) {
 265        skipauth = has_skipauth ? skipauth : false;
 266        vnc_display_add_client(NULL, fd, skipauth);
 267        return;
 268#endif
 269#ifdef CONFIG_DBUS_DISPLAY
 270    } else if (strcmp(protocol, "@dbus-display") == 0) {
 271        if (!qemu_using_dbus_display(errp)) {
 272            close(fd);
 273            return;
 274        }
 275        if (!qemu_dbus_display.add_client(fd, errp)) {
 276            close(fd);
 277            return;
 278        }
 279        return;
 280#endif
 281    } else if ((s = qemu_chr_find(protocol)) != NULL) {
 282        if (qemu_chr_add_client(s, fd) < 0) {
 283            error_setg(errp, "failed to add client");
 284            close(fd);
 285            return;
 286        }
 287        return;
 288    }
 289
 290    error_setg(errp, "protocol '%s' is invalid", protocol);
 291    close(fd);
 292}
 293
 294
 295MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
 296{
 297    return qmp_memory_device_list();
 298}
 299
 300ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
 301{
 302    bool ambig;
 303    ACPIOSTInfoList *head = NULL;
 304    ACPIOSTInfoList **prev = &head;
 305    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
 306
 307    if (obj) {
 308        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
 309        AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
 310
 311        adevc->ospm_status(adev, &prev);
 312    } else {
 313        error_setg(errp, "command is not supported, missing ACPI device");
 314    }
 315
 316    return head;
 317}
 318
 319MemoryInfo *qmp_query_memory_size_summary(Error **errp)
 320{
 321    MemoryInfo *mem_info = g_new0(MemoryInfo, 1);
 322    MachineState *ms = MACHINE(qdev_get_machine());
 323
 324    mem_info->base_memory = ms->ram_size;
 325
 326    mem_info->plugged_memory = get_plugged_memory_size();
 327    mem_info->has_plugged_memory =
 328        mem_info->plugged_memory != (uint64_t)-1;
 329
 330    return mem_info;
 331}
 332
 333void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
 334{
 335    switch (arg->type) {
 336    case DISPLAY_RELOAD_TYPE_VNC:
 337#ifdef CONFIG_VNC
 338        if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
 339            vnc_display_reload_certs(NULL, errp);
 340        }
 341#else
 342        error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
 343#endif
 344        break;
 345    default:
 346        abort();
 347    }
 348}
 349
 350static int qmp_x_query_rdma_foreach(Object *obj, void *opaque)
 351{
 352    RdmaProvider *rdma;
 353    RdmaProviderClass *k;
 354    GString *buf = opaque;
 355
 356    if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
 357        rdma = RDMA_PROVIDER(obj);
 358        k = RDMA_PROVIDER_GET_CLASS(obj);
 359        if (k->format_statistics) {
 360            k->format_statistics(rdma, buf);
 361        } else {
 362            g_string_append_printf(buf,
 363                                   "RDMA statistics not available for %s.\n",
 364                                   object_get_typename(obj));
 365        }
 366    }
 367
 368    return 0;
 369}
 370
 371HumanReadableText *qmp_x_query_rdma(Error **errp)
 372{
 373    g_autoptr(GString) buf = g_string_new("");
 374
 375    object_child_foreach_recursive(object_get_root(),
 376                                   qmp_x_query_rdma_foreach, buf);
 377
 378    return human_readable_text_from_str(buf);
 379}
 380
 381HumanReadableText *qmp_x_query_ramblock(Error **errp)
 382{
 383    g_autoptr(GString) buf = ram_block_format();
 384
 385    return human_readable_text_from_str(buf);
 386}
 387
 388static int qmp_x_query_irq_foreach(Object *obj, void *opaque)
 389{
 390    InterruptStatsProvider *intc;
 391    InterruptStatsProviderClass *k;
 392    GString *buf = opaque;
 393
 394    if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
 395        intc = INTERRUPT_STATS_PROVIDER(obj);
 396        k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
 397        uint64_t *irq_counts;
 398        unsigned int nb_irqs, i;
 399        if (k->get_statistics &&
 400            k->get_statistics(intc, &irq_counts, &nb_irqs)) {
 401            if (nb_irqs > 0) {
 402                g_string_append_printf(buf, "IRQ statistics for %s:\n",
 403                                       object_get_typename(obj));
 404                for (i = 0; i < nb_irqs; i++) {
 405                    if (irq_counts[i] > 0) {
 406                        g_string_append_printf(buf, "%2d: %" PRId64 "\n", i,
 407                                               irq_counts[i]);
 408                    }
 409                }
 410            }
 411        } else {
 412            g_string_append_printf(buf,
 413                                   "IRQ statistics not available for %s.\n",
 414                                   object_get_typename(obj));
 415        }
 416    }
 417
 418    return 0;
 419}
 420
 421HumanReadableText *qmp_x_query_irq(Error **errp)
 422{
 423    g_autoptr(GString) buf = g_string_new("");
 424
 425    object_child_foreach_recursive(object_get_root(),
 426                                   qmp_x_query_irq_foreach, buf);
 427
 428    return human_readable_text_from_str(buf);
 429}
 430