qemuMonitorMemoryDeviceSizeChangeFree(event->data);
break;
case QEMU_PROCESS_EVENT_PR_DISCONNECT:
+ case QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION:
case QEMU_PROCESS_EVENT_LAST:
break;
}
QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
QEMU_PROCESS_EVENT_GUEST_CRASHLOADED,
QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
+ QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION,
QEMU_PROCESS_EVENT_LAST
} qemuProcessEventType;
case QEMU_PROCESS_EVENT_MEMORY_DEVICE_SIZE_CHANGE:
processMemoryDeviceSizeChange(driver, vm, processEvent->data);
break;
+ case QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION:
+ qemuMigrationProcessUnattended(driver, vm,
+ processEvent->action,
+ processEvent->status);
+ break;
case QEMU_PROCESS_EVENT_LAST:
break;
}
qemuDomainSaveStatus(vm);
- /* Guest is successfully running, so cancel previous auto destroy */
- qemuProcessAutoDestroyRemove(driver, vm);
+ /* Guest is successfully running, so cancel previous auto destroy. There's
+ * nothing to remove when we are resuming post-copy migration.
+ */
+ if (!virDomainObjIsFailedPostcopy(vm))
+ qemuProcessAutoDestroyRemove(driver, vm);
/* Remove completed stats for post-copy, everything but timing fields
* is obsolete anyway.
}
+void
+qemuMigrationProcessUnattended(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainAsyncJob job,
+ qemuMonitorMigrationStatus status)
+{
+ qemuDomainObjPrivate *priv = vm->privateData;
+ qemuMigrationJobPhase phase;
+
+ if (!qemuMigrationJobIsActive(vm, job) ||
+ status != QEMU_MONITOR_MIGRATION_STATUS_COMPLETED)
+ return;
+
+ VIR_DEBUG("Unattended %s migration of domain %s successfully finished",
+ job == VIR_ASYNC_JOB_MIGRATION_IN ? "incoming" : "outgoing",
+ vm->def->name);
+
+ if (job == VIR_ASYNC_JOB_MIGRATION_IN)
+ phase = QEMU_MIGRATION_PHASE_FINISH3;
+ else
+ phase = QEMU_MIGRATION_PHASE_CONFIRM3;
+
+ qemuMigrationJobStartPhase(vm, phase);
+
+ if (job == VIR_ASYNC_JOB_MIGRATION_IN)
+ qemuMigrationDstComplete(driver, vm, true, job, &priv->job);
+ else
+ qemuMigrationSrcComplete(driver, vm, job);
+
+ qemuMigrationJobFinish(vm);
+
+ if (!virDomainObjIsActive(vm))
+ qemuDomainRemoveInactive(driver, vm);
+}
+
+
/* Helper function called while vm is active. */
int
qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm,
virDomainObj *vm,
virDomainAsyncJob asyncJob);
+void
+qemuMigrationProcessUnattended(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainAsyncJob job,
+ qemuMonitorMigrationStatus status);
+
bool
qemuMigrationSrcIsAllowed(virQEMUDriver *driver,
virDomainObj *vm,
}
break;
+ case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
+ /* A post-copy migration marked as failed when reconnecting to a domain
+ * with running migration may actually still be running, but we're not
+ * watching it in any thread. Let's make sure the migration is properly
+ * finished in case we get a "completed" event.
+ */
+ if (virDomainObjIsFailedPostcopy(vm) && priv->job.asyncOwner == 0)
+ qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_UNATTENDED_MIGRATION,
+ priv->job.asyncJob, status, NULL);
+ break;
+
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
case QEMU_MONITOR_MIGRATION_STATUS_PRE_SWITCHOVER:
case QEMU_MONITOR_MIGRATION_STATUS_DEVICE:
- case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING:
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: