mirror of https://github.com/xemu-project/xemu.git
QAPI patches patches for 2021-10-29
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmF8S3USHGFybWJydUBy ZWRoYXQuY29tAAoJEDhwtADrkYZTkfQP/34UaR77wfOvemMBCY7CX/AD6KsJTt2v /mVJ8kUC+aJdyDa1orhDxLxyvx0YxSUjDUoTVGrb/CO8eM8dL4Lz6jCi1OiBCaBq JJAtUduaLDUUfZnKwrvhW0cGZeJ02eqxIKhV/9BFcFSr0fAzZRnF1RwsNBO/AqCr 082bimWttsBpnNqnbWFK8uZYHMskbPOoXxklIMDM48BJhb6EOdH1/wZpeGdTUMIN zBTOynZW52xrDdlngo3UBr+uyDX8mjnwMOmpSa5YgkQselxDK172xZm31VQUMtGz S2qNCxxKf4J/wJMLElo0z3nEUUEFrpZzqifO1gsDit4eWexL35BHCdlRbB07iJ/+ V0wtF2M+KQGhoqLJTvlVlymRAeC3ItHHDgh9qs3nS7w9w13oGuB7xo8Po5PfKpc3 vT2XBYy8LPHLQ7/82nQGQdXkd1OB/8fwJt0bcPc+UIGAhNrwpSmCoO0ugqU2OD+C NJs6R3y1bbJnQGG5f3M/QU/dF0zYVpHv6a+QWFwwV+rc2RAjeeMrSYH+08t1c5+u Qh2P8YvgRPQxPmg9Rbqfcxq7CwVs0iZINfjmLwofbqBQUZUAq3phHRtJ9bmGbXkC pC4B+d76kefSxqlVNwi95Zg+CCURT8QzamKVlkZ/GNP73+orV9yQvA0aR4J2arLV 1QVm4jTqAqIo =HKnl -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-10-29' into staging QAPI patches patches for 2021-10-29 # gpg: Signature made Fri 29 Oct 2021 12:28:53 PM PDT # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] * remotes/armbru/tags/pull-qapi-2021-10-29: qapi: Extend -compat to set policy for unstable interfaces qapi: Factor out compat_policy_input_ok() qapi: Generalize enum member policy checking qapi: Generalize command policy checking qapi: Generalize struct member policy checking qapi: Tools for sets of special feature flags in generated code qapi: Eliminate QCO_NO_OPTIONS for a slight simplification qapi: Mark unstable QMP parts with feature 'unstable' qapi: New special feature flag "unstable" Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
dd61b91c08
|
@ -713,6 +713,10 @@ member as deprecated. It is not supported elsewhere so far.
|
|||
Interfaces so marked may be withdrawn in future releases in accordance
|
||||
with QEMU's deprecation policy.
|
||||
|
||||
Feature "unstable" marks a command, event, enum value, or struct
|
||||
member as unstable. It is not supported elsewhere so far. Interfaces
|
||||
so marked may be withdrawn or changed incompatibly in future releases.
|
||||
|
||||
|
||||
Naming rules and reserved names
|
||||
-------------------------------
|
||||
|
@ -746,9 +750,8 @@ Member name ``u`` and names starting with ``has-`` or ``has_`` are reserved
|
|||
for the generator, which uses them for unions and for tracking
|
||||
optional members.
|
||||
|
||||
Any name (command, event, type, member, or enum value) beginning with
|
||||
``x-`` is marked experimental, and may be withdrawn or changed
|
||||
incompatibly in a future release.
|
||||
Names beginning with ``x-`` used to signify "experimental". This
|
||||
convention has been replaced by special feature "unstable".
|
||||
|
||||
Pragmas ``command-name-exceptions`` and ``member-name-exceptions`` let
|
||||
you violate naming rules. Use for new code is strongly discouraged. See
|
||||
|
|
|
@ -13,10 +13,17 @@
|
|||
#ifndef QAPI_COMPAT_POLICY_H
|
||||
#define QAPI_COMPAT_POLICY_H
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-types-compat.h"
|
||||
|
||||
extern CompatPolicy compat_policy;
|
||||
|
||||
bool compat_policy_input_ok(unsigned special_features,
|
||||
const CompatPolicy *policy,
|
||||
ErrorClass error_class,
|
||||
const char *kind, const char *name,
|
||||
Error **errp);
|
||||
|
||||
/*
|
||||
* Create a QObject input visitor for @obj for use with QMP
|
||||
*
|
||||
|
|
|
@ -21,12 +21,10 @@ typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
|
|||
|
||||
typedef enum QmpCommandOptions
|
||||
{
|
||||
QCO_NO_OPTIONS = 0x0,
|
||||
QCO_NO_SUCCESS_RESP = (1U << 0),
|
||||
QCO_ALLOW_OOB = (1U << 1),
|
||||
QCO_ALLOW_PRECONFIG = (1U << 2),
|
||||
QCO_COROUTINE = (1U << 3),
|
||||
QCO_DEPRECATED = (1U << 4),
|
||||
} QmpCommandOptions;
|
||||
|
||||
typedef struct QmpCommand
|
||||
|
@ -35,6 +33,7 @@ typedef struct QmpCommand
|
|||
/* Runs in coroutine context if QCO_COROUTINE is set */
|
||||
QmpCommandFunc *fn;
|
||||
QmpCommandOptions options;
|
||||
unsigned special_features;
|
||||
QTAILQ_ENTRY(QmpCommand) node;
|
||||
bool enabled;
|
||||
const char *disable_reason;
|
||||
|
@ -43,7 +42,8 @@ typedef struct QmpCommand
|
|||
typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;
|
||||
|
||||
void qmp_register_command(QmpCommandList *cmds, const char *name,
|
||||
QmpCommandFunc *fn, QmpCommandOptions options);
|
||||
QmpCommandFunc *fn, QmpCommandOptions options,
|
||||
unsigned special_features);
|
||||
const QmpCommand *qmp_find_command(const QmpCommandList *cmds,
|
||||
const char *name);
|
||||
void qmp_disable_command(QmpCommandList *cmds, const char *name,
|
||||
|
|
|
@ -11,12 +11,14 @@
|
|||
#ifndef QAPI_UTIL_H
|
||||
#define QAPI_UTIL_H
|
||||
|
||||
/* QEnumLookup flags */
|
||||
#define QAPI_ENUM_DEPRECATED 1
|
||||
typedef enum {
|
||||
QAPI_DEPRECATED,
|
||||
QAPI_UNSTABLE,
|
||||
} QapiSpecialFeature;
|
||||
|
||||
typedef struct QEnumLookup {
|
||||
const char *const *array;
|
||||
const unsigned char *const flags;
|
||||
const unsigned char *const special_features;
|
||||
const int size;
|
||||
} QEnumLookup;
|
||||
|
||||
|
|
|
@ -114,10 +114,12 @@ struct Visitor
|
|||
void (*optional)(Visitor *v, const char *name, bool *present);
|
||||
|
||||
/* Optional */
|
||||
bool (*deprecated_accept)(Visitor *v, const char *name, Error **errp);
|
||||
bool (*policy_reject)(Visitor *v, const char *name,
|
||||
unsigned special_features, Error **errp);
|
||||
|
||||
/* Optional */
|
||||
bool (*deprecated)(Visitor *v, const char *name);
|
||||
bool (*policy_skip)(Visitor *v, const char *name,
|
||||
unsigned special_features);
|
||||
|
||||
/* Must be set */
|
||||
VisitorType type;
|
||||
|
|
|
@ -461,22 +461,31 @@ void visit_end_alternate(Visitor *v, void **obj);
|
|||
bool visit_optional(Visitor *v, const char *name, bool *present);
|
||||
|
||||
/*
|
||||
* Should we reject deprecated member @name?
|
||||
* Should we reject member @name due to policy?
|
||||
*
|
||||
* @special_features is the member's special features encoded as a
|
||||
* bitset of QapiSpecialFeature.
|
||||
*
|
||||
* @name must not be NULL. This function is only useful between
|
||||
* visit_start_struct() and visit_end_struct(), since only objects
|
||||
* have deprecated members.
|
||||
*/
|
||||
bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp);
|
||||
bool visit_policy_reject(Visitor *v, const char *name,
|
||||
unsigned special_features, Error **errp);
|
||||
|
||||
/*
|
||||
* Should we visit deprecated member @name?
|
||||
*
|
||||
* Should we skip member @name due to policy?
|
||||
*
|
||||
* @special_features is the member's special features encoded as a
|
||||
* bitset of QapiSpecialFeature.
|
||||
*
|
||||
* @name must not be NULL. This function is only useful between
|
||||
* visit_start_struct() and visit_end_struct(), since only objects
|
||||
* have deprecated members.
|
||||
*/
|
||||
bool visit_deprecated(Visitor *v, const char *name);
|
||||
bool visit_policy_skip(Visitor *v, const char *name,
|
||||
unsigned special_features);
|
||||
|
||||
/*
|
||||
* Set policy for handling deprecated management interfaces.
|
||||
|
|
|
@ -230,12 +230,13 @@ static void monitor_init_qmp_commands(void)
|
|||
|
||||
qmp_init_marshal(&qmp_commands);
|
||||
|
||||
qmp_register_command(&qmp_commands, "device_add", qmp_device_add,
|
||||
QCO_NO_OPTIONS);
|
||||
qmp_register_command(&qmp_commands, "device_add",
|
||||
qmp_device_add, 0, 0);
|
||||
|
||||
QTAILQ_INIT(&qmp_cap_negotiation_commands);
|
||||
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
|
||||
qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
|
||||
qmp_marshal_qmp_capabilities,
|
||||
QCO_ALLOW_PRECONFIG, 0);
|
||||
}
|
||||
|
||||
/* Set the current CPU defined by the user. Callers must hold BQL. */
|
||||
|
|
|
@ -1438,6 +1438,9 @@
|
|||
#
|
||||
# @x-perf: Performance options. (Since 6.0)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-perf is experimental.
|
||||
#
|
||||
# Note: @on-source-error and @on-target-error only affect background
|
||||
# I/O. If an error occurs during a guest write request, the device's
|
||||
# rerror/werror actions will be used.
|
||||
|
@ -1452,7 +1455,9 @@
|
|||
'*on-source-error': 'BlockdevOnError',
|
||||
'*on-target-error': 'BlockdevOnError',
|
||||
'*auto-finalize': 'bool', '*auto-dismiss': 'bool',
|
||||
'*filter-node-name': 'str', '*x-perf': 'BackupPerf' } }
|
||||
'*filter-node-name': 'str',
|
||||
'*x-perf': { 'type': 'BackupPerf',
|
||||
'features': [ 'unstable' ] } } }
|
||||
|
||||
##
|
||||
# @DriveBackup:
|
||||
|
@ -1916,9 +1921,13 @@
|
|||
#
|
||||
# Get the block graph.
|
||||
#
|
||||
# Features:
|
||||
# @unstable: This command is meant for debugging.
|
||||
#
|
||||
# Since: 4.0
|
||||
##
|
||||
{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph' }
|
||||
{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph',
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @drive-mirror:
|
||||
|
@ -2257,6 +2266,9 @@
|
|||
#
|
||||
# Get bitmap SHA256.
|
||||
#
|
||||
# Features:
|
||||
# @unstable: This command is meant for debugging.
|
||||
#
|
||||
# Returns: - BlockDirtyBitmapSha256 on success
|
||||
# - If @node is not a valid block device, DeviceNotFound
|
||||
# - If @name is not found or if hashing has failed, GenericError with an
|
||||
|
@ -2265,7 +2277,8 @@
|
|||
# Since: 2.10
|
||||
##
|
||||
{ 'command': 'x-debug-block-dirty-bitmap-sha256',
|
||||
'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' }
|
||||
'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256',
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @blockdev-mirror:
|
||||
|
@ -2495,27 +2508,57 @@
|
|||
#
|
||||
# Properties for throttle-group objects.
|
||||
#
|
||||
# The options starting with x- are aliases for the same key without x- in
|
||||
# the @limits object. As indicated by the x- prefix, this is not a stable
|
||||
# interface and may be removed or changed incompatibly in the future. Use
|
||||
# @limits for a supported stable interface.
|
||||
#
|
||||
# @limits: limits to apply for this throttle group
|
||||
#
|
||||
# Features:
|
||||
# @unstable: All members starting with x- are aliases for the same key
|
||||
# without x- in the @limits object. This is not a stable
|
||||
# interface and may be removed or changed incompatibly in
|
||||
# the future. Use @limits for a supported stable
|
||||
# interface.
|
||||
#
|
||||
# Since: 2.11
|
||||
##
|
||||
{ 'struct': 'ThrottleGroupProperties',
|
||||
'data': { '*limits': 'ThrottleLimits',
|
||||
'*x-iops-total' : 'int', '*x-iops-total-max' : 'int',
|
||||
'*x-iops-total-max-length' : 'int', '*x-iops-read' : 'int',
|
||||
'*x-iops-read-max' : 'int', '*x-iops-read-max-length' : 'int',
|
||||
'*x-iops-write' : 'int', '*x-iops-write-max' : 'int',
|
||||
'*x-iops-write-max-length' : 'int', '*x-bps-total' : 'int',
|
||||
'*x-bps-total-max' : 'int', '*x-bps-total-max-length' : 'int',
|
||||
'*x-bps-read' : 'int', '*x-bps-read-max' : 'int',
|
||||
'*x-bps-read-max-length' : 'int', '*x-bps-write' : 'int',
|
||||
'*x-bps-write-max' : 'int', '*x-bps-write-max-length' : 'int',
|
||||
'*x-iops-size' : 'int' } }
|
||||
'*x-iops-total': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-total-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-total-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-read': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-read-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-read-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-write': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-write-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-write-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-total': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-total-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-total-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-read': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-read-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-read-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-write': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-write-max': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-bps-write-max-length': { 'type': 'int',
|
||||
'features': [ 'unstable' ] },
|
||||
'*x-iops-size': { 'type': 'int',
|
||||
'features': [ 'unstable' ] } } }
|
||||
|
||||
##
|
||||
# @block-stream:
|
||||
|
@ -2916,6 +2959,7 @@
|
|||
# read-only when the last writer is detached. This
|
||||
# allows giving QEMU write permissions only on demand
|
||||
# when an operation actually needs write access.
|
||||
# @unstable: Member x-check-cache-dropped is meant for debugging.
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
|
@ -2926,7 +2970,8 @@
|
|||
'*aio': 'BlockdevAioOptions',
|
||||
'*drop-cache': {'type': 'bool',
|
||||
'if': 'CONFIG_LINUX'},
|
||||
'*x-check-cache-dropped': 'bool' },
|
||||
'*x-check-cache-dropped': { 'type': 'bool',
|
||||
'features': [ 'unstable' ] } },
|
||||
'features': [ { 'name': 'dynamic-auto-read-only',
|
||||
'if': 'CONFIG_POSIX' } ] }
|
||||
|
||||
|
@ -4041,13 +4086,16 @@
|
|||
# future requests before a successful reconnect will
|
||||
# immediately fail. Default 0 (Since 4.2)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-dirty-bitmap is experimental.
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsNbd',
|
||||
'data': { 'server': 'SocketAddress',
|
||||
'*export': 'str',
|
||||
'*tls-creds': 'str',
|
||||
'*x-dirty-bitmap': 'str',
|
||||
'*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] },
|
||||
'*reconnect-delay': 'uint32' } }
|
||||
|
||||
##
|
||||
|
@ -4865,13 +4913,17 @@
|
|||
# and replacement of an active keyslot
|
||||
# (possible loss of data if IO error happens)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: This command is experimental.
|
||||
#
|
||||
# Since: 5.1
|
||||
##
|
||||
{ 'command': 'x-blockdev-amend',
|
||||
'data': { 'job-id': 'str',
|
||||
'node-name': 'str',
|
||||
'options': 'BlockdevAmendOptions',
|
||||
'*force': 'bool' } }
|
||||
'*force': 'bool' },
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @BlockErrorAction:
|
||||
|
@ -5242,16 +5294,18 @@
|
|||
#
|
||||
# @node: the name of the node that will be added.
|
||||
#
|
||||
# Note: this command is experimental, and its API is not stable. It
|
||||
# does not support all kinds of operations, all kinds of children, nor
|
||||
# all block drivers.
|
||||
# Features:
|
||||
# @unstable: This command is experimental, and its API is not stable. It
|
||||
# does not support all kinds of operations, all kinds of
|
||||
# children, nor all block drivers.
|
||||
#
|
||||
# FIXME Removing children from a quorum node means introducing gaps in the
|
||||
# child indices. This cannot be represented in the 'children' list of
|
||||
# BlockdevOptionsQuorum, as returned by .bdrv_refresh_filename().
|
||||
# FIXME Removing children from a quorum node means introducing
|
||||
# gaps in the child indices. This cannot be represented in the
|
||||
# 'children' list of BlockdevOptionsQuorum, as returned by
|
||||
# .bdrv_refresh_filename().
|
||||
#
|
||||
# Warning: The data in a new quorum child MUST be consistent with that of
|
||||
# the rest of the array.
|
||||
# Warning: The data in a new quorum child MUST be consistent
|
||||
# with that of the rest of the array.
|
||||
#
|
||||
# Since: 2.7
|
||||
#
|
||||
|
@ -5280,7 +5334,8 @@
|
|||
{ 'command': 'x-blockdev-change',
|
||||
'data' : { 'parent': 'str',
|
||||
'*child': 'str',
|
||||
'*node': 'str' } }
|
||||
'*node': 'str' },
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @x-blockdev-set-iothread:
|
||||
|
@ -5297,8 +5352,9 @@
|
|||
# @force: true if the node and its children should be moved when a BlockBackend
|
||||
# is already attached
|
||||
#
|
||||
# Note: this command is experimental and intended for test cases that need
|
||||
# control over IOThreads only.
|
||||
# Features:
|
||||
# @unstable: This command is experimental and intended for test cases that
|
||||
# need control over IOThreads only.
|
||||
#
|
||||
# Since: 2.12
|
||||
#
|
||||
|
@ -5320,7 +5376,8 @@
|
|||
{ 'command': 'x-blockdev-set-iothread',
|
||||
'data' : { 'node-name': 'str',
|
||||
'iothread': 'StrOrNull',
|
||||
'*force': 'bool' } }
|
||||
'*force': 'bool' },
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @QuorumOpType:
|
||||
|
|
|
@ -47,9 +47,15 @@
|
|||
#
|
||||
# @deprecated-input: how to handle deprecated input (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
|
||||
##
|
||||
{ 'struct': 'CompatPolicy',
|
||||
'data': { '*deprecated-input': 'CompatPolicyInput',
|
||||
'*deprecated-output': 'CompatPolicyOutput' } }
|
||||
'*deprecated-output': 'CompatPolicyOutput',
|
||||
'*unstable-input': 'CompatPolicyInput',
|
||||
'*unstable-output': 'CompatPolicyOutput' } }
|
||||
|
|
|
@ -452,14 +452,20 @@
|
|||
# procedure starts. The VM RAM is saved with running VM.
|
||||
# (since 6.0)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Members @x-colo and @x-ignore-shared are experimental.
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'enum': 'MigrationCapability',
|
||||
'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
|
||||
'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',
|
||||
'compress', 'events', 'postcopy-ram',
|
||||
{ 'name': 'x-colo', 'features': [ 'unstable' ] },
|
||||
'release-ram',
|
||||
'block', 'return-path', 'pause-before-switchover', 'multifd',
|
||||
'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
|
||||
'x-ignore-shared', 'validate-uuid', 'background-snapshot'] }
|
||||
{ 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
|
||||
'validate-uuid', 'background-snapshot'] }
|
||||
|
||||
##
|
||||
# @MigrationCapabilityStatus:
|
||||
|
@ -743,6 +749,9 @@
|
|||
# block device name if there is one, and to their node name
|
||||
# otherwise. (Since 5.2)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-checkpoint-delay is experimental.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'enum': 'MigrationParameter',
|
||||
|
@ -753,7 +762,9 @@
|
|||
'cpu-throttle-initial', 'cpu-throttle-increment',
|
||||
'cpu-throttle-tailslow',
|
||||
'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth',
|
||||
'downtime-limit', 'x-checkpoint-delay', 'block-incremental',
|
||||
'downtime-limit',
|
||||
{ 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] },
|
||||
'block-incremental',
|
||||
'multifd-channels',
|
||||
'xbzrle-cache-size', 'max-postcopy-bandwidth',
|
||||
'max-cpu-throttle', 'multifd-compression',
|
||||
|
@ -903,6 +914,9 @@
|
|||
# block device name if there is one, and to their node name
|
||||
# otherwise. (Since 5.2)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-checkpoint-delay is experimental.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
# TODO either fuse back into MigrationParameters, or make
|
||||
|
@ -925,7 +939,8 @@
|
|||
'*tls-authz': 'StrOrNull',
|
||||
'*max-bandwidth': 'size',
|
||||
'*downtime-limit': 'uint64',
|
||||
'*x-checkpoint-delay': 'uint32',
|
||||
'*x-checkpoint-delay': { 'type': 'uint32',
|
||||
'features': [ 'unstable' ] },
|
||||
'*block-incremental': 'bool',
|
||||
'*multifd-channels': 'uint8',
|
||||
'*xbzrle-cache-size': 'size',
|
||||
|
@ -1099,6 +1114,9 @@
|
|||
# block device name if there is one, and to their node name
|
||||
# otherwise. (Since 5.2)
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-checkpoint-delay is experimental.
|
||||
#
|
||||
# Since: 2.4
|
||||
##
|
||||
{ 'struct': 'MigrationParameters',
|
||||
|
@ -1119,7 +1137,8 @@
|
|||
'*tls-authz': 'str',
|
||||
'*max-bandwidth': 'size',
|
||||
'*downtime-limit': 'uint64',
|
||||
'*x-checkpoint-delay': 'uint32',
|
||||
'*x-checkpoint-delay': { 'type': 'uint32',
|
||||
'features': [ 'unstable' ] },
|
||||
'*block-incremental': 'bool',
|
||||
'*multifd-channels': 'uint8',
|
||||
'*xbzrle-cache-size': 'size',
|
||||
|
@ -1351,6 +1370,9 @@
|
|||
# If sent to the Secondary, the Secondary side will run failover work,
|
||||
# then takes over server operation to become the service VM.
|
||||
#
|
||||
# Features:
|
||||
# @unstable: This command is experimental.
|
||||
#
|
||||
# Since: 2.8
|
||||
#
|
||||
# Example:
|
||||
|
@ -1359,7 +1381,8 @@
|
|||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'x-colo-lost-heartbeat' }
|
||||
{ 'command': 'x-colo-lost-heartbeat',
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @migrate_cancel:
|
||||
|
|
|
@ -185,6 +185,9 @@
|
|||
# available during the preconfig state (i.e. when the --preconfig command
|
||||
# line option was in use).
|
||||
#
|
||||
# Features:
|
||||
# @unstable: This command is experimental.
|
||||
#
|
||||
# Since 3.0
|
||||
#
|
||||
# Returns: nothing
|
||||
|
@ -195,7 +198,8 @@
|
|||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'x-exit-preconfig', 'allow-preconfig': true }
|
||||
{ 'command': 'x-exit-preconfig', 'allow-preconfig': true,
|
||||
'features': [ 'unstable' ] }
|
||||
|
||||
##
|
||||
# @human-monitor-command:
|
||||
|
|
|
@ -246,25 +246,27 @@ static void forward_field_optional(Visitor *v, const char *name, bool *present)
|
|||
visit_optional(ffv->target, name, present);
|
||||
}
|
||||
|
||||
static bool forward_field_deprecated_accept(Visitor *v, const char *name,
|
||||
Error **errp)
|
||||
static bool forward_field_policy_reject(Visitor *v, const char *name,
|
||||
unsigned special_features,
|
||||
Error **errp)
|
||||
{
|
||||
ForwardFieldVisitor *ffv = to_ffv(v);
|
||||
|
||||
if (!forward_field_translate_name(ffv, &name, errp)) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return visit_deprecated_accept(ffv->target, name, errp);
|
||||
return visit_policy_reject(ffv->target, name, special_features, errp);
|
||||
}
|
||||
|
||||
static bool forward_field_deprecated(Visitor *v, const char *name)
|
||||
static bool forward_field_policy_skip(Visitor *v, const char *name,
|
||||
unsigned special_features)
|
||||
{
|
||||
ForwardFieldVisitor *ffv = to_ffv(v);
|
||||
|
||||
if (!forward_field_translate_name(ffv, &name, NULL)) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return visit_deprecated(ffv->target, name);
|
||||
return visit_policy_skip(ffv->target, name, special_features);
|
||||
}
|
||||
|
||||
static void forward_field_complete(Visitor *v, void *opaque)
|
||||
|
@ -313,8 +315,8 @@ Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to
|
|||
v->visitor.type_any = forward_field_type_any;
|
||||
v->visitor.type_null = forward_field_type_null;
|
||||
v->visitor.optional = forward_field_optional;
|
||||
v->visitor.deprecated_accept = forward_field_deprecated_accept;
|
||||
v->visitor.deprecated = forward_field_deprecated;
|
||||
v->visitor.policy_reject = forward_field_policy_reject;
|
||||
v->visitor.policy_skip = forward_field_policy_skip;
|
||||
v->visitor.complete = forward_field_complete;
|
||||
v->visitor.free = forward_field_free;
|
||||
|
||||
|
|
|
@ -11,10 +11,53 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/ctype.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
||||
CompatPolicy compat_policy;
|
||||
|
||||
static bool compat_policy_input_ok1(const char *adjective,
|
||||
CompatPolicyInput policy,
|
||||
ErrorClass error_class,
|
||||
const char *kind, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
switch (policy) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
return true;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
error_set(errp, error_class, "%s %s %s disabled by policy",
|
||||
adjective, kind, name);
|
||||
return false;
|
||||
case COMPAT_POLICY_INPUT_CRASH:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool compat_policy_input_ok(unsigned special_features,
|
||||
const CompatPolicy *policy,
|
||||
ErrorClass error_class,
|
||||
const char *kind, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
if ((special_features & 1u << QAPI_DEPRECATED)
|
||||
&& !compat_policy_input_ok1("Deprecated",
|
||||
policy->deprecated_input,
|
||||
error_class, kind, name, errp)) {
|
||||
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;
|
||||
}
|
||||
|
||||
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
|
||||
{
|
||||
assert(val >= 0 && val < lookup->size);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
@ -139,22 +140,24 @@ bool visit_optional(Visitor *v, const char *name, bool *present)
|
|||
return *present;
|
||||
}
|
||||
|
||||
bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp)
|
||||
bool visit_policy_reject(Visitor *v, const char *name,
|
||||
unsigned special_features, Error **errp)
|
||||
{
|
||||
trace_visit_deprecated_accept(v, name);
|
||||
if (v->deprecated_accept) {
|
||||
return v->deprecated_accept(v, name, errp);
|
||||
trace_visit_policy_reject(v, name);
|
||||
if (v->policy_reject) {
|
||||
return v->policy_reject(v, name, special_features, errp);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit_deprecated(Visitor *v, const char *name)
|
||||
bool visit_policy_skip(Visitor *v, const char *name,
|
||||
unsigned special_features)
|
||||
{
|
||||
trace_visit_deprecated(v, name);
|
||||
if (v->deprecated) {
|
||||
return v->deprecated(v, name);
|
||||
trace_visit_policy_skip(v, name);
|
||||
if (v->policy_skip) {
|
||||
return v->policy_skip(v, name, special_features);
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void visit_set_policy(Visitor *v, CompatPolicy *policy)
|
||||
|
@ -406,18 +409,12 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
|
||||
switch (v->compat_policy.deprecated_input) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
break;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
error_setg(errp, "Deprecated value '%s' disabled by policy",
|
||||
enum_str);
|
||||
return false;
|
||||
case COMPAT_POLICY_INPUT_CRASH:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (lookup->special_features
|
||||
&& !compat_policy_input_ok(lookup->special_features[value],
|
||||
&v->compat_policy,
|
||||
ERROR_CLASS_GENERIC_ERROR,
|
||||
"value", enum_str, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*obj = value;
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include "qemu/coroutine.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
CompatPolicy compat_policy;
|
||||
|
||||
Visitor *qobject_input_visitor_new_qmp(QObject *obj)
|
||||
{
|
||||
Visitor *v = qobject_input_visitor_new(obj);
|
||||
|
@ -176,19 +174,10 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
|
|||
"The command %s has not been found", command);
|
||||
goto out;
|
||||
}
|
||||
if (cmd->options & QCO_DEPRECATED) {
|
||||
switch (compat_policy.deprecated_input) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
break;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
"Deprecated command %s disabled by policy",
|
||||
command);
|
||||
goto out;
|
||||
case COMPAT_POLICY_INPUT_CRASH:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (!compat_policy_input_ok(cmd->special_features, &compat_policy,
|
||||
ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
"command", command, &err)) {
|
||||
goto out;
|
||||
}
|
||||
if (!cmd->enabled) {
|
||||
error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include "qapi/qmp/dispatch.h"
|
||||
|
||||
void qmp_register_command(QmpCommandList *cmds, const char *name,
|
||||
QmpCommandFunc *fn, QmpCommandOptions options)
|
||||
QmpCommandFunc *fn, QmpCommandOptions options,
|
||||
unsigned special_features)
|
||||
{
|
||||
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
|
||||
|
||||
|
@ -27,6 +28,7 @@ void qmp_register_command(QmpCommandList *cmds, const char *name,
|
|||
cmd->fn = fn;
|
||||
cmd->enabled = true;
|
||||
cmd->options = options;
|
||||
cmd->special_features = special_features;
|
||||
QTAILQ_INSERT_TAIL(cmds, cmd, node);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include <math.h>
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
|
@ -662,20 +663,13 @@ static void qobject_input_optional(Visitor *v, const char *name, bool *present)
|
|||
*present = true;
|
||||
}
|
||||
|
||||
static bool qobject_input_deprecated_accept(Visitor *v, const char *name,
|
||||
Error **errp)
|
||||
static bool qobject_input_policy_reject(Visitor *v, const char *name,
|
||||
unsigned special_features,
|
||||
Error **errp)
|
||||
{
|
||||
switch (v->compat_policy.deprecated_input) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
return true;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
error_setg(errp, "Deprecated parameter '%s' disabled by policy",
|
||||
name);
|
||||
return false;
|
||||
case COMPAT_POLICY_INPUT_CRASH:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return !compat_policy_input_ok(special_features, &v->compat_policy,
|
||||
ERROR_CLASS_GENERIC_ERROR,
|
||||
"parameter", name, errp);
|
||||
}
|
||||
|
||||
static void qobject_input_free(Visitor *v)
|
||||
|
@ -712,7 +706,7 @@ static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj)
|
|||
v->visitor.end_list = qobject_input_end_list;
|
||||
v->visitor.start_alternate = qobject_input_start_alternate;
|
||||
v->visitor.optional = qobject_input_optional;
|
||||
v->visitor.deprecated_accept = qobject_input_deprecated_accept;
|
||||
v->visitor.policy_reject = qobject_input_policy_reject;
|
||||
v->visitor.free = qobject_input_free;
|
||||
|
||||
v->root = qobject_ref(obj);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "qemu/queue.h"
|
||||
|
@ -208,9 +209,15 @@ static bool qobject_output_type_null(Visitor *v, const char *name,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool qobject_output_deprecated(Visitor *v, const char *name)
|
||||
static bool qobject_output_policy_skip(Visitor *v, const char *name,
|
||||
unsigned special_features)
|
||||
{
|
||||
return v->compat_policy.deprecated_output != COMPAT_POLICY_OUTPUT_HIDE;
|
||||
CompatPolicy *pol = &v->compat_policy;
|
||||
|
||||
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.
|
||||
|
@ -262,7 +269,7 @@ Visitor *qobject_output_visitor_new(QObject **result)
|
|||
v->visitor.type_number = qobject_output_type_number;
|
||||
v->visitor.type_any = qobject_output_type_any;
|
||||
v->visitor.type_null = qobject_output_type_null;
|
||||
v->visitor.deprecated = qobject_output_deprecated;
|
||||
v->visitor.policy_skip = qobject_output_policy_skip;
|
||||
v->visitor.complete = qobject_output_complete;
|
||||
v->visitor.free = qobject_output_free;
|
||||
|
||||
|
|
|
@ -559,10 +559,8 @@
|
|||
# for ramblock-id. Disable this for 4.0
|
||||
# machine types or older to allow
|
||||
# migration with newer QEMU versions.
|
||||
# This option is considered stable
|
||||
# despite the x- prefix. (default:
|
||||
# false generally, but true for machine
|
||||
# types <= 4.0)
|
||||
# (default: false generally,
|
||||
# but true for machine types <= 4.0)
|
||||
#
|
||||
# Note: prealloc=true and reserve=false cannot be set at the same time. With
|
||||
# reserve=true, the behavior depends on the operating system: for example,
|
||||
|
@ -785,6 +783,9 @@
|
|||
##
|
||||
# @ObjectType:
|
||||
#
|
||||
# Features:
|
||||
# @unstable: Member @x-remote-object is experimental.
|
||||
#
|
||||
# Since: 6.0
|
||||
##
|
||||
{ 'enum': 'ObjectType',
|
||||
|
@ -836,7 +837,7 @@
|
|||
'tls-creds-psk',
|
||||
'tls-creds-x509',
|
||||
'tls-cipher-suites',
|
||||
'x-remote-object'
|
||||
{ 'name': 'x-remote-object', 'features': [ 'unstable' ] }
|
||||
] }
|
||||
|
||||
##
|
||||
|
|
|
@ -17,8 +17,8 @@ visit_start_alternate(void *v, const char *name, void *obj, size_t size) "v=%p n
|
|||
visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
|
||||
|
||||
visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
|
||||
visit_deprecated_accept(void *v, const char *name) "v=%p name=%s"
|
||||
visit_deprecated(void *v, const char *name) "v=%p name=%s"
|
||||
visit_policy_reject(void *v, const char *name) "v=%p name=%s"
|
||||
visit_policy_skip(void *v, const char *name) "v=%p name=%s"
|
||||
|
||||
visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p"
|
||||
visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
|
||||
|
|
|
@ -3641,7 +3641,9 @@ DEFHEADING(Debug/Expert options:)
|
|||
|
||||
DEF("compat", HAS_ARG, QEMU_OPTION_compat,
|
||||
"-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)
|
||||
SRST
|
||||
``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]``
|
||||
|
@ -3659,6 +3661,22 @@ SRST
|
|||
Suppress deprecated command results and events
|
||||
|
||||
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
|
||||
|
||||
DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg,
|
||||
|
|
|
@ -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:
|
||||
|
@ -229,15 +227,13 @@ 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);
|
||||
qmp_marshal_%(c_name)s, %(opts)s, %(feats)s);
|
||||
''',
|
||||
name=name, c_name=c_name(name),
|
||||
opts=" | ".join(options))
|
||||
opts=' | '.join(options) or 0,
|
||||
feats=gen_special_features(features))
|
||||
return ret
|
||||
|
||||
|
||||
|
|
|
@ -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('''
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -725,6 +727,9 @@ class QAPISchemaEnumMember(QAPISchemaMember):
|
|||
class QAPISchemaFeature(QAPISchemaMember):
|
||||
role = 'feature'
|
||||
|
||||
def is_special(self):
|
||||
return self.name in ('deprecated', 'unstable')
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeMember(QAPISchemaMember):
|
||||
def __init__(self, name, info, typ, optional, ifcond=None, features=None):
|
||||
|
|
|
@ -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,
|
||||
''',
|
||||
index=index)
|
||||
|
||||
if flags:
|
||||
special_features = gen_special_features(memb.features)
|
||||
if special_features != '0':
|
||||
feats += mcgen('''
|
||||
[%(index)s] = %(special_features)s,
|
||||
''',
|
||||
index=index, special_features=special_features)
|
||||
|
||||
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('''
|
||||
},
|
||||
|
|
|
@ -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('''
|
||||
}
|
||||
|
|
|
@ -146,7 +146,8 @@ static void init_qmp_commands(void)
|
|||
|
||||
QTAILQ_INIT(&qmp_cap_negotiation_commands);
|
||||
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
|
||||
qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
|
||||
qmp_marshal_qmp_capabilities,
|
||||
QCO_ALLOW_PRECONFIG, 0);
|
||||
}
|
||||
|
||||
static int getopt_set_loc(int argc, char **argv, const char *optstring,
|
||||
|
|
|
@ -273,7 +273,7 @@
|
|||
'data': { 'foo': { 'type': 'int', 'features': [ 'deprecated' ] } },
|
||||
'features': [ 'feature1' ] }
|
||||
{ 'struct': 'FeatureStruct2',
|
||||
'data': { 'foo': 'int' },
|
||||
'data': { 'foo': { 'type': 'int', 'features': [ 'unstable' ] } },
|
||||
'features': [ { 'name': 'feature1' } ] }
|
||||
{ 'struct': 'FeatureStruct3',
|
||||
'data': { 'foo': 'int' },
|
||||
|
@ -331,7 +331,7 @@
|
|||
{ 'command': 'test-command-features1',
|
||||
'features': [ 'deprecated' ] }
|
||||
{ 'command': 'test-command-features3',
|
||||
'features': [ 'feature1', 'feature2' ] }
|
||||
'features': [ 'unstable', 'feature1', 'feature2' ] }
|
||||
|
||||
{ 'command': 'test-command-cond-features1',
|
||||
'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'} ] }
|
||||
|
@ -348,3 +348,6 @@
|
|||
|
||||
{ 'event': 'TEST_EVENT_FEATURES1',
|
||||
'features': [ 'deprecated' ] }
|
||||
|
||||
{ 'event': 'TEST_EVENT_FEATURES2',
|
||||
'features': [ 'unstable' ] }
|
||||
|
|
|
@ -308,6 +308,7 @@ object FeatureStruct1
|
|||
feature feature1
|
||||
object FeatureStruct2
|
||||
member foo: int optional=False
|
||||
feature unstable
|
||||
feature feature1
|
||||
object FeatureStruct3
|
||||
member foo: int optional=False
|
||||
|
@ -373,6 +374,7 @@ command test-command-features1 None -> None
|
|||
feature deprecated
|
||||
command test-command-features3 None -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
feature unstable
|
||||
feature feature1
|
||||
feature feature2
|
||||
command test-command-cond-features1 None -> None
|
||||
|
@ -394,6 +396,9 @@ event TEST_EVENT_FEATURES0 FeatureStruct1
|
|||
event TEST_EVENT_FEATURES1 None
|
||||
boxed=False
|
||||
feature deprecated
|
||||
event TEST_EVENT_FEATURES2 None
|
||||
boxed=False
|
||||
feature unstable
|
||||
module include/sub-module.json
|
||||
include sub-sub-module.json
|
||||
object SecondArrayRef
|
||||
|
|
Loading…
Reference in New Issue