mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu_migration: Apply max-postcopy-bandwidth on post-copy resume
When resuming post-copy migration users may want to limit the bandwidth used by the migration and use a value that is different from the one specified when the migration was originally started. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/333 Signed-off-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
8c335b5530
commit
766abdc291
@ -5051,12 +5051,13 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
qemuMigrationSrcResume(virDomainObj *vm,
|
qemuMigrationSrcResume(virDomainObj *vm,
|
||||||
qemuMigrationParams *migParams G_GNUC_UNUSED,
|
qemuMigrationParams *migParams,
|
||||||
const char *cookiein,
|
const char *cookiein,
|
||||||
int cookieinlen,
|
int cookieinlen,
|
||||||
char **cookieout,
|
char **cookieout,
|
||||||
int *cookieoutlen,
|
int *cookieoutlen,
|
||||||
qemuMigrationSpec *spec)
|
qemuMigrationSpec *spec,
|
||||||
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivate *priv = vm->privateData;
|
qemuDomainObjPrivate *priv = vm->privateData;
|
||||||
virQEMUDriver *driver = priv->driver;
|
virQEMUDriver *driver = priv->driver;
|
||||||
@ -5073,6 +5074,10 @@ qemuMigrationSrcResume(virDomainObj *vm,
|
|||||||
if (!mig)
|
if (!mig)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (qemuMigrationParamsApply(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT,
|
||||||
|
migParams, flags) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (qemuDomainObjEnterMonitorAsync(driver, vm,
|
if (qemuDomainObjEnterMonitorAsync(driver, vm,
|
||||||
VIR_ASYNC_JOB_MIGRATION_OUT) < 0)
|
VIR_ASYNC_JOB_MIGRATION_OUT) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -5154,6 +5159,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver,
|
|||||||
|
|
||||||
if (STREQ(uribits->scheme, "unix")) {
|
if (STREQ(uribits->scheme, "unix")) {
|
||||||
if ((flags & VIR_MIGRATE_TLS) &&
|
if ((flags & VIR_MIGRATE_TLS) &&
|
||||||
|
!(flags & VIR_MIGRATE_POSTCOPY_RESUME) &&
|
||||||
!qemuMigrationParamsTLSHostnameIsSet(migParams)) {
|
!qemuMigrationParamsTLSHostnameIsSet(migParams)) {
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
_("Explicit destination hostname is required "
|
_("Explicit destination hostname is required "
|
||||||
@ -5185,7 +5191,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver,
|
|||||||
|
|
||||||
if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
|
if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
|
||||||
ret = qemuMigrationSrcResume(vm, migParams, cookiein, cookieinlen,
|
ret = qemuMigrationSrcResume(vm, migParams, cookiein, cookieinlen,
|
||||||
cookieout, cookieoutlen, &spec);
|
cookieout, cookieoutlen, &spec, flags);
|
||||||
} else {
|
} else {
|
||||||
ret = qemuMigrationSrcRun(driver, vm, persist_xml, cookiein, cookieinlen,
|
ret = qemuMigrationSrcRun(driver, vm, persist_xml, cookiein, cookieinlen,
|
||||||
cookieout, cookieoutlen, flags, resource,
|
cookieout, cookieoutlen, flags, resource,
|
||||||
|
@ -141,6 +141,7 @@ struct _qemuMigrationParamsTPMapItem {
|
|||||||
typedef struct _qemuMigrationParamInfoItem qemuMigrationParamInfoItem;
|
typedef struct _qemuMigrationParamInfoItem qemuMigrationParamInfoItem;
|
||||||
struct _qemuMigrationParamInfoItem {
|
struct _qemuMigrationParamInfoItem {
|
||||||
qemuMigrationParamType type;
|
qemuMigrationParamType type;
|
||||||
|
bool applyOnPostcopyResume;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Migration capabilities which should always be enabled as long as they
|
/* Migration capabilities which should always be enabled as long as they
|
||||||
@ -265,6 +266,7 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = {
|
|||||||
},
|
},
|
||||||
[QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = {
|
[QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH] = {
|
||||||
.type = QEMU_MIGRATION_PARAM_TYPE_ULL,
|
.type = QEMU_MIGRATION_PARAM_TYPE_ULL,
|
||||||
|
.applyOnPostcopyResume = true,
|
||||||
},
|
},
|
||||||
[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = {
|
[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = {
|
||||||
.type = QEMU_MIGRATION_PARAM_TYPE_INT,
|
.type = QEMU_MIGRATION_PARAM_TYPE_INT,
|
||||||
@ -782,7 +784,8 @@ qemuMigrationParamsFromJSON(virJSONValue *params)
|
|||||||
|
|
||||||
|
|
||||||
virJSONValue *
|
virJSONValue *
|
||||||
qemuMigrationParamsToJSON(qemuMigrationParams *migParams)
|
qemuMigrationParamsToJSON(qemuMigrationParams *migParams,
|
||||||
|
bool postcopyResume)
|
||||||
{
|
{
|
||||||
g_autoptr(virJSONValue) params = virJSONValueNewObject();
|
g_autoptr(virJSONValue) params = virJSONValueNewObject();
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -795,6 +798,9 @@ qemuMigrationParamsToJSON(qemuMigrationParams *migParams)
|
|||||||
if (!pv->set)
|
if (!pv->set)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (postcopyResume && !qemuMigrationParamInfo[i].applyOnPostcopyResume)
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (qemuMigrationParamInfo[i].type) {
|
switch (qemuMigrationParamInfo[i].type) {
|
||||||
case QEMU_MIGRATION_PARAM_TYPE_INT:
|
case QEMU_MIGRATION_PARAM_TYPE_INT:
|
||||||
rc = virJSONValueObjectAppendNumberInt(params, name, pv->value.i);
|
rc = virJSONValueObjectAppendNumberInt(params, name, pv->value.i);
|
||||||
@ -868,6 +874,7 @@ qemuMigrationCapsToJSON(virBitmap *caps,
|
|||||||
*
|
*
|
||||||
* Send parameters stored in @migParams to QEMU. If @apiFlags is non-zero, some
|
* Send parameters stored in @migParams to QEMU. If @apiFlags is non-zero, some
|
||||||
* parameters that do not make sense for the enabled flags will be ignored.
|
* parameters that do not make sense for the enabled flags will be ignored.
|
||||||
|
* VIR_MIGRATE_POSTCOPY_RESUME is the only flag checked currently.
|
||||||
*
|
*
|
||||||
* Returns 0 on success, -1 on failure.
|
* Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
@ -876,32 +883,38 @@ qemuMigrationParamsApply(virQEMUDriver *driver,
|
|||||||
virDomainObj *vm,
|
virDomainObj *vm,
|
||||||
int asyncJob,
|
int asyncJob,
|
||||||
qemuMigrationParams *migParams,
|
qemuMigrationParams *migParams,
|
||||||
unsigned long apiFlags G_GNUC_UNUSED)
|
unsigned long apiFlags)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivate *priv = vm->privateData;
|
qemuDomainObjPrivate *priv = vm->privateData;
|
||||||
bool xbzrleCacheSize_old = false;
|
bool xbzrleCacheSize_old = false;
|
||||||
g_autoptr(virJSONValue) params = NULL;
|
g_autoptr(virJSONValue) params = NULL;
|
||||||
g_autoptr(virJSONValue) caps = NULL;
|
g_autoptr(virJSONValue) caps = NULL;
|
||||||
qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE;
|
qemuMigrationParam xbzrle = QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE;
|
||||||
|
bool postcopyResume = !!(apiFlags & VIR_MIGRATE_POSTCOPY_RESUME);
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (asyncJob == VIR_ASYNC_JOB_NONE) {
|
/* Changing capabilities is only allowed before migration starts, we need
|
||||||
if (!virBitmapIsAllClear(migParams->caps)) {
|
* to skip them when resuming post-copy migration.
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
*/
|
||||||
_("Migration capabilities can only be set by "
|
if (!postcopyResume) {
|
||||||
"a migration job"));
|
if (asyncJob == VIR_ASYNC_JOB_NONE) {
|
||||||
goto cleanup;
|
if (!virBitmapIsAllClear(migParams->caps)) {
|
||||||
}
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
} else {
|
_("Migration capabilities can only be set by "
|
||||||
if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps)))
|
"a migration job"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (virJSONValueArraySize(caps) > 0 &&
|
if (virJSONValueArraySize(caps) > 0 &&
|
||||||
qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0)
|
qemuMonitorSetMigrationCapabilities(priv->mon, &caps) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If QEMU is too old to support xbzrle-cache-size migration parameter,
|
/* If QEMU is too old to support xbzrle-cache-size migration parameter,
|
||||||
@ -917,7 +930,7 @@ qemuMigrationParamsApply(virQEMUDriver *driver,
|
|||||||
migParams->params[xbzrle].set = false;
|
migParams->params[xbzrle].set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(params = qemuMigrationParamsToJSON(migParams)))
|
if (!(params = qemuMigrationParamsToJSON(migParams, postcopyResume)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virJSONValueObjectKeysNumber(params) > 0 &&
|
if (virJSONValueObjectKeysNumber(params) > 0 &&
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
virJSONValue *
|
virJSONValue *
|
||||||
qemuMigrationParamsToJSON(qemuMigrationParams *migParams);
|
qemuMigrationParamsToJSON(qemuMigrationParams *migParams,
|
||||||
|
bool postcopyResume);
|
||||||
|
|
||||||
qemuMigrationParams *
|
qemuMigrationParams *
|
||||||
qemuMigrationParamsFromJSON(virJSONValue *params);
|
qemuMigrationParamsFromJSON(virJSONValue *params);
|
||||||
|
@ -155,7 +155,7 @@ qemuMigParamsTestJSON(const void *opaque)
|
|||||||
if (!(migParams = qemuMigrationParamsFromJSON(paramsIn)))
|
if (!(migParams = qemuMigrationParamsFromJSON(paramsIn)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) ||
|
if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) ||
|
||||||
!(actualJSON = virJSONValueToString(paramsOut, true)))
|
!(actualJSON = virJSONValueToString(paramsOut, true)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ testQemuMigrationCookieBlockDirtyBitmaps(const void *opaque)
|
|||||||
|
|
||||||
qemuMigrationParamsSetBlockDirtyBitmapMapping(migParams, &migParamsBitmaps);
|
qemuMigrationParamsSetBlockDirtyBitmapMapping(migParams, &migParamsBitmaps);
|
||||||
|
|
||||||
if (!(paramsOut = qemuMigrationParamsToJSON(migParams)) ||
|
if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) ||
|
||||||
!(actualJSON = virJSONValueToString(paramsOut, true)))
|
!(actualJSON = virJSONValueToString(paramsOut, true)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user