276 lines
9.7 KiB
Diff
276 lines
9.7 KiB
Diff
From 89bfdeacefd0160080ab98a41109c75db6d5e913 Mon Sep 17 00:00:00 2001
|
|
Message-Id: <89bfdeacefd0160080ab98a41109c75db6d5e913@dist-git>
|
|
From: Michal Privoznik <mprivozn@redhat.com>
|
|
Date: Wed, 11 Jul 2018 17:27:26 +0200
|
|
Subject: [PATCH] qemu: Wire up PR_MANAGER_STATUS_CHANGED event
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1470007
|
|
|
|
This event is emitted on the monitor if one of pr-managers lost
|
|
connection to its pr-helper process. What libvirt needs to do is
|
|
restart the pr-helper process iff it corresponds to managed
|
|
pr-manager.
|
|
|
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
(cherry picked from commit 6fbda83330293ed8bec1ea9e3ba7273c4ee2b9e2)
|
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
---
|
|
src/qemu/qemu_domain.c | 1 +
|
|
src/qemu/qemu_domain.h | 1 +
|
|
src/qemu/qemu_driver.c | 17 +++++++++++
|
|
src/qemu/qemu_monitor.c | 15 ++++++++++
|
|
src/qemu/qemu_monitor.h | 11 ++++++++
|
|
src/qemu/qemu_monitor_json.c | 23 +++++++++++++++
|
|
src/qemu/qemu_process.c | 55 ++++++++++++++++++++++++++++++++++++
|
|
7 files changed, 123 insertions(+)
|
|
|
|
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
index cfecbaca74..dec057e021 100644
|
|
--- a/src/qemu/qemu_domain.c
|
|
+++ b/src/qemu/qemu_domain.c
|
|
@@ -12979,6 +12979,7 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
|
|
case QEMU_PROCESS_EVENT_MONITOR_EOF:
|
|
VIR_FREE(event->data);
|
|
break;
|
|
+ case QEMU_PROCESS_EVENT_PR_DISCONNECT:
|
|
case QEMU_PROCESS_EVENT_LAST:
|
|
break;
|
|
}
|
|
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
index 30d186a921..e748d78adb 100644
|
|
--- a/src/qemu/qemu_domain.h
|
|
+++ b/src/qemu/qemu_domain.h
|
|
@@ -477,6 +477,7 @@ typedef enum {
|
|
QEMU_PROCESS_EVENT_SERIAL_CHANGED,
|
|
QEMU_PROCESS_EVENT_BLOCK_JOB,
|
|
QEMU_PROCESS_EVENT_MONITOR_EOF,
|
|
+ QEMU_PROCESS_EVENT_PR_DISCONNECT,
|
|
|
|
QEMU_PROCESS_EVENT_LAST
|
|
} qemuProcessEventType;
|
|
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
index 825b2b27e6..868ef9d406 100644
|
|
--- a/src/qemu/qemu_driver.c
|
|
+++ b/src/qemu/qemu_driver.c
|
|
@@ -4792,6 +4792,20 @@ processMonitorEOFEvent(virQEMUDriverPtr driver,
|
|
}
|
|
|
|
|
|
+static void
|
|
+processPRDisconnectEvent(virDomainObjPtr vm)
|
|
+{
|
|
+ qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
+
|
|
+ if (!virDomainObjIsActive(vm))
|
|
+ return;
|
|
+
|
|
+ if (!priv->prDaemonRunning &&
|
|
+ virDomainDefHasManagedPR(vm->def))
|
|
+ qemuProcessStartManagedPRDaemon(vm);
|
|
+}
|
|
+
|
|
+
|
|
static void qemuProcessEventHandler(void *data, void *opaque)
|
|
{
|
|
struct qemuProcessEvent *processEvent = data;
|
|
@@ -4829,6 +4843,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
|
|
case QEMU_PROCESS_EVENT_MONITOR_EOF:
|
|
processMonitorEOFEvent(driver, vm);
|
|
break;
|
|
+ case QEMU_PROCESS_EVENT_PR_DISCONNECT:
|
|
+ processPRDisconnectEvent(vm);
|
|
+ break;
|
|
case QEMU_PROCESS_EVENT_LAST:
|
|
break;
|
|
}
|
|
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
|
|
index ae5b23b9fc..86b2b6e985 100644
|
|
--- a/src/qemu/qemu_monitor.c
|
|
+++ b/src/qemu/qemu_monitor.c
|
|
@@ -1669,6 +1669,21 @@ qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
|
|
}
|
|
|
|
|
|
+int
|
|
+qemuMonitorEmitPRManagerStatusChanged(qemuMonitorPtr mon,
|
|
+ const char *prManager,
|
|
+ bool connected)
|
|
+{
|
|
+ int ret = -1;
|
|
+ VIR_DEBUG("mon=%p, prManager='%s', connected=%d", mon, prManager, connected);
|
|
+
|
|
+ QEMU_MONITOR_CALLBACK(mon, ret, domainPRManagerStatusChanged,
|
|
+ mon->vm, prManager, connected);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
int
|
|
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
|
|
{
|
|
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
|
index e8adda8aa0..a906bc8410 100644
|
|
--- a/src/qemu/qemu_monitor.h
|
|
+++ b/src/qemu/qemu_monitor.h
|
|
@@ -273,6 +273,12 @@ typedef int (*qemuMonitorDomainDumpCompletedCallback)(qemuMonitorPtr mon,
|
|
const char *error,
|
|
void *opaque);
|
|
|
|
+typedef int (*qemuMonitorDomainPRManagerStatusChangedCallback)(qemuMonitorPtr mon,
|
|
+ virDomainObjPtr vm,
|
|
+ const char *prManager,
|
|
+ bool connected,
|
|
+ void *opaque);
|
|
+
|
|
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
|
|
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
|
|
struct _qemuMonitorCallbacks {
|
|
@@ -305,6 +311,7 @@ struct _qemuMonitorCallbacks {
|
|
qemuMonitorDomainAcpiOstInfoCallback domainAcpiOstInfo;
|
|
qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
|
|
qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
|
|
+ qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged;
|
|
};
|
|
|
|
char *qemuMonitorEscapeArg(const char *in);
|
|
@@ -433,6 +440,10 @@ int qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
|
|
qemuMonitorDumpStatsPtr stats,
|
|
const char *error);
|
|
|
|
+int qemuMonitorEmitPRManagerStatusChanged(qemuMonitorPtr mon,
|
|
+ const char *prManager,
|
|
+ bool connected);
|
|
+
|
|
int qemuMonitorStartCPUs(qemuMonitorPtr mon);
|
|
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
|
|
|
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
|
index 3e90279b71..03c94cd88b 100644
|
|
--- a/src/qemu/qemu_monitor_json.c
|
|
+++ b/src/qemu/qemu_monitor_json.c
|
|
@@ -91,6 +91,7 @@ static void qemuMonitorJSONHandleMigrationPass(qemuMonitorPtr mon, virJSONValueP
|
|
static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitorPtr mon, virJSONValuePtr data);
|
|
static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
|
|
static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
|
|
+static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon, virJSONValuePtr data);
|
|
|
|
typedef struct {
|
|
const char *type;
|
|
@@ -113,6 +114,7 @@ static qemuEventHandler eventHandlers[] = {
|
|
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
|
|
{ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
|
|
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
|
|
+ { "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
|
|
{ "RESET", qemuMonitorJSONHandleReset, },
|
|
{ "RESUME", qemuMonitorJSONHandleResume, },
|
|
{ "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
|
|
@@ -1297,6 +1299,27 @@ qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon,
|
|
}
|
|
|
|
|
|
+static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon,
|
|
+ virJSONValuePtr data)
|
|
+{
|
|
+ const char *name;
|
|
+ bool connected;
|
|
+
|
|
+ if (!(name = virJSONValueObjectGetString(data, "id"))) {
|
|
+ VIR_WARN("missing pr-manager alias in PR_MANAGER_STATUS_CHANGED event");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (virJSONValueObjectGetBoolean(data, "connected", &connected) < 0) {
|
|
+ VIR_WARN("missing connected state for %s "
|
|
+ "in PR_MANAGER_STATUS_CHANGED event", name);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ qemuMonitorEmitPRManagerStatusChanged(mon, name, connected);
|
|
+}
|
|
+
|
|
+
|
|
int
|
|
qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
|
|
const char *cmd_str,
|
|
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
index f200729cb1..fbc8529f3b 100644
|
|
--- a/src/qemu/qemu_process.c
|
|
+++ b/src/qemu/qemu_process.c
|
|
@@ -1615,6 +1615,60 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|
}
|
|
|
|
|
|
+static int
|
|
+qemuProcessHandlePRManagerStatusChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|
+ virDomainObjPtr vm,
|
|
+ const char *prManager,
|
|
+ bool connected,
|
|
+ void *opaque)
|
|
+{
|
|
+ virQEMUDriverPtr driver = opaque;
|
|
+ qemuDomainObjPrivatePtr priv;
|
|
+ struct qemuProcessEvent *processEvent = NULL;
|
|
+ const char *managedAlias = qemuDomainGetManagedPRAlias();
|
|
+ int ret = -1;
|
|
+
|
|
+ virObjectLock(vm);
|
|
+
|
|
+ VIR_DEBUG("pr-manager %s status changed for domain %p %s connected=%d",
|
|
+ prManager, vm, vm->def->name, connected);
|
|
+
|
|
+ if (connected) {
|
|
+ /* Connect events are boring. */
|
|
+ ret = 0;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ /* Disconnect events are more interesting. */
|
|
+
|
|
+ if (STRNEQ(prManager, managedAlias)) {
|
|
+ VIR_DEBUG("pr-manager %s not managed, ignoring event",
|
|
+ prManager);
|
|
+ ret = 0;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ priv = vm->privateData;
|
|
+ priv->prDaemonRunning = false;
|
|
+
|
|
+ if (VIR_ALLOC(processEvent) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ processEvent->eventType = QEMU_PROCESS_EVENT_PR_DISCONNECT;
|
|
+ processEvent->vm = virObjectRef(vm);
|
|
+
|
|
+ if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
|
|
+ qemuProcessEventFree(processEvent);
|
|
+ virObjectUnref(vm);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = 0;
|
|
+ cleanup:
|
|
+ virObjectUnlock(vm);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
static qemuMonitorCallbacks monitorCallbacks = {
|
|
.eofNotify = qemuProcessHandleMonitorEOF,
|
|
.errorNotify = qemuProcessHandleMonitorError,
|
|
@@ -1643,6 +1697,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
|
.domainAcpiOstInfo = qemuProcessHandleAcpiOstInfo,
|
|
.domainBlockThreshold = qemuProcessHandleBlockThreshold,
|
|
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
|
|
+ .domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
|
|
};
|
|
|
|
static void
|
|
--
|
|
2.18.0
|
|
|