From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com,
Jes.Sorensen@redhat.com, mdroth@linux.vnet.ibm.com,
aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com,
abeekhof@redhat.com
Subject: [Qemu-devel] [RFC][PATCH v5 19/21] virtagent: add virtagent guest daemon
Date: Fri, 3 Dec 2010 12:03:20 -0600 [thread overview]
Message-ID: <1291399402-20366-20-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1291399402-20366-1-git-send-email-mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
Makefile | 4 +-
qemu-va.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 330 insertions(+), 1 deletions(-)
create mode 100644 qemu-va.c
diff --git a/Makefile b/Makefile
index 4e120a2..556c853 100644
--- a/Makefile
+++ b/Makefile
@@ -150,7 +150,7 @@ version-obj-$(CONFIG_WIN32) += version.o
######################################################################
qemu-img.o: qemu-img-cmds.h
-qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)
+qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o qemu-va.o: $(GENERATED_HEADERS)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
@@ -158,6 +158,8 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-ob
qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+qemu-va$(EXESUF): qemu-va.o virtagent.o virtagent-server.o virtagent-common.o qemu-tool.o qemu-error.o qemu-sockets.c $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
diff --git a/qemu-va.c b/qemu-va.c
new file mode 100644
index 0000000..1035b50
--- /dev/null
+++ b/qemu-va.c
@@ -0,0 +1,327 @@
+/*
+ * virtagent - QEMU guest agent
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ * Michael Roth <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <getopt.h>
+#include <err.h>
+#include "qemu-option.h"
+#include "qemu_socket.h"
+#include "qemu-ioh.h"
+#include "virtagent-common.h"
+
+static bool verbose_enabled;
+#define DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+#define DEBUG(msg, ...) do { \
+ fprintf(stderr, "%s:%s():L%d: " msg "\n", \
+ __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
+} while(0)
+#else
+#define DEBUG(msg, ...) do {} while (0)
+#endif
+
+#define INFO(msg, ...) do { \
+ if (!verbose_enabled) { \
+ break; \
+ } \
+ warnx(msg, ## __VA_ARGS__); \
+} while(0)
+
+QemuOptsList va_opts = {
+ .name = "vaargs",
+ .head = QTAILQ_HEAD_INITIALIZER(va_opts.head),
+ .desc = {
+ {
+ .name = "channel_method",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "path",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "host",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "port",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "ipv4",
+ .type = QEMU_OPT_BOOL,
+ },{
+ .name = "ipv6",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};
+
+/* parse channel options */
+static int va_parse(QemuOpts *opts, const char *str)
+{
+ char channel_method[32];
+ char *addr;
+ char port[33];
+ int pos, ret;
+
+ /* parse connection type */
+ ret = sscanf(str,"%32[^:]:%n",channel_method,&pos);
+ if (ret != 1) {
+ LOG("error parsing channel method");
+ return -EINVAL;
+ }
+ qemu_opt_set(opts, "channel_method", channel_method);
+ str += pos;
+ pos = 0;
+
+ /* parse path/addr and port */
+ if (str[0] == '[') {
+ /* ipv6 formatted */
+ ret = sscanf(str,"[%a[^]:]]:%32[^:]%n",&addr,port,&pos);
+ qemu_opt_set(opts, "ipv6", "on");
+ } else {
+ ret = sscanf(str,"%a[^:]:%32[^:]%n",&addr,port,&pos);
+ qemu_opt_set(opts, "ipv4", "on");
+ }
+
+ if (ret != 2) {
+ LOG("error parsing path/addr/port");
+ return -EINVAL;
+ } else if (port[0] == '-') {
+ /* no port given, assume unix path */
+ qemu_opt_set(opts, "path", addr);
+ } else {
+ qemu_opt_set(opts, "host", addr);
+ qemu_opt_set(opts, "port", port);
+ qemu_free(addr);
+ }
+ str += pos;
+ pos = 0;
+
+ return 0;
+}
+
+/* mirror qemu I/O loop for standalone daemon */
+static void main_loop_wait(int nonblocking)
+{
+ fd_set rfds, wfds, xfds;
+ int ret, nfds;
+ struct timeval tv;
+ int timeout = 100000;
+
+ if (nonblocking) {
+ timeout = 0;
+ }
+
+ /* poll any events */
+ nfds = -1;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&xfds);
+ qemu_get_fdset(&nfds, &rfds, &wfds, &xfds);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+ if (ret > 0) {
+ qemu_process_fd_handlers(&rfds, &wfds, &xfds);
+ }
+}
+
+#define VP_ARG_LEN 256
+
+typedef struct VAData {
+ QemuOpts *opts;
+ void *opaque;
+ QTAILQ_ENTRY(VAData) next;
+} VAData;
+
+static QTAILQ_HEAD(, VAData) channels;
+
+static void usage(const char *cmd)
+{
+ printf(
+"Usage: %s -c <channel_opts>\n"
+"QEMU virtagent guest agent\n"
+"\n"
+" -c, --channel channel options of the form:\n"
+" <method>:<addr>:<port>[:channel_id]\n"
+" -v, --verbose display extra debugging information\n"
+" -h, --help display this help and exit\n"
+"\n"
+" channels are used to establish a data connection between 2 end-points in\n"
+" the host or the guest (connection method specified by <method>).\n"
+" The positional parameters for channels are:\n"
+"\n"
+" <method>: one of unix-connect, unix-listen, tcp-connect, tcp-listen,\n"
+" virtserial-open\n"
+" <addr>: path of unix socket or virtserial port, or IP of host, to\n"
+" connect/bind to\n"
+" <port>: port to bind/connect to, or '-' if addr is a path\n"
+"\n"
+"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
+ , cmd);
+}
+
+static int init_channels(void) {
+ VAData *channel_data;
+ const char *channel_method, *path;
+ int fd, ret;
+ bool listen;
+
+ if (QTAILQ_EMPTY(&channels)) {
+ warnx("no channel specified");
+ return -EINVAL;
+ }
+
+ channel_data = QTAILQ_FIRST(&channels);
+
+ /* TODO: add this support, optional idx param for -i/-o/-c
+ * args should suffice
+ */
+ if (QTAILQ_NEXT(channel_data, next) != NULL) {
+ warnx("multiple channels not currently supported, defaulting to first");
+ }
+
+ INFO("initializing channel...");
+ if (verbose_enabled) {
+ qemu_opts_print(channel_data->opts, NULL);
+ }
+
+ channel_method = qemu_opt_get(channel_data->opts, "channel_method");
+
+ if (strcmp(channel_method, "tcp-listen") == 0) {
+ fd = inet_listen_opts(channel_data->opts, 0);
+ listen = true;
+ } else if (strcmp(channel_method, "tcp-connect") == 0) {
+ fd = inet_connect_opts(channel_data->opts);
+ listen = false;
+ } else if (strcmp(channel_method, "unix-listen") == 0) {
+ fd = unix_listen_opts(channel_data->opts);
+ listen = true;
+ } else if (strcmp(channel_method, "unix-connect") == 0) {
+ fd = unix_connect_opts(channel_data->opts);
+ listen = false;
+ } else if (strcmp(channel_method, "virtio-serial") == 0) {
+ path = qemu_opt_get(channel_data->opts, "path");
+ fd = qemu_open(path, O_RDWR);
+ if (fd == -1) {
+ warn("error opening channel");
+ return errno;
+ }
+ ret = fcntl(fd, F_GETFL);
+ ret = fcntl(fd, F_SETFL, ret | O_ASYNC);
+ if (ret < 0) {
+ warn("error setting flags for fd");
+ return errno;
+ }
+ listen = false;
+ } else {
+ warnx("invalid channel type: %s", channel_method);
+ return -EINVAL;
+ }
+
+ if (fd == -1) {
+ warn("error opening connection");
+ return errno;
+ }
+
+ /* initialize virtagent */
+ ret = va_init(VA_CTX_GUEST, fd);
+ if (ret) {
+ errx(EXIT_FAILURE, "unable to initialize virtagent");
+ }
+
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ const char *sopt = "hVvc:";
+ struct option lopt[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "verbose", 0, NULL, 'v' },
+ { "channel", 0, NULL, 'c' },
+ { NULL, 0, NULL, 0 }
+ };
+ int opt_ind = 0, ch, ret;
+ QTAILQ_INIT(&channels);
+
+ while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+ QemuOpts *opts;
+ VAData *data;
+ switch (ch) {
+ case 'c':
+ opts = qemu_opts_create(&va_opts, NULL, 0);
+ ret = va_parse(opts, optarg);
+ if (ret) {
+ errx(EXIT_FAILURE, "error parsing arg: %s", optarg);
+ }
+ data = qemu_mallocz(sizeof(VAData));
+ data->opts = opts;
+ QTAILQ_INSERT_TAIL(&channels, data, next);
+ break;
+ case 'v':
+ verbose_enabled = 1;
+ break;
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case '?':
+ errx(EXIT_FAILURE, "Try '%s --help' for more information.",
+ argv[0]);
+ }
+ }
+
+ /* initialize communication channel and pass it to virtagent */
+ /* XXX: we only support one channel now so this should be simplified */
+ ret = init_channels();
+ if (ret) {
+ errx(EXIT_FAILURE, "error initializing communication channel");
+ }
+
+ /* tell the host the agent is running */
+ va_send_hello();
+
+ /* main i/o loop */
+ for (;;) {
+ DEBUG("entering main_loop_wait()");
+ main_loop_wait(0);
+ DEBUG("left main_loop_wait()");
+ }
+
+ return 0;
+}
--
1.7.0.4
next prev parent reply other threads:[~2010-12-03 18:04 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-03 18:03 [Qemu-devel] [RFC][PATCH v5 00/21] virtagent: host/guest RPC communication agent Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 01/21] Move code related to fd handlers into utility functions Michael Roth
2010-12-07 13:31 ` [Qemu-devel] " Jes Sorensen
2010-12-07 14:48 ` Michael Roth
2010-12-07 15:02 ` Jes Sorensen
2010-12-08 9:15 ` Stefan Hajnoczi
2010-12-08 9:17 ` Jes Sorensen
2010-12-08 9:23 ` Stefan Hajnoczi
2010-12-08 9:29 ` Jes Sorensen
2010-12-08 14:24 ` Anthony Liguori
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 02/21] Add qemu_set_fd_handler() wrappers to qemu-tools.c Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 03/21] virtagent: common code for managing client/server rpc jobs Michael Roth
2010-12-06 21:54 ` [Qemu-devel] " Adam Litke
2010-12-06 22:15 ` Michael Roth
2010-12-06 21:57 ` Adam Litke
2010-12-06 22:24 ` Michael Roth
2010-12-07 13:38 ` Jes Sorensen
2010-12-07 15:02 ` Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 04/21] virtagent: transport definitions and job callbacks Michael Roth
2010-12-06 22:02 ` [Qemu-devel] " Adam Litke
2010-12-06 22:34 ` Michael Roth
2010-12-07 13:44 ` Jes Sorensen
2010-12-07 17:19 ` Michael Roth
2010-12-08 19:16 ` Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 05/21] virtagent: base client definitions Michael Roth
2010-12-07 14:04 ` [Qemu-devel] " Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 06/21] virtagent: base server definitions Michael Roth
2010-12-07 14:07 ` [Qemu-devel] " Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 07/21] virtagent: add va.getfile RPC Michael Roth
2010-12-06 22:06 ` [Qemu-devel] " Adam Litke
2010-12-06 23:23 ` Michael Roth
2010-12-07 14:18 ` Jes Sorensen
2010-12-07 16:00 ` Adam Litke
2010-12-08 19:19 ` Jes Sorensen
2010-12-09 14:40 ` Adam Litke
2010-12-09 21:04 ` Michael Roth
2010-12-10 6:38 ` Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command Michael Roth
2010-12-06 22:08 ` [Qemu-devel] " Adam Litke
2010-12-06 23:20 ` Michael Roth
2010-12-07 14:09 ` Michael Roth
2010-12-07 14:26 ` Jes Sorensen
2010-12-09 21:12 ` Michael Roth
2010-12-10 6:43 ` Jes Sorensen
2010-12-10 17:09 ` Michael Roth
2010-12-13 8:29 ` Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 09/21] virtagent: add va.getdmesg RPC Michael Roth
2010-12-06 22:25 ` [Qemu-devel] " Adam Litke
2010-12-07 14:37 ` Jes Sorensen
2010-12-07 17:32 ` Michael Roth
2010-12-08 19:22 ` Jes Sorensen
2010-12-09 21:15 ` Michael Roth
2010-12-10 6:46 ` Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 10/21] virtagent: add agent_viewdmesg qmp/hmp commands Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 11/21] virtagent: add va.shutdown RPC Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 12/21] virtagent: add agent_shutdown qmp/hmp commands Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 13/21] virtagent: add va.ping RPC Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 14/21] virtagent: add agent_ping qmp/hmp commands Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 15/21] virtagent: add agent_capabilities " Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 16/21] virtagent: add client capabilities init function Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 17/21] virtagent: add va.hello RPC Michael Roth
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 18/21] virtagent: add "hello" notification function for guest agent Michael Roth
2010-12-03 18:03 ` Michael Roth [this message]
2010-12-06 22:26 ` [Qemu-devel] Re: [RFC][PATCH v5 19/21] virtagent: add virtagent guest daemon Adam Litke
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 20/21] virtagent: integrate virtagent server/client via chardev Michael Roth
2010-12-07 14:44 ` [Qemu-devel] " Jes Sorensen
2010-12-03 18:03 ` [Qemu-devel] [RFC][PATCH v5 21/21] virtagent: various bits to build QEMU with virtagent Michael Roth
2010-12-07 10:24 ` [Qemu-devel] Re: [RFC][PATCH v5 00/21] virtagent: host/guest RPC communication agent Jes Sorensen
2010-12-07 14:29 ` Michael Roth
2010-12-08 10:10 ` [Qemu-devel] " Stefan Hajnoczi
2010-12-09 20:45 ` Michael Roth
2010-12-09 21:03 ` Anthony Liguori
2010-12-10 9:42 ` Stefan Hajnoczi
2010-12-10 10:03 ` Stefan Hajnoczi
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=1291399402-20366-20-git-send-email-mdroth@linux.vnet.ibm.com \
--to=mdroth@linux.vnet.ibm.com \
--cc=Jes.Sorensen@redhat.com \
--cc=abeekhof@redhat.com \
--cc=agl@linux.vnet.ibm.com \
--cc=aliguori@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=ryanh@us.ibm.com \
--cc=stefanha@linux.vnet.ibm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).