Skip to content

Commit

Permalink
MTV-1536 | Use CDI for disk transfer in cold migration feature toggle
Browse files Browse the repository at this point in the history
Issue:
This is alternative to kubev2v#1109
which removes the virt-v2v disk transfer and replaces it with te CDI.
The main dissadvatage of that solution is that in case customer will
have problems with the new CDI method there won't be any easy way how to
go back, to the virt-v2v.

Fix:
This change adds a new feature toggle `feature_vsphere_cold_cdi` in the
forklift controller. By default the feature will be enabled and in case
there will be problems such as disk corruption the user can disable it.

Signed-off-by: Martin Necas <[email protected]>
  • Loading branch information
mnecas committed Nov 6, 2024
1 parent 9de3139 commit 53d631c
Show file tree
Hide file tree
Showing 11 changed files with 22 additions and 9 deletions.
1 change: 1 addition & 0 deletions operator/roles/forkliftcontroller/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ app_namespace: "{{ lookup( 'env', 'WATCH_NAMESPACE') or 'konveyor-forklift' }}"
feature_ui_plugin: true
feature_validation: true
feature_volume_populator: true
feature_vsphere_v2v_transport: false

k8s_cluster: false
feature_auth_required: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ spec:
{% if virt_customize_configmap_name is defined %}
- name: VIRT_CUSTOMIZE_MAP
value: {{ virt_customize_configmap_name }}
{% endif %}
- name: FEATURE_VSPHERE_VIRT_V2V_TRANSPORT
{% if feature_vsphere_v2v_transport|bool %}
value: "true"
{% else %}
value: "false"
{% endif %}
{% if controller_profile_kind is defined and controller_profile_path is defined and controller_profile_duration is defined %}
- name: PROFILE_KIND
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/forklift/v1beta1/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ go_library(
"//pkg/apis/forklift/v1beta1/ref",
"//pkg/lib/condition",
"//pkg/lib/error",
"//pkg/settings",
"//vendor/k8s.io/api/core/v1:core",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta",
"//vendor/k8s.io/apimachinery/pkg/runtime",
Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/forklift/v1beta1/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/ref"
libcnd "github.com/konveyor/forklift-controller/pkg/lib/condition"
liberr "github.com/konveyor/forklift-controller/pkg/lib/error"
"github.com/konveyor/forklift-controller/pkg/settings"
core "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -97,7 +98,7 @@ type Plan struct {
// just use virt-v2v directly to convert the vm while copying data over. In other
// cases, we use CDI to transfer disks to the destination cluster and then use
// virt-v2v-in-place to convert these disks after cutover.
func (p *Plan) VSphereColdLocal() (bool, error) {
func (p *Plan) VSphereUseV2vTransport() (bool, error) {
source := p.Referenced.Provider.Source
if source == nil {
return false, liberr.New("Cannot analyze plan, source provider is missing.")
Expand All @@ -109,7 +110,7 @@ func (p *Plan) VSphereColdLocal() (bool, error) {

switch source.Type() {
case VSphere:
return !p.Spec.Warm && destination.IsHost(), nil
return !p.Spec.Warm && destination.IsHost() && settings.Settings.VsphereV2vTransport, nil
case Ova:
return true, nil
default:
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/plan/adapter/vsphere/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ func (r *Builder) DataVolumes(vmRef ref.Ref, secret *core.Secret, _ *core.Config
if disk.Datastore.ID == ds.ID {
storageClass := mapped.Destination.StorageClass
var dvSource cdi.DataVolumeSource
coldLocal, vErr := r.Context.Plan.VSphereColdLocal()
coldLocal, vErr := r.Context.Plan.VSphereUseV2vTransport()
if vErr != nil {
err = vErr
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/plan/adapter/vsphere/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func (r *Client) getChangeIds(vmRef ref.Ref, snapshotId string, hosts util.Hosts
}

func (r *Client) getClient(vm *model.VM, hosts util.HostsFunc) (client *vim25.Client, err error) {
if coldLocal, vErr := r.Plan.VSphereColdLocal(); vErr == nil && coldLocal {
if coldLocal, vErr := r.Plan.VSphereUseV2vTransport(); vErr == nil && coldLocal {
// when virt-v2v runs the migration, forklift-controller should interact only
// with the component that serves the SDK endpoint of the provider
client = r.client.Client
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/plan/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,7 +1685,7 @@ func (r *KubeVirt) guestConversionPod(vm *plan.VMStatus, vmVolumes []cnv.Volume,
nonRoot := true
allowPrivilageEscalation := false
// virt-v2v image
coldLocal, vErr := r.Context.Plan.VSphereColdLocal()
coldLocal, vErr := r.Context.Plan.VSphereUseV2vTransport()
if vErr != nil {
err = vErr
return
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/plan/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -1658,7 +1658,7 @@ func (r *Migration) updateConversionProgress(vm *plan.VMStatus, step *plan.Step)
break
}

coldLocal, err := r.Context.Plan.VSphereColdLocal()
coldLocal, err := r.Context.Plan.VSphereUseV2vTransport()
switch {
case err != nil:
return liberr.Wrap(err)
Expand Down Expand Up @@ -1853,7 +1853,7 @@ type Predicate struct {

// Evaluate predicate flags.
func (r *Predicate) Evaluate(flag libitr.Flag) (allowed bool, err error) {
coldLocal, vErr := r.context.Plan.VSphereColdLocal()
coldLocal, vErr := r.context.Plan.VSphereUseV2vTransport()
if vErr != nil {
err = vErr
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/plan/scheduler/vsphere/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func (r *Scheduler) buildPending() (err error) {
}

func (r *Scheduler) cost(vm *model.VM, vmStatus *plan.VMStatus) int {
coldLocal, _ := r.Plan.VSphereColdLocal()
coldLocal, _ := r.Plan.VSphereUseV2vTransport()
if coldLocal {
switch vmStatus.Phase {
case CreateVM, PostHook, Completed:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (admitter *PlanAdmitter) validateLUKS() error {
return err
}

coldLocal, vErr := admitter.plan.VSphereColdLocal()
coldLocal, vErr := admitter.plan.VSphereUseV2vTransport()
if vErr != nil {
log.Error(vErr, "Could not analyze plan, failing")
return vErr
Expand Down
4 changes: 4 additions & 0 deletions pkg/settings/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const (
FeatureOvirtWarmMigration = "FEATURE_OVIRT_WARM_MIGRATION"
FeatureRetainPrecopyImporterPods = "FEATURE_RETAIN_PRECOPY_IMPORTER_PODS"
FeatureVsphereIncrementalBackup = "FEATURE_VSPHERE_INCREMENTAL_BACKUP"
FeatureVsphereV2vTransport = "FEATURE_VSPHERE_VIRT_V2V_TRANSPORT"
)

// Feature gates.
Expand All @@ -16,12 +17,15 @@ type Features struct {
RetainPrecopyImporterPods bool
// Whether to use changeID-based incremental backup workflow (with a version of CDI that supports it)
VsphereIncrementalBackup bool
// Whether to use changeID-based incremental backup workflow (with a version of CDI that supports it)
VsphereV2vTransport bool
}

// Load settings.
func (r *Features) Load() (err error) {
r.OvirtWarmMigration = getEnvBool(FeatureOvirtWarmMigration, false)
r.RetainPrecopyImporterPods = getEnvBool(FeatureRetainPrecopyImporterPods, false)
r.VsphereIncrementalBackup = getEnvBool(FeatureVsphereIncrementalBackup, false)
r.VsphereV2vTransport = getEnvBool(FeatureVsphereV2vTransport, false)
return
}

0 comments on commit 53d631c

Please sign in to comment.