qapi: Extend -compat to set policy for unstable interfaces

New option parameters unstable-input and unstable-output set policy
for unstable interfaces just like deprecated-input and
deprecated-output set policy for deprecated interfaces (see commit
6dd75472d5 "qemu-options: New -compat to set policy for deprecated
interfaces").  This is intended for testing users of the management
interfaces.  It is experimental.

For now, this covers only syntactic aspects of QMP, i.e. stuff tagged
with feature 'unstable'.  We may want to extend it to cover semantic
aspects, or the command line.

Note that there is no good way for management application to detect
presence of these new option parameters: they are not visible output
of query-qmp-schema or query-command-line-options.  Tolerable, because
it's meant for testing.  If running with -compat fails, skip the test.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: John Snow <jsnow@redhat.com>
Message-Id: <20211028102520.747396-10-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Doc comments fixed up]
This commit is contained in:
Markus Armbruster 2021-10-28 12:25:20 +02:00
parent 7ce5fc63c7
commit 57df0dff1a
7 changed files with 51 additions and 12 deletions

View File

@ -13,6 +13,7 @@
typedef enum { typedef enum {
QAPI_DEPRECATED, QAPI_DEPRECATED,
QAPI_UNSTABLE,
} QapiSpecialFeature; } QapiSpecialFeature;
typedef struct QEnumLookup { typedef struct QEnumLookup {

View File

@ -47,9 +47,15 @@
# #
# @deprecated-input: how to handle deprecated input (default 'accept') # @deprecated-input: how to handle deprecated input (default 'accept')
# @deprecated-output: how to handle deprecated output (default 'accept') # @deprecated-output: how to handle deprecated output (default 'accept')
# @unstable-input: how to handle unstable input (default 'accept')
# (since 6.2)
# @unstable-output: how to handle unstable output (default 'accept')
# (since 6.2)
# #
# Since: 6.0 # Since: 6.0
## ##
{ 'struct': 'CompatPolicy', { 'struct': 'CompatPolicy',
'data': { '*deprecated-input': 'CompatPolicyInput', 'data': { '*deprecated-input': 'CompatPolicyInput',
'*deprecated-output': 'CompatPolicyOutput' } } '*deprecated-output': 'CompatPolicyOutput',
'*unstable-input': 'CompatPolicyInput',
'*unstable-output': 'CompatPolicyOutput' } }

View File

@ -49,6 +49,12 @@ bool compat_policy_input_ok(unsigned special_features,
error_class, kind, name, errp)) { error_class, kind, name, errp)) {
return false; return false;
} }
if ((special_features & (1u << QAPI_UNSTABLE))
&& !compat_policy_input_ok1("Unstable",
policy->unstable_input,
error_class, kind, name, errp)) {
return false;
}
return true; return true;
} }

View File

@ -212,8 +212,12 @@ static bool qobject_output_type_null(Visitor *v, const char *name,
static bool qobject_output_policy_skip(Visitor *v, const char *name, static bool qobject_output_policy_skip(Visitor *v, const char *name,
unsigned special_features) unsigned special_features)
{ {
return !(special_features & 1u << QAPI_DEPRECATED) CompatPolicy *pol = &v->compat_policy;
|| v->compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE;
return ((special_features & 1u << QAPI_DEPRECATED)
&& pol->deprecated_output == COMPAT_POLICY_OUTPUT_HIDE)
|| ((special_features & 1u << QAPI_UNSTABLE)
&& pol->unstable_output == COMPAT_POLICY_OUTPUT_HIDE);
} }
/* Finish building, and return the root object. /* Finish building, and return the root object.

View File

@ -3641,7 +3641,9 @@ DEFHEADING(Debug/Expert options:)
DEF("compat", HAS_ARG, QEMU_OPTION_compat, DEF("compat", HAS_ARG, QEMU_OPTION_compat,
"-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]\n" "-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]\n"
" Policy for handling deprecated management interfaces\n", " Policy for handling deprecated management interfaces\n"
"-compat [unstable-input=accept|reject|crash][,unstable-output=accept|hide]\n"
" Policy for handling unstable management interfaces\n",
QEMU_ARCH_ALL) QEMU_ARCH_ALL)
SRST SRST
``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]`` ``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]``
@ -3659,6 +3661,22 @@ SRST
Suppress deprecated command results and events Suppress deprecated command results and events
Limitation: covers only syntactic aspects of QMP. Limitation: covers only syntactic aspects of QMP.
``-compat [unstable-input=@var{input-policy}][,unstable-output=@var{output-policy}]``
Set policy for handling unstable management interfaces (experimental):
``unstable-input=accept`` (default)
Accept unstable commands and arguments
``unstable-input=reject``
Reject unstable commands and arguments
``unstable-input=crash``
Crash on unstable commands and arguments
``unstable-output=accept`` (default)
Emit unstable command results and events
``unstable-output=hide``
Suppress unstable command results and events
Limitation: covers only syntactic aspects of QMP.
ERST ERST
DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg, DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg,

View File

@ -109,13 +109,15 @@ def gen_event_send(name: str,
if not boxed: if not boxed:
ret += gen_param_var(arg_type) ret += gen_param_var(arg_type)
if 'deprecated' in [f.name for f in features]: for f in features:
ret += mcgen(''' if f.is_special():
ret += mcgen('''
if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { if (compat_policy.%(feat)s_output == COMPAT_POLICY_OUTPUT_HIDE) {
return; return;
} }
''') ''',
feat=f.name)
ret += mcgen(''' ret += mcgen('''

View File

@ -254,9 +254,11 @@ class QAPISchemaType(QAPISchemaEntity):
def check(self, schema): def check(self, schema):
QAPISchemaEntity.check(self, schema) QAPISchemaEntity.check(self, schema)
if 'deprecated' in [f.name for f in self.features]: for feat in self.features:
raise QAPISemError( if feat.is_special():
self.info, "feature 'deprecated' is not supported for types") raise QAPISemError(
self.info,
f"feature '{feat.name}' is not supported for types")
def describe(self): def describe(self):
assert self.meta assert self.meta
@ -726,7 +728,7 @@ class QAPISchemaFeature(QAPISchemaMember):
role = 'feature' role = 'feature'
def is_special(self): def is_special(self):
return self.name in ('deprecated') return self.name in ('deprecated', 'unstable')
class QAPISchemaObjectTypeMember(QAPISchemaMember): class QAPISchemaObjectTypeMember(QAPISchemaMember):