mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
qemu: Implement VIR_MIGRATE_POSTCOPY_RESUME for Begin phase
Mostly we just need to check whether the domain is in a failed post-copy migration that can be resumed. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
a5e603c808
commit
37a67122dd
@ -2685,6 +2685,139 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qemuMigrationAnyCanResume(virDomainObj *vm,
|
||||
virDomainAsyncJob job,
|
||||
unsigned long flags,
|
||||
qemuMigrationJobPhase expectedPhase)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
|
||||
VIR_DEBUG("vm=%p, job=%s, flags=0x%lx, expectedPhase=%s",
|
||||
vm, virDomainAsyncJobTypeToString(job), flags,
|
||||
qemuDomainAsyncJobPhaseToString(VIR_ASYNC_JOB_MIGRATION_OUT,
|
||||
expectedPhase));
|
||||
|
||||
if (!(flags & VIR_MIGRATE_POSTCOPY)) {
|
||||
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("resuming failed post-copy migration requires post-copy to be enabled"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This should never happen since POSTCOPY_RESUME is newer than
|
||||
* CHANGE_PROTECTION, but let's check it anyway in case we're talking to
|
||||
* a weired client.
|
||||
*/
|
||||
if (job == VIR_ASYNC_JOB_MIGRATION_OUT &&
|
||||
expectedPhase < QEMU_MIGRATION_PHASE_PERFORM_RESUME &&
|
||||
!(flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
|
||||
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("resuming failed post-copy migration requires change protection"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!qemuMigrationJobIsActive(vm, job))
|
||||
return false;
|
||||
|
||||
if (priv->job.asyncOwner != 0 &&
|
||||
priv->job.asyncOwner != virThreadSelfID()) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("migration of domain %s is being actively monitored by another thread"),
|
||||
vm->def->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!virDomainObjIsPostcopy(vm, priv->job.current->operation)) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("migration of domain %s is not in post-copy phase"),
|
||||
vm->def->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (priv->job.phase < QEMU_MIGRATION_PHASE_POSTCOPY_FAILED &&
|
||||
!virDomainObjIsFailedPostcopy(vm)) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("post-copy migration of domain %s has not failed"),
|
||||
vm->def->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (priv->job.phase > expectedPhase) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||
_("resuming failed post-copy migration of domain %s already in progress"),
|
||||
vm->def->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qemuMigrationSrcBeginResume(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
const char *xmlin,
|
||||
char **cookieout,
|
||||
int *cookieoutlen,
|
||||
unsigned long flags)
|
||||
{
|
||||
virDomainJobStatus status;
|
||||
|
||||
if (qemuMigrationAnyRefreshStatus(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT,
|
||||
&status) < 0)
|
||||
return NULL;
|
||||
|
||||
if (status != VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED) {
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("QEMU reports migration is still running"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return qemuMigrationSrcBeginXML(vm, xmlin,
|
||||
cookieout, cookieoutlen, 0, NULL, 0, flags);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qemuMigrationSrcBeginResumePhase(virConnectPtr conn,
|
||||
virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
const char *xmlin,
|
||||
char **cookieout,
|
||||
int *cookieoutlen,
|
||||
unsigned long flags)
|
||||
{
|
||||
g_autofree char *xml = NULL;
|
||||
|
||||
VIR_DEBUG("vm=%p", vm);
|
||||
|
||||
if (!qemuMigrationAnyCanResume(vm, VIR_ASYNC_JOB_MIGRATION_OUT, flags,
|
||||
QEMU_MIGRATION_PHASE_POSTCOPY_FAILED))
|
||||
return NULL;
|
||||
|
||||
if (qemuMigrationJobStartPhase(vm, QEMU_MIGRATION_PHASE_BEGIN_RESUME) < 0)
|
||||
return NULL;
|
||||
|
||||
virCloseCallbacksUnset(driver->closeCallbacks, vm,
|
||||
qemuMigrationSrcCleanup);
|
||||
qemuDomainCleanupRemove(vm, qemuProcessCleanupMigrationJob);
|
||||
|
||||
xml = qemuMigrationSrcBeginResume(driver, vm, xmlin, cookieout, cookieoutlen, flags);
|
||||
|
||||
if (virCloseCallbacksSet(driver->closeCallbacks, vm, conn,
|
||||
qemuMigrationSrcCleanup) < 0)
|
||||
g_clear_pointer(&xml, g_free);
|
||||
|
||||
if (!xml)
|
||||
ignore_value(qemuMigrationJobSetPhase(vm, QEMU_MIGRATION_PHASE_POSTCOPY_FAILED));
|
||||
|
||||
qemuDomainCleanupAdd(vm, qemuProcessCleanupMigrationJob);
|
||||
qemuMigrationJobContinue(vm);
|
||||
return g_steal_pointer(&xml);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
qemuMigrationSrcBegin(virConnectPtr conn,
|
||||
virDomainObj *vm,
|
||||
@ -2710,6 +2843,12 @@ qemuMigrationSrcBegin(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (flags & VIR_MIGRATE_POSTCOPY_RESUME) {
|
||||
ret = qemuMigrationSrcBeginResumePhase(conn, driver, vm, xmlin,
|
||||
cookieout, cookieoutlen, flags);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
|
||||
if (qemuMigrationJobStart(driver, vm, VIR_ASYNC_JOB_MIGRATION_OUT,
|
||||
flags) < 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user