Skip to content

Commit

Permalink
qapi: Implement deprecated-input=reject for QMP commands
Browse files Browse the repository at this point in the history
This policy rejects deprecated input, and thus permits "testing the
future".  Implement it for QMP commands: make deprecated ones fail.
Example: when QEMU is run with -compat deprecated-input=reject, then

    {"execute": "query-cpus"}

fails like this

    {"error": {"class": "CommandNotFound", "desc": "Deprecated command query-cpus disabled by policy"}}

When the deprecated command is removed, the error will change to

    {"error": {"class": "CommandNotFound", "desc": "The command query-cpus has not been found"}}

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20210318155519.1224118-10-armbru@redhat.com>
  • Loading branch information
Markus Armbruster committed Mar 19, 2021
1 parent a698e66 commit 6aa45e0
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/qapi/qmp/dispatch.h
Expand Up @@ -26,6 +26,7 @@ typedef enum QmpCommandOptions
QCO_ALLOW_OOB = (1U << 1),
QCO_ALLOW_PRECONFIG = (1U << 2),
QCO_COROUTINE = (1U << 3),
QCO_DEPRECATED = (1U << 4),
} QmpCommandOptions;

typedef struct QmpCommand
Expand Down
13 changes: 13 additions & 0 deletions qapi/qmp-dispatch.c
Expand Up @@ -167,6 +167,19 @@ 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;
default:
abort();
}
}
if (!cmd->enabled) {
error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND,
"Command %s has been disabled%s%s",
Expand Down
10 changes: 7 additions & 3 deletions scripts/qapi/commands.py
Expand Up @@ -210,12 +210,16 @@ def gen_marshal(name: str,


def gen_register_command(name: str,
features: List[QAPISchemaFeature],
success_response: bool,
allow_oob: bool,
allow_preconfig: bool,
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:
Expand Down Expand Up @@ -326,9 +330,9 @@ def visit_command(self,
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
with self._temp_module('./init'):
with ifcontext(ifcond, self._genh, self._genc):
self._genc.add(gen_register_command(name, success_response,
allow_oob, allow_preconfig,
coroutine))
self._genc.add(gen_register_command(
name, features, success_response, allow_oob,
allow_preconfig, coroutine))


def gen_commands(schema: QAPISchema,
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/test-qmp-cmds.c
Expand Up @@ -281,6 +281,28 @@ static void test_dispatch_cmd_io(void)
qobject_unref(ret3);
}

static void test_dispatch_cmd_deprecated(void)
{
const char *cmd = "{ 'execute': 'test-command-features1' }";
QDict *ret;

memset(&compat_policy, 0, sizeof(compat_policy));

/* accept */
ret = qobject_to(QDict, do_qmp_dispatch(false, cmd));
assert(ret && qdict_size(ret) == 0);
qobject_unref(ret);

compat_policy.has_deprecated_input = true;
compat_policy.deprecated_input = COMPAT_POLICY_INPUT_ACCEPT;
ret = qobject_to(QDict, do_qmp_dispatch(false, cmd));
assert(ret && qdict_size(ret) == 0);
qobject_unref(ret);

compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT;
do_qmp_dispatch_error(false, ERROR_CLASS_COMMAND_NOT_FOUND, cmd);
}

static void test_dispatch_cmd_ret_deprecated(void)
{
const char *cmd = "{ 'execute': 'test-features0' }";
Expand Down Expand Up @@ -379,6 +401,8 @@ int main(int argc, char **argv)
g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
g_test_add_func("/qmp/dispatch_cmd_success_response",
test_dispatch_cmd_success_response);
g_test_add_func("/qmp/dispatch_cmd_deprecated",
test_dispatch_cmd_deprecated);
g_test_add_func("/qmp/dispatch_cmd_ret_deprecated",
test_dispatch_cmd_ret_deprecated);
g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
Expand Down

0 comments on commit 6aa45e0

Please sign in to comment.