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