qemu/qmp.c

784 lines
21 KiB
C
Raw Normal View History

/*
* QEMU Management Protocol
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu/osdep.h"
#include "qemu-version.h"
#include "qemu/cutils.h"
#include "qemu/option.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
#include "qemu/config-file.h"
#include "qemu/uuid.h"
#include "chardev/char.h"
#include "ui/qemu-spice.h"
#include "ui/vnc.h"
#include "sysemu/kvm.h"
#include "sysemu/arch_init.h"
#include "hw/qdev.h"
#include "sysemu/blockdev.h"
#include "sysemu/block-backend.h"
#include "qom/qom-qobject.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-ui.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qobject-input-visitor.h"
#include "hw/boards.h"
#include "qom/object_interfaces.h"
#include "hw/mem/pc-dimm.h"
#include "hw/acpi/acpi_dev_interface.h"
NameInfo *qmp_query_name(Error **errp)
{
NameInfo *info = g_malloc0(sizeof(*info));
if (qemu_name) {
info->has_name = true;
info->name = g_strdup(qemu_name);
}
return info;
}
VersionInfo *qmp_query_version(Error **errp)
{
VersionInfo *info = g_new0(VersionInfo, 1);
info->qemu = g_new0(VersionTriple, 1);
info->qemu->major = QEMU_VERSION_MAJOR;
info->qemu->minor = QEMU_VERSION_MINOR;
info->qemu->micro = QEMU_VERSION_MICRO;
info->package = g_strdup(QEMU_PKGVERSION);
return info;
}
KvmInfo *qmp_query_kvm(Error **errp)
{
KvmInfo *info = g_malloc0(sizeof(*info));
info->enabled = kvm_enabled();
info->present = kvm_available();
return info;
}
UuidInfo *qmp_query_uuid(Error **errp)
{
UuidInfo *info = g_malloc0(sizeof(*info));
info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
return info;
}
void qmp_quit(Error **errp)
{
no_shutdown = 0;
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP);
}
void qmp_stop(Error **errp)
{
/* if there is a dump in background, we should wait until the dump
* finished */
if (dump_in_progress()) {
error_setg(errp, "There is a dump in process, please wait.");
return;
}
if (runstate_check(RUN_STATE_INMIGRATE)) {
autostart = 0;
} else {
vm_stop(RUN_STATE_PAUSED);
}
}
void qmp_system_reset(Error **errp)
{
qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP);
}
void qmp_system_powerdown(Error **erp)
{
qemu_system_powerdown_request();
}
void qmp_cpu_add(int64_t id, Error **errp)
{
MachineClass *mc;
mc = MACHINE_GET_CLASS(current_machine);
if (mc->hot_add_cpu) {
mc->hot_add_cpu(id, errp);
} else {
error_setg(errp, "Not supported");
}
}
#ifndef CONFIG_VNC
/* If VNC support is enabled, the "true" query-vnc command is
defined in the VNC subsystem */
VncInfo *qmp_query_vnc(Error **errp)
{
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
return NULL;
};
VncInfo2List *qmp_query_vnc_servers(Error **errp)
{
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
return NULL;
};
#endif
#ifndef CONFIG_SPICE
/*
* qmp_unregister_commands_hack() ensures that QMP command query-spice
* exists only #ifdef CONFIG_SPICE. Necessary for an accurate
* query-commands result. However, the QAPI schema is blissfully
* unaware of that, and the QAPI code generator happily generates a
* dead qmp_marshal_query_spice() that calls qmp_query_spice().
* Provide it one, or else linking fails. FIXME Educate the QAPI
* schema on CONFIG_SPICE.
*/
SpiceInfo *qmp_query_spice(Error **errp)
{
abort();
};
#endif
void qmp_cont(Error **errp)
{
BlockBackend *blk;
Error *local_err = NULL;
/* if there is a dump in background, we should wait until the dump
* finished */
if (dump_in_progress()) {
error_setg(errp, "There is a dump in process, please wait.");
return;
}
if (runstate_needs_reset()) {
error_setg(errp, "Resetting the Virtual Machine is required");
return;
} else if (runstate_check(RUN_STATE_SUSPENDED)) {
return;
}
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
blk_iostatus_reset(blk);
}
block: Inactivate BDS when migration completes So far, live migration with shared storage meant that the image is in a not-really-ready don't-touch-me state on the destination while the source is still actively using it, but after completing the migration, the image was fully opened on both sides. This is bad. This patch adds a block driver callback to inactivate images on the source before completing the migration. Inactivation means that it goes to a state as if it was just live migrated to the qemu instance on the source (i.e. BDRV_O_INACTIVE is set). You're then supposed to continue either on the source or on the destination, which takes ownership of the image. A typical migration looks like this now with respect to disk images: 1. Destination qemu is started, the image is opened with BDRV_O_INACTIVE. The image is fully opened on the source. 2. Migration is about to complete. The source flushes the image and inactivates it. Now both sides have the image opened with BDRV_O_INACTIVE and are expecting the other side to still modify it. 3. One side (the destination on success) continues and calls bdrv_invalidate_all() in order to take ownership of the image again. This removes BDRV_O_INACTIVE on the resuming side; the flag remains set on the other side. This ensures that the same image isn't written to by both instances (unless both are resumed, but then you get what you deserve). This is important because .bdrv_close for non-BDRV_O_INACTIVE images could write to the image file, which is definitely forbidden while another host is using the image. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com>
2015-12-22 16:07:08 +03:00
/* Continuing after completed migration. Images have been inactivated to
* allow the destination to take control. Need to get control back now.
*
* If there are no inactive block nodes (e.g. because the VM was just
* paused rather than completing a migration), bdrv_inactivate_all() simply
* doesn't do anything. */
bdrv_invalidate_cache_all(&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
block: Inactivate BDS when migration completes So far, live migration with shared storage meant that the image is in a not-really-ready don't-touch-me state on the destination while the source is still actively using it, but after completing the migration, the image was fully opened on both sides. This is bad. This patch adds a block driver callback to inactivate images on the source before completing the migration. Inactivation means that it goes to a state as if it was just live migrated to the qemu instance on the source (i.e. BDRV_O_INACTIVE is set). You're then supposed to continue either on the source or on the destination, which takes ownership of the image. A typical migration looks like this now with respect to disk images: 1. Destination qemu is started, the image is opened with BDRV_O_INACTIVE. The image is fully opened on the source. 2. Migration is about to complete. The source flushes the image and inactivates it. Now both sides have the image opened with BDRV_O_INACTIVE and are expecting the other side to still modify it. 3. One side (the destination on success) continues and calls bdrv_invalidate_all() in order to take ownership of the image again. This removes BDRV_O_INACTIVE on the resuming side; the flag remains set on the other side. This ensures that the same image isn't written to by both instances (unless both are resumed, but then you get what you deserve). This is important because .bdrv_close for non-BDRV_O_INACTIVE images could write to the image file, which is definitely forbidden while another host is using the image. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: John Snow <jsnow@redhat.com>
2015-12-22 16:07:08 +03:00
}
if (runstate_check(RUN_STATE_INMIGRATE)) {
autostart = 1;
} else {
vm_start();
}
}
void qmp_system_wakeup(Error **errp)
{
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
}
ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
{
Object *obj;
bool ambiguous = false;
ObjectPropertyInfoList *props = NULL;
ObjectProperty *prop;
ObjectPropertyIterator iter;
obj = object_resolve_path(path, &ambiguous);
if (obj == NULL) {
if (ambiguous) {
error_setg(errp, "Path '%s' is ambiguous", path);
} else {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", path);
}
return NULL;
}
object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
entry->next = props;
props = entry;
entry->value->name = g_strdup(prop->name);
entry->value->type = g_strdup(prop->type);
}
return props;
}
void qmp_qom_set(const char *path, const char *property, QObject *value,
Error **errp)
{
Object *obj;
obj = object_resolve_path(path, NULL);
if (!obj) {
qmp: Wean off qerror_report() The traditional QMP command handler interface int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data); doesn't provide for returning an Error object. Instead, the handler is expected to stash it in the monitor with qerror_report(). When we rebased QMP on top of QAPI, we didn't change this interface. Instead, commit 776574d introduced "middle mode" as a temporary aid for converting existing QMP commands to QAPI one by one. More than three years later, we're still using it. Middle mode has two effects: * Instead of the native input marshallers static void qmp_marshal_input_FOO(QDict *, QObject **, Error **) it generates input marshallers conforming to the traditional QMP command handler interface. * It suppresses generation of code to register them with qmp_register_command() This permits giving them internal linkage. As long as we need qmp-commands.hx, we can't use the registry behind qmp_register_command(), so the latter has to stay for now. The former has to go to get rid of qerror_report(). Changing all QMP commands to fit the QAPI mold in one go was impractical back when we started, but by now there are just a few stragglers left: do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(), qmp_netdev_add(), do_device_add(). Switch middle mode to generate native input marshallers, and adapt the stragglers. Simplifies both the monitor code and the stragglers. Rename do_qmp_capabilities() to qmp_capabilities(), and do_device_add() to qmp_device_add, because that's how QMP command handlers are named today. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 19:25:50 +03:00
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", path);
qmp: Wean off qerror_report() The traditional QMP command handler interface int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data); doesn't provide for returning an Error object. Instead, the handler is expected to stash it in the monitor with qerror_report(). When we rebased QMP on top of QAPI, we didn't change this interface. Instead, commit 776574d introduced "middle mode" as a temporary aid for converting existing QMP commands to QAPI one by one. More than three years later, we're still using it. Middle mode has two effects: * Instead of the native input marshallers static void qmp_marshal_input_FOO(QDict *, QObject **, Error **) it generates input marshallers conforming to the traditional QMP command handler interface. * It suppresses generation of code to register them with qmp_register_command() This permits giving them internal linkage. As long as we need qmp-commands.hx, we can't use the registry behind qmp_register_command(), so the latter has to stay for now. The former has to go to get rid of qerror_report(). Changing all QMP commands to fit the QAPI mold in one go was impractical back when we started, but by now there are just a few stragglers left: do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(), qmp_netdev_add(), do_device_add(). Switch middle mode to generate native input marshallers, and adapt the stragglers. Simplifies both the monitor code and the stragglers. Rename do_qmp_capabilities() to qmp_capabilities(), and do_device_add() to qmp_device_add, because that's how QMP command handlers are named today. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 19:25:50 +03:00
return;
}
qmp: Wean off qerror_report() The traditional QMP command handler interface int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data); doesn't provide for returning an Error object. Instead, the handler is expected to stash it in the monitor with qerror_report(). When we rebased QMP on top of QAPI, we didn't change this interface. Instead, commit 776574d introduced "middle mode" as a temporary aid for converting existing QMP commands to QAPI one by one. More than three years later, we're still using it. Middle mode has two effects: * Instead of the native input marshallers static void qmp_marshal_input_FOO(QDict *, QObject **, Error **) it generates input marshallers conforming to the traditional QMP command handler interface. * It suppresses generation of code to register them with qmp_register_command() This permits giving them internal linkage. As long as we need qmp-commands.hx, we can't use the registry behind qmp_register_command(), so the latter has to stay for now. The former has to go to get rid of qerror_report(). Changing all QMP commands to fit the QAPI mold in one go was impractical back when we started, but by now there are just a few stragglers left: do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(), qmp_netdev_add(), do_device_add(). Switch middle mode to generate native input marshallers, and adapt the stragglers. Simplifies both the monitor code and the stragglers. Rename do_qmp_capabilities() to qmp_capabilities(), and do_device_add() to qmp_device_add, because that's how QMP command handlers are named today. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 19:25:50 +03:00
object_property_set_qobject(obj, value, property, errp);
}
QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
{
Object *obj;
obj = object_resolve_path(path, NULL);
if (!obj) {
qmp: Wean off qerror_report() The traditional QMP command handler interface int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data); doesn't provide for returning an Error object. Instead, the handler is expected to stash it in the monitor with qerror_report(). When we rebased QMP on top of QAPI, we didn't change this interface. Instead, commit 776574d introduced "middle mode" as a temporary aid for converting existing QMP commands to QAPI one by one. More than three years later, we're still using it. Middle mode has two effects: * Instead of the native input marshallers static void qmp_marshal_input_FOO(QDict *, QObject **, Error **) it generates input marshallers conforming to the traditional QMP command handler interface. * It suppresses generation of code to register them with qmp_register_command() This permits giving them internal linkage. As long as we need qmp-commands.hx, we can't use the registry behind qmp_register_command(), so the latter has to stay for now. The former has to go to get rid of qerror_report(). Changing all QMP commands to fit the QAPI mold in one go was impractical back when we started, but by now there are just a few stragglers left: do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(), qmp_netdev_add(), do_device_add(). Switch middle mode to generate native input marshallers, and adapt the stragglers. Simplifies both the monitor code and the stragglers. Rename do_qmp_capabilities() to qmp_capabilities(), and do_device_add() to qmp_device_add, because that's how QMP command handlers are named today. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 19:25:50 +03:00
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", path);
return NULL;
}
return object_property_get_qobject(obj, property, errp);
}
void qmp_set_password(const char *protocol, const char *password,
bool has_connected, const char *connected, Error **errp)
{
int disconnect_if_connected = 0;
int fail_if_connected = 0;
int rc;
if (has_connected) {
if (strcmp(connected, "fail") == 0) {
fail_if_connected = 1;
} else if (strcmp(connected, "disconnect") == 0) {
disconnect_if_connected = 1;
} else if (strcmp(connected, "keep") == 0) {
/* nothing */
} else {
error_setg(errp, QERR_INVALID_PARAMETER, "connected");
return;
}
}
if (strcmp(protocol, "spice") == 0) {
if (!qemu_using_spice(errp)) {
return;
}
rc = qemu_spice_set_passwd(password, fail_if_connected,
disconnect_if_connected);
if (rc != 0) {
error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
if (strcmp(protocol, "vnc") == 0) {
if (fail_if_connected || disconnect_if_connected) {
/* vnc supports "connected=keep" only */
error_setg(errp, QERR_INVALID_PARAMETER, "connected");
return;
}
/* Note that setting an empty password will not disable login through
* this interface. */
rc = vnc_display_password(NULL, password);
if (rc < 0) {
error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
}
void qmp_expire_password(const char *protocol, const char *whenstr,
Error **errp)
{
time_t when;
int rc;
if (strcmp(whenstr, "now") == 0) {
when = 0;
} else if (strcmp(whenstr, "never") == 0) {
when = TIME_MAX;
} else if (whenstr[0] == '+') {
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
} else {
when = strtoull(whenstr, NULL, 10);
}
if (strcmp(protocol, "spice") == 0) {
if (!qemu_using_spice(errp)) {
return;
}
rc = qemu_spice_set_pw_expire(when);
if (rc != 0) {
error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
if (strcmp(protocol, "vnc") == 0) {
rc = vnc_display_pw_expire(NULL, when);
if (rc != 0) {
error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
}
#ifdef CONFIG_VNC
void qmp_change_vnc_password(const char *password, Error **errp)
{
if (vnc_display_password(NULL, password) < 0) {
error_setg(errp, QERR_SET_PASSWD_FAILED);
}
}
static void qmp_change_vnc_listen(const char *target, Error **errp)
{
QemuOptsList *olist = qemu_find_opts("vnc");
QemuOpts *opts;
if (strstr(target, "id=")) {
error_setg(errp, "id not supported");
return;
}
opts = qemu_opts_find(olist, "default");
if (opts) {
qemu_opts_del(opts);
}
QemuOpts: Wean off qerror_report_err() qerror_report_err() is a transitional interface to help with converting existing monitor commands to QMP. It should not be used elsewhere. The only remaining user in qemu-option.c is qemu_opts_parse(). Is it used in QMP context? If not, we can simply replace qerror_report_err() by error_report_err(). The uses in qemu-img.c, qemu-io.c, qemu-nbd.c and under tests/ are clearly not in QMP context. The uses in vl.c aren't either, because the only QMP command handlers there are qmp_query_status() and qmp_query_machines(), and they don't call it. Remaining uses: * drive_def(): Command line -drive and such, HMP drive_add and pci_add * hmp_chardev_add(): HMP chardev-add * monitor_parse_command(): HMP core * tmp_config_parse(): Command line -tpmdev * net_host_device_add(): HMP host_net_add * net_client_parse(): Command line -net and -netdev * qemu_global_option(): Command line -global * vnc_parse_func(): Command line -display, -vnc, default display, HMP change, QMP change. Bummer. * qemu_pci_hot_add_nic(): HMP pci_add * usb_net_init(): Command line -usbdevice, HMP usb_add Propagate errors through qemu_opts_parse(). Create a convenience function qemu_opts_parse_noisily() that passes errors to error_report_err(). Switch all non-QMP users outside tests to it. That leaves vnc_parse_func(). Propagate errors through it. Since I'm touching it anyway, rename it to vnc_parse(). Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-02-13 14:50:26 +03:00
opts = vnc_parse(target, errp);
if (!opts) {
return;
}
vnc_display_open("default", errp);
}
static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
Error **errp)
{
if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
if (!has_arg) {
error_setg(errp, QERR_MISSING_PARAMETER, "password");
} else {
qmp_change_vnc_password(arg, errp);
}
} else {
qmp_change_vnc_listen(target, errp);
}
}
#else
void qmp_change_vnc_password(const char *password, Error **errp)
{
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
}
static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
Error **errp)
{
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
}
#endif /* !CONFIG_VNC */
void qmp_change(const char *device, const char *target,
bool has_arg, const char *arg, Error **errp)
{
if (strcmp(device, "vnc") == 0) {
qmp_change_vnc(target, has_arg, arg, errp);
} else {
qmp_blockdev_change_medium(true, device, false, NULL, target,
has_arg, arg, false, 0, errp);
}
}
static void qom_list_types_tramp(ObjectClass *klass, void *data)
{
ObjectTypeInfoList *e, **pret = data;
ObjectTypeInfo *info;
ObjectClass *parent = object_class_get_parent(klass);
info = g_malloc0(sizeof(*info));
info->name = g_strdup(object_class_get_name(klass));
info->has_abstract = info->abstract = object_class_is_abstract(klass);
if (parent) {
info->has_parent = true;
info->parent = g_strdup(object_class_get_name(parent));
}
e = g_malloc0(sizeof(*e));
e->value = info;
e->next = *pret;
*pret = e;
}
ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
const char *implements,
bool has_abstract,
bool abstract,
Error **errp)
{
ObjectTypeInfoList *ret = NULL;
object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
return ret;
}
/* Return a DevicePropertyInfo for a qdev property.
*
* If a qdev property with the given name does not exist, use the given default
* type. If the qdev property info should not be shown, return NULL.
*
* The caller must free the return value.
*/
static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass,
const char *name,
const char *default_type,
const char *description)
{
ObjectPropertyInfo *info;
Property *prop;
do {
for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
if (strcmp(name, prop->name) != 0) {
continue;
}
/*
* TODO Properties without a parser are just for dirty hacks.
* qdev_prop_ptr is the only such PropertyInfo. It's marked
* for removal. This conditional should be removed along with
* it.
*/
if (!prop->info->set && !prop->info->create) {
return NULL; /* no way to set it, don't show */
}
info = g_malloc0(sizeof(*info));
info->name = g_strdup(prop->name);
info->type = default_type ? g_strdup(default_type)
: g_strdup(prop->info->name);
qmp: Print descriptions of object properties Add a new "description" field to DevicePropertyInfo. The descriptions can serve as documentation in the code, and they can be used to provide better help. For example: $./qemu-system-x86_64 -device virtio-blk-pci,? Before this patch: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool virtio-blk-pci.scsi=bool virtio-blk-pci.config-wce=bool virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 virtio-blk-pci.logical_block_size=uint16 virtio-blk-pci.drive=str virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=on/off virtio-blk-pci.multifunction=on/off virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=pci-devfn virtio-blk-pci.event_idx=on/off virtio-blk-pci.indirect_desc=on/off virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=on/off virtio-blk-pci.class=uint32 After: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool (on/off) virtio-blk-pci.scsi=bool (on/off) virtio-blk-pci.config-wce=bool (on/off) virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.logical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.drive=str (ID of a drive to use as a backend) virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=bool (on/off) virtio-blk-pci.multifunction=bool (on/off) virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=int32 (Slot and optional function number, example: 06.0 or 06) virtio-blk-pci.event_idx=bool (on/off) virtio-blk-pci.indirect_desc=bool (on/off) virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=bool (on/off) virtio-blk-pci.class=uint32 Cc: Markus Armbruster <armbru@redhat.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-10-07 10:33:23 +04:00
info->has_description = !!prop->info->description;
info->description = g_strdup(prop->info->description);
return info;
}
klass = object_class_get_parent(klass);
} while (klass != object_class_by_name(TYPE_DEVICE));
/* Not a qdev property, use the default type */
info = g_malloc0(sizeof(*info));
info->name = g_strdup(name);
info->type = g_strdup(default_type);
qmp: Print descriptions of object properties Add a new "description" field to DevicePropertyInfo. The descriptions can serve as documentation in the code, and they can be used to provide better help. For example: $./qemu-system-x86_64 -device virtio-blk-pci,? Before this patch: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool virtio-blk-pci.scsi=bool virtio-blk-pci.config-wce=bool virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 virtio-blk-pci.logical_block_size=uint16 virtio-blk-pci.drive=str virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=on/off virtio-blk-pci.multifunction=on/off virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=pci-devfn virtio-blk-pci.event_idx=on/off virtio-blk-pci.indirect_desc=on/off virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=on/off virtio-blk-pci.class=uint32 After: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool (on/off) virtio-blk-pci.scsi=bool (on/off) virtio-blk-pci.config-wce=bool (on/off) virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.logical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.drive=str (ID of a drive to use as a backend) virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=bool (on/off) virtio-blk-pci.multifunction=bool (on/off) virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=int32 (Slot and optional function number, example: 06.0 or 06) virtio-blk-pci.event_idx=bool (on/off) virtio-blk-pci.indirect_desc=bool (on/off) virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=bool (on/off) virtio-blk-pci.class=uint32 Cc: Markus Armbruster <armbru@redhat.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-10-07 10:33:23 +04:00
info->has_description = !!description;
info->description = g_strdup(description);
return info;
}
ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
Error **errp)
{
ObjectClass *klass;
Object *obj;
ObjectProperty *prop;
ObjectPropertyIterator iter;
ObjectPropertyInfoList *prop_list = NULL;
klass = object_class_by_name(typename);
if (klass == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", typename);
return NULL;
}
klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
if (klass == NULL) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE);
return NULL;
}
if (object_class_is_abstract(klass)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
"non-abstract device type");
return NULL;
}
obj = object_new(typename);
object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info;
ObjectPropertyInfoList *entry;
/* Skip Object and DeviceState properties */
if (strcmp(prop->name, "type") == 0 ||
strcmp(prop->name, "realized") == 0 ||
strcmp(prop->name, "hotpluggable") == 0 ||
strcmp(prop->name, "hotplugged") == 0 ||
strcmp(prop->name, "parent_bus") == 0) {
continue;
}
/* Skip legacy properties since they are just string versions of
* properties that we already list.
*/
if (strstart(prop->name, "legacy-", NULL)) {
continue;
}
qmp: Print descriptions of object properties Add a new "description" field to DevicePropertyInfo. The descriptions can serve as documentation in the code, and they can be used to provide better help. For example: $./qemu-system-x86_64 -device virtio-blk-pci,? Before this patch: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool virtio-blk-pci.scsi=bool virtio-blk-pci.config-wce=bool virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 virtio-blk-pci.logical_block_size=uint16 virtio-blk-pci.drive=str virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=on/off virtio-blk-pci.multifunction=on/off virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=pci-devfn virtio-blk-pci.event_idx=on/off virtio-blk-pci.indirect_desc=on/off virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=on/off virtio-blk-pci.class=uint32 After: virtio-blk-pci.iothread=link<iothread> virtio-blk-pci.x-data-plane=bool (on/off) virtio-blk-pci.scsi=bool (on/off) virtio-blk-pci.config-wce=bool (on/off) virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.logical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.drive=str (ID of a drive to use as a backend) virtio-blk-pci.virtio-backend=child<virtio-blk-device> virtio-blk-pci.command_serr_enable=bool (on/off) virtio-blk-pci.multifunction=bool (on/off) virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=int32 (Slot and optional function number, example: 06.0 or 06) virtio-blk-pci.event_idx=bool (on/off) virtio-blk-pci.indirect_desc=bool (on/off) virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=bool (on/off) virtio-blk-pci.class=uint32 Cc: Markus Armbruster <armbru@redhat.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-10-07 10:33:23 +04:00
info = make_device_property_info(klass, prop->name, prop->type,
prop->description);
if (!info) {
continue;
}
entry = g_malloc0(sizeof(*entry));
entry->value = info;
entry->next = prop_list;
prop_list = entry;
}
object_unref(obj);
return prop_list;
}
ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
Error **errp)
{
ObjectClass *klass;
Object *obj = NULL;
ObjectProperty *prop;
ObjectPropertyIterator iter;
ObjectPropertyInfoList *prop_list = NULL;
klass = object_class_by_name(typename);
if (klass == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Class '%s' not found", typename);
return NULL;
}
klass = object_class_dynamic_cast(klass, TYPE_OBJECT);
if (klass == NULL) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT);
return NULL;
}
if (object_class_is_abstract(klass)) {
object_class_property_iter_init(&iter, klass);
} else {
obj = object_new(typename);
object_property_iter_init(&iter, obj);
}
while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info;
ObjectPropertyInfoList *entry;
info = g_malloc0(sizeof(*info));
info->name = g_strdup(prop->name);
info->type = g_strdup(prop->type);
info->has_description = !!prop->description;
info->description = g_strdup(prop->description);
entry = g_malloc0(sizeof(*entry));
entry->value = info;
entry->next = prop_list;
prop_list = entry;
}
object_unref(obj);
return prop_list;
}
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
return arch_query_cpu_definitions(errp);
}
CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model,
Error **errp)
{
return arch_query_cpu_model_expansion(type, model, errp);
}
CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
CpuModelInfo *modelb,
Error **errp)
{
return arch_query_cpu_model_comparison(modela, modelb, errp);
}
CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
CpuModelInfo *modelb,
Error **errp)
{
return arch_query_cpu_model_baseline(modela, modelb, errp);
}
void qmp_add_client(const char *protocol, const char *fdname,
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
Error **errp)
{
Chardev *s;
int fd;
fd = monitor_get_fd(cur_mon, fdname, errp);
if (fd < 0) {
return;
}
if (strcmp(protocol, "spice") == 0) {
if (!qemu_using_spice(errp)) {
close(fd);
return;
}
skipauth = has_skipauth ? skipauth : false;
tls = has_tls ? tls : false;
if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
error_setg(errp, "spice failed to add client");
close(fd);
}
return;
#ifdef CONFIG_VNC
} else if (strcmp(protocol, "vnc") == 0) {
skipauth = has_skipauth ? skipauth : false;
vnc_display_add_client(NULL, fd, skipauth);
return;
#endif
} else if ((s = qemu_chr_find(protocol)) != NULL) {
if (qemu_chr_add_client(s, fd) < 0) {
error_setg(errp, "failed to add client");
close(fd);
return;
}
return;
}
error_setg(errp, "protocol '%s' is invalid", protocol);
close(fd);
}
void qmp_object_add(const char *type, const char *id,
bool has_props, QObject *props, Error **errp)
{
QDict *pdict;
Visitor *v;
Object *obj;
if (props) {
pdict = qobject_to(QDict, props);
if (!pdict) {
qmp: Wean off qerror_report() The traditional QMP command handler interface int qmp_FOO(Monitor *mon, const QDict *params, QObject **ret_data); doesn't provide for returning an Error object. Instead, the handler is expected to stash it in the monitor with qerror_report(). When we rebased QMP on top of QAPI, we didn't change this interface. Instead, commit 776574d introduced "middle mode" as a temporary aid for converting existing QMP commands to QAPI one by one. More than three years later, we're still using it. Middle mode has two effects: * Instead of the native input marshallers static void qmp_marshal_input_FOO(QDict *, QObject **, Error **) it generates input marshallers conforming to the traditional QMP command handler interface. * It suppresses generation of code to register them with qmp_register_command() This permits giving them internal linkage. As long as we need qmp-commands.hx, we can't use the registry behind qmp_register_command(), so the latter has to stay for now. The former has to go to get rid of qerror_report(). Changing all QMP commands to fit the QAPI mold in one go was impractical back when we started, but by now there are just a few stragglers left: do_qmp_capabilities(), qmp_qom_set(), qmp_qom_get(), qmp_object_add(), qmp_netdev_add(), do_device_add(). Switch middle mode to generate native input marshallers, and adapt the stragglers. Simplifies both the monitor code and the stragglers. Rename do_qmp_capabilities() to qmp_capabilities(), and do_device_add() to qmp_device_add, because that's how QMP command handlers are named today. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-03-13 19:25:50 +03:00
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
return;
}
qobject_ref(pdict);
} else {
pdict = qdict_new();
}
v = qobject_input_visitor_new(QOBJECT(pdict));
obj = user_creatable_add_type(type, id, pdict, v, errp);
visit_free(v);
if (obj) {
object_unref(obj);
}
qobject_unref(pdict);
}
void qmp_object_del(const char *id, Error **errp)
{
user_creatable_del(id, errp);
}
MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
{
return qmp_pc_dimm_device_list();
}
ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
{
bool ambig;
ACPIOSTInfoList *head = NULL;
ACPIOSTInfoList **prev = &head;
Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);
if (obj) {
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
adevc->ospm_status(adev, &prev);
} else {
error_setg(errp, "command is not supported, missing ACPI device");
}
return head;
}
MemoryInfo *qmp_query_memory_size_summary(Error **errp)
{
MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));
mem_info->base_memory = ram_size;
mem_info->plugged_memory = get_plugged_memory_size();
mem_info->has_plugged_memory =
mem_info->plugged_memory != (uint64_t)-1;
return mem_info;
}
static QemuSemaphore x_oob_test_sem;
static void __attribute__((constructor)) x_oob_test_init(void)
{
qemu_sem_init(&x_oob_test_sem, 0);
}
void qmp_x_oob_test(bool lock, Error **errp)
{
if (lock) {
qemu_sem_wait(&x_oob_test_sem);
} else {
qemu_sem_post(&x_oob_test_sem);
}
}