From patchwork Thu Oct 24 12:34:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 1183109 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="AP+yPhdh"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46zTk71jkKz9sPv for ; Fri, 25 Oct 2019 01:13:34 +1100 (AEDT) Received: from localhost ([::1]:43749 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNdro-0007zw-Lu for incoming@patchwork.ozlabs.org; Thu, 24 Oct 2019 10:13:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47773) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcKk-0003z6-4k for qemu-devel@nongnu.org; Thu, 24 Oct 2019 08:35:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNcKi-0006BX-1U for qemu-devel@nongnu.org; Thu, 24 Oct 2019 08:35:17 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:60794 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNcKh-0006Ay-TV for qemu-devel@nongnu.org; Thu, 24 Oct 2019 08:35:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571920515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tH3KRe0Iy3dxA+vLYN3e4E2c91fWMAngW0oeY2mbIt0=; b=AP+yPhdhvU4/unFvTnouJJTp9JwABZld2Ebxj617ygwzqaJkyFnYw2D4vbgMFcTkRYnWMu bcXpsLYND6inAAAFBzXbG2izGi/pijYAMR4Q6yClNUvJzjGTGc4FWz8Gv9McASs1lIpRNQ 339vJ4+ABSaZN+uRlv56PCgWBSnxRSo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-218-Gnydq9ogM5CwbGJGAB-4Mw-1; Thu, 24 Oct 2019 08:35:09 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 49E261800DFC; Thu, 24 Oct 2019 12:35:08 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.36.118.123]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E0FAE52E7; Thu, 24 Oct 2019 12:35:07 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 2E5A71130346; Thu, 24 Oct 2019 14:34:59 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [RFC PATCH 16/19] qapi: Implement -compat deprecated-input=reject for commands Date: Thu, 24 Oct 2019 14:34:55 +0200 Message-Id: <20191024123458.13505-17-armbru@redhat.com> In-Reply-To: <20191024123458.13505-1-armbru@redhat.com> References: <20191024123458.13505-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Gnydq9ogM5CwbGJGAB-4Mw-1 X-Mimecast-Spam-Score: 0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: libvir-list@redhat.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This policy makes deprecated commands fail like this: ---> {"execute": "query-cpus"} <--- {"error": {"class": "CommandNotFound", "desc": "Deprecated command query-cpus disabled by policy"}} When the command is removed, the error will change to <--- {"error": {"class": "CommandNotFound", "desc": "The command query-cpus has not been found"}} The policy thus permits "testing the future". Signed-off-by: Markus Armbruster --- qapi/common.json | 4 ++-- include/qapi/qmp/dispatch.h | 1 + qapi/qmp-dispatch.c | 13 +++++++++++++ tests/test-qmp-cmds.c | 23 +++++++++++++++++++++++ qemu-options.hx | 4 +++- scripts/qapi/commands.py | 10 +++++++--- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/qapi/common.json b/qapi/common.json index 9fc3e6400c..3e9d12c90f 100644 --- a/qapi/common.json +++ b/qapi/common.json @@ -151,7 +151,7 @@ # Policy for handling "funny" input. # # @accept: Accept silently -# TODO @reject: Reject with an error +# @reject: Reject with an error # TODO @crash: abort() the process # # FIXME Guidance on intended use. @@ -159,7 +159,7 @@ # Since: 4.2 ## { 'enum': 'CompatPolicyInput', - 'data': [ 'accept' ] } + 'data': [ 'accept', 'reject' ] } ## # @CompatPolicyOutput: diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 9aa426a398..ef256f2bb7 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -24,6 +24,7 @@ typedef enum QmpCommandOptions QCO_NO_SUCCESS_RESP = (1U << 0), QCO_ALLOW_OOB = (1U << 1), QCO_ALLOW_PRECONFIG = (1U << 2), + QCO_DEPRECATED = (1U << 3), } QmpCommandOptions; typedef struct QmpCommand diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 8fe59cf54d..b079db85d2 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -132,6 +132,19 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request, "The command %s has not been found", command); goto out; } + if (cmd->options & QCO_DEPRECATED) { + switch (qapi_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, "The command %s has been disabled for this instance", diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index cf4fa1a091..005ea24a27 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qapi/compat-policy.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qnum.h" @@ -235,6 +236,26 @@ static void test_dispatch_cmd_success_response(void) qobject_unref(req); } +static void test_dispatch_cmd_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-command-features1' }"; + QDict *ret; + + /* accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + 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)); + assert(ret && qdict_size(ret) == 0); + qobject_unref(ret); + + qapi_compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT; + do_qmp_dispatch_error(false, ERROR_CLASS_COMMAND_NOT_FOUND, cmd); +} + /* test commands that involve both input parameters and return values */ static void test_dispatch_cmd_io(void) { @@ -344,6 +365,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/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); diff --git a/qemu-options.hx b/qemu-options.hx index c43f768a15..f107a57c81 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3320,7 +3320,7 @@ STEXI ETEXI DEF("compat", HAS_ARG, QEMU_OPTION_compat, - "-compat [deprecated-input=accept][,deprecated-output=accept]\n" + "-compat [deprecated-input=accept|reject][,deprecated-output=accept]\n" " Policy for handling deprecated management interfaces\n", QEMU_ARCH_ALL) STEXI @@ -3331,6 +3331,8 @@ Set policy for handling deprecated management interfaces: @table @option @item deprecated-input=accept (default) Accept deprecated commands +@item deprecated-input=reject +Reject deprecated commands @item deprecated-output=accept (default) Emit deprecated events @end table diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 11e9a6c095..df2a132915 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -194,9 +194,13 @@ out: return ret -def gen_register_command(name, success_response, allow_oob, allow_preconfig): +def gen_register_command(name, features, + success_response, allow_oob, allow_preconfig): 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: @@ -295,8 +299,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) - self._regy.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig)) + self._regy.add(gen_register_command( + name, features, success_response, allow_oob, allow_preconfig)) def gen_commands(schema, output_dir, prefix):