Skip to content

Commit

Permalink
MTV-446 | Warm: Add cbt check before migration
Browse files Browse the repository at this point in the history
Issue:
Right now we have a check to fail the migration when we start to create
the VM which does not have the CBT enabled. We should throw error much
earlier before the customer even start the migration.

Fix:
Add a CBT check to the plan validation. This fix right now affects only
VMware migrations.

Signed-off-by: Martin Necas <mnecas@redhat.com>
  • Loading branch information
mnecas committed Sep 18, 2024
1 parent c8a80f1 commit b7501bc
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 44 deletions.
2 changes: 2 additions & 0 deletions pkg/controller/plan/adapter/base/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ type Validator interface {
PodNetwork(vmRef ref.Ref) (bool, error)
// Validate that we have information about static IPs for every virtual NIC
StaticIPs(vmRef ref.Ref) (bool, error)
// Validate that the vm has the change tracking enabled
ChangeTrackingEnabled(vmRef ref.Ref) (bool, error)
}

// DestinationClient API.
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/ocp/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,8 @@ func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
func (r *Validator) StaticIPs(vmRef ref.Ref) (bool, error) {
return true, nil
}

// NO-OP
func (r *Validator) ChangeTrackingEnabled(vmRef ref.Ref) (bool, error) {
return true, nil
}
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/openstack/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,8 @@ func (r *Validator) StaticIPs(vmRef ref.Ref) (bool, error) {
// the guest operating system is not modified during the migration so static IPs should be preserved
return true, nil
}

// NO-OP
func (r *Validator) ChangeTrackingEnabled(vmRef ref.Ref) (bool, error) {
return true, nil
}
6 changes: 6 additions & 0 deletions pkg/controller/plan/adapter/ova/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
func (r *Validator) StaticIPs(vmRef ref.Ref) (bool, error) {
return true, nil
}

// NO-OP
func (r *Validator) ChangeTrackingEnabled(vmRef ref.Ref) (bool, error) {
// Validate that the vm has the change tracking enabled
return true, nil
}
6 changes: 6 additions & 0 deletions pkg/controller/plan/adapter/ovirt/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,9 @@ func (r *Validator) StaticIPs(vmRef ref.Ref) (bool, error) {
// the guest operating system is not modified during the migration so static IPs should be preserved
return true, nil
}

// NO-OP
func (r *Validator) ChangeTrackingEnabled(vmRef ref.Ref) (bool, error) {
// Validate that the vm has the change tracking enabled
return true, nil
}
13 changes: 13 additions & 0 deletions pkg/controller/plan/adapter/vsphere/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,16 @@ func (r *Validator) StaticIPs(vmRef ref.Ref) (ok bool, err error) {
ok = true
return
}

// Validate that the vm has the change tracking enabled
func (r *Validator) ChangeTrackingEnabled(vmRef ref.Ref) (bool, error) {
if !r.plan.Spec.Warm {
return true, nil
}
vm := &model.Workload{}
err := r.inventory.Find(vm, vmRef)
if err != nil {
return false, liberr.Wrap(err, "vm", vmRef)
}
return vm.ChangeTrackingEnabled, nil
}
112 changes: 68 additions & 44 deletions pkg/controller/plan/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,41 @@ import (

// Types
const (
WarmMigrationNotReady = "WarmMigrationNotReady"
NamespaceNotValid = "NamespaceNotValid"
TransferNetNotValid = "TransferNetworkNotValid"
NetRefNotValid = "NetworkMapRefNotValid"
NetMapNotReady = "NetworkMapNotReady"
DsMapNotReady = "StorageMapNotReady"
DsRefNotValid = "StorageRefNotValid"
VMRefNotValid = "VMRefNotValid"
VMNotFound = "VMNotFound"
VMAlreadyExists = "VMAlreadyExists"
VMNetworksNotMapped = "VMNetworksNotMapped"
VMStorageNotMapped = "VMStorageNotMapped"
VMStorageNotSupported = "VMStorageNotSupported"
VMMultiplePodNetworkMappings = "VMMultiplePodNetworkMappings"
VMMissingGuestIPs = "VMMissingGuestIPs"
HostNotReady = "HostNotReady"
DuplicateVM = "DuplicateVM"
NameNotValid = "TargetNameNotValid"
HookNotValid = "HookNotValid"
HookNotReady = "HookNotReady"
HookStepNotValid = "HookStepNotValid"
Executing = "Executing"
Succeeded = "Succeeded"
Failed = "Failed"
Canceled = "Canceled"
Deleted = "Deleted"
Paused = "Paused"
Pending = "Pending"
Running = "Running"
Blocked = "Blocked"
Archived = "Archived"
unsupportedVersion = "UnsupportedVersion"
VDDKInvalid = "VDDKInvalid"
ValidatingVDDK = "ValidatingVDDK"
WarmMigrationNotReady = "WarmMigrationNotReady"
NamespaceNotValid = "NamespaceNotValid"
TransferNetNotValid = "TransferNetworkNotValid"
NetRefNotValid = "NetworkMapRefNotValid"
NetMapNotReady = "NetworkMapNotReady"
DsMapNotReady = "StorageMapNotReady"
DsRefNotValid = "StorageRefNotValid"
VMRefNotValid = "VMRefNotValid"
VMNotFound = "VMNotFound"
VMAlreadyExists = "VMAlreadyExists"
VMNetworksNotMapped = "VMNetworksNotMapped"
VMStorageNotMapped = "VMStorageNotMapped"
VMStorageNotSupported = "VMStorageNotSupported"
VMMultiplePodNetworkMappings = "VMMultiplePodNetworkMappings"
VMMissingGuestIPs = "VMMissingGuestIPs"
VMMissingChangedBlockTracking = "VMMissingChangedBlockTracking"
HostNotReady = "HostNotReady"
DuplicateVM = "DuplicateVM"
NameNotValid = "TargetNameNotValid"
HookNotValid = "HookNotValid"
HookNotReady = "HookNotReady"
HookStepNotValid = "HookStepNotValid"
Executing = "Executing"
Succeeded = "Succeeded"
Failed = "Failed"
Canceled = "Canceled"
Deleted = "Deleted"
Paused = "Paused"
Pending = "Pending"
Running = "Running"
Blocked = "Blocked"
Archived = "Archived"
unsupportedVersion = "UnsupportedVersion"
VDDKInvalid = "VDDKInvalid"
ValidatingVDDK = "ValidatingVDDK"
)

// Categories
Expand All @@ -82,16 +83,17 @@ const (

// Reasons
const (
NotSet = "NotSet"
NotFound = "NotFound"
NotUnique = "NotUnique"
NotSupported = "NotSupported"
Ambiguous = "Ambiguous"
NotValid = "NotValid"
Modified = "Modified"
UserRequested = "UserRequested"
InMaintenanceMode = "InMaintenanceMode"
MissingGuestInfo = "MissingGuestInformation"
NotSet = "NotSet"
NotFound = "NotFound"
NotUnique = "NotUnique"
NotSupported = "NotSupported"
Ambiguous = "Ambiguous"
NotValid = "NotValid"
Modified = "Modified"
UserRequested = "UserRequested"
InMaintenanceMode = "InMaintenanceMode"
MissingGuestInfo = "MissingGuestInformation"
MissingChangedBlockTracking = "MissingChangedBlockTracking"
)

// Statuses
Expand Down Expand Up @@ -236,6 +238,28 @@ func (r *Reconciler) validateWarmMigration(plan *api.Plan) (err error) {
Message: "Warm migration from the source provider is not supported.",
})
}

missingCbtForWarm := libcnd.Condition{
Type: VMMissingChangedBlockTracking,
Status: True,
Reason: MissingChangedBlockTracking,
Category: Critical,
Message: "Changed Block Tracking (CBT) has not been enabled on some VM. This feature is a prerequisite for VM warm migration.",
Items: []string{},
}
for i := range plan.Spec.VMs {
ref := &plan.Spec.VMs[i].Ref
enabled, err := validator.ChangeTrackingEnabled(*ref)
if err != nil {
return err
}
if !enabled {
missingCbtForWarm.Items = append(missingCbtForWarm.Items, ref.String())
}
}
if len(missingCbtForWarm.Items) > 0 {
plan.Status.SetCondition(missingCbtForWarm)
}
return
}

Expand Down

0 comments on commit b7501bc

Please sign in to comment.