From 9bafe07bc8b00ce9ba5ea6f4c590239c579d83ee Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:14 +0200 Subject: qapi: Eliminate QCO_NO_OPTIONS for a slight simplification Signed-off-by: Markus Armbruster Reviewed-by: Juan Quintela Reviewed-by: John Snow Message-Id: <20211028102520.747396-4-armbru@redhat.com> --- scripts/qapi/commands.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 3654825..c8a9755 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -229,15 +229,12 @@ def gen_register_command(name: str, if coroutine: options += ['QCO_COROUTINE'] - if not options: - options = ['QCO_NO_OPTIONS'] - ret = mcgen(''' qmp_register_command(cmds, "%(name)s", qmp_marshal_%(c_name)s, %(opts)s); ''', name=name, c_name=c_name(name), - opts=" | ".join(options)) + opts=' | '.join(options) or 0) return ret -- cgit v1.1 From c67db1ed16ff5a7c1b186caa754e0c738aa945b8 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:15 +0200 Subject: qapi: Tools for sets of special feature flags in generated code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New enum QapiSpecialFeature enumerates the special feature flags. New helper gen_special_features() returns code to represent a collection of special feature flags as a bitset. The next few commits will put them to use. Signed-off-by: Markus Armbruster Reviewed-by: John Snow Message-Id: <20211028102520.747396-5-armbru@redhat.com> Reviewed-by: Juan Quintela Reviewed-by: Philippe Mathieu-Daudé --- scripts/qapi/gen.py | 8 ++++++++ scripts/qapi/schema.py | 3 +++ 2 files changed, 11 insertions(+) (limited to 'scripts') diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py index 2ec1e7b..995a97d 100644 --- a/scripts/qapi/gen.py +++ b/scripts/qapi/gen.py @@ -18,6 +18,7 @@ from typing import ( Dict, Iterator, Optional, + Sequence, Tuple, ) @@ -29,6 +30,7 @@ from .common import ( mcgen, ) from .schema import ( + QAPISchemaFeature, QAPISchemaIfCond, QAPISchemaModule, QAPISchemaObjectType, @@ -37,6 +39,12 @@ from .schema import ( from .source import QAPISourceInfo +def gen_special_features(features: Sequence[QAPISchemaFeature]) -> str: + special_features = [f"1u << QAPI_{feat.name.upper()}" + for feat in features if feat.is_special()] + return ' | '.join(special_features) or '0' + + class QAPIGen: def __init__(self, fname: str): self.fname = fname diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 6d5f465..55f82d7 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -725,6 +725,9 @@ class QAPISchemaEnumMember(QAPISchemaMember): class QAPISchemaFeature(QAPISchemaMember): role = 'feature' + def is_special(self): + return self.name in ('deprecated') + class QAPISchemaObjectTypeMember(QAPISchemaMember): def __init__(self, name, info, typ, optional, ifcond=None, features=None): -- cgit v1.1 From a130728554d0cc19ef0ed4c1c824305c1682e64b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:16 +0200 Subject: qapi: Generalize struct member policy checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated visitor functions call visit_deprecated_accept() and visit_deprecated() when visiting a struct member with special feature flag 'deprecated'. This makes the feature flag visible to the actual visitors. I want to make feature flag 'unstable' visible there as well, so I can add policy for it. To let me make it visible, replace these functions by visit_policy_reject() and visit_policy_skip(), which take the member's special features as an argument. Note that the new functions have the opposite sense, i.e. the return value flips. Signed-off-by: Markus Armbruster Message-Id: <20211028102520.747396-6-armbru@redhat.com> Reviewed-by: Juan Quintela Reviewed-by: Philippe Mathieu-Daudé [Unbreak forward visitor] --- scripts/qapi/visit.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 9d9196a..e13bbe4 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -21,7 +21,7 @@ from .common import ( indent, mcgen, ) -from .gen import QAPISchemaModularCVisitor, ifcontext +from .gen import QAPISchemaModularCVisitor, gen_special_features, ifcontext from .schema import ( QAPISchema, QAPISchemaEnumMember, @@ -76,7 +76,6 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) c_type=base.c_name()) for memb in members: - deprecated = 'deprecated' in [f.name for f in memb.features] ret += memb.ifcond.gen_if() if memb.optional: ret += mcgen(''' @@ -84,14 +83,15 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) ''', name=memb.name, c_name=c_name(memb.name)) indent.increase() - if deprecated: + special_features = gen_special_features(memb.features) + if special_features != '0': ret += mcgen(''' - if (!visit_deprecated_accept(v, "%(name)s", errp)) { + if (visit_policy_reject(v, "%(name)s", %(special_features)s, errp)) { return false; } - if (visit_deprecated(v, "%(name)s")) { + if (!visit_policy_skip(v, "%(name)s", %(special_features)s)) { ''', - name=memb.name) + name=memb.name, special_features=special_features) indent.increase() ret += mcgen(''' if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { @@ -100,7 +100,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) ''', c_type=memb.type.c_name(), name=memb.name, c_name=c_name(memb.name)) - if deprecated: + if special_features != '0': indent.decrease() ret += mcgen(''' } -- cgit v1.1 From 6604e4757a1fc5832f87b5f9244efccabb49be8e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:17 +0200 Subject: qapi: Generalize command policy checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code to check command policy can see special feature flag 'deprecated' as command flag QCO_DEPRECATED. I want to make feature flag 'unstable' visible there as well, so I can add policy for it. To let me make it visible, add member @special_features (a bitset of QapiSpecialFeature) to QmpCommand, and adjust the generator to pass it through qmp_register_command(). Then replace "QCO_DEPRECATED in @flags" by QAPI_DEPRECATED in @special_features", and drop QCO_DEPRECATED. Signed-off-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Acked-by: John Snow Message-Id: <20211028102520.747396-7-armbru@redhat.com> Reviewed-by: Juan Quintela Reviewed-by: Eric Blake --- scripts/qapi/commands.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index c8a9755..21001bb 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -26,6 +26,7 @@ from .gen import ( QAPISchemaModularCVisitor, build_params, ifcontext, + gen_special_features, ) from .schema import ( QAPISchema, @@ -217,9 +218,6 @@ def gen_register_command(name: str, coroutine: bool) -> str: options = [] - if 'deprecated' in [f.name for f in features]: - options += ['QCO_DEPRECATED'] - if not success_response: options += ['QCO_NO_SUCCESS_RESP'] if allow_oob: @@ -231,10 +229,11 @@ def gen_register_command(name: str, ret = mcgen(''' qmp_register_command(cmds, "%(name)s", - qmp_marshal_%(c_name)s, %(opts)s); + qmp_marshal_%(c_name)s, %(opts)s, %(feats)s); ''', name=name, c_name=c_name(name), - opts=' | '.join(options) or 0) + opts=' | '.join(options) or 0, + feats=gen_special_features(features)) return ret -- cgit v1.1 From c8688760437aaf4bfa9012ff5aef8ab1c92a38e1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:18 +0200 Subject: qapi: Generalize enum member policy checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code to check enumeration value policy can see special feature flag 'deprecated' in QEnumLookup member flags[value]. I want to make feature flag 'unstable' visible there as well, so I can add policy for it. Instead of extending flags[], replace it by @special_features (a bitset of QapiSpecialFeature), because that's how special features get passed around elsewhere. Signed-off-by: Markus Armbruster Acked-by: John Snow Message-Id: <20211028102520.747396-8-armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé --- scripts/qapi/types.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index ab2441a..3013329 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -16,7 +16,7 @@ This work is licensed under the terms of the GNU GPL, version 2. from typing import List, Optional from .common import c_enum_const, c_name, mcgen -from .gen import QAPISchemaModularCVisitor, ifcontext +from .gen import QAPISchemaModularCVisitor, gen_special_features, ifcontext from .schema import ( QAPISchema, QAPISchemaEnumMember, @@ -39,7 +39,7 @@ def gen_enum_lookup(name: str, members: List[QAPISchemaEnumMember], prefix: Optional[str] = None) -> str: max_index = c_enum_const(name, '_MAX', prefix) - flags = '' + feats = '' ret = mcgen(''' const QEnumLookup %(c_name)s_lookup = { @@ -54,19 +54,21 @@ const QEnumLookup %(c_name)s_lookup = { ''', index=index, name=memb.name) ret += memb.ifcond.gen_endif() - if 'deprecated' in (f.name for f in memb.features): - flags += mcgen(''' - [%(index)s] = QAPI_ENUM_DEPRECATED, + + special_features = gen_special_features(memb.features) + if special_features != '0': + feats += mcgen(''' + [%(index)s] = %(special_features)s, ''', - index=index) + index=index, special_features=special_features) - if flags: + if feats: ret += mcgen(''' }, - .flags = (const unsigned char[%(max_index)s]) { + .special_features = (const unsigned char[%(max_index)s]) { ''', max_index=max_index) - ret += flags + ret += feats ret += mcgen(''' }, -- cgit v1.1 From 57df0dff1a1f4c846aa74a082bfd595a8a990015 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 28 Oct 2021 12:25:20 +0200 Subject: 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 Acked-by: John Snow Message-Id: <20211028102520.747396-10-armbru@redhat.com> Reviewed-by: Eric Blake [Doc comments fixed up] --- scripts/qapi/events.py | 10 ++++++---- scripts/qapi/schema.py | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index 82475e8..27b44c4 100644 --- a/scripts/qapi/events.py +++ b/scripts/qapi/events.py @@ -109,13 +109,15 @@ def gen_event_send(name: str, if not boxed: ret += gen_param_var(arg_type) - if 'deprecated' in [f.name for f in features]: - ret += mcgen(''' + for f in features: + 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; } -''') +''', + feat=f.name) ret += mcgen(''' diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 55f82d7..b7b3fc0 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -254,9 +254,11 @@ class QAPISchemaType(QAPISchemaEntity): def check(self, schema): QAPISchemaEntity.check(self, schema) - if 'deprecated' in [f.name for f in self.features]: - raise QAPISemError( - self.info, "feature 'deprecated' is not supported for types") + for feat in self.features: + if feat.is_special(): + raise QAPISemError( + self.info, + f"feature '{feat.name}' is not supported for types") def describe(self): assert self.meta @@ -726,7 +728,7 @@ class QAPISchemaFeature(QAPISchemaMember): role = 'feature' def is_special(self): - return self.name in ('deprecated') + return self.name in ('deprecated', 'unstable') class QAPISchemaObjectTypeMember(QAPISchemaMember): -- cgit v1.1