[libvirt] [PATCH 5/6] qemu: enable monitor event reporting

Eric Blake eblake at redhat.com
Sat Feb 1 02:12:10 UTC 2014


Wire up all the pieces to send arbitrary qemu events to a
client using libvirt-qemu.so.  If the extra bookkeeping of
generating event objects even when no one is listening turns
out to be noticeable, we can try to further optimize things
by adding a counter for how many connections are using events,
and only dump events when the counter is non-zero; but for
now, I didn't think it was worth the code complexity.

* src/qemu/qemu_driver.c
(qemuConnectDomainQemuMonitorEventRegister)
(qemuConnectDomainQemuMonitorEventDeregister): New functions.
* src/qemu/qemu_monitor.h (qemuMonitorEmitEvent): New prototype.
(qemuMonitorDomainEventCallback): New typedef.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONIOProcessEvent):
Report events.
* src/qemu/qemu_monitor.c (qemuMonitorEmitEvent): New function, to
pass events through.
* src/qemu/qemu_process.c (qemuProcessHandleEvent): Likewise.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 src/qemu/qemu_driver.c       | 52 ++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c      | 16 +++++++++++++-
 src/qemu/qemu_monitor.h      | 13 ++++++++++-
 src/qemu/qemu_monitor_json.c | 23 ++++++++++++++++++--
 src/qemu/qemu_process.c      | 29 ++++++++++++++++++++++++
 5 files changed, 129 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index dd7c91f..31553c3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16281,6 +16281,56 @@ cleanup:
     return result;
 }

+
+static int
+qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
+                                          virDomainPtr dom,
+                                          const char *event,
+                                          virConnectDomainQemuMonitorEventCallback callback,
+                                          void *opaque,
+                                          virFreeCallback freecb,
+                                          unsigned int flags)
+{
+    virQEMUDriverPtr driver = conn->privateData;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (virConnectDomainQemuMonitorEventRegisterEnsureACL(conn) < 0)
+        goto cleanup;
+
+    if (virDomainQemuMonitorEventStateRegisterID(conn,
+                                                 driver->domainEventState,
+                                                 dom, event, callback,
+                                                 opaque, freecb, &ret) < 0)
+        ret = -1;
+
+cleanup:
+    return ret;
+}
+
+
+static int
+qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
+                                            int callbackID)
+{
+    virQEMUDriverPtr driver = conn->privateData;
+    int ret = -1;
+
+    if (virConnectDomainQemuMonitorEventDeregisterEnsureACL(conn) < 0)
+        goto cleanup;
+
+    if (virObjectEventStateDeregisterID(conn, driver->domainEventState,
+                                        callbackID) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    return ret;
+}
+
+
 static int
 qemuDomainFSTrim(virDomainPtr dom,
                  const char *mountPoint,
@@ -16624,6 +16674,8 @@ static virDriver qemuDriver = {
     .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
     .domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
     .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
+    .connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.2 */
+    .connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.2 */
     .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
     .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
     .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index a968901..670ab0e 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1,7 +1,7 @@
 /*
  * qemu_monitor.c: interaction with QEMU monitor console
  *
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -1157,6 +1157,20 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
 }


+int
+qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
+                     long long seconds, unsigned int micros,
+                     const char *details)
+{
+    int ret = -1;
+    VIR_DEBUG("mon=%p event=%s", mon, event);
+
+    QEMU_MONITOR_CALLBACK(mon, ret, domainEvent, mon->vm, event, seconds,
+                          micros, details);
+    return ret;
+}
+
+
 int qemuMonitorEmitShutdown(qemuMonitorPtr mon)
 {
     int ret = -1;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index eabf000..51848ca 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1,7 +1,7 @@
 /*
  * qemu_monitor.h: interaction with QEMU monitor console
  *
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -90,6 +90,13 @@ typedef int (*qemuMonitorDiskSecretLookupCallback)(qemuMonitorPtr mon,
                                                    char **secret,
                                                    size_t *secretLen,
                                                    void *opaque);
+typedef int (*qemuMonitorDomainEventCallback)(qemuMonitorPtr mon,
+                                              virDomainObjPtr vm,
+                                              const char *event,
+                                              long long seconds,
+                                              unsigned int micros,
+                                              const char *details,
+                                              void *opaque);
 typedef int (*qemuMonitorDomainShutdownCallback)(qemuMonitorPtr mon,
                                                  virDomainObjPtr vm,
                                                  void *opaque);
@@ -171,6 +178,7 @@ struct _qemuMonitorCallbacks {
     qemuMonitorEofNotifyCallback eofNotify;
     qemuMonitorErrorNotifyCallback errorNotify;
     qemuMonitorDiskSecretLookupCallback diskSecretLookup;
+    qemuMonitorDomainEventCallback domainEvent;
     qemuMonitorDomainShutdownCallback domainShutdown;
     qemuMonitorDomainResetCallback domainReset;
     qemuMonitorDomainPowerdownCallback domainPowerdown;
@@ -236,6 +244,9 @@ int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
                              char **secret,
                              size_t *secretLen);

+int qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
+                         long long seconds, unsigned int micros,
+                         const char *details);
 int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
 int qemuMonitorEmitReset(qemuMonitorPtr mon);
 int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ec3b958..d64fe49 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1,7 +1,7 @@
 /*
  * qemu_monitor_json.c: interaction with QEMU monitor console
  *
- * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
  * Copyright (C) 2006 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -126,6 +126,12 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
 {
     const char *type;
     qemuEventHandler *handler;
+    virJSONValuePtr data;
+    char *details = NULL;
+    virJSONValuePtr timestamp;
+    long long seconds = -1;
+    unsigned int micros = 0;
+
     VIR_DEBUG("mon=%p obj=%p", mon, obj);

     type = virJSONValueObjectGetString(obj, "event");
@@ -135,10 +141,23 @@ qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon,
         return -1;
     }

+    /* Not all events have data; and event reporting is best-effort only */
+    if ((data = virJSONValueObjectGet(obj, "data")))
+        details = virJSONValueToString(data, false);
+    if ((timestamp = virJSONValueObjectGet(obj, "timestamp"))) {
+        virJSONValuePtr elt;
+
+        if ((elt = virJSONValueObjectGet(timestamp, "seconds")))
+            ignore_value(virJSONValueGetNumberLong(elt, &seconds));
+        if ((elt = virJSONValueObjectGet(timestamp, "microseconds")))
+            ignore_value(virJSONValueGetNumberUint(elt, &micros));
+    }
+    qemuMonitorEmitEvent(mon, type, seconds, micros, details);
+    VIR_FREE(details);
+
     handler = bsearch(type, eventHandlers, ARRAY_CARDINALITY(eventHandlers),
                       sizeof(eventHandlers[0]), qemuMonitorEventCompare);
     if (handler) {
-        virJSONValuePtr data = virJSONValueObjectGet(obj, "data");
         VIR_DEBUG("handle %s handler=%p data=%p", type,
                   handler->handler, data);
         (handler->handler)(mon, data);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 8bcd98e..8905590 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -646,6 +646,34 @@ qemuProcessShutdownOrReboot(virQEMUDriverPtr driver,
     }
 }

+
+static int
+qemuProcessHandleEvent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                       virDomainObjPtr vm,
+                       const char *eventName,
+                       long long seconds,
+                       unsigned int micros,
+                       const char *details,
+                       void *opaque)
+{
+    virQEMUDriverPtr driver = opaque;
+    virObjectEventPtr event = NULL;
+
+    VIR_DEBUG("vm=%p", vm);
+
+    virObjectLock(vm);
+    event = virDomainQemuMonitorEventNew(vm->def->id, vm->def->name,
+                                         vm->def->uuid, eventName,
+                                         seconds, micros, details);
+
+    virObjectUnlock(vm);
+    if (event)
+        qemuDomainEventQueue(driver, event);
+
+    return 0;
+}
+
+
 static int
 qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                           virDomainObjPtr vm,
@@ -1367,6 +1395,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
     .eofNotify = qemuProcessHandleMonitorEOF,
     .errorNotify = qemuProcessHandleMonitorError,
     .diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
+    .domainEvent = qemuProcessHandleEvent,
     .domainShutdown = qemuProcessHandleShutdown,
     .domainStop = qemuProcessHandleStop,
     .domainResume = qemuProcessHandleResume,
-- 
1.8.5.3




More information about the libvir-list mailing list