*/
#include "qemu-common.h"
+#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
#include "qmp-commands.h"
#include "sysemu/char.h"
#include "hw/qdev.h"
#include "sysemu/blockdev.h"
#include "qom/qom-qobject.h"
+#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qobject.h"
#include "qapi/qmp-input-visitor.h"
#include "hw/boards.h"
VersionInfo *qmp_query_version(Error **errp)
{
- VersionInfo *info = g_malloc0(sizeof(*info));
+ VersionInfo *info = g_new0(VersionInfo, 1);
const char *version = QEMU_VERSION;
- char *tmp;
+ const char *tmp;
+ int err;
- info->qemu.major = strtol(version, &tmp, 10);
+ info->qemu = g_new0(VersionTriple, 1);
+ err = qemu_strtoll(version, &tmp, 10, &info->qemu->major);
+ assert(err == 0);
tmp++;
- info->qemu.minor = strtol(tmp, &tmp, 10);
+
+ err = qemu_strtoll(tmp, &tmp, 10, &info->qemu->minor);
+ assert(err == 0);
tmp++;
- info->qemu.micro = strtol(tmp, &tmp, 10);
+
+ err = qemu_strtoll(tmp, &tmp, 10, &info->qemu->micro);
+ assert(err == 0);
info->package = g_strdup(QEMU_PKGVERSION);
return info;
defined in the VNC subsystem */
VncInfo *qmp_query_vnc(Error **errp)
{
- error_set(errp, QERR_FEATURE_DISABLED, "vnc");
+ 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
-/* If SPICE support is enabled, the "true" query-spice command is
- defined in the SPICE subsystem. Also note that we use a small
- trick to maintain query-spice's original behavior, which is not
- to be available in the namespace if SPICE is not compiled in */
+/*
+ * qmp-commands.hx 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)
{
- error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice");
- return NULL;
+ abort();
};
#endif
void qmp_cont(Error **errp)
{
+ Error *local_err = NULL;
BlockDriverState *bs;
if (runstate_needs_reset()) {
bdrv_iostatus_reset(bs);
}
for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
- if (bdrv_key_required(bs)) {
- error_set(errp, QERR_DEVICE_ENCRYPTED,
- bdrv_get_device_name(bs),
- bdrv_get_encrypted_filename(bs));
+ bdrv_add_key(bs, NULL, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
}
if (ambiguous) {
error_setg(errp, "Path '%s' is ambiguous", path);
} else {
- error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "Device '%s' not found", path);
}
return NULL;
}
return props;
}
-/* FIXME: teach qapi about how to pass through Visitors */
-int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
+void qmp_qom_set(const char *path, const char *property, QObject *value,
+ Error **errp)
{
- const char *path = qdict_get_str(qdict, "path");
- const char *property = qdict_get_str(qdict, "property");
- QObject *value = qdict_get(qdict, "value");
- Error *local_err = NULL;
Object *obj;
obj = object_resolve_path(path, NULL);
if (!obj) {
- error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
- goto out;
- }
-
- object_property_set_qobject(obj, value, property, &local_err);
-
-out:
- if (local_err) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "Device '%s' not found", path);
+ return;
}
- return 0;
+ object_property_set_qobject(obj, value, property, errp);
}
-int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
+QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
{
- const char *path = qdict_get_str(qdict, "path");
- const char *property = qdict_get_str(qdict, "property");
- Error *local_err = NULL;
Object *obj;
obj = object_resolve_path(path, NULL);
if (!obj) {
- error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
- goto out;
- }
-
- *ret = object_property_get_qobject(obj, property, &local_err);
-
-out:
- if (local_err) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "Device '%s' not found", path);
+ return NULL;
}
- return 0;
+ return object_property_get_qobject(obj, property, errp);
}
void qmp_set_password(const char *protocol, const char *password,
} else if (strcmp(connected, "keep") == 0) {
/* nothing */
} else {
- error_set(errp, QERR_INVALID_PARAMETER, "connected");
+ error_setg(errp, QERR_INVALID_PARAMETER, "connected");
return;
}
}
if (strcmp(protocol, "spice") == 0) {
- if (!using_spice) {
- /* correct one? spice isn't a device ,,, */
- error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
+ if (!qemu_using_spice(errp)) {
return;
}
rc = qemu_spice_set_passwd(password, fail_if_connected,
disconnect_if_connected);
if (rc != 0) {
- error_set(errp, QERR_SET_PASSWD_FAILED);
+ 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_set(errp, QERR_INVALID_PARAMETER, "connected");
+ 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_set(errp, QERR_SET_PASSWD_FAILED);
+ error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
- error_set(errp, QERR_INVALID_PARAMETER, "protocol");
+ error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
}
void qmp_expire_password(const char *protocol, const char *whenstr,
}
if (strcmp(protocol, "spice") == 0) {
- if (!using_spice) {
- /* correct one? spice isn't a device ,,, */
- error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
+ if (!qemu_using_spice(errp)) {
return;
}
rc = qemu_spice_set_pw_expire(when);
if (rc != 0) {
- error_set(errp, QERR_SET_PASSWD_FAILED);
+ error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
if (strcmp(protocol, "vnc") == 0) {
rc = vnc_display_pw_expire(NULL, when);
if (rc != 0) {
- error_set(errp, QERR_SET_PASSWD_FAILED);
+ error_setg(errp, QERR_SET_PASSWD_FAILED);
}
return;
}
- error_set(errp, QERR_INVALID_PARAMETER, "protocol");
+ 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_set(errp, QERR_SET_PASSWD_FAILED);
+ error_setg(errp, QERR_SET_PASSWD_FAILED);
}
}
static void qmp_change_vnc_listen(const char *target, Error **errp)
{
- vnc_display_open(NULL, target, 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);
+ }
+ 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,
{
if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
if (!has_arg) {
- error_set(errp, QERR_MISSING_PARAMETER, "password");
+ error_setg(errp, QERR_MISSING_PARAMETER, "password");
} else {
qmp_change_vnc_password(arg, errp);
}
#else
void qmp_change_vnc_password(const char *password, Error **errp)
{
- error_set(errp, QERR_FEATURE_DISABLED, "vnc");
+ error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
}
static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
Error **errp)
{
- error_set(errp, QERR_FEATURE_DISABLED, "vnc");
+ error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
}
#endif /* !CONFIG_VNC */
*/
static DevicePropertyInfo *make_device_property_info(ObjectClass *klass,
const char *name,
- const char *default_type)
+ const char *default_type,
+ const char *description)
{
DevicePropertyInfo *info;
Property *prop;
info = g_malloc0(sizeof(*info));
info->name = g_strdup(prop->name);
- info->type = g_strdup(prop->info->legacy_name ?: prop->info->name);
+ info->type = g_strdup(prop->info->name);
+ info->has_description = !!prop->info->description;
+ info->description = g_strdup(prop->info->description);
return info;
}
klass = object_class_get_parent(klass);
info = g_malloc0(sizeof(*info));
info->name = g_strdup(name);
info->type = g_strdup(default_type);
+ info->has_description = !!description;
+ info->description = g_strdup(description);
+
return info;
}
klass = object_class_by_name(typename);
if (klass == NULL) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, typename);
+ 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_set(errp, QERR_INVALID_PARAMETER_VALUE,
- "name", TYPE_DEVICE);
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name", TYPE_DEVICE);
return NULL;
}
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;
}
continue;
}
- info = make_device_property_info(klass, prop->name, prop->type);
+ info = make_device_property_info(klass, prop->name, prop->type,
+ prop->description);
if (!info) {
continue;
}
}
if (strcmp(protocol, "spice") == 0) {
- if (!using_spice) {
- error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
+ if (!qemu_using_spice(errp)) {
close(fd);
return;
}
}
}
- object_property_add_child(container_get(object_get_root(), "/objects"),
+ object_property_add_child(object_get_objects_root(),
id, obj, &local_err);
if (local_err) {
goto out;
user_creatable_complete(obj, &local_err);
if (local_err) {
- object_property_del(container_get(object_get_root(), "/objects"),
+ object_property_del(object_get_objects_root(),
id, &error_abort);
goto out;
}
object_unref(obj);
}
-int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret)
+void qmp_object_add(const char *type, const char *id,
+ bool has_props, QObject *props, Error **errp)
{
- const char *type = qdict_get_str(qdict, "qom-type");
- const char *id = qdict_get_str(qdict, "id");
- QObject *props = qdict_get(qdict, "props");
const QDict *pdict = NULL;
- Error *local_err = NULL;
QmpInputVisitor *qiv;
if (props) {
pdict = qobject_to_qdict(props);
if (!pdict) {
- error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
- goto out;
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
+ return;
}
}
qiv = qmp_input_visitor_new(props);
- object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err);
+ object_add(type, id, pdict, qmp_input_get_visitor(qiv), errp);
qmp_input_visitor_cleanup(qiv);
-
-out:
- if (local_err) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
- }
-
- return 0;
}
void qmp_object_del(const char *id, Error **errp)
Object *container;
Object *obj;
- container = container_get(object_get_root(), "/objects");
+ container = object_get_objects_root();
obj = object_resolve_path_component(container, id);
if (!obj) {
error_setg(errp, "object id not found");
return;
}
+
+ if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) {
+ error_setg(errp, "%s is in use, can not be deleted", id);
+ return;
+ }
object_unparent(obj);
}