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(a)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 c80b7870c8..73873c0110 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13003,6 +13003,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 9a35e04a85..5de9aaefbb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4778,6 +4778,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;
@@ -4815,6 +4829,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 6ed475ede0..ca95f6f94a 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 b3d62324b4..f1ea0bc541 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..ac2f73c99e 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);
+ ignore_value(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.16.4