[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/3] qga: Add optional stream-output argument to guest-exec
From: |
Daniel Xu |
Subject: |
[PATCH 2/3] qga: Add optional stream-output argument to guest-exec |
Date: |
Mon, 18 Sep 2023 04:54:22 -0600 |
Currently, commands run through guest-exec are "silent" until they
finish running. This is fine for short lived commands. But for commands
that take a while, this is a bad user experience.
Usually long running programs know that they will run for a while. To
improve user experience, they will typically print some kind of status
to output at a regular interval. So that the user knows that their
command isn't just hanging.
This commit adds support for an optional stream-output parameter to
guest-exec. This causes subsequent calls to guest-exec-status to return
all buffered output. This allows downstream applications to be able to
relay "status" to the end user.
If stream-output is requested, it is up to the guest-exec-status caller
to keep track of the last seen output position and slice the returned
output appropriately. This is fairly trivial for a client to do. And it
is a more reliable design than having QGA internally keep track of
position -- for the cases that the caller "loses" a response.
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
qga/commands.c | 12 ++++++++++++
qga/qapi-schema.json | 7 ++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/qga/commands.c b/qga/commands.c
index ce172edd2d..8cabc2460f 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -97,6 +97,7 @@ struct GuestExecInfo {
int64_t pid_numeric;
gint status;
bool has_output;
+ bool stream_output;
bool finished;
GuestExecIOData in;
GuestExecIOData out;
@@ -218,6 +219,15 @@ GuestExecStatus *qmp_guest_exec_status(int64_t pid, Error
**errp)
QTAILQ_REMOVE(&guest_exec_state.processes, gei, next);
g_free(gei);
+ } else if (gei->stream_output) {
+ if (gei->out.length > 0) {
+ ges->out_data = g_base64_encode(gei->out.data, gei->out.length);
+ ges->has_out_truncated = gei->out.truncated;
+ }
+ if (gei->err.length > 0) {
+ ges->err_data = g_base64_encode(gei->err.data, gei->err.length);
+ ges->has_err_truncated = gei->err.truncated;
+ }
}
return ges;
@@ -410,6 +420,7 @@ GuestExec *qmp_guest_exec(const char *path,
bool has_env, strList *env,
const char *input_data,
GuestExecCaptureOutput *capture_output,
+ bool has_stream_output, bool stream_output,
Error **errp)
{
GPid pid;
@@ -485,6 +496,7 @@ GuestExec *qmp_guest_exec(const char *path,
gei = guest_exec_info_add(pid);
gei->has_output = has_output;
+ gei->stream_output = has_stream_output && stream_output;
g_child_watch_add(pid, guest_exec_child_watch, gei);
if (input_data) {
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index b720dd4379..0a76e35082 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1315,13 +1315,18 @@
# @capture-output: bool flag to enable capture of stdout/stderr of
# running process. defaults to false.
#
+# @stream-output: causes future guest-exec-status calls to always
+# return current captured output rather than waiting to return
+# it all when the command exits. defaults to false. (since: 8.2)
+#
# Returns: PID on success.
#
# Since: 2.5
##
{ 'command': 'guest-exec',
'data': { 'path': 'str', '*arg': ['str'], '*env': ['str'],
- '*input-data': 'str', '*capture-output':
'GuestExecCaptureOutput' },
+ '*input-data': 'str', '*capture-output':
'GuestExecCaptureOutput',
+ '*stream-output': 'bool' },
'returns': 'GuestExec' }
--
2.41.0