From patchwork Mon Sep 14 08:47:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273832 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78597C43461 for ; Mon, 14 Sep 2020 08:51:00 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 0B28320756 for ; Mon, 14 Sep 2020 08:50:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dcoF7wRW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0B28320756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39270 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkCR-00034b-1h for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:50:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41370) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9k-0006bN-SW for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:13 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:41078 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9i-0005DP-8c for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073289; 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=ZVYGpXY6+gkZvGfPrHmNExooqUnhdkkdmUY/MaXIzPA=; b=dcoF7wRWFFCh7m9v09hL/EbxHFBcwyiUcHDizXrZ7K2A/10Ko8wKxt7wihZM/CnfKK+Gef XBUbXhRN3nhRky3F4hOfxzxlfpT0nQDOKh5KbiuBrZoMz33WgBi9zATSnWjGR8DEzmKYv+ CRBZul4cXnWewa4+uFV2817xvxufko0= 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-23-56nd3RA0MYORTc6MJUxxDQ-1; Mon, 14 Sep 2020 04:48:07 -0400 X-MC-Unique: 56nd3RA0MYORTc6MJUxxDQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0E57E801AE3; Mon, 14 Sep 2020 08:48:06 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F3AB75DE93; Mon, 14 Sep 2020 08:48:03 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 75F7F1138461; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 1/8] qemu-options: New -compat to set policy for deprecated interfaces Date: Mon, 14 Sep 2020 10:47:55 +0200 Message-Id: <20200914084802.4185028-2-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.002 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.120; envelope-from=armbru@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 01:36:47 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Policy is separate for input and output. Input policy can be "accept" (accept silently), or "reject" (reject the request with an error). Output policy can be "accept" (pass on unchanged), or "hide" (filter out the deprecated parts). Default is "accept". Policies other than "accept" are implemented later in this series. For now, -compat covers only syntactic aspects of QMP, i.e. stuff tagged with feature 'deprecated'. We may want to extend it to cover semantic aspects, CLI, and experimental features. The option is experimental. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/compat.json | 51 ++++++++++++++++++++++++++++++++++++ qapi/qapi-schema.json | 1 + include/qapi/compat-policy.h | 20 ++++++++++++++ qapi/qmp-dispatch.c | 3 +++ softmmu/vl.c | 17 ++++++++++++ qapi/meson.build | 1 + qemu-options.hx | 20 ++++++++++++++ 7 files changed, 113 insertions(+) create mode 100644 qapi/compat.json create mode 100644 include/qapi/compat-policy.h diff --git a/qapi/compat.json b/qapi/compat.json new file mode 100644 index 0000000000..d2c02a21aa --- /dev/null +++ b/qapi/compat.json @@ -0,0 +1,51 @@ +# -*- Mode: Python -*- + +## +# = Compatibility policy +## + +## +# @CompatPolicyInput: +# +# Policy for handling "funny" input. +# +# @accept: Accept silently +# @reject: Reject with an error +# +# Since: 5.2 +## +{ 'enum': 'CompatPolicyInput', + 'data': [ 'accept', 'reject' ] } + +## +# @CompatPolicyOutput: +# +# Policy for handling "funny" output. +# +# @accept: Pass on unchanged +# @hide: Filter out +# +# Since: 5.2 +## +{ 'enum': 'CompatPolicyOutput', + 'data': [ 'accept', 'hide' ] } + +## +# @CompatPolicy: +# +# Policy for handling deprecated management interfaces. +# +# This is intended for testing users of the management interfaces. +# +# Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged +# with feature 'deprecated'. We may want to extend it to cover +# semantic aspects, CLI, and experimental features. +# +# @deprecated-input: how to handle deprecated input (default 'accept') +# @deprecated-output: how to handle deprecated output (default 'accept') +# +# Since: 5.2 +## +{ 'struct': 'CompatPolicy', + 'data': { '*deprecated-input': 'CompatPolicyInput', + '*deprecated-output': 'CompatPolicyOutput' } } diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index f03ff91ceb..2550b16028 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -76,6 +76,7 @@ { 'include': 'migration.json' } { 'include': 'transaction.json' } { 'include': 'trace.json' } +{ 'include': 'compat.json' } { 'include': 'control.json' } { 'include': 'introspect.json' } { 'include': 'qom.json' } diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h new file mode 100644 index 0000000000..b8c6638156 --- /dev/null +++ b/include/qapi/compat-policy.h @@ -0,0 +1,20 @@ +/* + * Policy for handling "funny" management interfaces + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Authors: + * Markus Armbruster + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef QAPI_COMPAT_POLICY_H +#define QAPI_COMPAT_POLICY_H + +#include "qapi/qapi-types-compat.h" + +extern CompatPolicy compat_policy; + +#endif diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 79347e0864..f65b8cf000 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/dispatch.h" #include "qapi/qmp/qdict.h" @@ -19,6 +20,8 @@ #include "sysemu/runstate.h" #include "qapi/qmp/qbool.h" +CompatPolicy compat_policy; + static QDict *qmp_dispatch_check_obj(QDict *dict, bool allow_oob, Error **errp) { diff --git a/softmmu/vl.c b/softmmu/vl.c index 0cc86b0766..dbe9dc06f0 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -27,6 +27,7 @@ #include "qemu/units.h" #include "hw/boards.h" #include "hw/qdev-properties.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qemu-version.h" #include "qemu/cutils.h" @@ -106,6 +107,7 @@ #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-run-state.h" @@ -3771,6 +3773,21 @@ void qemu_init(int argc, char **argv, char **envp) qemu_opt_get_bool(opts, "mem-lock", false); enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); break; + case QEMU_OPTION_compat: + { + CompatPolicy *opts; + Visitor *v; + + v = qobject_input_visitor_new_str(optarg, NULL, + &error_fatal); + + visit_type_CompatPolicy(v, NULL, &opts, &error_fatal); + QAPI_CLONE_MEMBERS(CompatPolicy, &compat_policy, opts); + + qapi_free_CompatPolicy(opts); + visit_free(v); + break; + } case QEMU_OPTION_msg: opts = qemu_opts_parse_noisily(qemu_find_opts("msg"), optarg, false); diff --git a/qapi/meson.build b/qapi/meson.build index 2b2872a41d..c72fcd9616 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -20,6 +20,7 @@ qapi_all_modules = [ 'block', 'char', 'common', + 'compat', 'control', 'crypto', 'dump', diff --git a/qemu-options.hx b/qemu-options.hx index b0f020594e..bb0c6bb70e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3391,6 +3391,26 @@ DEFHEADING() DEFHEADING(Debug/Expert options:) +DEF("compat", HAS_ARG, QEMU_OPTION_compat, + "-compat [deprecated-input=accept|reject][,deprecated-output=accept|hide]\n" + " Policy for handling deprecated management interfaces\n", + QEMU_ARCH_ALL) +SRST +``-compat [deprecated-input=@var{input-policy}][,deprecated-output=@var{output-policy}]`` + Set policy for handling deprecated management interfaces (experimental): + + ``deprecated-input=accept`` (default) + Accept deprecated commands and arguments + ``deprecated-input=reject`` + Reject deprecated commands and arguments + ``deprecated-output=accept`` (default) + Emit deprecated command results and events + ``deprecated-output=hide`` + Suppress deprecated command results and events + + Limitation: covers only syntactic aspects of QMP. +ERST + DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg, "-fw_cfg [name=],file=\n" " add named fw_cfg entry with contents from file\n" From patchwork Mon Sep 14 08:47:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273831 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AF68C433E2 for ; Mon, 14 Sep 2020 08:52:18 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id D43F420756 for ; Mon, 14 Sep 2020 08:52:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="E4/nsqrX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D43F420756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44444 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkDg-0005Aj-UV for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:52:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41390) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9l-0006bn-Lp for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:35694 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9h-0005DH-GV for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073288; 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=i8fVyV4Rsx+vMUWvr3Kw0vp2F5RwbCfcOISfLkQDy+k=; b=E4/nsqrXuNN/YpNlQdLLOOgm9sDSk1qeVGkP16L7A+hoK9FlLQ3ra9TztJl80sHBjskNmz HGZoXsGI495gCFv61mEZ7XUsE7x9SWb2MT4t5/8j2DN7RBfGAaak022Gl+RWkZ9vU6+irp xRkgcCVFIPcB0YgEXA5wyUwwWl3jZK4= 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-579-jrpbV60iOn-2oY3vbLk-Fg-1; Mon, 14 Sep 2020 04:48:05 -0400 X-MC-Unique: jrpbV60iOn-2oY3vbLk-Fg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9A37318BA291; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0A63E7E43C; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7974E1138468; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 2/8] qapi: Implement deprecated-output=hide for QMP command results Date: Mon, 14 Sep 2020 10:47:56 +0200 Message-Id: <20200914084802.4185028-3-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.81; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 00:11:19 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This policy suppresses deprecated bits in output, and thus permits "testing the future". Implement it for QMP command results. Example: when QEMU is run with -compat deprecated-output=hide, then {"execute": "query-cpus-fast"} yields {"return": [{"thread-id": 9805, "props": {"core-id": 0, "thread-id": 0, "socket-id": 0}, "qom-path": "/machine/unattached/device[0]", "cpu-index": 0, "target": "x86_64"}]} instead of {"return": [{"arch": "x86", "thread-id": 22436, "props": {"core-id": 0, "thread-id": 0, "socket-id": 0}, "qom-path": "/machine/unattached/device[0]", "cpu-index": 0, "target": "x86_64"}]} Note the suppression of deprecated member "arch". Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/qobject-output-visitor.h | 9 ++++++ include/qapi/visitor-impl.h | 3 ++ include/qapi/visitor.h | 9 ++++++ qapi/qapi-visit-core.c | 9 ++++++ qapi/qobject-output-visitor.c | 19 +++++++++++ tests/test-qmp-cmds.c | 42 ++++++++++++++++++++++--- qapi/trace-events | 1 + scripts/qapi/commands.py | 2 +- scripts/qapi/visit.py | 12 +++++++ tests/qapi-schema/qapi-schema-test.json | 17 +++++----- tests/qapi-schema/qapi-schema-test.out | 18 +++++------ 11 files changed, 118 insertions(+), 23 deletions(-) diff --git a/include/qapi/qobject-output-visitor.h b/include/qapi/qobject-output-visitor.h index 2b1726baf5..29f4ea6aad 100644 --- a/include/qapi/qobject-output-visitor.h +++ b/include/qapi/qobject-output-visitor.h @@ -53,4 +53,13 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor; */ Visitor *qobject_output_visitor_new(QObject **result); +/* + * Create a QObject output visitor for @obj for use with QMP + * + * This is like qobject_output_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_output_visitor_new_qmp(QObject **result); + #endif diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 7362c043be..2d853255a3 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -113,6 +113,9 @@ struct Visitor The core takes care of the return type in the public interface. */ void (*optional)(Visitor *v, const char *name, bool *present); + /* Optional */ + bool (*deprecated)(Visitor *v, const char *name); + /* Must be set */ VisitorType type; diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index ebc19ede7f..4d23b59853 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -459,6 +459,15 @@ void visit_end_alternate(Visitor *v, void **obj); */ bool visit_optional(Visitor *v, const char *name, bool *present); +/* + * Should we visit deprecated member @name? + * + * @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); + /* * Visit an enum value. * diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 7e5f40e7f0..d9726ecaa1 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -135,6 +135,15 @@ bool visit_optional(Visitor *v, const char *name, bool *present) return *present; } +bool visit_deprecated(Visitor *v, const char *name) +{ + trace_visit_deprecated(v, name); + if (v->deprecated) { + return v->deprecated(v, name); + } + return true; +} + bool visit_is_input(Visitor *v) { return v->type == VISITOR_INPUT; diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c index ba6f6ac8a7..5c4aa0f64d 100644 --- a/qapi/qobject-output-visitor.c +++ b/qapi/qobject-output-visitor.c @@ -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" @@ -31,6 +32,8 @@ 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 */ QObject **result; /* User's storage location for result */ @@ -207,6 +210,13 @@ static bool qobject_output_type_null(Visitor *v, const char *name, return true; } +static bool qobject_output_deprecated(Visitor *v, const char *name) +{ + QObjectOutputVisitor *qov = to_qov(v); + + return qov->deprecated_policy != COMPAT_POLICY_OUTPUT_HIDE; +} + /* Finish building, and return the root object. * The root object is never null. The caller becomes the object's * owner, and should use qobject_unref() when done with it. */ @@ -256,6 +266,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.complete = qobject_output_complete; v->visitor.free = qobject_output_free; @@ -264,3 +275,11 @@ Visitor *qobject_output_visitor_new(QObject **result) return &v->visitor; } + +Visitor *qobject_output_visitor_new_qmp(QObject **result) +{ + QObjectOutputVisitor *v = to_qov(qobject_output_visitor_new(result)); + + v->deprecated_policy = compat_policy.deprecated_output; + return &v->visitor; +} diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index d12ff47e26..bca89f8e88 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" @@ -45,12 +46,17 @@ void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp) { } -void qmp_test_features0(FeatureStruct0 *fs0, FeatureStruct1 *fs1, - FeatureStruct2 *fs2, FeatureStruct3 *fs3, - FeatureStruct4 *fs4, CondFeatureStruct1 *cfs1, - CondFeatureStruct2 *cfs2, CondFeatureStruct3 *cfs3, - Error **errp) +FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0, + bool has_fs1, FeatureStruct1 *fs1, + bool has_fs2, FeatureStruct2 *fs2, + bool has_fs3, FeatureStruct3 *fs3, + bool has_fs4, FeatureStruct4 *fs4, + bool has_cfs1, CondFeatureStruct1 *cfs1, + bool has_cfs2, CondFeatureStruct2 *cfs2, + bool has_cfs3, CondFeatureStruct3 *cfs3, + Error **errp) { + return g_new0(FeatureStruct1, 1); } void qmp_test_command_features1(Error **errp) @@ -271,6 +277,30 @@ static void test_dispatch_cmd_io(void) qobject_unref(ret3); } +static void test_dispatch_cmd_ret_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-features0' }"; + QDict *ret; + + memset(&compat_policy, 0, sizeof(compat_policy)); + + /* default accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_ACCEPT; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + qobject_unref(ret); + + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 0); + qobject_unref(ret); +} + /* test generated dealloc functions for generated types */ static void test_dealloc_types(void) { @@ -345,6 +375,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_ret_deprecated", + test_dispatch_cmd_ret_deprecated); g_test_add_func("/qmp/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); diff --git a/qapi/trace-events b/qapi/trace-events index 5eb4afa110..eff1fbd199 100644 --- a/qapi/trace-events +++ b/qapi/trace-events @@ -17,6 +17,7 @@ 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(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" diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 3cf9e1110b..14662515f3 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -69,7 +69,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, { Visitor *v; - v = qobject_output_visitor_new(ret_out); + v = qobject_output_visitor_new_qmp(ret_out); if (visit_type_%(c_name)s(v, "unused", &ret_in, errp)) { visit_complete(v, ret_out); } diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index cdabc5fa28..110563e56f 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -53,6 +53,7 @@ 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 += gen_if(memb.ifcond) if memb.optional: ret += mcgen(''' @@ -60,6 +61,12 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) ''', name=memb.name, c_name=c_name(memb.name)) push_indent() + if deprecated: + ret += mcgen(''' + if (visit_deprecated(v, "%(name)s")) { +''', + name=memb.name) + push_indent() ret += mcgen(''' if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { return false; @@ -67,6 +74,11 @@ 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: + pop_indent() + ret += mcgen(''' + } +''') if memb.optional: pop_indent() ret += mcgen(''' diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 3a9f2cbb33..309e60566d 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -298,14 +298,15 @@ 'features': [ 'feature1' ] } { 'command': 'test-features0', - 'data': { 'fs0': 'FeatureStruct0', - 'fs1': 'FeatureStruct1', - 'fs2': 'FeatureStruct2', - 'fs3': 'FeatureStruct3', - 'fs4': 'FeatureStruct4', - 'cfs1': 'CondFeatureStruct1', - 'cfs2': 'CondFeatureStruct2', - 'cfs3': 'CondFeatureStruct3' }, + 'data': { '*fs0': 'FeatureStruct0', + '*fs1': 'FeatureStruct1', + '*fs2': 'FeatureStruct2', + '*fs3': 'FeatureStruct3', + '*fs4': 'FeatureStruct4', + '*cfs1': 'CondFeatureStruct1', + '*cfs2': 'CondFeatureStruct2', + '*cfs3': 'CondFeatureStruct3' }, + 'returns': 'FeatureStruct1', 'features': [] } { 'command': 'test-command-features1', diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 891b4101e0..cd53323abd 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -407,15 +407,15 @@ alternate FeatureAlternate1 case eins: FeatureStruct1 feature feature1 object q_obj_test-features0-arg - member fs0: FeatureStruct0 optional=False - member fs1: FeatureStruct1 optional=False - member fs2: FeatureStruct2 optional=False - member fs3: FeatureStruct3 optional=False - member fs4: FeatureStruct4 optional=False - member cfs1: CondFeatureStruct1 optional=False - member cfs2: CondFeatureStruct2 optional=False - member cfs3: CondFeatureStruct3 optional=False -command test-features0 q_obj_test-features0-arg -> None + member fs0: FeatureStruct0 optional=True + member fs1: FeatureStruct1 optional=True + member fs2: FeatureStruct2 optional=True + member fs3: FeatureStruct3 optional=True + member fs4: FeatureStruct4 optional=True + member cfs1: CondFeatureStruct1 optional=True + member cfs2: CondFeatureStruct2 optional=True + member cfs3: CondFeatureStruct3 optional=True +command test-features0 q_obj_test-features0-arg -> FeatureStruct1 gen=True success_response=True boxed=False oob=False preconfig=False command test-command-features1 None -> None gen=True success_response=True boxed=False oob=False preconfig=False From patchwork Mon Sep 14 08:47:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCE2EC433E2 for ; Mon, 14 Sep 2020 08:49:20 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 40087206DC for ; Mon, 14 Sep 2020 08:49:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="S3rlhgo6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 40087206DC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59518 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkAp-0008Ea-7r for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:49:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41314) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9j-0006ad-1d for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:11 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:21055 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9h-0005DE-6w for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073288; 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=s3Qbp7v97u0gkincEc06YlAQyuldnRs3C7IH3sh7GGw=; b=S3rlhgo68KB4AF5daejrPi76+Zq50Os8eUX2UnomY4UB7w60Zlxluko9iYWmdeGshKLJBK zUphQjJoU1kItGiDyt/PMBpHQBfhgPl7wECjUoIkF2OT2RpqJhy76udE2EOLe3ZnILPEwh qF0R7etkYYuFNTwcdSGmp1TVLqtCzac= 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-580-LmkFhWFzN7Se9p8mu8-nhg-1; Mon, 14 Sep 2020 04:48:05 -0400 X-MC-Unique: LmkFhWFzN7Se9p8mu8-nhg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 492401007C87; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 174717E8CD; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7D2D311329B3; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 3/8] qapi: Implement deprecated-output=hide for QMP events Date: Mon, 14 Sep 2020 10:47:57 +0200 Message-Id: <20200914084802.4185028-4-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.120; envelope-from=armbru@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 01:39:17 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This policy suppresses deprecated bits in output, and thus permits "testing the future". Implement it for QMP events: suppress deprecated ones. No QMP event is deprecated right now. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- tests/test-qmp-event.c | 20 ++++++++++++++++++++ scripts/qapi/events.py | 14 ++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c index 7dd0053190..ab059fb5c2 100644 --- a/tests/test-qmp-event.c +++ b/tests/test-qmp-event.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" @@ -140,6 +141,24 @@ static void test_event_d(TestEventData *data, qobject_unref(data->expect); } +static void test_event_deprecated(TestEventData *data, const void *unused) +{ + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES1' }"); + + memset(&compat_policy, 0, sizeof(compat_policy)); + + qapi_event_send_test_event_features1(); + g_assert(data->emitted); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + data->emitted = false; + qapi_event_send_test_event_features1(); + g_assert(!data->emitted); + + qobject_unref(data->expect); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -148,6 +167,7 @@ int main(int argc, char **argv) event_test_add("/event/event_b", test_event_b); event_test_add("/event/event_c", test_event_c); event_test_add("/event/event_d", test_event_d); + event_test_add("/event/deprecated", test_event_deprecated); g_test_run(); return 0; diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index b544af5a1c..95ca4b4753 100644 --- a/scripts/qapi/events.py +++ b/scripts/qapi/events.py @@ -61,7 +61,8 @@ def gen_param_var(typ): return ret -def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit): +def gen_event_send(name, arg_type, features, boxed, + event_enum_name, event_emit): # FIXME: Our declaration of local variables (and of 'errp' in the # parameter list) can collide with exploded members of the event's # data type passed in as parameters. If this collision ever hits in @@ -86,6 +87,14 @@ def gen_event_send(name, arg_type, boxed, event_enum_name, event_emit): if not boxed: ret += gen_param_var(arg_type) + if 'deprecated' in [f.name for f in features]: + ret += mcgen(''' + + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return; + } +''') + ret += mcgen(''' qmp = qmp_event_build_dict("%(name)s"); @@ -154,6 +163,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor): #include "%(prefix)sqapi-emit-events.h" #include "%(events)s.h" #include "%(visit)s.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qobject-output-visitor.h" @@ -192,7 +202,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict); def visit_event(self, name, info, ifcond, features, arg_type, boxed): with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_event_send_decl(name, arg_type, boxed)) - self._genc.add(gen_event_send(name, arg_type, boxed, + self._genc.add(gen_event_send(name, arg_type, features, boxed, self._event_enum_name, self._event_emit_name)) # Note: we generate the enum member regardless of @ifcond, to From patchwork Mon Sep 14 08:47:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 305506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABACFC43461 for ; Mon, 14 Sep 2020 08:49:21 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id C5BE0221E8 for ; Mon, 14 Sep 2020 08:49:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MT81ceP8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C5BE0221E8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59566 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkAp-0008FR-Ns for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:49:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41310) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9i-0006aZ-R2 for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:20082) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9g-0005D6-TI for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073287; 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=5+0FEcmNlzWw4XpECqngOMwcHt/XS0yzjIW17fj7ZTk=; b=MT81ceP8xfsCDm0GPAfOrIMfslHsauwuJ+kt7Z2itzBHNO36s4MMxVEYGMZ+btRdNvkQEq vECKI3yfK3o0M7O9j3mi8a/Pt4jijg24Zt7nMiHdu30NLGmzOymdIGRp6kBTNVbuY/jyTz TSRBvChsKPKgQSCSKU1qbMAGosa/jnM= 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-590-oQEX3AvCMKWaxG08v1M3Mw-1; Mon, 14 Sep 2020 04:48:05 -0400 X-MC-Unique: oQEX3AvCMKWaxG08v1M3Mw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5C98B8030A0; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 13E7A6FEE6; Mon, 14 Sep 2020 08:48:04 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8087611329BE; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 4/8] qapi: Implement deprecated-output=hide for QMP event data Date: Mon, 14 Sep 2020 10:47:58 +0200 Message-Id: <20200914084802.4185028-5-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 02:55:39 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This policy suppresses deprecated bits in output, and thus permits "testing the future". Implement it for QMP event data: suppress deprecated members. No QMP event data is deprecated right now. Signed-off-by: Markus Armbruster --- tests/test-qmp-event.c | 21 +++++++++++++++++++++ scripts/qapi/events.py | 8 ++++++-- tests/qapi-schema/qapi-schema-test.json | 3 +++ tests/qapi-schema/qapi-schema-test.out | 2 ++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c index ab059fb5c2..047f44ff9a 100644 --- a/tests/test-qmp-event.c +++ b/tests/test-qmp-event.c @@ -159,6 +159,26 @@ static void test_event_deprecated(TestEventData *data, const void *unused) qobject_unref(data->expect); } +static void test_event_deprecated_data(TestEventData *data, const void *unused) +{ + memset(&compat_policy, 0, sizeof(compat_policy)); + + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES0'," + " 'data': { 'foo': 42 } }"); + qapi_event_send_test_event_features0(42); + g_assert(data->emitted); + + qobject_unref(data->expect); + + compat_policy.has_deprecated_output = true; + compat_policy.deprecated_output = COMPAT_POLICY_OUTPUT_HIDE; + data->expect = qdict_from_jsonf_nofail("{ 'event': 'TEST-EVENT-FEATURES0' }"); + qapi_event_send_test_event_features0(42); + g_assert(data->emitted); + + qobject_unref(data->expect); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -168,6 +188,7 @@ int main(int argc, char **argv) event_test_add("/event/event_c", test_event_c); event_test_add("/event/event_d", test_event_d); event_test_add("/event/deprecated", test_event_deprecated); + event_test_add("/event/deprecated_data", test_event_deprecated_data); g_test_run(); return 0; diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py index 95ca4b4753..f03c825cc1 100644 --- a/scripts/qapi/events.py +++ b/scripts/qapi/events.py @@ -104,7 +104,7 @@ def gen_event_send(name, arg_type, features, boxed, if have_args: ret += mcgen(''' - v = qobject_output_visitor_new(&obj); + v = qobject_output_visitor_new_qmp(&obj); ''') if not arg_type.is_implicit(): ret += mcgen(''' @@ -123,7 +123,11 @@ def gen_event_send(name, arg_type, features, boxed, ret += mcgen(''' visit_complete(v, &obj); - qdict_put_obj(qmp, "data", obj); + if (qdict_size(qobject_to(QDict, obj))) { + qdict_put_obj(qmp, "data", obj); + } else { + qobject_unref(obj); + } ''') ret += mcgen(''' diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 309e60566d..3f2943341e 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -323,5 +323,8 @@ 'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'] } ] } +{ 'event': 'TEST-EVENT-FEATURES0', + 'data': 'FeatureStruct1' } + { 'event': 'TEST-EVENT-FEATURES1', 'features': [ 'deprecated' ] } diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index cd53323abd..1a63d3bca7 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -438,6 +438,8 @@ command test-command-cond-features3 None -> None gen=True success_response=True boxed=False oob=False preconfig=False feature feature1 if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'] +event TEST-EVENT-FEATURES0 FeatureStruct1 + boxed=False event TEST-EVENT-FEATURES1 None boxed=False feature deprecated From patchwork Mon Sep 14 08:47:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273834 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16B1DC2D0E3 for ; Mon, 14 Sep 2020 08:49:22 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 9E545206DC for ; Mon, 14 Sep 2020 08:49:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hufimOgp" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9E545206DC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59768 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkAq-0008KQ-Ky for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:49:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41396) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9m-0006bp-El for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:26042 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9j-0005Ds-M1 for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073290; 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=1u9NWIU9e+h4x1Ho41s0GHWSR48hakGDdp22Egnawiw=; b=hufimOgpFv+jGqv3ntE1ihdoUV0mTCqtm81Ylrtm3URU0w49KRAZYeXuoYAxbtK1LU9QK+ pB4rTj7HJ6xgrFuuGsLPId3xYauxqKcmu4PkwkmN6e/dkTWQiMpSRBZM5CTosVz3odmZuc kKQFKKlfcIgNX71eMXG4vps5WqlcfyE= 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-438-kiyrIyJtPCq0SUCrzEbJQQ-1; Mon, 14 Sep 2020 04:48:07 -0400 X-MC-Unique: kiyrIyJtPCq0SUCrzEbJQQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F223E5705D; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 997CC6886B; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 84078113275D; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 5/8] qapi: Implement deprecated-output=hide for QMP introspection Date: Mon, 14 Sep 2020 10:47:59 +0200 Message-Id: <20200914084802.4185028-6-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.61; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 02:33:07 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This policy suppresses deprecated bits in output, and thus permits "testing the future". Implement it for QMP command query-qmp-schema: suppress information on deprecated commands, events and object type members, i.e. anything that has the special feature flag "deprecated". Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/introspect.json | 2 +- monitor/monitor-internal.h | 3 - monitor/misc.c | 2 - monitor/qmp-cmds-control.c | 100 +++++++++++++++++++++++---- storage-daemon/qemu-storage-daemon.c | 2 - 5 files changed, 89 insertions(+), 20 deletions(-) diff --git a/qapi/introspect.json b/qapi/introspect.json index 944bb87a20..39bd303778 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -49,7 +49,7 @@ ## { 'command': 'query-qmp-schema', 'returns': [ 'SchemaInfo' ], - 'gen': false } # just to simplify qmp_query_json() + 'allow-preconfig': true } ## # @SchemaMetaType: diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index b39e03b744..8833afaa65 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -180,7 +180,4 @@ void help_cmd(Monitor *mon, const char *name); void handle_hmp_command(MonitorHMP *mon, const char *cmdline); int hmp_compare_cmd(const char *name, const char *list); -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp); - #endif diff --git a/monitor/misc.c b/monitor/misc.c index e847b58a8c..3fd335e737 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -242,8 +242,6 @@ static void monitor_init_qmp_commands(void) qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); qmp_register_command(&qmp_commands, "device_add", qmp_device_add, QCO_NO_OPTIONS); qmp_register_command(&qmp_commands, "object-add", qmp_object_add, diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c index 8f04cfa6e6..5b07c7e765 100644 --- a/monitor/qmp-cmds-control.c +++ b/monitor/qmp-cmds-control.c @@ -26,10 +26,14 @@ #include "monitor-internal.h" #include "qemu-version.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qapi-commands-control.h" +#include "qapi/qapi-commands-introspect.h" #include "qapi/qapi-emit-events.h" #include "qapi/qapi-introspect.h" +#include "qapi/qapi-visit-introspect.h" +#include "qapi/qobject-input-visitor.h" /* * Accept QMP capabilities in @list for @mon. @@ -153,17 +157,89 @@ EventInfoList *qmp_query_events(Error **errp) return ev_list; } -/* - * Minor hack: generated marshalling suppressed for this command - * ('gen': false in the schema) so we can parse the JSON string - * directly into QObject instead of first parsing it with - * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it - * to QObject with generated output marshallers, every time. Instead, - * we do it in test-qobject-input-visitor.c, just to make sure - * qapi-gen.py's output actually conforms to the schema. - */ -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp) +static void *split_off_generic_list(void *list, + bool (*splitp)(void *elt), + void **part) { - *ret_data = qobject_from_qlit(&qmp_schema_qlit); + GenericList *keep = NULL, **keep_tailp = &keep; + GenericList *split = NULL, **split_tailp = &split; + GenericList *tail; + + for (tail = list; tail; tail = tail->next) { + if (splitp(tail)) { + *split_tailp = tail; + split_tailp = &tail->next; + } else { + *keep_tailp = tail; + keep_tailp = &tail->next; + } + } + + *keep_tailp = *split_tailp = NULL; + *part = split; + return keep; +} + +static bool is_in(const char *s, strList *list) +{ + strList *tail; + + for (tail = list; tail; tail = tail->next) { + if (!strcmp(tail->value, s)) { + return true; + } + } + return false; +} + +static bool is_entity_deprecated(void *link) +{ + return is_in("deprecated", ((SchemaInfoList *)link)->value->features); +} + +static bool is_member_deprecated(void *link) +{ + return is_in("deprecated", + ((SchemaInfoObjectMemberList *)link)->value->features); +} + +static SchemaInfoList *zap_deprecated(SchemaInfoList *schema) +{ + void *to_zap; + SchemaInfoList *tail; + SchemaInfo *ent; + + schema = split_off_generic_list(schema, is_entity_deprecated, &to_zap); + qapi_free_SchemaInfoList(to_zap); + + for (tail = schema; tail; tail = tail->next) { + ent = tail->value; + if (ent->meta_type == SCHEMA_META_TYPE_OBJECT) { + ent->u.object.members + = split_off_generic_list(ent->u.object.members, + is_member_deprecated, &to_zap); + qapi_free_SchemaInfoObjectMemberList(to_zap); + } + } + + return schema; +} + +SchemaInfoList *qmp_query_qmp_schema(Error **errp) +{ + QObject *obj = qobject_from_qlit(&qmp_schema_qlit); + Visitor *v = qobject_input_visitor_new(obj); + SchemaInfoList *schema = NULL; + + /* test_visitor_in_qmp_introspect() ensures this can't fail */ + visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); + g_assert(schema); + + qobject_unref(obj); + visit_free(v); + + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return zap_deprecated(schema); + } + return schema; } diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index 7e9b0e0d3f..9490099036 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -142,8 +142,6 @@ static QemuOptsList qemu_object_opts = { static void init_qmp_commands(void) { qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); QTAILQ_INIT(&qmp_cap_negotiation_commands); qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", From patchwork Mon Sep 14 08:48:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 305505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99ADFC43461 for ; Mon, 14 Sep 2020 08:52:12 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 1EC7A2076C for ; Mon, 14 Sep 2020 08:52:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="eZWJgmKa" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1EC7A2076C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44056 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkDa-00051I-VB for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:52:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41392) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9l-0006bo-QK for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:45431 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9j-0005Dg-Dg for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073290; 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=a2IM1AK5Mp2iQqof7Oe9gQXsSUqKPrL+H4aa3OY81BM=; b=eZWJgmKaWOFIru0Xm68IrT22Ezym4NcCNGvy7qWOqrOcP+mdhV45b6JBI4ibSU7PDudUcn 55yHwEZXBlS7gqnQTzhrudGnGHE0t3yUEWPOM/mAt0TmKnPMYOlwgYE9id70whIXFpaD0u 54UNjKgSk9g3tgNMXB5SJB5nuQQiSGQ= 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-448-DEFfeH4_PKWOg9LvClhOGA-1; Mon, 14 Sep 2020 04:48:08 -0400 X-MC-Unique: DEFfeH4_PKWOg9LvClhOGA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5B00A81F005; Mon, 14 Sep 2020 08:48:07 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A05C46FEE5; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 879CE11326AE; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 6/8] qapi: Implement deprecated-input=reject for QMP commands Date: Mon, 14 Sep 2020 10:48:00 +0200 Message-Id: <20200914084802.4185028-7-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=205.139.110.61; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 02:33:07 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- include/qapi/qmp/dispatch.h | 1 + qapi/qmp-dispatch.c | 13 +++++++++++++ tests/test-qmp-cmds.c | 24 ++++++++++++++++++++++++ scripts/qapi/commands.py | 10 +++++++--- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 5a9cf82472..3307b57a96 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 f65b8cf000..634e9c0a7d 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -130,6 +130,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, "The command %s has been disabled for this instance", diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index bca89f8e88..033d5dae9d 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -277,6 +277,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' }"; @@ -375,6 +397,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); diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 14662515f3..5f4b16fed0 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -176,9 +176,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: @@ -284,8 +288,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): From patchwork Mon Sep 14 08:48:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273830 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DFC1C43461 for ; Mon, 14 Sep 2020 08:53:34 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id ED64920756 for ; Mon, 14 Sep 2020 08:53:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XV5XqzMM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ED64920756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:50180 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkEu-0007X6-UE for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:53:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41398) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9m-0006cn-O6 for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:32314) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9j-0005Dk-DV for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073290; 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=V1xzQ9OKgozbVFDbN1rz6hXKlTxyjndGGNrLvi6gbZY=; b=XV5XqzMMsXML+BL+AABkq1O59hjiVq1WjY3oWg7G+67RH7fLvbJcsm9B11uUhvB//wt72l Os6F8ahcG+WRiuljcmZf0fzrCOsmfaV2OJAaWL/e2x0HCtNG+DPFMsfMuCwuTbUdmHuHce pQQQpx9uzIMkLYgNia93ObekpeK5Kks= 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-166-iDpInMY3NeefTL_Q_2mOew-1; Mon, 14 Sep 2020 04:48:08 -0400 X-MC-Unique: iDpInMY3NeefTL_Q_2mOew-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 54EEA18BA2AE; Mon, 14 Sep 2020 08:48:07 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A90DF6FEE6; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8B2781141D22; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 7/8] qapi: Implement deprecated-input=reject for QMP command arguments Date: Mon, 14 Sep 2020 10:48:01 +0200 Message-Id: <20200914084802.4185028-8-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=63.128.21.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 02:55:39 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This policy rejects deprecated input, and thus permits "testing the future". Implement it for QMP command arguments: reject commands with deprecated ones. Example: when QEMU is run with -compat deprecated-input=reject, then {"execute": "eject", "arguments": {"device": "cd"}} fails like this {"error": {"class": "GenericError", "desc": "Deprecated parameter 'device' disabled by policy"}} When the deprecated parameter is removed, the error will change to {"error": {"class": "GenericError", "desc": "Parameter 'device' is unexpected"}} Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/qobject-input-visitor.h | 9 +++++++++ include/qapi/visitor-impl.h | 3 +++ include/qapi/visitor.h | 9 +++++++++ qapi/qapi-visit-core.c | 9 +++++++++ qapi/qobject-input-visitor.c | 28 ++++++++++++++++++++++++++++ tests/test-qmp-cmds.c | 25 +++++++++++++++++++++++++ qapi/trace-events | 1 + scripts/qapi/commands.py | 2 +- scripts/qapi/visit.py | 3 +++ 9 files changed, 88 insertions(+), 1 deletion(-) diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h index 95985e25e5..cbc54de4ac 100644 --- a/include/qapi/qobject-input-visitor.h +++ b/include/qapi/qobject-input-visitor.h @@ -58,6 +58,15 @@ typedef struct QObjectInputVisitor QObjectInputVisitor; */ Visitor *qobject_input_visitor_new(QObject *obj); +/* + * Create a QObject input visitor for @obj for use with QMP + * + * This is like qobject_input_visitor_new(), except it obeys the + * policy for handling deprecated management interfaces set with + * -compat. + */ +Visitor *qobject_input_visitor_new_qmp(QObject *obj); + /* * Create a QObject input visitor for @obj for use with keyval_parse() * diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 2d853255a3..3b950f6e3d 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -113,6 +113,9 @@ struct Visitor The core takes care of the return type in the public interface. */ void (*optional)(Visitor *v, const char *name, bool *present); + /* Optional */ + bool (*deprecated_accept)(Visitor *v, const char *name, Error **errp); + /* Optional */ bool (*deprecated)(Visitor *v, const char *name); diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 4d23b59853..b3c9ef7a81 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -459,6 +459,15 @@ void visit_end_alternate(Visitor *v, void **obj); */ bool visit_optional(Visitor *v, const char *name, bool *present); +/* + * Should we reject deprecated member @name? + * + * @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); + /* * Should we visit deprecated member @name? * diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index d9726ecaa1..a641adec51 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -135,6 +135,15 @@ bool visit_optional(Visitor *v, const char *name, bool *present) return *present; } +bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp) +{ + trace_visit_deprecated_accept(v, name); + if (v->deprecated_accept) { + return v->deprecated_accept(v, name, errp); + } + return true; +} + bool visit_deprecated(Visitor *v, const char *name) { trace_visit_deprecated(v, name); diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index f918a05e5f..91e2d84ad2 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qobject-input-visitor.h" #include "qapi/visitor-impl.h" @@ -43,6 +44,7 @@ typedef struct StackObject { struct QObjectInputVisitor { Visitor visitor; + CompatPolicyInput deprecated_policy; /* Root of visit at visitor creation. */ QObject *root; @@ -666,6 +668,23 @@ 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) +{ + QObjectInputVisitor *qiv = to_qiv(v); + + switch (qiv->deprecated_policy) { + case COMPAT_POLICY_INPUT_ACCEPT: + return true; + case COMPAT_POLICY_INPUT_REJECT: + error_setg(errp, "Deprecated parameter '%s' disabled by policy", + name); + return false; + default: + abort(); + } +} + static void qobject_input_free(Visitor *v) { QObjectInputVisitor *qiv = to_qiv(v); @@ -700,6 +719,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.free = qobject_input_free; v->root = qobject_ref(obj); @@ -722,6 +742,14 @@ Visitor *qobject_input_visitor_new(QObject *obj) return &v->visitor; } +Visitor *qobject_input_visitor_new_qmp(QObject *obj) +{ + QObjectInputVisitor *v = to_qiv(qobject_input_visitor_new(obj)); + + v->deprecated_policy = compat_policy.deprecated_input; + return &v->visitor; +} + Visitor *qobject_input_visitor_new_keyval(QObject *obj) { QObjectInputVisitor *v = qobject_input_visitor_base_new(obj); diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 033d5dae9d..9aec9da2ce 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -299,6 +299,29 @@ static void test_dispatch_cmd_deprecated(void) do_qmp_dispatch_error(false, ERROR_CLASS_COMMAND_NOT_FOUND, cmd); } +static void test_dispatch_cmd_arg_deprecated(void) +{ + const char *cmd = "{ 'execute': 'test-features0'," + " 'arguments': { 'fs1': { 'foo': 42 } } }"; + QDict *ret; + + memset(&compat_policy, 0, sizeof(compat_policy)); + + /* accept */ + ret = qobject_to(QDict, do_qmp_dispatch(false, cmd)); + assert(ret && qdict_size(ret) == 1); + 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) == 1); + qobject_unref(ret); + + compat_policy.deprecated_input = COMPAT_POLICY_INPUT_REJECT; + do_qmp_dispatch_error(false, ERROR_CLASS_GENERIC_ERROR, cmd); +} + static void test_dispatch_cmd_ret_deprecated(void) { const char *cmd = "{ 'execute': 'test-features0' }"; @@ -399,6 +422,8 @@ int main(int argc, char **argv) test_dispatch_cmd_success_response); g_test_add_func("/qmp/dispatch_cmd_deprecated", test_dispatch_cmd_deprecated); + g_test_add_func("/qmp/dispatch_cmd_arg_deprecated", + test_dispatch_cmd_arg_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); diff --git a/qapi/trace-events b/qapi/trace-events index eff1fbd199..3cabe912ae 100644 --- a/qapi/trace-events +++ b/qapi/trace-events @@ -17,6 +17,7 @@ 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_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p" diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 5f4b16fed0..9c9b119f32 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -121,7 +121,7 @@ def gen_marshal(name, arg_type, boxed, ret_type): ret += mcgen(''' - v = qobject_input_visitor_new(QOBJECT(args)); + v = qobject_input_visitor_new_qmp(QOBJECT(args)); if (!visit_start_struct(v, NULL, NULL, 0, errp)) { goto out; } diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 110563e56f..ad1747a84f 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -63,6 +63,9 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) push_indent() if deprecated: ret += mcgen(''' + if (!visit_deprecated_accept(v, "%(name)s", errp)) { + return false; + } if (visit_deprecated(v, "%(name)s")) { ''', name=memb.name) From patchwork Mon Sep 14 08:48:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 273833 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CE0CC433E2 for ; Mon, 14 Sep 2020 08:50:54 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id B98AE20756 for ; Mon, 14 Sep 2020 08:50:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="fu6UTCO5" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B98AE20756 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:38756 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHkCK-0002ol-Km for qemu-devel@archiver.kernel.org; Mon, 14 Sep 2020 04:50:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41384) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHk9l-0006bi-Dg for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:14 -0400 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:44246 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kHk9i-0005DM-9u for qemu-devel@nongnu.org; Mon, 14 Sep 2020 04:48:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1600073289; 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=cdSUC5X8U3KAbhNvN5WsmG7xAmx3jtCQw9EdybdTm6k=; b=fu6UTCO5o1H8jpedman8tYT/u1U4ib3st2pO5BQ3ooagoADCNt7ofVgm7yxFA0XSX0hlQH PpVoiSx7u04Z0J9j5hO+uJ6KeSkffPXqXzAyWMJPhqplm6/OAye3v2Hp8Egd0EsBPR1v40 sAW+bydG3KXrP/sqTUrXvyNoy4/Ryec= 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-201-qr07o48NMOyL7NpW__Ooaw-1; Mon, 14 Sep 2020 04:48:07 -0400 X-MC-Unique: qr07o48NMOyL7NpW__Ooaw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E106618BA281; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-114-66.ams2.redhat.com [10.36.114.66]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B1DDC7E43C; Mon, 14 Sep 2020 08:48:05 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 8EB4011420C2; Mon, 14 Sep 2020 10:48:02 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH v5 8/8] qapi: New -compat deprecated-input=crash Date: Mon, 14 Sep 2020 10:48:02 +0200 Message-Id: <20200914084802.4185028-9-armbru@redhat.com> In-Reply-To: <20200914084802.4185028-1-armbru@redhat.com> References: <20200914084802.4185028-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=207.211.31.81; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/14 00:11:19 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -37 X-Spam_score: -3.8 X-Spam_bar: --- X-Spam_report: (-3.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.695, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: marcandre.lureau@gmail.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Policy "crash" calls abort() when deprecated input is received. Bugs in integration tests may mask the error from policy "reject". Provide a larger hammer: crash outright. Masking that seems unlikely. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- qapi/compat.json | 3 ++- qapi/qmp-dispatch.c | 1 + qapi/qobject-input-visitor.c | 1 + qemu-options.hx | 4 +++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/qapi/compat.json b/qapi/compat.json index d2c02a21aa..936602dcc6 100644 --- a/qapi/compat.json +++ b/qapi/compat.json @@ -11,11 +11,12 @@ # # @accept: Accept silently # @reject: Reject with an error +# @crash: abort() the process # # Since: 5.2 ## { 'enum': 'CompatPolicyInput', - 'data': [ 'accept', 'reject' ] } + 'data': [ 'accept', 'reject', 'crash' ] } ## # @CompatPolicyOutput: diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 634e9c0a7d..9954894d95 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -139,6 +139,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, "Deprecated command %s disabled by policy", command); goto out; + case COMPAT_POLICY_INPUT_CRASH: default: abort(); } diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 91e2d84ad2..d21ba0db8e 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -680,6 +680,7 @@ static bool qobject_input_deprecated_accept(Visitor *v, const char *name, error_setg(errp, "Deprecated parameter '%s' disabled by policy", name); return false; + case COMPAT_POLICY_INPUT_CRASH: default: abort(); } diff --git a/qemu-options.hx b/qemu-options.hx index bb0c6bb70e..f36d2073e5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3392,7 +3392,7 @@ DEFHEADING() DEFHEADING(Debug/Expert options:) DEF("compat", HAS_ARG, QEMU_OPTION_compat, - "-compat [deprecated-input=accept|reject][,deprecated-output=accept|hide]\n" + "-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]\n" " Policy for handling deprecated management interfaces\n", QEMU_ARCH_ALL) SRST @@ -3403,6 +3403,8 @@ SRST Accept deprecated commands and arguments ``deprecated-input=reject`` Reject deprecated commands and arguments + ``deprecated-input=crash`` + Crash on deprecated command ``deprecated-output=accept`` (default) Emit deprecated command results and events ``deprecated-output=hide``