9119d9
From e646797b59c759839d3f0b97223d5cb67ef5ea04 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <e646797b59c759839d3f0b97223d5cb67ef5ea04@dist-git>
9119d9
From: Peter Krempa <pkrempa@redhat.com>
9119d9
Date: Mon, 24 Nov 2014 17:51:15 +0100
9119d9
Subject: [PATCH] qemu: Add handling for VSERPORT_CHANGE event
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1146944
9119d9
9119d9
New qemu added a new event that is emitted when a virtio serial channel
9119d9
is opened in the guest OS. This allows us to update the state of the
9119d9
port in the output-only XML element.
9119d9
9119d9
This patch implements the monitor callbacks and necessary handlers to
9119d9
update the state in the definition.
9119d9
9119d9
(cherry picked from commit 15bbaaf014d0eb524a941be2b924d7768ef7c269)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_domain.h       |  1 +
9119d9
 src/qemu/qemu_driver.c       | 57 ++++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/qemu/qemu_monitor.c      | 14 +++++++++++
9119d9
 src/qemu/qemu_monitor.h      | 10 ++++++++
9119d9
 src/qemu/qemu_monitor_json.c | 23 ++++++++++++++++++
9119d9
 src/qemu/qemu_process.c      | 44 ++++++++++++++++++++++++++++++++++
9119d9
 6 files changed, 149 insertions(+)
9119d9
9119d9
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
9119d9
index ad45a66..e4ea4ce 100644
9119d9
--- a/src/qemu/qemu_domain.h
9119d9
+++ b/src/qemu/qemu_domain.h
9119d9
@@ -196,6 +196,7 @@ typedef enum {
9119d9
     QEMU_PROCESS_EVENT_GUESTPANIC,
9119d9
     QEMU_PROCESS_EVENT_DEVICE_DELETED,
9119d9
     QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
9119d9
+    QEMU_PROCESS_EVENT_SERIAL_CHANGED,
9119d9
 
9119d9
     QEMU_PROCESS_EVENT_LAST
9119d9
 } qemuProcessEventType;
9119d9
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
9119d9
index 5d2a335..fe498b9 100644
9119d9
--- a/src/qemu/qemu_driver.c
9119d9
+++ b/src/qemu/qemu_driver.c
9119d9
@@ -4339,6 +4339,60 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static void
9119d9
+processSerialChangedEvent(virQEMUDriverPtr driver,
9119d9
+                          virDomainObjPtr vm,
9119d9
+                          char *devAlias,
9119d9
+                          bool connected)
9119d9
+{
9119d9
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
9119d9
+    virDomainChrDeviceState newstate;
9119d9
+    virDomainDeviceDef dev;
9119d9
+
9119d9
+    if (connected)
9119d9
+        newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
9119d9
+    else
9119d9
+        newstate = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
9119d9
+
9119d9
+    VIR_DEBUG("Changing serial port state %s in domain %p %s",
9119d9
+              devAlias, vm, vm->def->name);
9119d9
+
9119d9
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (!virDomainObjIsActive(vm)) {
9119d9
+        VIR_DEBUG("Domain is not running");
9119d9
+        goto endjob;
9119d9
+    }
9119d9
+
9119d9
+    if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
9119d9
+        goto endjob;
9119d9
+
9119d9
+    /* we care only about certain devices */
9119d9
+    if (dev.type != VIR_DOMAIN_DEVICE_CHR ||
9119d9
+        dev.data.chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
9119d9
+        dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
9119d9
+        goto endjob;
9119d9
+
9119d9
+    dev.data.chr->state = newstate;
9119d9
+
9119d9
+    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
9119d9
+        VIR_WARN("unable to save status of domain %s after updating state of "
9119d9
+                 "channel %s", vm->def->name, devAlias);
9119d9
+
9119d9
+ endjob:
9119d9
+    /* We had an extra reference to vm before starting a new job so ending the
9119d9
+     * job is guaranteed not to remove the last reference.
9119d9
+     */
9119d9
+    ignore_value(qemuDomainObjEndJob(driver, vm));
9119d9
+
9119d9
+ cleanup:
9119d9
+    VIR_FREE(devAlias);
9119d9
+    virObjectUnref(cfg);
9119d9
+
9119d9
+}
9119d9
+
9119d9
+
9119d9
 static void qemuProcessEventHandler(void *data, void *opaque)
9119d9
 {
9119d9
     struct qemuProcessEvent *processEvent = data;
9119d9
@@ -4362,6 +4416,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
9119d9
     case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
9119d9
         processNicRxFilterChangedEvent(driver, vm, processEvent->data);
9119d9
         break;
9119d9
+    case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
9119d9
+        processSerialChangedEvent(driver, vm, processEvent->data,
9119d9
+                                  processEvent->action);
9119d9
     case QEMU_PROCESS_EVENT_LAST:
9119d9
         break;
9119d9
     }
9119d9
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
9119d9
index 09935f5..55a0542 100644
9119d9
--- a/src/qemu/qemu_monitor.c
9119d9
+++ b/src/qemu/qemu_monitor.c
9119d9
@@ -1404,6 +1404,20 @@ qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+int
9119d9
+qemuMonitorEmitSerialChange(qemuMonitorPtr mon,
9119d9
+                            const char *devAlias,
9119d9
+                            bool connected)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    VIR_DEBUG("mon=%p, devAlias='%s', connected=%d", mon, devAlias, connected);
9119d9
+
9119d9
+    QEMU_MONITOR_CALLBACK(mon, ret, domainSerialChange, mon->vm, devAlias, connected);
9119d9
+
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
9119d9
 {
9119d9
     int ret;
9119d9
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
9119d9
index b63799b..8ae0dbe 100644
9119d9
--- a/src/qemu/qemu_monitor.h
9119d9
+++ b/src/qemu/qemu_monitor.h
9119d9
@@ -176,6 +176,12 @@ typedef int (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitorPtr mon,
9119d9
                                                            const char *devAlias,
9119d9
                                                            void *opaque);
9119d9
 
9119d9
+typedef int (*qemuMonitorDomainSerialChangeCallback)(qemuMonitorPtr mon,
9119d9
+                                                     virDomainObjPtr vm,
9119d9
+                                                     const char *devAlias,
9119d9
+                                                     bool connected,
9119d9
+                                                     void *opaque);
9119d9
+
9119d9
 typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
9119d9
 typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
9119d9
 struct _qemuMonitorCallbacks {
9119d9
@@ -202,6 +208,7 @@ struct _qemuMonitorCallbacks {
9119d9
     qemuMonitorDomainGuestPanicCallback domainGuestPanic;
9119d9
     qemuMonitorDomainDeviceDeletedCallback domainDeviceDeleted;
9119d9
     qemuMonitorDomainNicRxFilterChangedCallback domainNicRxFilterChanged;
9119d9
+    qemuMonitorDomainSerialChangeCallback domainSerialChange;
9119d9
 };
9119d9
 
9119d9
 char *qemuMonitorEscapeArg(const char *in);
9119d9
@@ -292,6 +299,9 @@ int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
9119d9
                                  const char *devAlias);
9119d9
 int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
9119d9
                                       const char *devAlias);
9119d9
+int qemuMonitorEmitSerialChange(qemuMonitorPtr mon,
9119d9
+                                const char *devAlias,
9119d9
+                                bool connected);
9119d9
 
9119d9
 int qemuMonitorStartCPUs(qemuMonitorPtr mon,
9119d9
                          virConnectPtr conn);
9119d9
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
9119d9
index bf28832..e5f49ef 100644
9119d9
--- a/src/qemu/qemu_monitor_json.c
9119d9
+++ b/src/qemu/qemu_monitor_json.c
9119d9
@@ -82,6 +82,7 @@ static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValueP
9119d9
 static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
+static void qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 
9119d9
 typedef struct {
9119d9
     const char *type;
9119d9
@@ -112,6 +113,7 @@ static qemuEventHandler eventHandlers[] = {
9119d9
     { "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
9119d9
     { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
9119d9
     { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
9119d9
+    { "VSERPORT_CHANGE", qemuMonitorJSONHandleSerialChange, },
9119d9
     { "WAKEUP", qemuMonitorJSONHandlePMWakeup, },
9119d9
     { "WATCHDOG", qemuMonitorJSONHandleWatchdog, },
9119d9
     /* We use bsearch, so keep this list sorted.  */
9119d9
@@ -1038,6 +1040,27 @@ qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static void
9119d9
+qemuMonitorJSONHandleSerialChange(qemuMonitorPtr mon,
9119d9
+                                  virJSONValuePtr data)
9119d9
+{
9119d9
+    const char *name;
9119d9
+    bool connected;
9119d9
+
9119d9
+    if (!(name = virJSONValueObjectGetString(data, "id"))) {
9119d9
+        VIR_WARN("missing device alias in VSERPORT_CHANGE event");
9119d9
+        return;
9119d9
+    }
9119d9
+
9119d9
+    if (virJSONValueObjectGetBoolean(data, "open", &connected) < 0) {
9119d9
+        VIR_WARN("missing port state for '%s' in VSERPORT_CHANGE event", name);
9119d9
+        return;
9119d9
+    }
9119d9
+
9119d9
+    qemuMonitorEmitSerialChange(mon, name, connected);
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int
9119d9
 qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
9119d9
                                   const char *cmd_str,
9119d9
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
9119d9
index b7b2d80..7e1b9a2 100644
9119d9
--- a/src/qemu/qemu_process.c
9119d9
+++ b/src/qemu/qemu_process.c
9119d9
@@ -1539,6 +1539,49 @@ qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static int
9119d9
+qemuProcessHandleSerialChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
9119d9
+                               virDomainObjPtr vm,
9119d9
+                               const char *devAlias,
9119d9
+                               bool connected,
9119d9
+                               void *opaque)
9119d9
+{
9119d9
+    virQEMUDriverPtr driver = opaque;
9119d9
+    struct qemuProcessEvent *processEvent = NULL;
9119d9
+    char *data;
9119d9
+
9119d9
+    virObjectLock(vm);
9119d9
+
9119d9
+    VIR_DEBUG("Serial port %s state changed to '%d' in domain %p %s",
9119d9
+              devAlias, connected, vm, vm->def->name);
9119d9
+
9119d9
+    if (VIR_ALLOC(processEvent) < 0)
9119d9
+        goto error;
9119d9
+
9119d9
+    processEvent->eventType = QEMU_PROCESS_EVENT_SERIAL_CHANGED;
9119d9
+    if (VIR_STRDUP(data, devAlias) < 0)
9119d9
+        goto error;
9119d9
+    processEvent->data = data;
9119d9
+    processEvent->action = connected;
9119d9
+    processEvent->vm = vm;
9119d9
+
9119d9
+    virObjectRef(vm);
9119d9
+    if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
9119d9
+        ignore_value(virObjectUnref(vm));
9119d9
+        goto error;
9119d9
+    }
9119d9
+
9119d9
+ cleanup:
9119d9
+    virObjectUnlock(vm);
9119d9
+    return 0;
9119d9
+ error:
9119d9
+    if (processEvent)
9119d9
+        VIR_FREE(processEvent->data);
9119d9
+    VIR_FREE(processEvent);
9119d9
+    goto cleanup;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 static qemuMonitorCallbacks monitorCallbacks = {
9119d9
     .eofNotify = qemuProcessHandleMonitorEOF,
9119d9
     .errorNotify = qemuProcessHandleMonitorError,
9119d9
@@ -1561,6 +1604,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
9119d9
     .domainGuestPanic = qemuProcessHandleGuestPanic,
9119d9
     .domainDeviceDeleted = qemuProcessHandleDeviceDeleted,
9119d9
     .domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged,
9119d9
+    .domainSerialChange = qemuProcessHandleSerialChanged,
9119d9
 };
9119d9
 
9119d9
 static int
9119d9
-- 
9119d9
2.1.3
9119d9