From nobody Sun May 5 05:51:13 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 1679530844394931.1682978399153; Wed, 22 Mar 2023 17:20:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pf8gS-0007eK-Qx; Wed, 22 Mar 2023 20:20:01 -0400 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 1pf8gH-0007dE-TB for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:51 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pf8gG-0005fW-4y for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:49 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id B3D7B5C00E9; Wed, 22 Mar 2023 20:19:47 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Wed, 22 Mar 2023 20:19:47 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Mar 2023 20:19:46 -0400 (EDT) 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=fm1; t= 1679530787; x=1679617187; bh=O86jAUROcuMAf5eThlp+O6BhkjqpUq6KDyY eULVJdb4=; b=ZzVegQd8uRfM9rc+4xjwN/biV9GS3n8rU2BkiD/3Fu4W6RmZw+e GNPeD1fjLwuio6BJwbfQdP74K+L2IZsLJefkpPz1F97Xt+HvQE0DHFyN2Otg3e3e DfKPs8op9aZ1ZtS74tIUOi6NX65MU/aqcMQyYPO9h853QLIg81+46XF7RmpLAR3P aR8NAmsxzVPLdpPbvD9LQehE80igYr+ZpCUaT7y+bcGJCJI7BPPWRtewATrp7WCp 89+euEg43H+RpY4Yjlq3Y0J0isZ2vpfcvzhoEv6e9mxFs4XjaBRMGxlC5cq2diPk JnOFr+USl3wbInMHMur0lbCfz3EnJU2uBBA== 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=fm2; t= 1679530787; x=1679617187; bh=O86jAUROcuMAf5eThlp+O6BhkjqpUq6KDyY eULVJdb4=; b=g6tYeJfmfJm9v5ftxzYIjH1K7LLPLoCCjZ4Hlt0r/5f1vIeu8eJ qpP4RfTbEa6vv7t00Tbw0i8ZGbou1iDqgw6/694MTEDA1CU/tDMMMEhTO3fwzxAo OkFnN/sXOFlFMzHsDqt0Uc1NIiByA0zjcrAfOpRgZFVrlwMGDvI78a8kICxaBHOJ hBglFRyiPaHSlRpV8mj2Uyaoq2CwAOahH6OiVEziWkkkA1t+++v16Z7fC4yXzUdF fQvJsrULichWqu4+y/VurIoMWuMDPU3Di2vEEgQNwXY9LrVGB+/HS4bFOvr6djcO 82nWnEKlpR2bK/BG8CqJ1TZUR63XVxIKdwg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdegfedgvddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucgfrhhlucfvnfffucdlfeehmdenucfjughrpefhvf evufffkffojghfgggtgfesthekredtredtjeenucfhrhhomhepffgrnhhivghlucgiuhcu oegugihusegugihuuhhurdighiiiqeenucggtffrrghtthgvrhhnpeetheekkefggfeive dvtefgleeiffdtleegfeeuledvuddtvdduhfekgfdutdevkeenucevlhhushhtvghrufhi iigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegugihusegugihuuhhurdighiii 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 v6 1/3] qga: Refactor guest-exec capture-output to take enum Date: Wed, 22 Mar 2023 18:19:26 -0600 Message-Id: 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.29; envelope-from=dxu@dxuuu.xyz; helo=out5-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, 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: 1679530845058100001 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 Reviewed-by: Daniel P. Berrang=C3=A9 Signed-off-by: Daniel Xu --- qga/commands.c | 37 ++++++++++++++++++++++++++++++++++--- qga/qapi-schema.json | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/qga/commands.c b/qga/commands.c index 172826f8f8..01f68b45ab 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_SEP= ARATED + : 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_SEPARATED: + 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..d1e00a4234 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1200,6 +1200,37 @@ { '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 +# @separated: capture both stdout and stderr, but separated into +# GuestExecStatus out-data and err-data, respectively +# +# Since: 8.0 +## + { 'enum': 'GuestExecCaptureOutputMode', + 'data': [ 'none', 'stdout', 'stderr', 'separated' ] } + +## +# @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 +1249,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 Sun May 5 05:51:13 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 1679530869750690.5634355947544; Wed, 22 Mar 2023 17:21:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pf8ga-0007iY-1F; Wed, 22 Mar 2023 20:20:08 -0400 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 1pf8gI-0007dF-NF for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:52 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pf8gG-0005fa-UW for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:50 -0400 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 7FEC55C016A; Wed, 22 Mar 2023 20:19:48 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Wed, 22 Mar 2023 20:19:48 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Mar 2023 20:19:47 -0400 (EDT) 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=fm1; t=1679530788; x= 1679617188; bh=EsWfeB8H0OpI9E8ri8JT0/6raJPZMclIjTMCoAentAw=; b=e BpgL6hQiaKgUDFpB77Qb6UsOO6J6Hn2dkmqUMb3xyj/k6C/KZl+R4KkWK6vVJTVW am+dk6RzzKS5oxIoeTyP/O7ImWk+Bw6WPsRParK+ypChTGV0E6ymb5iXOU1C6oY2 kLQQbRcOsFcNVl5MYTCok0DPs0KWZj3fj7cpC9LlKBoe67q45YBpdVi2uEF9o4ws LonsLXzDlzZgHy9ocqrmYLibPWibb74xjMi4DzbH2YaRGGvM2KJcSaGS4RsmVu0a /n3sFFE4ISbYlkXZNjUjeQFWyn6CT1BZY/4Bjx6Tvi4KHSWIgA5sWVAqba1Vu3Ai telWNroSIHkXQ5UvCrTfA== 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=fm2; t=1679530788; x= 1679617188; bh=EsWfeB8H0OpI9E8ri8JT0/6raJPZMclIjTMCoAentAw=; b=Q qg3KEboNW3egnEC6FqZY2fSYE+COlkSEeTX3LaBUJgct2ys9Eb3Q3pcjf1+r/fqY XzrSRko0dalye2Orfc6wZBb+62G35p83R8nt1v/JtiYKiJpa/51BS/lFxStNMqeX zX5TYUmFmJBB9VAvF4cYXbWXi5ri9rkT2fQpkvUWz9vgsf4cz1KHKywXLvVlG94P Fx+XXr42q/IkkbYuQJ4aWW1NlLWd8Rb1mz2qQXBfLDYP2WRIQjjGJZGn8leug5NN onic2nwUnQLQ3rEG2glXuzRTGIUy/4qiX5XzrtwHnpmqF3FlUSg4OiOtC3qGg3su IfEyRV4iDTQruajnBYJMg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdegfedgvddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucgfrhhlucfvnfffucdljedtmdenucfjughrpefhvf evufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeffrghnihgvlhcuighuuceo ugiguhesugiguhhuuhdrgiihiieqnecuggftrfgrthhtvghrnhepgfefgfegjefhudeike dvueetffelieefuedvhfehjeeljeejkefgffeghfdttdetnecuvehluhhsthgvrhfuihii vgeptdenucfrrghrrghmpehmrghilhhfrhhomhepugiguhesugiguhhuuhdrgiihii 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 v6 2/3] qga: Add `merged` variant to GuestExecCaptureOutputMode Date: Wed, 22 Mar 2023 18:19:27 -0600 Message-Id: <9b355e4fe0574022459c0fd94ed30de3b7415011.1679530587.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.29; envelope-from=dxu@dxuuu.xyz; helo=out5-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, 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: 1679530871215100003 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 Reviewed-by: Daniel P. Berrang=C3=A9 --- qga/commands.c | 25 +++++++++++++++++++++++-- qga/qapi-schema.json | 5 ++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/qga/commands.c b/qga/commands.c index 01f68b45ab..09c683e263 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,19 @@ GuestExec *qmp_guest_exec(const char *path, case GUEST_EXEC_CAPTURE_OUTPUT_MODE_SEPARATED: has_output =3D true; break; +#if !defined(G_OS_WIN32) + case GUEST_EXEC_CAPTURE_OUTPUT_MODE_MERGED: + has_output =3D true; + has_merge =3D true; + break; +#endif case GUEST_EXEC_CAPTURE_OUTPUT_MODE__MAX: /* Silence warning; impossible branch */ break; } =20 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 d1e00a4234..39dd006d16 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1210,11 +1210,14 @@ # @stderr: only capture stderr # @separated: capture both stdout and stderr, but separated into # GuestExecStatus out-data and err-data, respectively +# @merged: capture both stdout and stderr, but merge together +# into out-data. not effective on windows guests. # # Since: 8.0 ## { 'enum': 'GuestExecCaptureOutputMode', - 'data': [ 'none', 'stdout', 'stderr', 'separated' ] } + 'data': [ 'none', 'stdout', 'stderr', 'separated', + { 'name': 'merged', 'if': { 'not': 'CONFIG_WIN32' } } ] } =20 ## # @GuestExecCaptureOutput: --=20 2.39.1 From nobody Sun May 5 05:51:13 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 1679530857469389.37290186674716; Wed, 22 Mar 2023 17:20:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pf8ga-0007iz-K4; Wed, 22 Mar 2023 20:20:08 -0400 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 1pf8gJ-0007dI-Pc for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:54 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pf8gH-0005ff-MK for qemu-devel@nongnu.org; Wed, 22 Mar 2023 20:19:51 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 3E6F45C00E8; Wed, 22 Mar 2023 20:19:49 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Wed, 22 Mar 2023 20:19:49 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Mar 2023 20:19:48 -0400 (EDT) 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=fm1; t= 1679530789; x=1679617189; bh=IGHLqqNiDmgU13SjSAGFc98CRdKinjQJXaq NCCC9s+k=; b=t39AkN5Ec44Ohz42HY9zTvkS4TAZU8fDTPF/WaGgFeDZr6ASLMm nTo92c9fl7LZvsXSlGSFki542TccdprIums7LLrvYSNSFneChb/4O2ocr3tnHKQh C0b18yXa8XyRmZ7x6pwhDJvmD8wgEU9/wEU697BrPP5howVjKaRKsIOJKxzChNMY dzWSwS4Lj0iIjfBhRtkSClwLpf5RG9Xq18zRhwiJZ+vgjfuYyXWn43tzD91kCg2s D3NTV78OtBUvCLa5+KPGEiU75r3ymsId9ZSbzVLRU7Y+UBp7lUpL/j8GAyI1ss8t o+X0y3Pevvghfv0RpoHWw/SNqg1ygew4p3g== 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=fm2; t= 1679530789; x=1679617189; bh=IGHLqqNiDmgU13SjSAGFc98CRdKinjQJXaq NCCC9s+k=; b=AjQD1fUt4bGYxSiwyepfxs2Q3eOAJBP3K3Jlgok+k/6fmMH80pV V4y39P2CrmocTZ+xGHJ5suC5EuwsusovZyM3t3MthPVW1b7Xj2MRaoGoY+ubVTB3 1ipchKZLKzmoJxO8jZ8ZIW4DoNh7Td8LGGOiVGOMFQx9ZiCfxkjdKvxoakfpgEPL JCW6VEmswrynO48Hhb5c5xzgcguXcuplhOVFQ465qkLEeVrdcys9CwXvaPfoRq9B ic1PUZzDDIDsesjYSX4VU4cVpMp2rpUQUfTeP2wZdD13bL0ZRM41rriGX/aldbj7 ejMDFVVQnqJSDysda7/du01VtHPCODuoRJQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdegfedgvddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucgfrhhlucfvnfffucdlfeehmdenucfjughrpefhvf evufffkffojghfgggtgfesthekredtredtjeenucfhrhhomhepffgrnhhivghlucgiuhcu oegugihusegugihuuhhurdighiiiqeenucggtffrrghtthgvrhhnpeetheekkefggfeive dvtefgleeiffdtleegfeeuledvuddtvdduhfekgfdutdevkeenucevlhhushhtvghrufhi iigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegugihusegugihuuhhurdighiii 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 v6 3/3] qga: test: Add tests for `merged` flag Date: Wed, 22 Mar 2023 18:19:28 -0600 Message-Id: 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.29; envelope-from=dxu@dxuuu.xyz; helo=out5-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, 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: 1679530859106100003 This commit adds a test to ensure `merged` functions as expected. We also add a negative test to ensure we haven't regressed previous functionality. Reviewed-by: Daniel P. Berrang=C3=A9 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..360b4cab23 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_separated(gconstpointer fix) +{ +} +static void test_qga_guest_exec_merged(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': 'merged' } }"); + + 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_separated(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': 'separated' } }"); + 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_merged(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': 'merged' } }"); + 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-separated", &fix, + test_qga_guest_exec_separated); + g_test_add_data_func("/qga/guest-exec-merged", &fix, + test_qga_guest_exec_merged); 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