QAPI patches patches for 2021-10-27

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmF5bpISHGFybWJydUBy
 ZWRoYXQuY29tAAoJEDhwtADrkYZThBsP/jgLAry80cEd+xZUTQTfQDfWEB9ScE0R
 V/yV385klxl/yXf7D7pzel89fflu8V1sjSHn6x29HbOTHWctG8u8LtRO4lBqooRq
 yG4EZ7xWChchrjyBzeEtL/eHBJWktPVqvK7U2Z+2jCqM5gy1xgCsMzqPpPraOHoi
 Z3g50JKYQE+JVkoqzzry+yRckHtQsOF2CR+QQGpf+e3xvUrOnOyukGftr3Cfppcg
 fMkb70mPknHMDepHSYQop7n7LPIbZuX8nbV0uFfGShMyiJa0zSzfWEfWhPxRQgwv
 mMuV0yzxnXE0EP515rQ7HVRaYUopmMJaTVa7gBRMu5kh16/7eFXBjs/vSUlV1reH
 ZkNefKIsLpFlgFMOLbEVAPF3/VIlFkO1IQI+UvNz5FDKCR65YLUTZ0D89+XCQqlp
 zi8NXDQ+IhHIBRSMsCFgLClzmDrXeDW6g3IEJUvjP+vV6IqmbiU6TfvOkMurF+KI
 0QEH3LfKIWU/vkvecWd2EjDWoGatsqtQm5GMBEUHLnrQyekYc0k1f8W230EG2mKJ
 19Eh/R6aYc9K4Vgx0OgfZjxBh3GARrOO7TEnaLQNeClBR8UKGqP0iVtYdVkroyIB
 ui2U/hiRCi115Wj4y4F7M6er7MbkxR5iBy/8H7H96hOG5vFC9UyagUw1L6bsaRDt
 EMAnG+4daNgX
 =Ff93
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-10-27' into staging

QAPI patches patches for 2021-10-27

# gpg: Signature made Wed 27 Oct 2021 08:21:54 AM 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-27:
  qapi: Implement deprecated-input={reject,crash} for enum values
  qapi: Move compat policy from QObject to generic visitor
  qapi: Add feature flags to enum members
  qapi: Enable enum member introspection to show more than name
  qapi: Improve input_type_enum()'s error message

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-10-27 09:42:40 -07:00
commit 5c49c6c241
31 changed files with 182 additions and 73 deletions

View File

@ -228,6 +228,12 @@ Use the more generic commands ``block-export-add`` and ``block-export-del``
instead. As part of this deprecation, where ``nbd-server-add`` used a
single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``.
``query-qmp-schema`` return value member ``values`` (since 6.2)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Member ``values`` in return value elements with meta-type ``enum`` is
deprecated. Use ``members`` instead.
System accelerators
-------------------

View File

@ -200,7 +200,9 @@ Syntax::
'*if': COND,
'*features': FEATURES }
ENUM-VALUE = STRING
| { 'name': STRING, '*if': COND }
| { 'name': STRING,
'*if': COND,
'*features': FEATURES }
Member 'enum' names the enum type.
@ -706,8 +708,10 @@ QEMU shows a certain behaviour.
Special features
~~~~~~~~~~~~~~~~
Feature "deprecated" marks a command, event, or struct member as
deprecated. It is not supported elsewhere so far.
Feature "deprecated" marks a command, event, enum value, or struct
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.
Naming rules and reserved names
@ -1157,7 +1161,8 @@ and "variants".
"members" is a JSON array describing the object's common members, if
any. Each element is a JSON object with members "name" (the member's
name), "type" (the name of its type), and optionally "default". The
name), "type" (the name of its type), "features" (a JSON array of
feature strings), and "default". The latter two are optional. The
member is optional if "default" is present. Currently, "default" can
only have value null. Other values are reserved for future
extensions. The "members" array is in no particular order; clients
@ -1231,14 +1236,22 @@ Example: the SchemaInfo for ['str'] ::
"element-type": "str" }
The SchemaInfo for an enumeration type has meta-type "enum" and
variant member "values". The values are listed in no particular
order; clients must search the entire enum when learning whether a
particular value is supported.
variant member "members".
"members" is a JSON array describing the enumeration values. Each
element is a JSON object with member "name" (the member's name), and
optionally "features" (a JSON array of feature strings). The
"members" array is in no particular order; clients must search the
entire array when learning whether a particular value is supported.
Example: the SchemaInfo for MyEnum from section `Enumeration types`_ ::
{ "name": "MyEnum", "meta-type": "enum",
"values": [ "value1", "value2", "value3" ] }
"members": [
{ "name": "value1" },
{ "name": "value2" },
{ "name": "value3" }
] }
The SchemaInfo for a built-in type has the same name as the type in
the QAPI schema (see section `Built-in Types`_), with one exception

View File

@ -15,7 +15,6 @@
#ifndef QOBJECT_INPUT_VISITOR_H
#define QOBJECT_INPUT_VISITOR_H
#include "qapi/qapi-types-compat.h"
#include "qapi/visitor.h"
typedef struct QObjectInputVisitor QObjectInputVisitor;
@ -59,9 +58,6 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
*/
Visitor *qobject_input_visitor_new(QObject *obj);
void qobject_input_visitor_set_policy(Visitor *v,
CompatPolicyInput deprecated);
/*
* Create a QObject input visitor for @obj for use with keyval_parse()
*

View File

@ -15,7 +15,6 @@
#define QOBJECT_OUTPUT_VISITOR_H
#include "qapi/visitor.h"
#include "qapi/qapi-types-compat.h"
typedef struct QObjectOutputVisitor QObjectOutputVisitor;
@ -54,7 +53,4 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor;
*/
Visitor *qobject_output_visitor_new(QObject **result);
void qobject_output_visitor_set_policy(Visitor *v,
CompatPolicyOutput deprecated);
#endif

View File

@ -11,9 +11,13 @@
#ifndef QAPI_UTIL_H
#define QAPI_UTIL_H
/* QEnumLookup flags */
#define QAPI_ENUM_DEPRECATED 1
typedef struct QEnumLookup {
const char *const *array;
int size;
const unsigned char *const flags;
const int size;
} QEnumLookup;
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);

View File

@ -122,6 +122,9 @@ struct Visitor
/* Must be set */
VisitorType type;
/* Optional */
struct CompatPolicy compat_policy;
/* Must be set for output visitors, optional otherwise. */
void (*complete)(Visitor *v, void *opaque);

View File

@ -16,6 +16,7 @@
#define QAPI_VISITOR_H
#include "qapi/qapi-builtin-types.h"
#include "qapi/qapi-types-compat.h"
/*
* The QAPI schema defines both a set of C data types, and a QMP wire
@ -477,6 +478,14 @@ bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp);
*/
bool visit_deprecated(Visitor *v, const char *name);
/*
* Set policy for handling deprecated management interfaces.
*
* Intended use: call visit_set_policy(v, &compat_policy) when
* visiting management interface input or output.
*/
void visit_set_policy(Visitor *v, CompatPolicy *policy);
/*
* Visit an enum value.
*

View File

@ -42,6 +42,9 @@
# with feature 'deprecated'. We may want to extend it to cover
# semantic aspects, CLI, and experimental features.
#
# Limitation: deprecated-output policy @hide is not implemented for
# enumeration values. They behave the same as with policy @accept.
#
# @deprecated-input: how to handle deprecated input (default 'accept')
# @deprecated-output: how to handle deprecated output (default 'accept')
#

View File

@ -142,14 +142,38 @@
#
# Additional SchemaInfo members for meta-type 'enum'.
#
# @values: the enumeration type's values, in no particular order.
# @members: the enum type's members, in no particular order
# (since 6.2).
#
# @values: the enumeration type's member names, in no particular order.
# Redundant with @members. Just for backward compatibility.
#
# Features:
# @deprecated: Member @values is deprecated. Use @members instead.
#
# Values of this type are JSON string on the wire.
#
# Since: 2.5
##
{ 'struct': 'SchemaInfoEnum',
'data': { 'values': ['str'] } }
'data': { 'members': [ 'SchemaInfoEnumMember' ],
'values': { 'type': [ 'str' ],
'features': [ 'deprecated' ] } } }
##
# @SchemaInfoEnumMember:
#
# An object member.
#
# @name: the member's name, as defined in the QAPI schema.
#
# @features: names of features associated with the member, in no
# particular order.
#
# Since: 6.2
##
{ 'struct': 'SchemaInfoEnumMember',
'data': { 'name': 'str', '*features': [ 'str' ] } }
##
# @SchemaInfoArray:

View File

@ -19,6 +19,10 @@
#include "qapi/visitor-impl.h"
#include "trace.h"
/* Zero-initialization must result in default policy */
QEMU_BUILD_BUG_ON(COMPAT_POLICY_INPUT_ACCEPT || COMPAT_POLICY_OUTPUT_ACCEPT);
void visit_complete(Visitor *v, void *opaque)
{
assert(v->type != VISITOR_OUTPUT || v->complete);
@ -153,6 +157,11 @@ bool visit_deprecated(Visitor *v, const char *name)
return true;
}
void visit_set_policy(Visitor *v, CompatPolicy *policy)
{
v->compat_policy = *policy;
}
bool visit_is_input(Visitor *v)
{
return v->type == VISITOR_INPUT;
@ -384,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
const QEnumLookup *lookup, Error **errp)
{
int64_t value;
char *enum_str;
g_autofree char *enum_str = NULL;
if (!visit_type_str(v, name, &enum_str, errp)) {
return false;
@ -392,12 +401,25 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
value = qapi_enum_parse(lookup, enum_str, -1, NULL);
if (value < 0) {
error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
g_free(enum_str);
error_setg(errp, "Parameter '%s' does not accept value '%s'",
name ? name : "null", enum_str);
return false;
}
g_free(enum_str);
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();
}
}
*obj = value;
return true;
}

View File

@ -32,7 +32,7 @@ Visitor *qobject_input_visitor_new_qmp(QObject *obj)
{
Visitor *v = qobject_input_visitor_new(obj);
qobject_input_visitor_set_policy(v, compat_policy.deprecated_input);
visit_set_policy(v, &compat_policy);
return v;
}
@ -40,7 +40,7 @@ Visitor *qobject_output_visitor_new_qmp(QObject **result)
{
Visitor *v = qobject_output_visitor_new(result);
qobject_output_visitor_set_policy(v, compat_policy.deprecated_output);
visit_set_policy(v, &compat_policy);
return v;
}

View File

@ -14,7 +14,6 @@
#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"
@ -44,7 +43,6 @@ typedef struct StackObject {
struct QObjectInputVisitor {
Visitor visitor;
CompatPolicyInput deprecated_policy;
/* Root of visit at visitor creation. */
QObject *root;
@ -667,9 +665,7 @@ static void qobject_input_optional(Visitor *v, const char *name, bool *present)
static bool qobject_input_deprecated_accept(Visitor *v, const char *name,
Error **errp)
{
QObjectInputVisitor *qiv = to_qiv(v);
switch (qiv->deprecated_policy) {
switch (v->compat_policy.deprecated_input) {
case COMPAT_POLICY_INPUT_ACCEPT:
return true;
case COMPAT_POLICY_INPUT_REJECT:
@ -739,14 +735,6 @@ Visitor *qobject_input_visitor_new(QObject *obj)
return &v->visitor;
}
void qobject_input_visitor_set_policy(Visitor *v,
CompatPolicyInput deprecated)
{
QObjectInputVisitor *qiv = to_qiv(v);
qiv->deprecated_policy = deprecated;
}
Visitor *qobject_input_visitor_new_keyval(QObject *obj)
{
QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);

View File

@ -13,7 +13,6 @@
*/
#include "qemu/osdep.h"
#include "qapi/compat-policy.h"
#include "qapi/qobject-output-visitor.h"
#include "qapi/visitor-impl.h"
#include "qemu/queue.h"
@ -32,7 +31,6 @@ typedef struct QStackEntry {
struct QObjectOutputVisitor {
Visitor visitor;
CompatPolicyOutput deprecated_policy;
QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
QObject *root; /* Root of the output visit */
@ -212,9 +210,7 @@ static bool qobject_output_type_null(Visitor *v, const char *name,
static bool qobject_output_deprecated(Visitor *v, const char *name)
{
QObjectOutputVisitor *qov = to_qov(v);
return qov->deprecated_policy != COMPAT_POLICY_OUTPUT_HIDE;
return v->compat_policy.deprecated_output != COMPAT_POLICY_OUTPUT_HIDE;
}
/* Finish building, and return the root object.
@ -275,11 +271,3 @@ Visitor *qobject_output_visitor_new(QObject **result)
return &v->visitor;
}
void qobject_output_visitor_set_policy(Visitor *v,
CompatPolicyOutput deprecated)
{
QObjectOutputVisitor *qov = to_qov(v);
qov->deprecated_policy = deprecated;
}

View File

@ -472,7 +472,7 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None:
for m in members]
for member in members:
source = "'data' member"
check_keys(member, info, source, ['name'], ['if'])
check_keys(member, info, source, ['name'], ['if', 'features'])
member_name = member['name']
check_name_is_str(member_name, info, source)
source = "%s '%s'" % (source, member_name)
@ -483,6 +483,7 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None:
permit_upper=permissive,
permit_underscore=permissive)
check_if(member, info, source)
check_features(member.get('features'), info)
def check_struct(expr: _JSONObject, info: QAPISourceInfo) -> None:

View File

@ -68,6 +68,7 @@ JSONValue = Union[_Value, 'Annotated[_Value]']
# TypedDict constructs, so they are broadly typed here as simple
# Python Dicts.
SchemaInfo = Dict[str, object]
SchemaInfoEnumMember = Dict[str, object]
SchemaInfoObject = Dict[str, object]
SchemaInfoObjectVariant = Dict[str, object]
SchemaInfoObjectMember = Dict[str, object]
@ -274,8 +275,17 @@ const QLitObject %(c_name)s = %(c_string)s;
obj['features'] = self._gen_features(features)
self._trees.append(Annotated(obj, ifcond, comment))
def _gen_member(self, member: QAPISchemaObjectTypeMember
) -> Annotated[SchemaInfoObjectMember]:
def _gen_enum_member(self, member: QAPISchemaEnumMember
) -> Annotated[SchemaInfoEnumMember]:
obj: SchemaInfoEnumMember = {
'name': member.name,
}
if member.features:
obj['features'] = self._gen_features(member.features)
return Annotated(obj, member.ifcond)
def _gen_object_member(self, member: QAPISchemaObjectTypeMember
) -> Annotated[SchemaInfoObjectMember]:
obj: SchemaInfoObjectMember = {
'name': member.name,
'type': self._use_type(member.type)
@ -305,7 +315,8 @@ const QLitObject %(c_name)s = %(c_string)s;
prefix: Optional[str]) -> None:
self._gen_tree(
name, 'enum',
{'values': [Annotated(m.name, m.ifcond) for m in members]},
{'members': [self._gen_enum_member(m) for m in members],
'values': [Annotated(m.name, m.ifcond) for m in members]},
ifcond, features
)
@ -322,7 +333,7 @@ const QLitObject %(c_name)s = %(c_string)s;
members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> None:
obj: SchemaInfoObject = {
'members': [self._gen_member(m) for m in members]
'members': [self._gen_object_member(m) for m in members]
}
if variants:
obj['tag'] = variants.tag_member.name

View File

@ -708,6 +708,19 @@ class QAPISchemaMember:
class QAPISchemaEnumMember(QAPISchemaMember):
role = 'value'
def __init__(self, name, info, ifcond=None, features=None):
super().__init__(name, info, ifcond)
for f in features or []:
assert isinstance(f, QAPISchemaFeature)
f.set_defined_in(name)
self.features = features or []
def connect_doc(self, doc):
super().connect_doc(doc)
if doc:
for f in self.features:
doc.connect_feature(f)
class QAPISchemaFeature(QAPISchemaMember):
role = 'feature'
@ -980,9 +993,14 @@ class QAPISchema:
QAPISchemaIfCond(f.get('if')))
for f in features]
def _make_enum_member(self, name, ifcond, features, info):
return QAPISchemaEnumMember(name, info,
QAPISchemaIfCond(ifcond),
self._make_features(features, info))
def _make_enum_members(self, values, info):
return [QAPISchemaEnumMember(v['name'], info,
QAPISchemaIfCond(v.get('if')))
return [self._make_enum_member(v['name'], v.get('if'),
v.get('features'), info)
for v in values]
def _make_array_type(self, element_type, info):

View File

@ -38,6 +38,8 @@ objects_seen = set()
def gen_enum_lookup(name: str,
members: List[QAPISchemaEnumMember],
prefix: Optional[str] = None) -> str:
max_index = c_enum_const(name, '_MAX', prefix)
flags = ''
ret = mcgen('''
const QEnumLookup %(c_name)s_lookup = {
@ -52,13 +54,26 @@ 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:
ret += mcgen('''
},
.flags = (const unsigned char[%(max_index)s]) {
''',
max_index=max_index)
ret += flags
ret += mcgen('''
},
.size = %(max_index)s
};
''',
max_index=c_enum_const(name, '_MAX', prefix))
max_index=max_index)
return ret

View File

@ -58,11 +58,14 @@
#
# Features:
# @enum-feat: Also _one_ {and only}
# @enum-member-feat: a member feature
#
# @two is undocumented
##
{ 'enum': 'Enum',
'data': [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
'data': [ { 'name': 'one', 'if': 'IFONE',
'features': [ 'enum-member-feat' ] },
'two' ],
'features': [ 'enum-feat' ],
'if': 'IFCOND' }

View File

@ -13,6 +13,7 @@ module doc-good.json
enum Enum
member one
if IFONE
feature enum-member-feat
member two
if IFCOND
feature enum-feat
@ -108,6 +109,8 @@ The _one_ {and only}
feature=enum-feat
Also _one_ {and only}
feature=enum-member-feat
a member feature
section=None
@two is undocumented
doc symbol=Base

View File

@ -56,6 +56,9 @@ Features
"enum-feat"
Also _one_ {and only}
"enum-member-feat"
a member feature
"two" is undocumented

View File

@ -1,3 +1,3 @@
enum-dict-member-unknown.json: In enum 'MyEnum':
enum-dict-member-unknown.json:2: 'data' member has unknown key 'bad-key'
Valid keys are 'if', 'name'.
Valid keys are 'features', 'if', 'name'.

View File

@ -301,7 +301,8 @@
'TEST_IF_COND_2'] } } ] }
{ 'enum': 'FeatureEnum1',
'data': [ 'eins', 'zwei', 'drei' ],
'data': [ 'eins', 'zwei',
{ 'name': 'drei', 'features': [ 'deprecated' ] } ],
'features': [ 'feature1' ] }
{ 'union': 'FeatureUnion1',

View File

@ -341,6 +341,7 @@ enum FeatureEnum1
member eins
member zwei
member drei
feature deprecated
feature feature1
object q_obj_FeatureUnion1-base
member tag: FeatureEnum1 optional=False

View File

@ -37,6 +37,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
for m in members:
print(' member %s' % m.name)
self._print_if(m.ifcond, indent=8)
self._print_features(m.features, indent=8)
self._print_if(ifcond)
self._print_features(features)

View File

@ -174,11 +174,11 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value '0.42'
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value 'foobar'
== Check preallocation option ==
@ -190,7 +190,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off prea
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
qemu-img: TEST_DIR/t.qcow2: Parameter 'preallocation' does not accept value '1234'
== Check encryption option ==

View File

@ -192,7 +192,7 @@ Job failed: Could not resize image: Failed to grow the L1 table: File too large
=== Invalid version ===
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
{"error": {"class": "GenericError", "desc": "Parameter 'version' does not accept value 'v1'"}}
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
{"return": {}}

View File

@ -116,13 +116,13 @@ Job failed: Cannot find device='this doesn't exist' nor node-name='this doesn't
== Invalid adapter types ==
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'foo'"}}
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'IDE'"}}
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'legacyesx'"}}
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}

View File

@ -149,7 +149,7 @@ class TestBlockdevReopen(iotests.QMPTestCase):
self.reopen(opts, {'node-name': ''}, "Failed to find node with node-name=''")
self.reopen(opts, {'node-name': None}, "Invalid parameter type for 'options[0].node-name', expected: string")
self.reopen(opts, {'driver': 'raw'}, "Cannot change the option 'driver'")
self.reopen(opts, {'driver': ''}, "Invalid parameter ''")
self.reopen(opts, {'driver': ''}, "Parameter 'driver' does not accept value ''")
self.reopen(opts, {'driver': None}, "Invalid parameter type for 'options[0].driver', expected: string")
self.reopen(opts, {'file': 'not-found'}, "Cannot find device='' nor node-name='not-found'")
self.reopen(opts, {'file': ''}, "Cannot find device='' nor node-name=''")

View File

@ -53,7 +53,7 @@ CLUSTER_SIZE=65536
# Check if we can run this test.
output=$(_make_test_img -o 'compression_type=zstd' 64M; _cleanup_test_img)
if echo "$output" | grep -q "Invalid parameter 'zstd'"; then
if echo "$output" | grep -q "Parameter 'compression-type' does not accept value 'zstd'"; then
_notrun "ZSTD is disabled"
fi

View File

@ -148,7 +148,7 @@ rmdir "$EXT_MP" 2>/dev/null
rm -f "$EXT_MP"
output=$(fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error)
if echo "$output" | grep -q "Invalid parameter 'fuse'"; then
if echo "$output" | grep -q "Parameter 'type' does not accept value 'fuse'"; then
_notrun 'No FUSE support'
fi

View File

@ -488,7 +488,7 @@ static void test_dummy_badenum(void)
g_assert(dobj == NULL);
g_assert(err != NULL);
g_assert_cmpstr(error_get_pretty(err), ==,
"Invalid parameter 'yeti'");
"Parameter 'av' does not accept value 'yeti'");
g_assert(object_resolve_path_component(parent, "dummy0")
== NULL);