if (qemuMigrationDstPrepareAnyBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
goto error;
- if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_IN,
- migParams, mig->caps->automatic) < 0)
+ if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_IN, migParams,
+ mig->caps->supported, mig->caps->automatic) < 0)
goto error;
/* Save original migration parameters */
qemuMigrationSrcRunPrepareBlockDirtyBitmaps(vm, mig, migParams, flags) < 0)
goto error;
- if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_OUT,
- migParams, mig->caps->automatic) < 0)
+ if (qemuMigrationParamsCheck(vm, VIR_ASYNC_JOB_MIGRATION_OUT, migParams,
+ mig->caps->supported, mig->caps->automatic) < 0)
goto error;
/* Save original migration parameters */
struct _qemuMigrationParams {
unsigned long long compMethods; /* bit-wise OR of qemuMigrationCompressMethod */
virBitmap *caps;
+ /* Optional capabilities are enabled only if supported by QEMU */
+ virBitmap *optional;
+ /* A capability present on both optional and remoteOptional bitmaps are
+ * enabled only if they are supported by both sides of migration. */
+ virBitmap *remoteOptional;
qemuMigrationParamValue params[QEMU_MIGRATION_PARAM_LAST];
virJSONValue *blockDirtyBitmapMapping;
};
virDomainMigrateFlags flag;
/* Migration capability to be enabled or disabled based on the flag. */
qemuMigrationCapability cap;
+ /* An optional capability to set in addition to @cap in case it is
+ * supported. Depending on @part either one or both sides of migration
+ * has to support the optional capability to be enabled. */
+ qemuMigrationCapability optional;
/* Bit-wise OR of qemuMigrationParty. Determines whether the capability has
* to be enabled on the source, on the destination, or on both sides of
* migration. */
params = g_new0(qemuMigrationParams, 1);
params->caps = virBitmapNew(QEMU_MIGRATION_CAP_LAST);
+ params->optional = virBitmapNew(QEMU_MIGRATION_CAP_LAST);
+ params->remoteOptional = virBitmapNew(QEMU_MIGRATION_CAP_LAST);
return g_steal_pointer(¶ms);
}
}
virBitmapFree(migParams->caps);
+ virBitmapFree(migParams->optional);
+ virBitmapFree(migParams->remoteOptional);
virJSONValueFree(migParams->blockDirtyBitmapMapping);
g_free(migParams);
}
VIR_DEBUG("Enabling migration capability '%s'",
qemuMigrationCapabilityTypeToString(item->cap));
ignore_value(virBitmapSetBit(migParams->caps, item->cap));
+
+ if (item->optional) {
+ qemuMigrationCapability opt = item->optional;
+ ignore_value(virBitmapSetBit(migParams->optional, opt));
+ if (item->party != party)
+ ignore_value(virBitmapSetBit(migParams->remoteOptional, opt));
+ }
}
}
qemuMigrationParamsCheck(virDomainObj *vm,
int asyncJob,
qemuMigrationParams *migParams,
+ virBitmap *remoteSupported,
virBitmap *remoteAuto)
{
qemuDomainJobPrivate *jobPriv = vm->job->privateData;
party = QEMU_MIGRATION_DESTINATION;
for (cap = 0; cap < QEMU_MIGRATION_CAP_LAST; cap++) {
- bool state = false;
-
- ignore_value(virBitmapGetBit(migParams->caps, cap, &state));
-
- if (state && !qemuMigrationCapsGet(vm, cap)) {
+ bool enable = false;
+ bool optional = false;
+ bool remoteOpt = false;
+ bool remote = false;
+ bool qemu = qemuMigrationCapsGet(vm, cap);
+
+ ignore_value(virBitmapGetBit(migParams->caps, cap, &enable));
+ ignore_value(virBitmapGetBit(migParams->optional, cap, &optional));
+ ignore_value(virBitmapGetBit(migParams->remoteOptional, cap, &remoteOpt));
+ ignore_value(virBitmapGetBit(remoteSupported, cap, &remote));
+
+ if (enable && !qemu) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
_("Migration option '%1$s' is not supported by QEMU binary"),
qemuMigrationCapabilityTypeToString(cap));
return -1;
}
+
+ if (optional) {
+ if (!qemu) {
+ VIR_DEBUG("Optional migration capability '%s' not supported by QEMU",
+ qemuMigrationCapabilityTypeToString(cap));
+ optional = false;
+ } else if (remoteOpt && !remote) {
+ VIR_DEBUG("Optional migration capability '%s' not supported "
+ "by the other side of migration",
+ qemuMigrationCapabilityTypeToString(cap));
+ optional = false;
+ }
+
+ if (optional) {
+ VIR_DEBUG("Enabling optional migration capability '%s'",
+ qemuMigrationCapabilityTypeToString(cap));
+ ignore_value(virBitmapSetBit(migParams->caps, cap));
+ }
+ }
}
for (i = 0; i < G_N_ELEMENTS(qemuMigrationParamsAlwaysOn); i++) {