]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add new migration phases for post-copy recovery
authorJiri Denemark <jdenemar@redhat.com>
Tue, 10 May 2022 13:20:25 +0000 (15:20 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Tue, 7 Jun 2022 15:40:20 +0000 (17:40 +0200)
When recovering from a failed post-copy migration, we need to go through
all migration phases again, but don't need to repeat all the steps in
each phase. Let's create a new set of migration phases dedicated to
post-copy recovery so that we can easily distinguish between normal and
recovery code.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
src/qemu/qemu_migration.c
src/qemu/qemu_migration.h
src/qemu/qemu_process.c

index b6263a58089909d5de5fc9ef7464937dc152a2d9..ae3927201fa61bbd411376c7c5a8c9d042b5a364 100644 (file)
@@ -79,6 +79,12 @@ VIR_ENUM_IMPL(qemuMigrationJobPhase,
               "prepare",
               "finish2",
               "finish3",
+              "postcopy_failed",
+              "begin_resume",
+              "perform_resume",
+              "confirm_resume",
+              "prepare_resume",
+              "finish_resume",
 );
 
 
@@ -139,7 +145,8 @@ qemuMigrationJobSetPhase(virDomainObj *vm,
 {
     qemuDomainObjPrivate *priv = vm->privateData;
 
-    if (phase < priv->job.phase) {
+    if (phase < QEMU_MIGRATION_PHASE_POSTCOPY_FAILED &&
+        phase < priv->job.phase) {
         VIR_ERROR(_("migration protocol going backwards %s => %s"),
                   qemuMigrationJobPhaseTypeToString(priv->job.phase),
                   qemuMigrationJobPhaseTypeToString(phase));
@@ -2328,18 +2335,29 @@ qemuMigrationSrcCleanup(virDomainObj *vm,
         }
         break;
 
+    case QEMU_MIGRATION_PHASE_BEGIN_RESUME:
+    case QEMU_MIGRATION_PHASE_PERFORM_RESUME:
+        qemuMigrationSrcPostcopyFailed(vm);
+        qemuDomainCleanupAdd(vm, qemuProcessCleanupMigrationJob);
+        qemuMigrationJobContinue(vm);
+        break;
+
     case QEMU_MIGRATION_PHASE_PERFORM3:
         /* cannot be seen without an active migration API; unreachable */
     case QEMU_MIGRATION_PHASE_CONFIRM3:
     case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
+    case QEMU_MIGRATION_PHASE_CONFIRM_RESUME:
         /* all done; unreachable */
     case QEMU_MIGRATION_PHASE_PREPARE:
     case QEMU_MIGRATION_PHASE_FINISH2:
     case QEMU_MIGRATION_PHASE_FINISH3:
+    case QEMU_MIGRATION_PHASE_PREPARE_RESUME:
+    case QEMU_MIGRATION_PHASE_FINISH_RESUME:
         /* incoming migration; unreachable */
     case QEMU_MIGRATION_PHASE_PERFORM2:
         /* single phase outgoing migration; unreachable */
     case QEMU_MIGRATION_PHASE_NONE:
+    case QEMU_MIGRATION_PHASE_POSTCOPY_FAILED:
     case QEMU_MIGRATION_PHASE_LAST:
         /* unreachable */
         ;
index 9351d6ac512af0b892526a7e52c30f5732960d44..7eb0d4fe0220681eb714dce3a2641a6c93510ebe 100644 (file)
@@ -100,6 +100,12 @@ typedef enum {
     QEMU_MIGRATION_PHASE_PREPARE,
     QEMU_MIGRATION_PHASE_FINISH2,
     QEMU_MIGRATION_PHASE_FINISH3,
+    QEMU_MIGRATION_PHASE_POSTCOPY_FAILED, /* marker for resume phases */
+    QEMU_MIGRATION_PHASE_BEGIN_RESUME,
+    QEMU_MIGRATION_PHASE_PERFORM_RESUME,
+    QEMU_MIGRATION_PHASE_CONFIRM_RESUME,
+    QEMU_MIGRATION_PHASE_PREPARE_RESUME,
+    QEMU_MIGRATION_PHASE_FINISH_RESUME,
 
     QEMU_MIGRATION_PHASE_LAST
 } qemuMigrationJobPhase;
index 6dd643a38b48412f24ad75f7f0482b6a05036d5d..f752668b2fc701dc7f730176f14825fa5673567f 100644 (file)
@@ -3507,6 +3507,10 @@ qemuProcessRecoverMigrationIn(virQEMUDriver *driver,
     case QEMU_MIGRATION_PHASE_PERFORM3_DONE:
     case QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED:
     case QEMU_MIGRATION_PHASE_CONFIRM3:
+    case QEMU_MIGRATION_PHASE_POSTCOPY_FAILED:
+    case QEMU_MIGRATION_PHASE_BEGIN_RESUME:
+    case QEMU_MIGRATION_PHASE_PERFORM_RESUME:
+    case QEMU_MIGRATION_PHASE_CONFIRM_RESUME:
     case QEMU_MIGRATION_PHASE_LAST:
         /* N/A for incoming migration */
         break;
@@ -3540,6 +3544,10 @@ qemuProcessRecoverMigrationIn(virQEMUDriver *driver,
             return -1;
         }
         break;
+
+    case QEMU_MIGRATION_PHASE_PREPARE_RESUME:
+    case QEMU_MIGRATION_PHASE_FINISH_RESUME:
+        return 1;
     }
 
     return 0;
@@ -3548,7 +3556,8 @@ qemuProcessRecoverMigrationIn(virQEMUDriver *driver,
 
 /*
  * Returns
- *     -1 on error, the domain will be killed,
+ *     -1 the domain should be killed (either after a successful migration or
+ *        on error),
  *      0 the domain should remain running with the migration job discarded,
  *      1 the daemon was restarted during post-copy phase
  */
@@ -3556,6 +3565,7 @@ static int
 qemuProcessRecoverMigrationOut(virQEMUDriver *driver,
                                virDomainObj *vm,
                                qemuDomainJobObj *job,
+                               virDomainJobStatus migStatus,
                                virDomainState state,
                                int reason,
                                unsigned int *stopFlags)
@@ -3571,6 +3581,9 @@ qemuProcessRecoverMigrationOut(virQEMUDriver *driver,
     case QEMU_MIGRATION_PHASE_PREPARE:
     case QEMU_MIGRATION_PHASE_FINISH2:
     case QEMU_MIGRATION_PHASE_FINISH3:
+    case QEMU_MIGRATION_PHASE_POSTCOPY_FAILED:
+    case QEMU_MIGRATION_PHASE_PREPARE_RESUME:
+    case QEMU_MIGRATION_PHASE_FINISH_RESUME:
     case QEMU_MIGRATION_PHASE_LAST:
         /* N/A for outgoing migration */
         break;
@@ -3621,6 +3634,18 @@ qemuProcessRecoverMigrationOut(virQEMUDriver *driver,
         /* migration completed, we need to kill the domain here */
         *stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
         return -1;
+
+    case QEMU_MIGRATION_PHASE_CONFIRM_RESUME:
+        if (migStatus == VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED) {
+            /* migration completed, we need to kill the domain here */
+            *stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
+            return -1;
+        }
+        return 1;
+
+    case QEMU_MIGRATION_PHASE_BEGIN_RESUME:
+    case QEMU_MIGRATION_PHASE_PERFORM_RESUME:
+        return 1;
     }
 
     if (resume) {
@@ -3659,7 +3684,7 @@ qemuProcessRecoverMigration(virQEMUDriver *driver,
     qemuMigrationAnyRefreshStatus(driver, vm, VIR_ASYNC_JOB_NONE, &migStatus);
 
     if (job->asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT) {
-        rc = qemuProcessRecoverMigrationOut(driver, vm, job,
+        rc = qemuProcessRecoverMigrationOut(driver, vm, job, migStatus,
                                             state, reason, stopFlags);
     } else {
         rc = qemuProcessRecoverMigrationIn(driver, vm, job, state);