QEMU Migration Phases ===================== Qemu supports only migration protocols 2 and 3 (1 was lacking too many steps). Repeating the protocol sequences from libvirt.c: Sequence v2: Src: DumpXML - Generate XML to pass to dst Dst: Prepare - Get ready to accept incoming VM - Generate optional cookie to pass to src Src: Perform - Start migration and wait for send completion - Kill off VM if successful, resume if failed Dst: Finish - Wait for recv completion and check status - Kill off VM if unsuccessful Sequence v3: Src: Begin - Generate XML to pass to dst - Generate optional cookie to pass to dst Dst: Prepare - Get ready to accept incoming VM - Generate optional cookie to pass to src Src: Perform - Start migration and wait for send completion - Generate optional cookie to pass to dst Dst: Finish - Wait for recv completion and check status - Kill off VM if failed, resume if success - Generate optional cookie to pass to src Src: Confirm - Kill off VM if success, resume if failed QEMU Migration Locking Rules ============================ Migration is a complicated beast which may span across several APIs on both source and destination side and we need to keep the domain we are migrating in a consistent state during the whole process. To avoid anyone from changing the domain in the middle of migration we need to keep MIGRATION_OUT job active during migration from Begin to Confirm on the source side and MIGRATION_IN job has to be active from Prepare to Finish on the destination side. For this purpose we introduce several helper methods to deal with locking primitives (described in THREADS.txt) in the right way: * qemuMigrationJobStart * qemuMigrationJobContinue * qemuMigrationJobStartPhase * qemuMigrationJobSetPhase * qemuMigrationJobFinish The sequence of calling qemuMigrationJob* helper methods is as follows: - The first API of a migration protocol (Prepare or Perform/Begin depending on migration type and version) has to start migration job and keep it active: qemuMigrationJobStart(driver, vm, QEMU_JOB_MIGRATION_{IN,OUT}); qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_*); ...do work... qemuMigrationJobContinue(vm); - All consequent phases except for the last one have to keep the job active: if (!qemuMigrationJobIsActive(vm, QEMU_JOB_MIGRATION_{IN,OUT})) return; qemuMigrationJobStartPhase(driver, vm, QEMU_MIGRATION_PHASE_*); ...do work... qemuMigrationJobContinue(vm); - The last migration phase finally finishes the migration job: if (!qemuMigrationJobIsActive(vm, QEMU_JOB_MIGRATION_{IN,OUT})) return; qemuMigrationJobStartPhase(driver, vm, QEMU_MIGRATION_PHASE_*); ...do work... qemuMigrationJobFinish(driver, vm); While migration job is running (i.e., after qemuMigrationJobStart* but before qemuMigrationJob{Continue,Finish}), migration phase can be advanced using qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_*);