mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
qemu: Recover from interrupted migration
This commit is contained in:
parent
d58e91a812
commit
9cfd2197e4
@ -37,6 +37,7 @@
|
|||||||
#include "qemu_hostdev.h"
|
#include "qemu_hostdev.h"
|
||||||
#include "qemu_hotplug.h"
|
#include "qemu_hotplug.h"
|
||||||
#include "qemu_bridge_filter.h"
|
#include "qemu_bridge_filter.h"
|
||||||
|
#include "qemu_migration.h"
|
||||||
|
|
||||||
#if HAVE_NUMACTL
|
#if HAVE_NUMACTL
|
||||||
# define NUMA_VERSION1_COMPATIBILITY 1
|
# define NUMA_VERSION1_COMPATIBILITY 1
|
||||||
@ -2280,6 +2281,111 @@ qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuProcessRecoverMigration(struct qemud_driver *driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virConnectPtr conn,
|
||||||
|
enum qemuDomainAsyncJob job,
|
||||||
|
enum qemuMigrationJobPhase phase,
|
||||||
|
virDomainState state,
|
||||||
|
int reason)
|
||||||
|
{
|
||||||
|
if (job == QEMU_ASYNC_JOB_MIGRATION_IN) {
|
||||||
|
switch (phase) {
|
||||||
|
case QEMU_MIGRATION_PHASE_NONE:
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM2:
|
||||||
|
case QEMU_MIGRATION_PHASE_BEGIN3:
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM3:
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
|
||||||
|
case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
|
||||||
|
case QEMU_MIGRATION_PHASE_CONFIRM3:
|
||||||
|
case QEMU_MIGRATION_PHASE_LAST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_PREPARE:
|
||||||
|
VIR_DEBUG("Killing unfinished incoming migration for domain %s",
|
||||||
|
vm->def->name);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_FINISH2:
|
||||||
|
/* source domain is already killed so let's just resume the domain
|
||||||
|
* and hope we are all set */
|
||||||
|
VIR_DEBUG("Incoming migration finished, resuming domain %s",
|
||||||
|
vm->def->name);
|
||||||
|
if (qemuProcessStartCPUs(driver, vm, conn,
|
||||||
|
VIR_DOMAIN_RUNNING_UNPAUSED) < 0) {
|
||||||
|
VIR_WARN("Could not resume domain %s", vm->def->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_FINISH3:
|
||||||
|
/* migration finished, we started resuming the domain but didn't
|
||||||
|
* confirm success or failure yet; killing it seems safest */
|
||||||
|
VIR_DEBUG("Killing migrated domain %s", vm->def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (job == QEMU_ASYNC_JOB_MIGRATION_OUT) {
|
||||||
|
switch (phase) {
|
||||||
|
case QEMU_MIGRATION_PHASE_NONE:
|
||||||
|
case QEMU_MIGRATION_PHASE_PREPARE:
|
||||||
|
case QEMU_MIGRATION_PHASE_FINISH2:
|
||||||
|
case QEMU_MIGRATION_PHASE_FINISH3:
|
||||||
|
case QEMU_MIGRATION_PHASE_LAST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_BEGIN3:
|
||||||
|
/* nothing happen so far, just forget we were about to migrate the
|
||||||
|
* domain */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM2:
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM3:
|
||||||
|
/* migration is still in progress, let's cancel it and resume the
|
||||||
|
* domain */
|
||||||
|
VIR_DEBUG("Canceling unfinished outgoing migration of domain %s",
|
||||||
|
vm->def->name);
|
||||||
|
/* TODO cancel possibly running migrate operation */
|
||||||
|
/* resume the domain but only if it was paused as a result of
|
||||||
|
* migration */
|
||||||
|
if (state == VIR_DOMAIN_PAUSED &&
|
||||||
|
(reason == VIR_DOMAIN_PAUSED_MIGRATION ||
|
||||||
|
reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
|
||||||
|
if (qemuProcessStartCPUs(driver, vm, conn,
|
||||||
|
VIR_DOMAIN_RUNNING_UNPAUSED) < 0) {
|
||||||
|
VIR_WARN("Could not resume domain %s", vm->def->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
|
||||||
|
/* migration finished but we didn't have a chance to get the result
|
||||||
|
* of Finish3 step; third party needs to check what to do next
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
|
||||||
|
/* Finish3 failed, we need to resume the domain */
|
||||||
|
VIR_DEBUG("Resuming domain %s after failed migration",
|
||||||
|
vm->def->name);
|
||||||
|
if (state == VIR_DOMAIN_PAUSED &&
|
||||||
|
(reason == VIR_DOMAIN_PAUSED_MIGRATION ||
|
||||||
|
reason == VIR_DOMAIN_PAUSED_UNKNOWN)) {
|
||||||
|
if (qemuProcessStartCPUs(driver, vm, conn,
|
||||||
|
VIR_DOMAIN_RUNNING_UNPAUSED) < 0) {
|
||||||
|
VIR_WARN("Could not resume domain %s", vm->def->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMU_MIGRATION_PHASE_CONFIRM3:
|
||||||
|
/* migration completed, we need to kill the domain here */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuProcessRecoverJob(struct qemud_driver *driver,
|
qemuProcessRecoverJob(struct qemud_driver *driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
@ -2294,7 +2400,9 @@ qemuProcessRecoverJob(struct qemud_driver *driver,
|
|||||||
switch (job->asyncJob) {
|
switch (job->asyncJob) {
|
||||||
case QEMU_ASYNC_JOB_MIGRATION_OUT:
|
case QEMU_ASYNC_JOB_MIGRATION_OUT:
|
||||||
case QEMU_ASYNC_JOB_MIGRATION_IN:
|
case QEMU_ASYNC_JOB_MIGRATION_IN:
|
||||||
/* we don't know what to do yet */
|
if (qemuProcessRecoverMigration(driver, vm, conn, job->asyncJob,
|
||||||
|
job->phase, state, reason) < 0)
|
||||||
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QEMU_ASYNC_JOB_SAVE:
|
case QEMU_ASYNC_JOB_SAVE:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user