<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>