Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PVC Clone Populator #2709

Merged
merged 12 commits into from
May 24, 2023
Merged

PVC Clone Populator #2709

merged 12 commits into from
May 24, 2023

Conversation

mhenriks
Copy link
Member

@mhenriks mhenriks commented May 9, 2023

What this PR does / why we need it:

Overview

VolumeCloneSource populator for PersistentVolumeClaim sources. VolumeSnapshot coming soon.

The populator will do pretty much exactly the same work as a DataVolume with a PVC source. Efficient clone with snapshots if possible. CSI clone if specifically configured. Host "copy" clone otherwise. HOWEVER we can now do WaitForFirstConsumer snapshot/csi clones which is a nice new feature brought to you by the glory of populators.

API

apiVersion: cdi.kubevirt.io/v1beta1
kind: VolumeCloneSource
metadata:
  name: my-clone-source
spec:
  source:
    kind: PersistentVolumeClaim
    name: my-pvc-source
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name:  my-cloned-pvc
spec:
  dataSourceRef:
    apiGroup: cdi.kubevirt.io
    kind: VolumeCloneSource
    name: my-clone-source
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Implementation Details

Reviewers, focus your attention here: https://github.com/mhenriks/containerized-data-importer/tree/clone-pop/pkg/controller/clone

And here: https://github.com/mhenriks/containerized-data-importer/blob/clone-pop/pkg/controller/populators/clone-populator.go

I attempted to break the clone operation into two processes, planning and execution. The entrypoint for those processes is the Planner. ChooseStrategy evaluates the source, target, and chooses the best strategy (snapshot, csi-clone, or copy).

Plan takes a given source, target, strategy and returns a chain of Phases. A Phase is typically responsible for doing a single operation like snapshot a PVC. When a Phase is complete, it returns nil, nil and the caller (clone populator) will execute the next phase in the chain. When all phases execute successfully, the controller will wait for the target PVC to be bound then clean up any temp resources created.

For a snapshot clone, the planner will return the following chain of phases:

snapshot -> snap-clone -> prep-claim -> rebind

For csi-clone, the planner will return:

csi-clone -> prep-claim -> rebind

copy looks like this

host-clone -> rebind

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #

Special notes for your reviewer:

AGAIN

Reviewers, focus your attention here: https://github.com/mhenriks/containerized-data-importer/tree/clone-pop/pkg/controller/clone

And here: https://github.com/mhenriks/containerized-data-importer/blob/clone-pop/pkg/controller/populators/clone-populator.go

Release note:

VolumeCloneSource Populator

@kubevirt-bot kubevirt-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. labels May 9, 2023
@kubevirt-bot kubevirt-bot requested review from awels and maya-r May 9, 2023 03:47
if restoreSize.IsZero() {
return nil, fmt.Errorf("unable to determine restore size of PVC")
}
reqSize := targetPvcSpec.Resources.Requests[corev1.ResourceStorage]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would sleep better at night if you use the copy here targetPvcSpecCopy

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The smart clone controller is not long for this world in subsequent PR I will be deleting it then we will all sleep better

@mhenriks mhenriks changed the title [Draft] Clone populator [WIP] PVC Clone Populator May 9, 2023
@kubevirt-bot kubevirt-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 9, 2023
Copy link
Collaborator

@alromeros alromeros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! I really like the planning/phase logic. Currently just some questions and silly comments about styling. Once I start working on the clone from snapshot I'll review it again with better insight.

@@ -280,6 +280,10 @@ func start() {
klog.Errorf("Unable to setup upload populator: %v", err)
os.Exit(1)
}
if _, err := populators.NewClonePopulator(ctx, mgr, log, clonerImage, pullPolicy, installerLabels); err != nil {
klog.Errorf("Unable to setup import populator: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: import populator

return "CSIClone"
}

// Reconcile ensures a snapshot is created correctly
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Not snapshot

pkg/controller/clone/host-clone.go Show resolved Hide resolved
return "PrepClaim"
}

// Reconcile ensures a snapshot is created correctly
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Not snapshot

case HostAssistedClone:
return "network"
return "copy"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "copy" is representative of what a hostAssistedClone does, but I feel like we should avoid having several names to describe the same operation. Why not simply use host-assisted-clone?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

)

// Planner plans clone operations
type Planner struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, do we plan to eventually reuse the planning/phase structure in the old clone flow? I assumed a lot of this new logic would be reused when we discussed this PR yesterday.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't have the details nailed down yet, but it would be nice if datavolume controller can call Plan. Strategy will always be host assisted in that case for pvc or snapshot source. The main difference is that datavolume controller will not get a rebind phase

Strategy: *cs,
}

phases, err := r.planner.Plan(ctx, args)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really like this design, but I can't help but wonder how other users/contributors will figure out what's happening here. I think this would benefit by having more comments or even by dividing reconcilePending into smaller functions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll think about how it can be clearer.

}

clonePopulator, err := controller.New(clonePopulatorName, mgr, controller.Options{
MaxConcurrentReconciles: 5,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time I see us specifying this, why 5?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is a bug that we are only using one thread in other controllers. Especially controllers that poll status from pods that are coming/going. Things can get jammed up

@mhenriks mhenriks changed the title [WIP] PVC Clone Populator PVC Clone Populator May 18, 2023
@kubevirt-bot kubevirt-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 18, 2023
@mhenriks
Copy link
Member Author

/retest-required

Copy link
Collaborator

@alromeros alromeros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good! Still want to do another review but I'll continue tomorrow.

}
})

It("should should do filesystem to filesystem clone", func() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Repeated "should" (all cases)

Expect(targetHash).To(Equal(sourceHash))
})

It("should should do csi clone if possible", func() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a test case to explicitly test smart clone?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure

}

// AddCoreWatches watches "core" types
func (p *Planner) AddCoreWatches(log logr.Logger) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we add this watch here instead of adding it to the clone populator? Why do we need to watch core types if we already have watches for PVCs? I'm missing something here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a little wonky. The idea is that the clone populator would be ignorant of the types of resources created by the phases so the planner would handle creating the watches. This includes an additional PVC watch because the one in base populator does not cover PVCs with ownership label.

BUT the clone populator currently knows what types are created because they are needed for the cleanup function here: https://github.com/mhenriks/containerized-data-importer/blob/clone-pop/pkg/controller/populators/clone-populator.go#L274-L278

I think it would be better if the clone controller either 1) gets the types to cleanup from the planner or 2) calls a function on the planner to do the actual cleanup .

}
reconciler.planner = planner

if err := addCommonPopulatorsWatches(mgr, clonePopulator, log, cdiv1.VolumeCloneSourceRef, &cdiv1.VolumeCloneSource{}); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need to add a watch for clones without source, so we retrigger the reconcile once the source PVC is created.

Copy link
Member Author

@mhenriks mhenriks May 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently will requeue if the planner returns nil. This covers the source not existing case. https://github.com/mhenriks/containerized-data-importer/blob/clone-pop/pkg/controller/populators/clone-populator.go#L207

There is a functional test for this case.

Replacing the requeue with a watch is doable but it is a kind of complicated. Will require an index on the source field of VolumeCloneSource. Maybe a subsequent PR

@kubevirt-bot kubevirt-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 18, 2023
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
only supports PVC source now

snapshot coming soon

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
@kubevirt-bot kubevirt-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 18, 2023
other review comments

verifier pod should bount readonly

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
@mhenriks
Copy link
Member Author

/test pull-cdi-linter

synchronize get hash calls

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
Copy link
Collaborator

@alromeros alromeros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unable to see any errors/missing stuff in the functionality, but I still have some suggestions about styling and naming. Let me know what you think!

pkg/controller/clone/common.go Show resolved Hide resolved
}

// IsSourceClaimReady checks that PVC exists, is bound, and is not being used
func IsSourceClaimReady(ctx context.Context, c client.Client, namespace, name string) (bool, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another minor complaint, but since we consistently use PVC or PersistentVolumeClaim in our code, I think it can be inconsistent to use claim in all these new functions. I think it wouldn't hurt to change Claim to PVC, wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I get that we use PVC a lot but I think Claim is better and I think more in line with kubernetes/kubernetes. Rather than enforcing naming schemes for the whole repo, how do you feel about doing it on a package level?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to be consistent across the whole repo, but if Kubernetes is using claim in its code then I'm ok if we start using it in new code.

}

// MustGetStorageClassForClaim returns the storageclass for a PVC
func MustGetStorageClassForClaim(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*storagev1.StorageClass, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function name is a little bit awkward. I also think it doesn't make that much sense to have it since we still need to check its error return (we are only saving two checks in planner.go).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine

return sc, nil
}

// GetCompatibleVolumeSnapshotClass returns a VolumeSNapshotClass name that works for all PVCs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo: Uppercase N in VolumeSNapshotClass.

}
}

func claimBoundOrWFFC(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (bool, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think either isClaimBoundOrWFFC or isPVCBoundOrWFFC is more consistent with the rest of our code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah

}

if !exists {
// TODO EVENT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add the event now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah

return nil
}

func (p *Planner) strategyForSourcePVC(ctx context.Context, args *ChooseStrategyArgs) (*cdiv1.CDICloneStrategy, error) {
Copy link
Collaborator

@alromeros alromeros May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just preference but I miss having the verb in several function names. For example, I think getStrategyForSourcePVC sounds better and it's more informative than just strategyForSourcePVC.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps this is a bit pedantic, but I like the prefix get/set for simple operations. simply returning a value that is already set/stored somewhere for example. This is actually computing a value that is not stored anywhere. I will add 'compute' prefix

Recorder: p.Recorder,
}

rp := &RebindPhase{
Copy link
Collaborator

@alromeros alromeros May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's not necessary, but since we are assembling these phases in a bunch of functions what do you think of adding a constructor function for each phase? In that way we can do something like:

rb := createRebindPhase(source, target, client, log, recorder)

I think it can be cleaner and easier to understand (also, less room for mistakes when setting parameters).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think functions have more opportunity for error especially when there are multiple parameters of the same type.

Copy link
Contributor

@ShellyKa13 ShellyKa13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I think the phases and planner really help simplify the clone process.
I do have an issue with the planner being populator inclined but it is not in the populators package.
I have a comment regarding the desiredPVC that is not clear to me.
I understand that we might want to use the planner and the phases in the regular flow but as is it really seems like it has very specific populators behavior, so why not move the whole new 'clone' directory under the populators package?
btw havn't reviewed the UT and tests yet.. I need a break :)

}

// GetVolumeCloneSource returns the VolumeCloneSource dataSourceRef
func GetVolumeCloneSource(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*cdiv1.VolumeCloneSource, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is only used in pkg/controller/populators/clone-populator.go so why not put it there? also with IsDataSourceVolumeClone function

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, I'll get rid of or move this


// GetVolumeCloneSource returns the VolumeCloneSource dataSourceRef
func GetVolumeCloneSource(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*cdiv1.VolumeCloneSource, error) {
if !IsDataSourceVolumeClone(pvc.Spec.DataSourceRef) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is an existing function to check a kind of datasourceref: populators.IsPVCDataSourceRefKind(pvc, cdiv1.VolumeCloneSourceRef)

}

sc := &storagev1.StorageClass{}
exists, err := getResource(ctx, c, "", *pvc.Spec.StorageClassName, sc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just making sure if you dont want to use existing: GetStorageClassByName instead of new code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetStorageClassByName will return the default storageclass if storageclassname is nil and I do not want that

}

func claimBoundOrWFFC(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (bool, error) {
if pvc.Spec.VolumeName != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use existing function: !IsUnbound(pvc)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You love this function, huh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just think if we have it lets use it, if you dont like the double negative you can create IsBound function, its just a check done a lot in the code, and I think it explains what volumename == "" means

@@ -170,65 +178,6 @@ func (r *ReconcilerBase) getPV(volName string) (*corev1.PersistentVolume, error)
return pv, nil
}

func (r *ReconcilerBase) rebindPV(targetPVC, pvcPrime *corev1.PersistentVolumeClaim) error {
pv, err := r.getPV(pvcPrime.Spec.VolumeName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPV is only used here, delete it if you dont use it anymore. or use it where you rewrote Rebind

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but is used in upload populator unit tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was used in the UT since it already existed. since now it is not used in the code (not sure why not using it is better but ok) it should not be in the code, can be move to the UT framework instead..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine

return nil, fmt.Errorf("actual PVC size missing")
}

p.Log.V(3).Info("prep pod required to force bind")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for this log, its not required to 'force bind' more like for 'resize'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no for WFFC need to force bind even if source/target are the same size

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my mistake I confused it with rebind which as I mentioned in previous commit is not relevant to prep-claim phase


// RebindPhase binds a PV from one PVC to another
type RebindPhase struct {
SourceNamespace string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name 'source' is confusing with the source of the clone, the rebind is used only to rebind the pv from pvcPrime to targetPVC, so I think we can be explicit about it in the rebind phase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree. To me, Phases stand on their own. And when you think of a rebind operation in isolation, source and target makes sense

}

if !exists {
actualClaim, err = p.createClaim(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here no need to check IsSourceClaimReady ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No that is handled in clone controller

}

// Rebind binds the PV of source to target
func Rebind(ctx context.Context, c client.Client, source, target *corev1.PersistentVolumeClaim) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems weird for me that a function used only in populators context is not in the populators package..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in the clone package and the populators package

@@ -344,13 +345,20 @@ func (p *Planner) planHostAssistedFromPVC(ctx context.Context, args *PlanArgs) (
desiredClaim.Spec.Resources.Requests[corev1.ResourceStorage] = is
}

ct := cdiv1.DataVolumeKubeVirt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use: cc.GetContentType(string(uploadSource.Spec.ContentType))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is outdated code, contentType was removed

… exist

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
@mhenriks
Copy link
Member Author

Great work! I think the phases and planner really help simplify the clone process. I do have an issue with the planner being populator inclined but it is not in the populators package. I have a comment regarding the desiredPVC that is not clear to me. I understand that we might want to use the planner and the phases in the regular flow but as is it really seems like it has very specific populators behavior, so why not move the whole new 'clone' directory under the populators package? btw havn't reviewed the UT and tests yet.. I need a break :)

Plan is to expand the clone package to usable by datavolume controller as well. But I haven't figured out all the details yet. Having it's own package gives us flexibility.

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
}

if *pvc.Spec.StorageClassName == "" {
return false, "", fmt.Errorf("PVC %s/%s has empty storage class name", pvc.Namespace, pvc.Name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so incase storageclass name is empty we want to return error and not go by the default storageclass?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default storageclass is irrelevent. PVC is created and storageclass has been assigned. This is not like pvc definition in a datavolume where there is flexibility

@@ -335,7 +273,7 @@ func (r *ReconcilerBase) reconcileCommon(pvc *corev1.PersistentVolumeClaim, popu
return nil, err
}
// Check storage class
ready, waitForFirstConsumer, err := r.handleStorageClass(pvc)
ready, nodeName, err := claimReadyForPopulation(context.TODO(), r.client, pvc)
Copy link
Contributor

@ShellyKa13 ShellyKa13 May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it better to return nodeName instead of a boolean if its != ""

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to me it is a more useful api with nodename

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are only using it again once to check != "". I dont see the value, but I wont insist

@ShellyKa13
Copy link
Contributor

/lgtm

@kubevirt-bot kubevirt-bot added the lgtm Indicates that a PR is ready to be merged. label May 23, 2023
@alromeros
Copy link
Collaborator

/lgtm

Copy link
Member

@awels awels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good a few nitpicks/typos and one ask.

pkg/controller/clone-controller.go Show resolved Hide resolved
pkg/controller/clone/csi-clone.go Show resolved Hide resolved
return nil, fmt.Errorf("unknown strategy/source %s", string(args.Strategy))
}

func (p *Planner) watchSnapshots(ctx context.Context, log logr.Logger) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah maybe name this addSnapshotWatches or something

}

if n == nil {
strategy = cdiv1.CloneStrategyHostAssisted
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we emit an event on the target claim here that explains we switched to host assisted clone because no compatible volume snapshot class could be found?

func (p *Planner) validateAdvancedClonePVC(ctx context.Context, args *ChooseStrategyArgs, sourceClaim *corev1.PersistentVolumeClaim) (bool, error) {
if !SameVolumeMode(sourceClaim, args.TargetClaim) {
args.Log.V(3).Info("volume modes not compatible for advanced clone")
return false, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to emit an event here indicating why we switched to host assisted clone? In most cases we are not logging at V(3) and this piece of information gets lost. I would settle for a V(1) log honestly.

}

if srcCapacity.Cmp(targetRequest) < 0 && !allowExpansion {
args.Log.V(3).Info("advanced clone not possible, no volume expansion")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to emit an event here indicating why we switched to host assisted clone? In most cases we are not logging at V(3) and this piece of information gets lost. I would settle for a V(1) log honestly.

return nil, fmt.Errorf("snapshot missing restoresize")
}

// 0 restore size is a special case, provisioners that do that seem to all restoring to bigger pvcs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo restoring should be restore

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"allow restoring"

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
@kubevirt-bot kubevirt-bot removed the lgtm Indicates that a PR is ready to be merged. label May 23, 2023
@awels
Copy link
Member

awels commented May 23, 2023

/lgtm
/approve

@kubevirt-bot kubevirt-bot added the lgtm Indicates that a PR is ready to be merged. label May 23, 2023
@kubevirt-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: awels

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubevirt-bot kubevirt-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 23, 2023
@awels
Copy link
Member

awels commented May 24, 2023

/test pull-containerized-data-importer-e2e-nfs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. lgtm Indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants