case QEMU_PROCESS_EVENT_MONITOR_EOF:
VIR_FREE(event->data);
break;
+ case QEMU_PROCESS_EVENT_PR_DISCONNECT:
case QEMU_PROCESS_EVENT_LAST:
break;
}
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;
}
+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;
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;
}
}
+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)
{
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 {
qemuMonitorDomainAcpiOstInfoCallback domainAcpiOstInfo;
qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
+ qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged;
};
char *qemuMonitorEscapeArg(const char *in);
qemuMonitorDumpStatsPtr stats,
const char *error);
+int qemuMonitorEmitPRManagerStatusChanged(qemuMonitorPtr mon,
+ const char *prManager,
+ bool connected);
+
int qemuMonitorStartCPUs(qemuMonitorPtr mon);
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
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;
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
{ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
+ { "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
{ "RESET", qemuMonitorJSONHandleReset, },
{ "RESUME", qemuMonitorJSONHandleResume, },
{ "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
}
+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,
}
+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,
.domainAcpiOstInfo = qemuProcessHandleAcpiOstInfo,
.domainBlockThreshold = qemuProcessHandleBlockThreshold,
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
+ .domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
};
static void