From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: "Denis V. Lunev" <den@openvz.org>
Cc: Olga Krishtal <okrishtal@parallels.com>,
qemu-devel@nongnu.org, Semen Zolin <szolin@parallels.com>
Subject: Re: [Qemu-devel] [PATCH v2 0/8] qemu: guest agent: implement guest-exec command for Linux
Date: Fri, 09 Jan 2015 11:06:21 -0600 [thread overview]
Message-ID: <20150109170621.8810.42855@loki> (raw)
In-Reply-To: <1420031214-6053-1-git-send-email-den@openvz.org>
Quoting Denis V. Lunev (2014-12-31 07:06:46)
> hese patches for guest-agent add the functionality to execute commands on
> a guest UNIX machine.
Hi Denis,
Glad to see these getting picked up. I did at some point hack up a rewrite
of the original code though which has some elements might be worth considering
incorporating into your patchset.
The main one is the use of g_spawn_async_with_pipes(), which wraps fork/exec
vs. CreateProcess() and allows for more shared code between posix/win32.
It also creates the stdin/out/err FDs for you, which I suppose we could
do ourselves manually here as well, but it also raises the question of
whether guest-pipe-open is really necessary. In my code I ended up dropping
it since I can't imagine a use-case outside of guest-exec, but in doing so
also I dropped the ability to pipe one process into another...
But thinking about it more I think you can still pipe one process into
another by dup2()'ing the stdin FD returned by g_spawn_async_with_pipes()
to whatever stdout/stderr you wish to specify from a previous process.
The other one worth considering is allowing cmdline to simply be a string,
to parse it into arguments using g_shell_parse_argv(), which should also
be cross-platform.
If you do things that the core exec code ends up looking something like
this:
static GuestExecInfo *guest_exec_spawn(const char *cmdline, bool interactive,
Error **errp)
{
GSpawnFlags default_flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;
gboolean ret;
GPid gpid;
gchar **argv;
gint argc;
GError *gerr = NULL;
gint fd_in = -1, fd_out = -1, fd_err = -1;
ret = g_shell_parse_argv(cmdline, &argc, &argv, &gerr);
if (!ret || gerr) {
error_setg(errp, "failed to parse command: %s, %s", cmdline,
gerr->message);
return NULL;
}
ret = g_spawn_async_with_pipes(NULL, argv, NULL,
default_flags, NULL, NULL, &gpid,
interactive ? &fd_in : NULL, &fd_out, &fd_err, &gerr);
if (gerr) {
error_setg(errp, "failed to execute command: %s, %s", cmdline,
gerr->message);
return NULL;
}
if (!ret) {
error_setg(errp, "failed to execute command");
return NULL;
}
return guest_exec_info_new(gpid, cmdline, fd_in, fd_out, fd_err);
}
GuestExecResponse *qmp_guest_exec_async(const char *cmdline,
bool has_interactive,
bool interactive,
Error **errp)
{
GuestExecResponse *ger;
GuestExecInfo *gei;
int32_t handle;
gei = guest_exec_spawn(cmdline, has_interactive && interactive, errp);
if (error_is_set(errp)) {
return NULL;
}
print_gei(gei);
ger = g_new0(GuestExecResponse, 1);
if (has_interactive && interactive) {
ger->has_handle_stdin = true;
ger->handle_stdin =
guest_file_handle_add_fd(gei->fd_in, "a", errp);
if (error_is_set(errp)) {
return NULL;
}
}
ger->has_handle_stdout = true;
ger->handle_stdout =
guest_file_handle_add_fd(gei->fd_out, "r", errp);
if (error_is_set(errp)) {
return NULL;
}
ger->has_handle_stderr = true;
ger->handle_stderr =
guest_file_handle_add_fd(gei->fd_err, "r", errp);
if (error_is_set(errp)) {
return NULL;
}
handle = guest_exec_info_register(gei);
ger->status = qmp_guest_exec_status(handle, false, false, false, 0, errp);
if (error_is_set(errp)) {
return NULL;
}
return ger;
}
Where GuestExecResponse takes the place of the original PID return, since
we now need to fetch the stdin/stdout/stderr handles as well. In my code
it was defined as:
{ 'type': 'GuestExecResponse',
'data': { 'status': 'GuestExecStatus',
'*handle-stdin': 'int', '*handle-stdout': 'int',
'*handle-stderr': 'int' } }
Sorry for not just posting the patchset somewhere, the code was initially lost
in an accidental wipe of /home so I currently only have vim backup files to
piece it together from atm.
>
> These patches add the following interfaces:
>
> guest-pipe-open
> guest-exec
> guest-exec-status
>
> With these interfaces it's possible to:
>
> * Open an anonymous pipe and work with it as with a file using already
> implemented interfaces guest-file-{read,write,flush,close}.
>
> * Execute a binary or a script on a guest machine.
> We can pass arbitrary arguments and environment to a new child process.
>
> * Pass redirected IO from/to stdin, stdout, stderr from a child process to a
> local file or an anonymous pipe.
>
> * Check the status of a child process, get its exit status if it exited or get
> signal number if it was killed.
>
> We plan to add support for Windows in the near future using the same interfaces
> we introduce here.
>
> Example of usage:
>
> {"execute": "guest-pipe-open", "arguments":{"mode": "r"}}
> {'return': 1000}
>
> {"execute":"guest-exec", "arguments":{ "path": "id", "params": ["user"],
> "env": ["MYENV=myvalue"], "handle_stdout": 1000 }}'
> {"return": 2636}
>
> {"execute": "guest-exec-status", "arguments": {"pid": 2636}}
> {"return":{"exit":0,"handle_stderr":-1,"handle_stdin":-1,"handle_stdout":1000,"signal":-1}}
>
> {"execute": "guest-file-read", "arguments": {"handle": 1000, "count":128}}
> {"return":{"count":58,"buf-b64":"dWlk...","eof":true}}
>
> {"execute": "guest-file-close", "arguments": {"handle": 1000}}
> {"return":{}}
>
>
> These patches are based on the patches proposed by Michael Roth in 2011:
> http://lists.gnu.org/archive/html/qemu-devel/2011-12/msg00722.html
>
> We made several modifications to the interfaces proposed by Michael to simplify
> their usage and we also added several new functions:
>
> * Arguments to an executable file are passed as an array of strings.
>
> Before that we had to pass parameters like this:
> 'params': [ {'param': '-b'}, {'param': '-n1'} ]
>
> Now we may pass them just as an array of strings:
> 'params': [ '-b', '-n1' ]
>
> * Environment can be passed to a child process.
>
> "env": ["MYENV=myvalue"]
>
> * Removed "detach" argument from "guest-exec" - it never waits for a child
> process to signal. With this change it's possible to return just PID from
> "guest-exec", a user must call "guest-exec-status" to get the status of a child.
>
> * Removed "wait" argument from "guest-exec-status" - waiting for a child process
> to signal is dangerous, because it may block the whole qemu-ga. Instead, the
> command polls just once a status of a child.
>
> * "guest-exec-status" returns exit status of a child process or a signal number,
> in case a process was killed.
>
> * Simplified the command "guest-pipe-open" - the way how it stores the pipe
> fd's. No additional logic is needed about which end of pipe should be closed
> with "guest-file-close". This way we avoid modifying the interface of the
> existing "guest-file-close".
>
> In the conversation about the original patches there was a suggestion to merge
> "path" and "params" into one single list. But we didn't do so, because having
> separate "path" is similar to exec*() family functions in UNIX. That way it
> looks more consistent.
>
> Changes from v1:
> - Windows version of the patchset is added
> - SIGPIPE processing is added for Unix version of the patchset
> - added guest_exec_file_busy() to prevent GuestFileHandle* object from being
> deleted in case it's used in guest-exec command.
>
> Signed-off-by: Semen Zolin <szolin@parallels.com>
> Signed-off-by: Olga Krishtal <okrishtal@parallels.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
next prev parent reply other threads:[~2015-01-09 17:06 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-31 13:06 [Qemu-devel] [PATCH v2 0/8] qemu: guest agent: implement guest-exec command for Linux Denis V. Lunev
2014-12-31 13:06 ` [Qemu-devel] [PATCH 1/8] qga: fixed warning in qemu-ga.exe for mingw >= 4.9.1 Denis V. Lunev
2015-02-03 21:29 ` Eric Blake
2015-02-04 14:25 ` Olga Krishtal
2014-12-31 13:06 ` [Qemu-devel] [PATCH 2/8] qga: implement file commands for Windows guest Denis V. Lunev
2015-02-03 21:15 ` Michael Roth
2014-12-31 13:06 ` [Qemu-devel] [PATCH 3/8] guest agent: guest-file-open: refactoring Denis V. Lunev
2015-02-03 22:04 ` Eric Blake
2014-12-31 13:06 ` [Qemu-devel] [PATCH 4/8] guest agent: add guest-pipe-open Denis V. Lunev
2015-02-03 21:57 ` Eric Blake
2015-02-03 22:06 ` Eric Blake
2014-12-31 13:06 ` [Qemu-devel] [PATCH 5/8] guest agent: add guest-exec and guest-exec-status interfaces Denis V. Lunev
2015-02-03 21:45 ` Eric Blake
2014-12-31 13:06 ` [Qemu-devel] [PATCH 6/8] guest agent: ignore SIGPIPE signal Denis V. Lunev
2014-12-31 13:06 ` [Qemu-devel] [PATCH 7/8] guest agent: add guest-pipe-open command on Windows Denis V. Lunev
2014-12-31 13:06 ` [Qemu-devel] [PATCH 8/8] guest agent: add guest-exec and guest-exec-status interfaces " Denis V. Lunev
2015-01-09 17:06 ` Michael Roth [this message]
2015-01-09 17:10 ` [Qemu-devel] [PATCH v2 0/8] qemu: guest agent: implement guest-exec command for Linux Eric Blake
2015-01-09 18:09 ` Denis V. Lunev
2015-01-09 19:29 ` Michael Roth
2015-01-13 10:13 ` Denis V. Lunev
2015-02-03 20:24 ` Michael Roth
2015-02-03 21:31 ` Denis V. Lunev
2015-01-27 13:52 ` Denis V. Lunev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150109170621.8810.42855@loki \
--to=mdroth@linux.vnet.ibm.com \
--cc=den@openvz.org \
--cc=okrishtal@parallels.com \
--cc=qemu-devel@nongnu.org \
--cc=szolin@parallels.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.