* cancellation to complete.
*
* The thread (the caller itself in most cases) which is watching the migration
- * will do all the cleanup once migration is canceled. If no thread is watching
- * the migration, use qemuMigrationSrcCancelUnattended instead.
+ * will do all the cleanup once migration is canceled.
*/
int
qemuMigrationSrcCancel(virDomainObj *vm,
/**
- * This function is supposed to be used only when no other thread is watching
- * the migration.
+ * This function is supposed to be used only to while reconnecting to a domain
+ * with an active migration job.
*/
int
-qemuMigrationSrcCancelUnattended(virDomainObj *vm)
+qemuMigrationSrcCancelUnattended(virDomainObj *vm,
+ virDomainJobObj *oldJob)
{
bool storage = false;
size_t i;
VIR_DEBUG("Canceling unfinished outgoing migration of domain %s",
vm->def->name);
+ /* Make sure MIGRATION event handler can store the current migration state
+ * in the job.
+ */
+ if (!vm->job->current) {
+ qemuDomainObjRestoreAsyncJob(vm, VIR_ASYNC_JOB_MIGRATION_OUT,
+ oldJob->phase, oldJob->asyncStarted,
+ VIR_DOMAIN_JOB_OPERATION_MIGRATION_OUT,
+ QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION,
+ VIR_DOMAIN_JOB_STATUS_FAILED,
+ VIR_JOB_NONE);
+ }
+
+ /* We're inside a MODIFY job and the restored MIGRATION_OUT async job is
+ * used only for processing migration events from QEMU. Thus we don't want
+ * to start a nested job for talking to QEMU.
+ */
qemuMigrationSrcCancel(vm, VIR_ASYNC_JOB_NONE, true);
+ virDomainObjEndAsyncJob(vm);
+
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDef *disk = vm->def->disks[i];
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
*/
VIR_DEBUG("Cancelling unfinished migration of domain %s",
vm->def->name);
- if (qemuMigrationSrcCancelUnattended(vm) < 0) {
+ if (qemuMigrationSrcCancelUnattended(vm, job) < 0) {
VIR_WARN("Could not cancel ongoing migration of domain %s",
vm->def->name);
}
case VIR_ASYNC_JOB_SAVE:
case VIR_ASYNC_JOB_DUMP:
case VIR_ASYNC_JOB_SNAPSHOT:
- qemuMigrationSrcCancel(vm, VIR_ASYNC_JOB_NONE, true);
+ qemuMigrationSrcCancel(vm, VIR_ASYNC_JOB_NONE, false);
/* resume the domain but only if it was paused as a result of
* running a migration-to-file operation. Although we are
* recovering an async job, this function is run at startup