]> git.proxmox.com Git - mirror_qemu.git/blobdiff - qmp.c
tests/acpi: don't pack a structure
[mirror_qemu.git] / qmp.c
diff --git a/qmp.c b/qmp.c
index d701cff5ac1f764cddd3461fc09e3e57381491bf..fa82b598c6d0c58c4919cc2a2d5451f7c70a67e2 100644 (file)
--- a/qmp.c
+++ b/qmp.c
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "qemu-common.h"
+#include "qemu/osdep.h"
+#include "qemu-version.h"
+#include "qemu/cutils.h"
+#include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
+#include "qemu/config-file.h"
+#include "qemu/uuid.h"
 #include "qmp-commands.h"
 #include "sysemu/char.h"
 #include "ui/qemu-spice.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/qmp/qerror.h"
 #include "qapi/qmp/qobject.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
 #include "hw/boards.h"
 #include "qom/object_interfaces.h"
 #include "hw/mem/pc-dimm.h"
@@ -45,15 +52,12 @@ NameInfo *qmp_query_name(Error **errp)
 
 VersionInfo *qmp_query_version(Error **errp)
 {
-    VersionInfo *info = g_malloc0(sizeof(*info));
-    const char *version = QEMU_VERSION;
-    char *tmp;
+    VersionInfo *info = g_new0(VersionInfo, 1);
 
-    info->qemu.major = strtol(version, &tmp, 10);
-    tmp++;
-    info->qemu.minor = strtol(tmp, &tmp, 10);
-    tmp++;
-    info->qemu.micro = strtol(tmp, &tmp, 10);
+    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;
@@ -72,15 +76,8 @@ KvmInfo *qmp_query_kvm(Error **errp)
 UuidInfo *qmp_query_uuid(Error **errp)
 {
     UuidInfo *info = g_malloc0(sizeof(*info));
-    char uuid[64];
 
-    snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
-                   qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
-                   qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
-                   qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
-                   qemu_uuid[14], qemu_uuid[15]);
-
-    info->UUID = g_strdup(uuid);
+    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
     return info;
 }
 
@@ -92,6 +89,13 @@ void qmp_quit(Error **errp)
 
 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 {
@@ -131,13 +135,13 @@ void qmp_cpu_add(int64_t id, Error **errp)
    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_set(errp, QERR_FEATURE_DISABLED, "vnc");
+    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
     return NULL;
 };
 #endif
@@ -148,9 +152,9 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
  * #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_input_query_spice() that calls qmp_query_spice().
- * Provide it one, or else linking fails.
- * FIXME Educate the QAPI schema on CONFIG_SPICE.
+ * 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)
 {
@@ -161,7 +165,16 @@ SpiceInfo *qmp_query_spice(Error **errp)
 void qmp_cont(Error **errp)
 {
     Error *local_err = NULL;
+    BlockBackend *blk;
     BlockDriverState *bs;
+    BdrvNextIterator it;
+
+    /* 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");
@@ -170,10 +183,11 @@ void qmp_cont(Error **errp)
         return;
     }
 
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        bdrv_iostatus_reset(bs);
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+        blk_iostatus_reset(blk);
     }
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+
+    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
         bdrv_add_key(bs, NULL, &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
@@ -181,6 +195,18 @@ void qmp_cont(Error **errp)
         }
     }
 
+    /* Continuing after completed migration. Images have been inactivated to
+     * allow the destination to take control. Need to get control back now. */
+    if (runstate_check(RUN_STATE_FINISH_MIGRATE) ||
+        runstate_check(RUN_STATE_POSTMIGRATE))
+    {
+        bdrv_invalidate_cache_all(&local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+
     if (runstate_check(RUN_STATE_INMIGRATE)) {
         autostart = 1;
     } else {
@@ -199,18 +225,21 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
     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, QERR_DEVICE_NOT_FOUND, path);
+            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+                      "Device '%s' not found", path);
         }
         return NULL;
     }
 
-    QTAILQ_FOREACH(prop, &obj->properties, node) {
+    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));
@@ -224,56 +253,33 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
     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,
@@ -291,7 +297,7 @@ 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;
         }
     }
@@ -303,7 +309,7 @@ void qmp_set_password(const char *protocol, const char *password,
         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;
     }
@@ -311,19 +317,19 @@ void qmp_set_password(const char *protocol, const char *password,
     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,
@@ -348,7 +354,7 @@ void qmp_expire_password(const char *protocol, const char *whenstr,
         }
         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;
     }
@@ -356,19 +362,19 @@ void qmp_expire_password(const char *protocol, const char *whenstr,
     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);
     }
 }
 
@@ -386,12 +392,11 @@ static void qmp_change_vnc_listen(const char *target, Error **errp)
     if (opts) {
         qemu_opts_del(opts);
     }
-    opts = vnc_parse_func(target);
+    opts = vnc_parse(target, errp);
     if (!opts) {
         return;
     }
 
-    vnc_auto_assign_id(olist, opts);
     vnc_display_open("default", errp);
 }
 
@@ -400,7 +405,7 @@ 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);
         }
@@ -411,12 +416,12 @@ static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
 #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 */
 
@@ -426,7 +431,8 @@ void qmp_change(const char *device, const char *target,
     if (strcmp(device, "vnc") == 0) {
         qmp_change_vnc(target, has_arg, arg, errp);
     } else {
-        qmp_change_blockdev(device, target, arg, errp);
+        qmp_blockdev_change_medium(true, device, false, NULL, target,
+                                   has_arg, arg, false, 0, errp);
     }
 }
 
@@ -514,24 +520,37 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
     ObjectClass *klass;
     Object *obj;
     ObjectProperty *prop;
+    ObjectPropertyIterator iter;
     DevicePropertyInfoList *prop_list = NULL;
 
     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, "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;
+    }
+
+    if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
+        error_setg(errp, "Can't list properties of device '%s'", typename);
         return NULL;
     }
 
     obj = object_new(typename);
 
-    QTAILQ_FOREACH(prop, &obj->properties, node) {
+    object_property_iter_init(&iter, obj);
+    while ((prop = object_property_iter_next(&iter))) {
         DevicePropertyInfo *info;
         DevicePropertyInfoList *entry;
 
@@ -573,11 +592,32 @@ 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)
 {
-    CharDriverState *s;
+    Chardev *s;
     int fd;
 
     fd = monitor_get_fd(cur_mon, fdname, errp);
@@ -616,103 +656,37 @@ void qmp_add_client(const char *protocol, const char *fdname,
     close(fd);
 }
 
-void object_add(const char *type, const char *id, const QDict *qdict,
-                Visitor *v, Error **errp)
-{
-    Object *obj;
-    ObjectClass *klass;
-    const QDictEntry *e;
-    Error *local_err = NULL;
-
-    klass = object_class_by_name(type);
-    if (!klass) {
-        error_setg(errp, "invalid object type: %s", type);
-        return;
-    }
-
-    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
-        error_setg(errp, "object type '%s' isn't supported by object-add",
-                   type);
-        return;
-    }
-
-    if (object_class_is_abstract(klass)) {
-        error_setg(errp, "object type '%s' is abstract", type);
-        return;
-    }
-
-    obj = object_new(type);
-    if (qdict) {
-        for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
-            object_property_set(obj, v, e->key, &local_err);
-            if (local_err) {
-                goto out;
-            }
-        }
-    }
 
-    object_property_add_child(container_get(object_get_root(), "/objects"),
-                              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"),
-                            id, &error_abort);
-        goto out;
-    }
-out:
-    if (local_err) {
-        error_propagate(errp, local_err);
-    }
-    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;
+    QDict *pdict;
+    Visitor *v;
+    Object *obj;
 
     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;
         }
+        QINCREF(pdict);
+    } else {
+        pdict = qdict_new();
     }
 
-    qiv = qmp_input_visitor_new(props);
-    object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err);
-    qmp_input_visitor_cleanup(qiv);
-
-out:
-    if (local_err) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
+    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);
     }
-
-    return 0;
+    QDECREF(pdict);
 }
 
 void qmp_object_del(const char *id, Error **errp)
 {
-    Object *container;
-    Object *obj;
-
-    container = container_get(object_get_root(), "/objects");
-    obj = object_resolve_path_component(container, id);
-    if (!obj) {
-        error_setg(errp, "object id not found");
-        return;
-    }
-    object_unparent(obj);
+    user_creatable_del(id, errp);
 }
 
 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)