priv->reconnectBlockjobs = VIR_TRISTATE_BOOL_ABSENT;
priv->allowReboot = VIR_TRISTATE_BOOL_ABSENT;
+
+ virBitmapFree(priv->migrationCaps);
+ priv->migrationCaps = NULL;
}
}
return true;
}
+
+
+int
+qemuDomainCheckMigrationCapabilities(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ char **caps = NULL;
+ char **capStr;
+ int ret = -1;
+ int rc;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ rc = qemuMonitorGetMigrationCapabilities(priv->mon, &caps);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+ goto cleanup;
+
+ if (!caps) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ priv->migrationCaps = virBitmapNew(QEMU_MONITOR_MIGRATION_CAPS_LAST);
+ if (!priv->migrationCaps)
+ goto cleanup;
+
+ for (capStr = caps; *capStr; capStr++) {
+ int cap = qemuMonitorMigrationCapsTypeFromString(*capStr);
+
+ if (cap < 0) {
+ VIR_DEBUG("Unknown migration capability: '%s'", *capStr);
+ } else {
+ ignore_value(virBitmapSetBit(priv->migrationCaps, cap));
+ VIR_DEBUG("Found migration capability: '%s'", *capStr);
+ }
+ }
+
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT)) {
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ goto cleanup;
+
+ rc = qemuMonitorSetMigrationCapability(priv->mon,
+ QEMU_MONITOR_MIGRATION_CAPS_EVENTS,
+ true);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ goto cleanup;
+
+ if (rc < 0) {
+ virResetLastError();
+ VIR_DEBUG("Cannot enable migration events; clearing capability");
+ virQEMUCapsClear(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ virStringListFree(caps);
+ return ret;
+}
/* Tracks blockjob state for vm. Valid only while reconnecting to qemu. */
virTristateBool reconnectBlockjobs;
+
+ /* Migration capabilities. Rechecked on reconnect, not to be saved in
+ * private XML. */
+ virBitmapPtr migrationCaps;
};
# define QEMU_DOMAIN_PRIVATE(vm) \
virQEMUCapsPtr qemuCaps,
const char *devicename);
+int
+qemuDomainCheckMigrationCapabilities(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob);
+
#endif /* __QEMU_DOMAIN_H__ */
if (qemuProcessInitMonitor(driver, vm, asyncJob) < 0)
return -1;
- if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
- return -1;
-
- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT) &&
- qemuMonitorSetMigrationCapability(priv->mon,
- QEMU_MONITOR_MIGRATION_CAPS_EVENTS,
- true) < 0) {
- VIR_DEBUG("Cannot enable migration events; clearing capability");
- virQEMUCapsClear(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
- }
-
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ if (qemuDomainCheckMigrationCapabilities(driver, vm, asyncJob) < 0)
return -1;
return 0;