From 2dd30223bfe323a1ec459c5cb8592cbcb0834870 Mon Sep 17 00:00:00 2001 From: Martin Necas Date: Tue, 3 Dec 2024 15:05:58 +0100 Subject: [PATCH] MTV-1717 | Wait for DV status Issue: When CDI is managing lot of DVs at once it can take some time before the CDI reconciles the DVs status and start the import. In the function `updateCopyProgress` we check the DV status and if it is paused we do continue and as next phase we have snapshot removal. So if the DV is still in paused state and we start the cutover and MTV skips over the phase thinking it already finished as the DV is in paused. Fix: Add WaitForDataVolumesStatus phase to wait until the DVs do not have the paused status. Ref: https://issues.redhat.com/browse/MTV-1717 https://github.com/kubev2v/forklift/blob/ea83264881b3dcd4a88dd627c1ca75da2483f408/pkg/controller/plan/migration.go#L1573-L1575 Signed-off-by: Martin Necas --- pkg/controller/plan/migration.go | 95 +++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/pkg/controller/plan/migration.go b/pkg/controller/plan/migration.go index 4ef55f4cb..aa393e24b 100644 --- a/pkg/controller/plan/migration.go +++ b/pkg/controller/plan/migration.go @@ -55,36 +55,38 @@ var ( // Phases. const ( - Started = "Started" - PreHook = "PreHook" - StorePowerState = "StorePowerState" - PowerOffSource = "PowerOffSource" - WaitForPowerOff = "WaitForPowerOff" - CreateDataVolumes = "CreateDataVolumes" - CreateVM = "CreateVM" - CopyDisks = "CopyDisks" - AllocateDisks = "AllocateDisks" - CopyingPaused = "CopyingPaused" - AddCheckpoint = "AddCheckpoint" - AddFinalCheckpoint = "AddFinalCheckpoint" - CreateSnapshot = "CreateSnapshot" - CreateInitialSnapshot = "CreateInitialSnapshot" - CreateFinalSnapshot = "CreateFinalSnapshot" - Finalize = "Finalize" - CreateGuestConversionPod = "CreateGuestConversionPod" - ConvertGuest = "ConvertGuest" - CopyDisksVirtV2V = "CopyDisksVirtV2V" - PostHook = "PostHook" - Completed = "Completed" - WaitForSnapshot = "WaitForSnapshot" - WaitForInitialSnapshot = "WaitForInitialSnapshot" - WaitForFinalSnapshot = "WaitForFinalSnapshot" - ConvertOpenstackSnapshot = "ConvertOpenstackSnapshot" - StoreSnapshotDeltas = "StoreSnapshotDeltas" - StoreInitialSnapshotDeltas = "StoreInitialSnapshotDeltas" - RemovePreviousSnapshot = "RemovePreviousSnapshot" - RemovePenultimateSnapshot = "RemovePenultimateSnapshot" - RemoveFinalSnapshot = "RemoveFinalSnapshot" + Started = "Started" + PreHook = "PreHook" + StorePowerState = "StorePowerState" + PowerOffSource = "PowerOffSource" + WaitForPowerOff = "WaitForPowerOff" + CreateDataVolumes = "CreateDataVolumes" + WaitForDataVolumesStatus = "WaitForDataVolumesStatus" + WaitForFinalDataVolumesStatus = "WaitForFinalDataVolumesStatus" + CreateVM = "CreateVM" + CopyDisks = "CopyDisks" + AllocateDisks = "AllocateDisks" + CopyingPaused = "CopyingPaused" + AddCheckpoint = "AddCheckpoint" + AddFinalCheckpoint = "AddFinalCheckpoint" + CreateSnapshot = "CreateSnapshot" + CreateInitialSnapshot = "CreateInitialSnapshot" + CreateFinalSnapshot = "CreateFinalSnapshot" + Finalize = "Finalize" + CreateGuestConversionPod = "CreateGuestConversionPod" + ConvertGuest = "ConvertGuest" + CopyDisksVirtV2V = "CopyDisksVirtV2V" + PostHook = "PostHook" + Completed = "Completed" + WaitForSnapshot = "WaitForSnapshot" + WaitForInitialSnapshot = "WaitForInitialSnapshot" + WaitForFinalSnapshot = "WaitForFinalSnapshot" + ConvertOpenstackSnapshot = "ConvertOpenstackSnapshot" + StoreSnapshotDeltas = "StoreSnapshotDeltas" + StoreInitialSnapshotDeltas = "StoreInitialSnapshotDeltas" + RemovePreviousSnapshot = "RemovePreviousSnapshot" + RemovePenultimateSnapshot = "RemovePenultimateSnapshot" + RemoveFinalSnapshot = "RemoveFinalSnapshot" ) // Steps. @@ -134,6 +136,7 @@ var ( {Name: WaitForInitialSnapshot}, {Name: StoreInitialSnapshotDeltas, All: VSphere}, {Name: CreateDataVolumes}, + {Name: WaitForDataVolumesStatus}, {Name: CopyDisks}, {Name: CopyingPaused}, {Name: RemovePreviousSnapshot, All: VSphere}, @@ -148,6 +151,7 @@ var ( {Name: CreateFinalSnapshot}, {Name: WaitForFinalSnapshot}, {Name: AddFinalCheckpoint}, + {Name: WaitForFinalDataVolumesStatus}, {Name: Finalize}, {Name: RemoveFinalSnapshot, All: VSphere}, {Name: CreateGuestConversionPod, All: RequiresConversion}, @@ -662,9 +666,9 @@ func (r *Migration) step(vm *plan.VMStatus) (step string) { step = Initialize case AllocateDisks: step = DiskAllocation - case CopyDisks, CopyingPaused, RemovePreviousSnapshot, CreateSnapshot, WaitForSnapshot, StoreSnapshotDeltas, AddCheckpoint, ConvertOpenstackSnapshot: + case CopyDisks, CopyingPaused, RemovePreviousSnapshot, CreateSnapshot, WaitForSnapshot, StoreSnapshotDeltas, AddCheckpoint, ConvertOpenstackSnapshot, WaitForDataVolumesStatus: step = DiskTransfer - case RemovePenultimateSnapshot, CreateFinalSnapshot, WaitForFinalSnapshot, AddFinalCheckpoint, Finalize, RemoveFinalSnapshot: + case RemovePenultimateSnapshot, CreateFinalSnapshot, WaitForFinalSnapshot, AddFinalCheckpoint, Finalize, RemoveFinalSnapshot, WaitForFinalDataVolumesStatus: step = Cutover case CreateGuestConversionPod, ConvertGuest: step = ImageConversion @@ -1039,6 +1043,22 @@ func (r *Migration) execute(vm *plan.VMStatus) (err error) { if ready { vm.Phase = r.next(vm.Phase) } + case WaitForDataVolumesStatus, WaitForFinalDataVolumesStatus: + step, found := vm.FindStep(r.step(vm)) + if !found { + vm.AddError(fmt.Sprintf("Step '%s' not found", r.step(vm))) + break + } + + dvs, err := r.kubevirt.getDVs(vm) + if err != nil { + step.AddError(err.Error()) + err = nil + break + } + if !r.hasPausedDv(dvs) { + vm.Phase = r.next(vm.Phase) + } case StoreInitialSnapshotDeltas, StoreSnapshotDeltas: step, found := vm.FindStep(r.step(vm)) if !found { @@ -1073,7 +1093,7 @@ func (r *Migration) execute(vm *plan.VMStatus) (err error) { switch vm.Phase { case AddCheckpoint: - vm.Phase = CopyDisks + vm.Phase = WaitForDataVolumesStatus case AddFinalCheckpoint: vm.Phase = Finalize } @@ -1259,6 +1279,15 @@ func (r *Migration) execute(vm *plan.VMStatus) (err error) { return } +func (r *Migration) hasPausedDv(dvs []ExtendedDataVolume) bool { + for _, dv := range dvs { + if dv.Status.Phase == Paused { + return true + } + } + return false +} + func (r *Migration) resetPrecopyTasks(vm *plan.VMStatus, step *plan.Step) { step.Completed = nil for _, task := range step.Tasks {