[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 1/3] qemu-ga: add support for events
From: |
Tomáš Golembiovský |
Subject: |
[Qemu-devel] [RFC 1/3] qemu-ga: add support for events |
Date: |
Fri, 23 Jun 2017 15:02:35 +0200 |
Events can play an integral role when monitoring internal state of the
guest OS. This patch adds the core functionality for adding events to
QEMU Guest Agent.
Signed-off-by: Tomáš Golembiovský <address@hidden>
---
Makefile | 7 +++++-
qga/Makefile.objs | 2 +-
qga/channel-posix.c | 8 +++++++
qga/channel-win32.c | 6 +++++
qga/channel.h | 1 +
qga/guest-agent-core.h | 1 +
qga/main.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
qga/qapi-event.json | 2 ++
qga/qapi-schema.json | 2 ++
9 files changed, 86 insertions(+), 2 deletions(-)
create mode 100644 qga/qapi-event.json
diff --git a/Makefile b/Makefile
index c830d7a46c..03e2174a18 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,11 @@ $(SRC_PATH)/qga/qapi-schema.json
$(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@")
+qga/qapi-generated/qga-qapi-event.c qga/qapi-generated/qga-qapi-event.h :\
+$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
+ $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
+ "GEN","$@")
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
@@ -441,7 +446,7 @@ $(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py
$(qapi-py)
$(gen-out-type) -o "." $<, \
"GEN","$@")
-QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h
qga-qmp-commands.h)
+QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h
qga-qmp-commands.h qga-qapi-event.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
qemu-ga$(EXESUF): $(qga-obj-y) $(COMMON_LDADDS)
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 1c5986c0bb..24399b6325 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
qga-obj-$(CONFIG_WIN32) += vss-win32.o
qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
-qga-obj-y += qapi-generated/qga-qmp-marshal.o
+qga-obj-y += qapi-generated/qga-qmp-marshal.o qapi-generated/qga-qapi-event.o
qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index 3f34465159..22e440724c 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -118,6 +118,14 @@ static int ga_channel_client_add(GAChannel *c, int fd)
return 0;
}
+gboolean ga_channel_client_attached(GAChannel *c)
+{
+ g_assert(c);
+ /* TODO: make this work with all methods. following works only with
+ * unix-listen */
+ return c->client_channel != NULL;
+}
+
static gboolean ga_channel_open(GAChannel *c, const gchar *path,
GAChannelMethod method, int fd)
{
diff --git a/qga/channel-win32.c b/qga/channel-win32.c
index 7e6dc4d26f..b62a6a3859 100644
--- a/qga/channel-win32.c
+++ b/qga/channel-win32.c
@@ -315,6 +315,12 @@ static gboolean ga_channel_open(GAChannel *c,
GAChannelMethod method,
return true;
}
+gboolean ga_channel_client_attached(GAChannel *c)
+{
+ /* TODO: make this work with all methods */
+ return true;
+}
+
GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path,
int listen_fd, GAChannelCallback cb, gpointer opaque)
{
diff --git a/qga/channel.h b/qga/channel.h
index 1778416115..030ec9e551 100644
--- a/qga/channel.h
+++ b/qga/channel.h
@@ -30,5 +30,6 @@ GAChannel *ga_channel_new(GAChannelMethod method, const gchar
*path,
void ga_channel_free(GAChannel *c);
GIOStatus ga_channel_read(GAChannel *c, gchar *buf, gsize size, gsize *count);
GIOStatus ga_channel_write_all(GAChannel *c, const gchar *buf, gsize size);
+gboolean ga_channel_client_attached(GAChannel *c);
#endif
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index 3e8a4acff2..47d6c73458 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -13,6 +13,7 @@
#include "qapi/qmp/dispatch.h"
#include "qemu-common.h"
#include "qga-qmp-commands.h"
+#include "qga-qapi-event.h"
#define QGA_READ_COUNT_DEFAULT 4096
diff --git a/qga/main.c b/qga/main.c
index cc58d2b53d..f16abb5cbb 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -23,6 +23,8 @@
#include "qapi/qmp/qjson.h"
#include "qga/guest-agent-core.h"
#include "qemu/module.h"
+#include "qapi/qmp-event.h"
+#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/dispatch.h"
#include "qga/channel.h"
@@ -674,6 +676,59 @@ static gboolean channel_event_cb(GIOCondition condition,
gpointer data)
return true;
}
+/* TODO: HACK HACK HACK... can't we get a GAstate somehow? */
+QDict *queued_event;
+static void ga_event_emit(qga_QAPIEvent event, QDict *qdict, Error **errp)
+{
+ if (queued_event) {
+ error_setg(errp, "unsent event already waiting");
+ } else {
+ QINCREF(qdict);
+ queued_event = qdict;
+ }
+}
+/* HACK HACK HACK!!! */
+
+static gboolean monitoring_cb(gpointer data)
+{
+ Error *err = NULL;
+ GAState *s = (GAState *)data;
+
+ g_assert(s->channel);
+ g_warning("monitoring!");
+
+ if (!ga_channel_client_attached(s->channel)) {
+ goto ok;
+ }
+
+ /* TODO: call something */
+ goto ok;
+
+/*fail:*/
+ g_assert(err);
+ g_warning("%s", error_get_pretty(err));
+ error_free(err);
+
+ok:
+ /* Always return true. False would remove this callback. */
+ return true;
+}
+
+static gboolean monitoring_init(GAState *s)
+{
+ if (g_timeout_add_seconds(5, monitoring_cb, (gpointer)s) <= 0) {
+ g_error("failed to create monitoring timer");
+ goto fail;
+ }
+ g_debug("monitoring timer created");
+
+ qmp_event_set_func_emit(ga_event_emit);
+ return true;
+
+fail:
+ return false;
+}
+
static gboolean channel_init(GAState *s, const gchar *method, const gchar
*path,
int listen_fd)
{
@@ -1330,6 +1385,10 @@ static int run_agent(GAState *s, GAConfig *config, int
socket_activation)
g_critical("failed to initialize guest agent channel");
return EXIT_FAILURE;
}
+
+ /* TODO: error handling? */
+ monitoring_init(ga_state);
+
#ifndef _WIN32
g_main_loop_run(ga_state->main_loop);
#else
diff --git a/qga/qapi-event.json b/qga/qapi-event.json
new file mode 100644
index 0000000000..9c14e4609e
--- /dev/null
+++ b/qga/qapi-event.json
@@ -0,0 +1,2 @@
+# *-*- Mode: Python -*-*
+
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 03743ab905..f30ba183bb 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1,5 +1,7 @@
# *-*- Mode: Python -*-*
+{ 'include': 'qapi-event.json' }
+
##
#
# General note concerning the use of guest agent interfaces:
--
2.13.1