<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Oct 25, 2021 at 1:26 AM Markus Armbruster <<a href="mailto:armbru@redhat.com">armbru@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">New option parameters unstable-input and unstable-output set policy<br>
for unstable interfaces just like deprecated-input and<br>
deprecated-output set policy for deprecated interfaces (see commit<br>
6dd75472d5 "qemu-options: New -compat to set policy for deprecated<br>
interfaces").  This is intended for testing users of the management<br>
interfaces.  It is experimental.<br>
<br>
For now, this covers only syntactic aspects of QMP, i.e. stuff tagged<br>
with feature 'unstable'.  We may want to extend it to cover semantic<br>
aspects, or the command line.<br>
<br>
Note that there is no good way for management application to detect<br>
presence of these new option parameters: they are not visible output<br>
of query-qmp-schema or query-command-line-options.  Tolerable, because<br>
it's meant for testing.  If running with -compat fails, skip the test.<br>
<br>
Signed-off-by: Markus Armbruster <<a href="mailto:armbru@redhat.com" target="_blank">armbru@redhat.com</a>><br>
---<br>
 qapi/compat.json              |  6 +++++-<br>
 include/qapi/util.h           |  1 +<br>
 qapi/qmp-dispatch.c           |  6 ++++++<br>
 qapi/qobject-output-visitor.c |  8 ++++++--<br>
 qemu-options.hx               | 20 +++++++++++++++++++-<br>
 scripts/qapi/events.py        | 10 ++++++----<br>
 scripts/qapi/schema.py        | 10 ++++++----<br>
 7 files changed, 49 insertions(+), 12 deletions(-)<br>
<br>
diff --git a/qapi/compat.json b/qapi/compat.json<br>
index 74a8493d3d..9bc9804abb 100644<br>
--- a/qapi/compat.json<br>
+++ b/qapi/compat.json<br>
@@ -47,9 +47,13 @@<br>
 #<br>
 # @deprecated-input: how to handle deprecated input (default 'accept')<br>
 # @deprecated-output: how to handle deprecated output (default 'accept')<br>
+# @unstable-input: how to handle unstable input (default 'accept')<br>
+# @unstable-output: how to handle unstable output (default 'accept')<br>
 #<br>
 # Since: 6.0<br>
 ##<br>
 { 'struct': 'CompatPolicy',<br>
   'data': { '*deprecated-input': 'CompatPolicyInput',<br>
-            '*deprecated-output': 'CompatPolicyOutput' } }<br>
+            '*deprecated-output': 'CompatPolicyOutput',<br>
+            '*unstable-input': 'CompatPolicyInput',<br>
+            '*unstable-output': 'CompatPolicyOutput' } }<br>
diff --git a/include/qapi/util.h b/include/qapi/util.h<br>
index 0cc98db9f9..81a2b13a33 100644<br>
--- a/include/qapi/util.h<br>
+++ b/include/qapi/util.h<br>
@@ -13,6 +13,7 @@<br>
<br>
 typedef enum {<br>
     QAPI_DEPRECATED,<br>
+    QAPI_UNSTABLE,<br>
 } QapiSpecialFeature;<br>
<br>
 typedef struct QEnumLookup {<br>
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c<br>
index e29ade134c..c5c6e521a2 100644<br>
--- a/qapi/qmp-dispatch.c<br>
+++ b/qapi/qmp-dispatch.c<br>
@@ -59,6 +59,12 @@ bool compat_policy_input_ok(unsigned special_features,<br>
                                     error_class, kind, name, errp)) {<br>
         return false;<br>
     }<br>
+    if ((special_features & (1u << QAPI_UNSTABLE))<br>
+        && !compat_policy_input_ok1("Unstable",<br>
+                                    policy->unstable_input,<br>
+                                    error_class, kind, name, errp)) {<br>
+        return false;<br>
+    }<br>
     return true;<br>
 }<br>
<br>
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c<br>
index b5c6564cbb..74770edd73 100644<br>
--- a/qapi/qobject-output-visitor.c<br>
+++ b/qapi/qobject-output-visitor.c<br>
@@ -212,8 +212,12 @@ static bool qobject_output_type_null(Visitor *v, const char *name,<br>
 static bool qobject_output_policy_skip(Visitor *v, const char *name,<br>
                                        unsigned special_features)<br>
 {<br>
-    return !(special_features && 1u << QAPI_DEPRECATED)<br>
-        || v->compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE;<br>
+    CompatPolicy *pol = &v->compat_policy;<br>
+<br>
+    return ((special_features & 1u << QAPI_DEPRECATED)<br>
+            && pol->deprecated_output == COMPAT_POLICY_OUTPUT_HIDE)<br>
+        || ((special_features & 1u << QAPI_UNSTABLE)<br>
+            && pol->unstable_output == COMPAT_POLICY_OUTPUT_HIDE);<br>
 }<br>
<br>
 /* Finish building, and return the root object.<br>
diff --git a/qemu-options.hx b/qemu-options.hx<br>
index 5f375bbfa6..f051536b63 100644<br>
--- a/qemu-options.hx<br>
+++ b/qemu-options.hx<br>
@@ -3641,7 +3641,9 @@ DEFHEADING(Debug/Expert options:)<br>
<br>
 DEF("compat", HAS_ARG, QEMU_OPTION_compat,<br>
     "-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]\n"<br>
-    "                Policy for handling deprecated management interfaces\n",<br>
+    "                Policy for handling deprecated management interfaces\n"<br>
+    "-compat [unstable-input=accept|reject|crash][,unstable-output=accept|hide]\n"<br>
+    "                Policy for handling unstable management interfaces\n",<br>
     QEMU_ARCH_ALL)<br>
 SRST<br>
 ``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]``<br>
@@ -3659,6 +3661,22 @@ SRST<br>
         Suppress deprecated command results and events<br>
<br>
     Limitation: covers only syntactic aspects of QMP.<br>
+<br>
+``-compat [unstable-input=@var{input-policy}][,unstable-output=@var{output-policy}]``<br>
+    Set policy for handling unstable management interfaces (experimental):<br>
+<br>
+    ``unstable-input=accept`` (default)<br>
+        Accept unstable commands and arguments<br>
+    ``unstable-input=reject``<br>
+        Reject unstable commands and arguments<br>
+    ``unstable-input=crash``<br>
+        Crash on unstable commands and arguments<br>
+    ``unstable-output=accept`` (default)<br>
+        Emit unstable command results and events<br>
+    ``unstable-output=hide``<br>
+        Suppress unstable command results and events<br>
+<br>
+    Limitation: covers only syntactic aspects of QMP.<br>
 ERST<br>
<br>
 DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg,<br>
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py<br>
index 82475e84ec..27b44c49f5 100644<br>
--- a/scripts/qapi/events.py<br>
+++ b/scripts/qapi/events.py<br>
@@ -109,13 +109,15 @@ def gen_event_send(name: str,<br>
         if not boxed:<br>
             ret += gen_param_var(arg_type)<br>
<br>
-    if 'deprecated' in [<a href="http://f.name" rel="noreferrer" target="_blank">f.name</a> for f in features]:<br>
-        ret += mcgen('''<br>
+    for f in features:<br>
+        if f.is_special():<br>
+            ret += mcgen('''<br>
<br>
-    if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) {<br>
+    if (compat_policy.%(feat)s_output == COMPAT_POLICY_OUTPUT_HIDE) {<br>
         return;<br>
     }<br>
-''')<br>
+''',<br>
+                         feat=<a href="http://f.name" rel="noreferrer" target="_blank">f.name</a>)<br>
<br>
     ret += mcgen('''<br>
<br>
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py<br>
index 55f82d7389..b7b3fc0ce4 100644<br>
--- a/scripts/qapi/schema.py<br>
+++ b/scripts/qapi/schema.py<br>
@@ -254,9 +254,11 @@ def doc_type(self):<br>
<br>
     def check(self, schema):<br>
         QAPISchemaEntity.check(self, schema)<br>
-        if 'deprecated' in [<a href="http://f.name" rel="noreferrer" target="_blank">f.name</a> for f in self.features]:<br>
-            raise QAPISemError(<br>
-                <a href="http://self.info" rel="noreferrer" target="_blank">self.info</a>, "feature 'deprecated' is not supported for types")<br>
+        for feat in self.features:<br>
+            if feat.is_special():<br>
+                raise QAPISemError(<br>
+                    <a href="http://self.info" rel="noreferrer" target="_blank">self.info</a>,<br>
+                    f"feature '{<a href="http://feat.name" rel="noreferrer" target="_blank">feat.name</a>}' is not supported for types")<br>
<br>
     def describe(self):<br>
         assert self.meta<br>
@@ -726,7 +728,7 @@ class QAPISchemaFeature(QAPISchemaMember):<br>
     role = 'feature'<br>
<br>
     def is_special(self):<br>
-        return <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> in ('deprecated')<br>
+        return <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> in ('deprecated', 'unstable')<br>
<br>
<br>
 class QAPISchemaObjectTypeMember(QAPISchemaMember):<br>
-- <br>
2.31.1<br>
<br></blockquote><div><br></div><div>Python bits: Acked-by: John Snow <<a href="mailto:jsnow@redhat.com">jsnow@redhat.com</a>></div><div><br></div><div>Looks good overall from what I can see, minor style quibbles that I'd probably fold on if you frowned at me.</div><div><br></div><div>--js<br></div></div></div>