There are a couple of situations where all fields of a
MigrationParameters object need to be marked as present: when cloning
an entire object and when creating the transient object in
qmp_query_migrate(). The query-migrate-parameters QMP command contract
requires that all parameters, except block-bitmap-mapping, are present
in the output.

Validate that a given object has all has_* fields set to true.

Signed-off-by: Fabiano Rosas <[email protected]>
---
 migration/options.c | 54 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/migration/options.c b/migration/options.c
index bd7be8f9832..5d17acdd881 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -12,6 +12,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qemu/error-report.h"
 #include "qemu/units.h"
 #include "exec/target_page.h"
@@ -23,8 +24,10 @@
 #include "qapi/qmp/qerror.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
+#include "qobject/qbool.h"
 #include "qobject/qdict.h"
 #include "qobject/qnull.h"
+#include "qobject/qstring.h"
 #include "system/runstate.h"
 #include "migration/colo.h"
 #include "migration/cpr.h"
@@ -1149,12 +1152,63 @@ static void 
migrate_mark_all_params_present(MigrationParameters *p)
     }
 }
 
+static bool assert_all_params_present(MigrationParameters *params, Error 
**errp)
+{
+    g_autoptr(QDict) d = migrate_params_to_dict(params, errp);
+    const QDictEntry *e = NULL;
+    int i = 0;
+
+    if (!d) {
+        return false;
+    }
+
+    for (e = qdict_first(d); e; e = qdict_next(d, e), i++) {
+        const char *key = qdict_entry_key(e);
+        const char *p;
+
+        if (strstart(key, "tls-", &p)) {
+            QString *s = qobject_to(QString, qdict_entry_value(e));
+
+            if (!s) {
+                break;
+            }
+        } else if (strstart(key, "has-", &p)) {
+            if (qdict_haskey(d, p)) {
+                QBool *b = qobject_to(QBool, qdict_entry_value(e));
+
+                if (!b || !qbool_get_bool(b)) {
+                    break;
+                }
+            }
+        }
+    }
+
+    if (i && !e) {
+        return true;
+    }
+
+    /*
+     * Should never happen, but avoid asserting becase this is
+     * reachable from QMP.
+     */
+    error_setg(errp, "Missing parameter. Query output will be incomplete.");
+    return false;
+}
+
 MigrationParameters *qmp_query_migrate_parameters(Error **errp)
 {
     MigrationState *s = migrate_get_current();
     MigrationParameters *params = QAPI_CLONE(MigrationParameters,
                                              &s->parameters);
 
+    /*
+     * Validate all parameters have their has_* field set to true as
+     * consequence of the initial migrate_mark_all_params_present().
+     */
+    if (!assert_all_params_present(params, errp)) {
+        return NULL;
+    }
+
     /*
      * The block-bitmap-mapping breaks the expected API of
      * query-migrate-parameters of having all members present. To keep
-- 
2.53.0


Reply via email to