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_monitor.c | 15 +++++++++++++
src/qemu/qemu_monitor.h | 11 +++++++++
src/qemu/qemu_monitor_json.c | 23 +++++++++++++++++++
src/qemu/qemu_process.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+)
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..94b7de76d7 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1615,6 +1615,58 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon
ATTRIBUTE_UNUSED,
}
+static int
+qemuProcessHandlePRManagerStatusChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ const char *prManager,
+ bool connected,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ qemuDomainObjPrivatePtr priv;
+ size_t i;
+ 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. */
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ const char *mgralias;
+
+ mgralias =
virStorageSourceChainGetManagedPRAlias(vm->def->disks[i]->src);
+
+ if (STREQ_NULLABLE(prManager, mgralias))
+ break;
+ }
+
+ if (i == vm->def->ndisks) {
+ VIR_DEBUG("pr-manager %s not managed, ignoring event",
+ prManager);
+ ret = 0;
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+ priv->prDaemonRunning = false;
+
+ if (qemuProcessStartManagedPRDaemon(vm) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ virObjectUnlock(vm);
+ return ret;
+}
+
+
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuProcessHandleMonitorEOF,
.errorNotify = qemuProcessHandleMonitorError,
@@ -1643,6 +1695,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
.domainAcpiOstInfo = qemuProcessHandleAcpiOstInfo,
.domainBlockThreshold = qemuProcessHandleBlockThreshold,
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
+ .domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
};
static void
--
2.16.4