|
|
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 |
|