Looks like this
---> {"execute": "query-cpus"}
<--- {"return": [...], "warnings": [{"class":
"CommandNotFound", "desc": "command is deprecated"}]}
Management applications may want to log such warnings.
This commit is not for merging as is, because
* docs/interop/qmp-spec.txt needs an update for the new success
response member "warnings".
* I'd like to see a prospective user before I extend the QMP protocol.
If you have specific plans to put them to use, let me know.
* The same warning should be included in a deprecated event.
* Emitting the same warning over and over again might be annoying or
slow. Perhaps warning just once would be better.
Signed-off-by: Markus Armbruster <armbru(a)redhat.com>
---
qapi/qmp-dispatch.c | 8 ++++++++
tests/test-qmp-cmds.c | 43 +++++++++++++++++++++++++++++++++++++++++--
qemu-options.hx | 2 +-
3 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 6436417844..9c17a59f31 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -197,6 +197,14 @@ out:
} else {
rsp = qdict_new();
qdict_put_obj(rsp, "return", ret);
+ if (cmd->options & QCO_DEPRECATED) {
+ qdict_put_obj(
+ rsp, "warnings",
+ qobject_from_jsonf_nofail(
+ "[ { 'class': %s, 'desc': %s } ]",
+ QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND),
+ "command is deprecated"));
+ }
}
if (id) {
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 005ea24a27..38d2e5b4a7 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -2,6 +2,7 @@
#include "qapi/compat-policy.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
#include "qapi/error.h"
@@ -164,6 +165,40 @@ static QObject *do_qmp_dispatch(bool allow_oob, const char *template,
...)
return ret;
}
+static QObject *do_qmp_dispatch_warning(bool allow_oob, ErrorClass cls,
+ const char *template, ...)
+{
+ va_list ap;
+ QDict *req, *resp;
+ QObject *ret;
+ QList *warnings;
+ QDict *warning;
+
+ va_start(ap, template);
+ req = qdict_from_vjsonf_nofail(template, ap);
+ va_end(ap);
+
+ resp = qmp_dispatch(&qmp_commands, QOBJECT(req), allow_oob);
+ g_assert(resp);
+ ret = qdict_get(resp, "return");
+ g_assert(ret);
+ warnings = qdict_get_qlist(resp, "warnings");
+ g_assert(warnings);
+ warning = qobject_to(QDict, qlist_peek(warnings));
+ g_assert(warning);
+ g_assert_cmpstr(qdict_get_try_str(warning, "class"),
+ ==, QapiErrorClass_str(cls));
+ g_assert(qdict_get_try_str(warning, "desc"));
+ g_assert(qdict_size(warning) == 2);
+ g_assert(qlist_size(warnings) == 1);
+ g_assert(qdict_size(resp) == 2);
+
+ qobject_ref(ret);
+ qobject_unref(resp);
+ qobject_unref(req);
+ return ret;
+}
+
static void do_qmp_dispatch_error(bool allow_oob, ErrorClass cls,
const char *template, ...)
{
@@ -242,13 +277,17 @@ static void test_dispatch_cmd_deprecated(void)
QDict *ret;
/* accept */
- ret = qobject_to(QDict, do_qmp_dispatch(false, cmd));
+ ret = qobject_to(QDict, do_qmp_dispatch_warning(
+ false, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "{ 'execute': 'test-command-features1' }"));
assert(ret && qdict_size(ret) == 0);
qobject_unref(ret);
qapi_compat_policy.has_deprecated_input = true;
qapi_compat_policy.deprecated_input = COMPAT_POLICY_INPUT_ACCEPT;
- ret = qobject_to(QDict, do_qmp_dispatch(false, cmd));
+ ret = qobject_to(QDict, do_qmp_dispatch_warning(
+ false, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "{ 'execute': 'test-command-features1' }"));
assert(ret && qdict_size(ret) == 0);
qobject_unref(ret);
diff --git a/qemu-options.hx b/qemu-options.hx
index 3a740ea7b1..645629457a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3330,7 +3330,7 @@ STEXI
Set policy for handling deprecated management interfaces:
@table @option
@item deprecated-input=accept (default)
-Accept deprecated commands
+Accept deprecated commands with a warning
@item deprecated-input=reject
Reject deprecated commands
@item deprecated-input=crash
--
2.21.0