From nobody Thu May 2 21:39:51 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1678315816814845.0164444156313; Wed, 8 Mar 2023 14:50:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pa2bn-0001MP-Tc; Wed, 08 Mar 2023 17:50:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bn-0001M3-3Y for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:07 -0500 Received: from out2-smtp.messagingengine.com ([66.111.4.26]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bl-00083y-Cz for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:06 -0500 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id D8B785C01BA; Wed, 8 Mar 2023 17:50:04 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Wed, 08 Mar 2023 17:50:04 -0500 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 8 Mar 2023 17:50:03 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dxuuu.xyz; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm3; t= 1678315804; x=1678402204; bh=OhArRTgo0J5rYnJUDmCvpzUB5JbFQB8TBpZ 4jyTDxQ4=; b=LKGzXD3c8n5QA/LZq8XWwd1Oa1fgcgfkAzxQTd7BVYInl25sVPu Ll40BQKfruvKcHRRiKrPwxUTjbgAv7Eq8d9o7MhO3X7vozkzRGN2aLnS1698VVLN w+pSJtOmJbwi8wLsqbILJ7wYQncRPBnKroNwqXpDhtEt4IKdv+rrcrLz4etSB670 GfQCp5TEdgMZswAURKEDptkblKk3BJu7K7LyjRFwMjv2bGubkKwrhkg/wpM6WEef hF41bWQ+CadyTRgKULHpolrBNyw7P5tkl3Ox51Wbc7wlJ6oeBlu0o104zAkQ9F9y hTg+Blh4Jz+VGS6a9zT4AO71u59fkyh7Ygw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1678315804; x=1678402204; bh=OhArRTgo0J5rYnJUDmCvpzUB5JbFQB8TBpZ 4jyTDxQ4=; b=iJMvK34p+b9Lu+D7nFLH+fm5v2d0E9d07PV823yJq7zGo/0Wvwp hZAQBnEMdjPma9n0lbXBZP63fImwht0V/lQFMumsZR3PhXRybyqKSov0JLhKiwzM JTXObrNhrN/8Mp82j8ybWKdYEdPjkxClZ7aIAgrsjJlQYb2uZ9lC5KVtSHM9Bpby UneG/zGCY6L+pYSf7xnXI3MvW427zchTzIXx1IGmVW2113zJUjmUtfBlD4M+DREg dRMdXT8ZvjzMQhP8Jm9ws/asFSm2jhp7PPSNqUSgPL0prGq6hLDwmC3C1O2v5tk7 K8KaPsB4OL6emcdElnkx9EAx/UtgoOKYMxA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvddugecutefuodetggdotefrodftvfcurf hrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecufghrlhcuvffnffculdefhedmnecujfgurhephffvvefuff fkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeffrghnihgvlhcuighuuceougig uhesugiguhhuuhdrgiihiieqnecuggftrfgrthhtvghrnhepteehkeekgffgieevvdetgf eliefftdelgeefueelvddutddvudfhkefguddtveeknecuvehluhhsthgvrhfuihiivgep tdenucfrrghrrghmpehmrghilhhfrhhomhepugiguhesugiguhhuuhdrgiihii X-ME-Proxy: Feedback-ID: i6a694271:Fastmail From: Daniel Xu To: kkostiuk@redhat.com, michael.roth@amd.com, marcandre.lureau@gmail.com, berrange@redhat.com Cc: qemu-devel@nongnu.org Subject: [PATCH v4 1/3] qga: Refactor guest-exec capture-output to take enum Date: Wed, 8 Mar 2023 15:49:39 -0700 Message-Id: <59f4f17ac2cbe719fa4f571a1c373c36597b12a3.1678314204.git.dxu@dxuuu.xyz> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=66.111.4.26; envelope-from=dxu@dxuuu.xyz; helo=out2-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_PASS=-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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZM-MESSAGEID: 1678315817402100009 Previously capture-output was an optional boolean flag that either captured all output or captured none. While this is OK in most cases, it lacks flexibility for more advanced capture cases, such as wanting to only capture stdout. This commits refactors guest-exec qapi to take an enum for capture mode instead while preserving backwards compatibility. Suggested-by: Daniel P. Berrang=C3=A9 Signed-off-by: Daniel Xu --- qga/commands.c | 37 ++++++++++++++++++++++++++++++++++--- qga/qapi-schema.json | 32 +++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/qga/commands.c b/qga/commands.c index 172826f8f8..5504fc5b8c 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -379,11 +379,23 @@ close: return false; } =20 +static GuestExecCaptureOutputMode ga_parse_capture_output( + GuestExecCaptureOutput *capture_output) +{ + if (!capture_output) + return GUEST_EXEC_CAPTURE_OUTPUT_MODE_NONE; + else if (capture_output->type =3D=3D QTYPE_QBOOL) + return capture_output->u.flag ? GUEST_EXEC_CAPTURE_OUTPUT_MODE_ALL + : GUEST_EXEC_CAPTURE_OUTPUT_MODE_NON= E; + else + return capture_output->u.mode; +} + GuestExec *qmp_guest_exec(const char *path, bool has_arg, strList *arg, bool has_env, strList *env, const char *input_data, - bool has_capture_output, bool capture_output, + GuestExecCaptureOutput *capture_output, Error **errp) { GPid pid; @@ -396,7 +408,8 @@ GuestExec *qmp_guest_exec(const char *path, gint in_fd, out_fd, err_fd; GIOChannel *in_ch, *out_ch, *err_ch; GSpawnFlags flags; - bool has_output =3D (has_capture_output && capture_output); + bool has_output =3D false; + GuestExecCaptureOutputMode output_mode; g_autofree uint8_t *input =3D NULL; size_t ninput =3D 0; =20 @@ -415,8 +428,26 @@ GuestExec *qmp_guest_exec(const char *path, =20 flags =3D G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH_FROM_ENVP; - if (!has_output) { + + output_mode =3D ga_parse_capture_output(capture_output); + switch (output_mode) { + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_NONE: flags |=3D G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL; + break; + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_STDOUT: + has_output =3D true; + flags |=3D G_SPAWN_STDERR_TO_DEV_NULL; + break; + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_STDERR: + has_output =3D true; + flags |=3D G_SPAWN_STDOUT_TO_DEV_NULL; + break; + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_ALL: + has_output =3D true; + break; + case GUEST_EXEC_CAPTURE_OUTPUT_MODE__MAX: + /* Silence warning; impossible branch */ + break; } =20 ret =3D g_spawn_async_with_pipes(NULL, argv, envp, flags, diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 796434ed34..4ef585da5d 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1200,6 +1200,36 @@ { 'struct': 'GuestExec', 'data': { 'pid': 'int'} } =20 +## +# @GuestExecCaptureOutputMode: +# +# An enumeration of guest-exec capture modes. +# +# @none: do not capture any output +# @stdout: only capture stdout +# @stderr: only capture stderr +# @all: capture both stdout and stderr +# +# Since: 8.0 +## + { 'enum': 'GuestExecCaptureOutputMode', + 'data': [ 'none', 'stdout', 'stderr', 'all' ] } + +## +# @GuestExecCaptureOutput: +# +# Controls what guest-exec output gets captures. +# +# @flag: captures both stdout and stderr if true. Equivalent +# to GuestExecCaptureOutputMode::all. (since 2.5) +# @mode: capture mode; preferred interface +# +# Since: 8.0 +## + { 'alternate': 'GuestExecCaptureOutput', + 'data': { 'flag': 'bool', + 'mode': 'GuestExecCaptureOutputMode'} } + ## # @guest-exec: # @@ -1218,7 +1248,7 @@ ## { 'command': 'guest-exec', 'data': { 'path': 'str', '*arg': ['str'], '*env': ['str'], - '*input-data': 'str', '*capture-output': 'bool' }, + '*input-data': 'str', '*capture-output': 'GuestExecCaptureO= utput' }, 'returns': 'GuestExec' } =20 =20 --=20 2.39.1 From nobody Thu May 2 21:39:51 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 167831581677544.46125982444869; Wed, 8 Mar 2023 14:50:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pa2bp-0001P7-6x; Wed, 08 Mar 2023 17:50:09 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bn-0001MH-Q2 for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:07 -0500 Received: from out2-smtp.messagingengine.com ([66.111.4.26]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bm-00084S-1q for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:07 -0500 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 967C65C0194; Wed, 8 Mar 2023 17:50:05 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Wed, 08 Mar 2023 17:50:05 -0500 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 8 Mar 2023 17:50:04 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dxuuu.xyz; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm3; t=1678315805; x= 1678402205; bh=yoW8IBadWWrC4GNpMhxwRyCIfIwhj0PWxXVer2KZ6uU=; b=m Wand3FIZ05cFibGZhnFTqIO02Z6Urokeh7sXNI3aJGyyiQYBm2knBfRBMUULdZ7u LgSvVsJJL7yXx7oQHy/I3F9wEZu8ljZ6a396arh2jOj1Yzpt423NZc1y/cPWm7OL GI6eQNZgVszAWV/RLaUlVC1yPTXcC3ooCMBShb9V3oXzTTeyehyxE7zpls6jeQLB 0T5nHNgNMzDTqGdjp+a+NDMjS1CGMR6jCp0qmT+RRPitTTlLL2Dxf3eVqqVKSFYG irqKcLUzMiQA/Xaay0WUwXZGN6pCzEHBYHVUdcqSovA73EfG2m7c4qKldTUtap4d Dg5S8xWgg+Wbmx3piwkfQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1678315805; x= 1678402205; bh=yoW8IBadWWrC4GNpMhxwRyCIfIwhj0PWxXVer2KZ6uU=; b=G w5g/IZ/CBv2bfYUmiC4L+rLHFeCzM9MSwLRDvx7DymkPdp3Ixt3HdOIjNvpsReUa a7JJibt5lVGO2S41OSIGhucYdsY/K3MMmbinezwIAJmcXYYawK4NRHxEceoak+ka rpXRthYSnvnamIwIAN4zth7k3ME0UX70WYpdzFTwMLdIcA6EhK2Ai7iirKK9uDKY gCisHay+B+OYBJu90MUwI15Bx7E8NWMYp3SzJYDvimP9b0wyz41JktGaX7wf0gH7 uMF8GxWPPOuzkSLSHEL3BC+SEyAZrNTiMKKPDwqIoNMTGJ/h2GFH1QKILWmOceQL 6CKluuyzfjB+XdQeqdN0Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvddugecutefuodetggdotefrodftvfcurf hrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecufghrlhcuvffnffculdejtddmnecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomhepffgrnhhivghlucgiuhcuoegugihu segugihuuhhurdighiiiqeenucggtffrrghtthgvrhhnpefgfefggeejhfduieekvdeute ffleeifeeuvdfhheejleejjeekgfffgefhtddtteenucevlhhushhtvghrufhiiigvpedt necurfgrrhgrmhepmhgrihhlfhhrohhmpegugihusegugihuuhhurdighiii X-ME-Proxy: Feedback-ID: i6a694271:Fastmail From: Daniel Xu To: kkostiuk@redhat.com, michael.roth@amd.com, marcandre.lureau@gmail.com, berrange@redhat.com Cc: qemu-devel@nongnu.org Subject: [PATCH v4 2/3] qga: Add `all-merge` variant to GuestExecCaptureOutputMode Date: Wed, 8 Mar 2023 15:49:40 -0700 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=66.111.4.26; envelope-from=dxu@dxuuu.xyz; helo=out2-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_PASS=-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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZM-MESSAGEID: 1678315817415100010 Content-Type: text/plain; charset="utf-8" Currently, any captured output (via `capture-output`) is segregated into separate GuestExecStatus fields (`out-data` and `err-data`). This means that downstream consumers have no way to reassemble the captured data back into the original stream. This is relevant for chatty and semi-interactive (ie. read only) CLI tools. Such tools may deliberately interleave stdout and stderr for visual effect. If segregated, the output becomes harder to visually understand. This commit adds a new enum variant to the GuestExecCaptureOutputMode qapi to merge the output streams such that consumers can have a pristine view of the original command output. Signed-off-by: Daniel Xu --- qga/commands.c | 31 +++++++++++++++++++++++++++++-- qga/qapi-schema.json | 4 +++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/qga/commands.c b/qga/commands.c index 5504fc5b8c..7d458d0aca 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -270,12 +270,26 @@ static void guest_exec_child_watch(GPid pid, gint sta= tus, gpointer data) g_spawn_close_pid(pid); } =20 -/** Reset ignored signals back to default. */ static void guest_exec_task_setup(gpointer data) { #if !defined(G_OS_WIN32) + bool has_merge =3D *(bool *)data; struct sigaction sigact; =20 + if (has_merge) { + /* + * FIXME: When `GLIB_VERSION_MIN_REQUIRED` is bumped to 2.58+, use + * g_spawn_async_with_fds() to be portable on windows. The current + * logic does not work on windows b/c `GSpawnChildSetupFunc` is run + * inside the parent, not the child. + */ + if (dup2(STDOUT_FILENO, STDERR_FILENO) !=3D 0) { + slog("dup2() failed to merge stderr into stdout: %s", + strerror(errno)); + } + } + + /* Reset ignored signals back to default. */ memset(&sigact, 0, sizeof(struct sigaction)); sigact.sa_handler =3D SIG_DFL; =20 @@ -409,6 +423,7 @@ GuestExec *qmp_guest_exec(const char *path, GIOChannel *in_ch, *out_ch, *err_ch; GSpawnFlags flags; bool has_output =3D false; + bool has_merge =3D false; GuestExecCaptureOutputMode output_mode; g_autofree uint8_t *input =3D NULL; size_t ninput =3D 0; @@ -445,13 +460,25 @@ GuestExec *qmp_guest_exec(const char *path, case GUEST_EXEC_CAPTURE_OUTPUT_MODE_ALL: has_output =3D true; break; + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_ALL_MERGE: + has_output =3D true; + has_merge =3D true; + break; case GUEST_EXEC_CAPTURE_OUTPUT_MODE__MAX: /* Silence warning; impossible branch */ break; } =20 +#if defined(G_OS_WIN32) + /* FIXME: see comment in guest_exec_task_setup() */ + if (has_merge) { + error_setg(errp, "all-merge unsupported on windows"); + return NULL; + } +#endif + ret =3D g_spawn_async_with_pipes(NULL, argv, envp, flags, - guest_exec_task_setup, NULL, &pid, input_data ? &in_fd : NULL, + guest_exec_task_setup, &has_merge, &pid, input_data ? &in_fd := NULL, has_output ? &out_fd : NULL, has_output ? &err_fd : NULL, &ger= r); if (!ret) { error_setg(errp, QERR_QGA_COMMAND_FAILED, gerr->message); diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 4ef585da5d..d364ab78de 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1209,11 +1209,13 @@ # @stdout: only capture stdout # @stderr: only capture stderr # @all: capture both stdout and stderr +# @all-merge: capture both stdout and stderr and merge together +# into stdout. not effective on windows guests. # # Since: 8.0 ## { 'enum': 'GuestExecCaptureOutputMode', - 'data': [ 'none', 'stdout', 'stderr', 'all' ] } + 'data': [ 'none', 'stdout', 'stderr', 'all', 'all-merge' ] } =20 ## # @GuestExecCaptureOutput: --=20 2.39.1 From nobody Thu May 2 21:39:51 2024 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1678315843636840.6758817621112; Wed, 8 Mar 2023 14:50:43 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pa2bq-0001R1-Sz; Wed, 08 Mar 2023 17:50:10 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bo-0001P3-Uv for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:09 -0500 Received: from out2-smtp.messagingengine.com ([66.111.4.26]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pa2bm-00084l-Tz for qemu-devel@nongnu.org; Wed, 08 Mar 2023 17:50:08 -0500 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 66F235C012D; Wed, 8 Mar 2023 17:50:06 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Wed, 08 Mar 2023 17:50:06 -0500 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 8 Mar 2023 17:50:05 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dxuuu.xyz; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm3; t=1678315806; x= 1678402206; bh=xQTrFt+LfgKM0nx7+MDilf5Eq/wi2bQFetpOeY/fifU=; b=u IJx4jE8lJWzsMfQ4QWR4WstOYFNke2cXeENlRkRdVZMpiwJo+zI/g9+AyB1/RFE7 zKSAutoIynNpK7Z7sJQa9hj2SCsuwpo44bA5SnUUe253T0Lj2r0c231GCuDPJrDz VcWUbHnw1z4SPbKPS+oqxt77uWbYxMZjcCSaV6h2gUO0ruVxMliSnpOhg26BWwaK 4DZi+JGGGncimzMuOLU5U6ZfxnzySZxtFYUsNX8WtOoJVTjw6QonP8AjM+ZezeeH S9kpSOckpuwF75sW3Je35bIuG1xZhvfuSMh7UsdJQBAZ8+52S23iFLEVVFI0k2ql jsfnIkkVbh7eK23pU41uQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1678315806; x= 1678402206; bh=xQTrFt+LfgKM0nx7+MDilf5Eq/wi2bQFetpOeY/fifU=; b=h 9tbAzT+HSSmiJXmV04XzcKZ0jMdf435URQaauItTqs7571dXeg7FslMcWnNIO7ef LGpXRJ8TsoVIvpZCyGW14U40B2MLKhTpyj14cILzHcnmEI+QwoZ57ql4WLeCZaGy sxcI16+PatkDp0TCTLLb/NKaXBaNt7JujbH3z8aMxiylHeAKyKaX3yNAX3yWV5GQ W5JOcBeUcH9bZ8yMf3MphAsNBD4yMzauoDwdLfMdZgrhoiY0Hz3tcrDdyHnwOIwY gEY6RafXBldQbw877FaPc6YwNPDSXmVyOzmbnr3vxSmoMhhlSy1FCAog75UT3LhR /wvnPcn5q4G8spgtCC73A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvddugecutefuodetggdotefrodftvfcurf hrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecufghrlhcuvffnffculdejtddmnecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomhepffgrnhhivghlucgiuhcuoegugihu segugihuuhhurdighiiiqeenucggtffrrghtthgvrhhnpefgfefggeejhfduieekvdeute ffleeifeeuvdfhheejleejjeekgfffgefhtddtteenucevlhhushhtvghrufhiiigvpedt necurfgrrhgrmhepmhgrihhlfhhrohhmpegugihusegugihuuhhurdighiii X-ME-Proxy: Feedback-ID: i6a694271:Fastmail From: Daniel Xu To: kkostiuk@redhat.com, michael.roth@amd.com, marcandre.lureau@gmail.com, berrange@redhat.com Cc: qemu-devel@nongnu.org Subject: [PATCH v4 3/3] qga: test: Add tests for `all-merge` flag Date: Wed, 8 Mar 2023 15:49:41 -0700 Message-Id: <31e6def3bd18f1f06632c773bd45fd5a83e58f78.1678314204.git.dxu@dxuuu.xyz> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=66.111.4.26; envelope-from=dxu@dxuuu.xyz; helo=out2-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_PASS=-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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZM-MESSAGEID: 1678315845486100003 Content-Type: text/plain; charset="utf-8" This commit adds a test to ensure `all-merge` functions as expected. We also add a negative test to ensure we haven't regressed previous functionality. Signed-off-by: Daniel Xu --- tests/unit/test-qga.c | 158 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 17 deletions(-) diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index b4e0a14573..fcb84ab81f 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -755,6 +755,31 @@ static void test_qga_fsfreeze_status(gconstpointer fix) g_assert_cmpstr(status, =3D=3D, "thawed"); } =20 +static QDict *wait_for_guest_exec_completion(int fd, int64_t pid) +{ + QDict *ret =3D NULL; + int64_t now; + bool exited; + QDict *val; + + now =3D g_get_monotonic_time(); + do { + ret =3D qmp_fd(fd, + "{'execute': 'guest-exec-status'," + " 'arguments': { 'pid': %" PRId64 " } }", pid); + g_assert_nonnull(ret); + val =3D qdict_get_qdict(ret, "return"); + exited =3D qdict_get_bool(val, "exited"); + if (!exited) { + qobject_unref(ret); + } + } while (!exited && + g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND); + g_assert(exited); + + return ret; +} + static void test_qga_guest_exec(gconstpointer fix) { const TestFixture *fixture =3D fix; @@ -762,9 +787,8 @@ static void test_qga_guest_exec(gconstpointer fix) QDict *val; const gchar *out; g_autofree guchar *decoded =3D NULL; - int64_t pid, now, exitcode; + int64_t pid, exitcode; gsize len; - bool exited; =20 /* exec 'echo foo bar' */ ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" @@ -777,23 +801,10 @@ static void test_qga_guest_exec(gconstpointer fix) g_assert_cmpint(pid, >, 0); qobject_unref(ret); =20 - /* wait for completion */ - now =3D g_get_monotonic_time(); - do { - ret =3D qmp_fd(fixture->fd, - "{'execute': 'guest-exec-status'," - " 'arguments': { 'pid': %" PRId64 " } }", pid); - g_assert_nonnull(ret); - val =3D qdict_get_qdict(ret, "return"); - exited =3D qdict_get_bool(val, "exited"); - if (!exited) { - qobject_unref(ret); - } - } while (!exited && - g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND); - g_assert(exited); + ret =3D wait_for_guest_exec_completion(fixture->fd, pid); =20 /* check stdout */ + val =3D qdict_get_qdict(ret, "return"); exitcode =3D qdict_get_int(val, "exitcode"); g_assert_cmpint(exitcode, =3D=3D, 0); out =3D qdict_get_str(val, "out-data"); @@ -802,6 +813,115 @@ static void test_qga_guest_exec(gconstpointer fix) g_assert_cmpstr((char *)decoded, =3D=3D, "\" test_str \""); } =20 +#if defined(G_OS_WIN32) +static void test_qga_guest_exec_all_no_merge(gconstpointer fix) +{ +} +static void test_qga_guest_exec_all_merge(gconstpointer fix) +{ + const TestFixture *fixture =3D fix; + g_autoptr(QDict) ret =3D NULL; + QDict *val; + const gchar *class, *desc; + g_autofree guchar *decoded =3D NULL; + + /* exec 'echo foo bar' */ + ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" + " 'path': 'echo'," + " 'arg': [ 'execution never reaches here' ]," + " 'capture-output': 'all-merge' } }"); + + g_assert_nonnull(ret); + val =3D qdict_get_qdict(ret, "error"); + g_assert_nonnull(val); + class =3D qdict_get_str(val, "class"); + desc =3D qdict_get_str(val, "desc"); + g_assert_cmpstr(class, =3D=3D, "GenericError"); + g_assert_cmpint(strlen(desc), >, 0); +} +#else +static void test_qga_guest_exec_all_no_merge(gconstpointer fix) +{ + const TestFixture *fixture =3D fix; + g_autoptr(QDict) ret =3D NULL; + QDict *val; + const gchar *out, *err; + g_autofree guchar *out_decoded =3D NULL; + g_autofree guchar *err_decoded =3D NULL; + int64_t pid, exitcode; + gsize len; + + /* exec 'echo foo bar' */ + ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" + " 'path': '/bin/bash'," + " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 ));= then echo stdout; else echo stderr 1>&2; fi; done;' ]," + " 'capture-output': 'all' } }"); + g_assert_nonnull(ret); + qmp_assert_no_error(ret); + val =3D qdict_get_qdict(ret, "return"); + pid =3D qdict_get_int(val, "pid"); + g_assert_cmpint(pid, >, 0); + qobject_unref(ret); + + ret =3D wait_for_guest_exec_completion(fixture->fd, pid); + + val =3D qdict_get_qdict(ret, "return"); + exitcode =3D qdict_get_int(val, "exitcode"); + g_assert_cmpint(exitcode, =3D=3D, 0); + + /* check stdout */ + out =3D qdict_get_str(val, "out-data"); + out_decoded =3D g_base64_decode(out, &len); + g_assert_cmpint(len, =3D=3D, 14); + g_assert_cmpstr((char *)out_decoded, =3D=3D, "stdout\nstdout\n"); + + /* check stderr */ + err =3D qdict_get_try_str(val, "err-data"); + err_decoded =3D g_base64_decode(err, &len); + g_assert_cmpint(len, =3D=3D, 14); + g_assert_cmpstr((char *)err_decoded, =3D=3D, "stderr\nstderr\n"); +} + +static void test_qga_guest_exec_all_merge(gconstpointer fix) +{ + const TestFixture *fixture =3D fix; + g_autoptr(QDict) ret =3D NULL; + QDict *val; + const gchar *out, *err; + g_autofree guchar *decoded =3D NULL; + int64_t pid, exitcode; + gsize len; + + /* exec 'echo foo bar' */ + ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" + " 'path': '/bin/bash'," + " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 ));= then echo stdout; else echo stderr 1>&2; fi; done;' ]," + " 'capture-output': 'all-merge' } }"); + g_assert_nonnull(ret); + qmp_assert_no_error(ret); + val =3D qdict_get_qdict(ret, "return"); + pid =3D qdict_get_int(val, "pid"); + g_assert_cmpint(pid, >, 0); + qobject_unref(ret); + + ret =3D wait_for_guest_exec_completion(fixture->fd, pid); + + val =3D qdict_get_qdict(ret, "return"); + exitcode =3D qdict_get_int(val, "exitcode"); + g_assert_cmpint(exitcode, =3D=3D, 0); + + /* check stdout */ + out =3D qdict_get_str(val, "out-data"); + decoded =3D g_base64_decode(out, &len); + g_assert_cmpint(len, =3D=3D, 28); + g_assert_cmpstr((char *)decoded, =3D=3D, "stdout\nstderr\nstdout\nstde= rr\n"); + + /* check stderr */ + err =3D qdict_get_try_str(val, "err-data"); + g_assert_null(err); +} +#endif + static void test_qga_guest_exec_invalid(gconstpointer fix) { const TestFixture *fixture =3D fix; @@ -972,6 +1092,10 @@ int main(int argc, char **argv) g_test_add_data_func("/qga/blockedrpcs", NULL, test_qga_blockedrpcs); g_test_add_data_func("/qga/config", NULL, test_qga_config); g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec); + g_test_add_data_func("/qga/guest-exec-all-no-merge", &fix, + test_qga_guest_exec_all_no_merge); + g_test_add_data_func("/qga/guest-exec-all-merge", &fix, + test_qga_guest_exec_all_merge); g_test_add_data_func("/qga/guest-exec-invalid", &fix, test_qga_guest_exec_invalid); g_test_add_data_func("/qga/guest-get-osinfo", &fix, --=20 2.39.1