diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index f573bd3eba..42194c0ea8 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1913,6 +1913,9 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver, cookieFlags |= QEMU_MIGRATION_COOKIE_ALLOW_REBOOT; + if (!(flags & VIR_MIGRATE_OFFLINE)) + cookieFlags |= QEMU_MIGRATION_COOKIE_CAPS; + if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0))) goto cleanup; @@ -2205,7 +2208,8 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, } cookieFlags = 0; } else { - cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS; + cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS | + QEMU_MIGRATION_COOKIE_CAPS; } if (flags & VIR_MIGRATE_POSTCOPY && @@ -2299,7 +2303,8 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG | QEMU_MIGRATION_COOKIE_CPU_HOTPLUG | QEMU_MIGRATION_COOKIE_CPU | - QEMU_MIGRATION_COOKIE_ALLOW_REBOOT))) + QEMU_MIGRATION_COOKIE_ALLOW_REBOOT | + QEMU_MIGRATION_COOKIE_CAPS))) goto cleanup; if (STREQ_NULLABLE(protocol, "rdma") && @@ -2378,7 +2383,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, } if (qemuMigrationParamsCheck(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, - migParams) < 0) + migParams, mig->caps->automatic) < 0) goto stopjob; /* Migrations using TLS need to add the "tls-creds-x509" object and @@ -3302,7 +3307,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver, } mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, - cookieFlags | QEMU_MIGRATION_COOKIE_GRAPHICS); + cookieFlags | + QEMU_MIGRATION_COOKIE_GRAPHICS | + QEMU_MIGRATION_COOKIE_CAPS); if (!mig) goto error; @@ -3310,7 +3317,7 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver, VIR_WARN("unable to provide data for graphics client relocation"); if (qemuMigrationParamsCheck(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - migParams) < 0) + migParams, mig->caps->automatic) < 0) goto error; if (flags & VIR_MIGRATE_TLS) { diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index 1b1e5829e8..979610c3a8 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -116,7 +116,9 @@ struct _qemuMigrationParamsFlagMapItem { }; /* Migration capabilities which should always be enabled as long as they - * are supported by QEMU. */ + * are supported by QEMU. If the capability is supposed to be enabled on both + * sides of migration, it won't be enabled unless both sides support it. + */ static const qemuMigrationParamsAlwaysOnItem qemuMigrationParamsAlwaysOn[] = { {QEMU_MIGRATION_CAP_PAUSE_BEFORE_SWITCHOVER, QEMU_MIGRATION_SOURCE}, @@ -975,7 +977,8 @@ int qemuMigrationParamsCheck(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, - qemuMigrationParamsPtr migParams) + qemuMigrationParamsPtr migParams, + virBitmapPtr remoteCaps) { qemuDomainObjPrivatePtr priv = vm->privateData; qemuMigrationCapability cap; @@ -1005,6 +1008,21 @@ qemuMigrationParamsCheck(virQEMUDriverPtr driver, if (qemuMigrationParamsAlwaysOn[i].party & party && qemuMigrationCapsGet(vm, cap)) { + if (qemuMigrationParamsAlwaysOn[i].party != party) { + bool remote = false; + + if (remoteCaps) + ignore_value(virBitmapGetBit(remoteCaps, cap, &remote)); + + if (!remote) { + VIR_DEBUG("Not enabling migration capability '%s'; it is " + "not supported or automatically enabled by the " + "other side of migration", + qemuMigrationCapabilityTypeToString(cap)); + continue; + } + } + VIR_DEBUG("Enabling migration capability '%s'", qemuMigrationCapabilityTypeToString(cap)); ignore_value(virBitmapSetBit(migParams->caps, cap)); diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index 75a441e1e1..eb4016806d 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -123,7 +123,8 @@ int qemuMigrationParamsCheck(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob, - qemuMigrationParamsPtr migParams); + qemuMigrationParamsPtr migParams, + virBitmapPtr remoteCaps); void qemuMigrationParamsReset(virQEMUDriverPtr driver,