-
Notifications
You must be signed in to change notification settings - Fork 267
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
PVC Clone Populator #2709
Conversation
if restoreSize.IsZero() { | ||
return nil, fmt.Errorf("unable to determine restore size of PVC") | ||
} | ||
reqSize := targetPvcSpec.Resources.Requests[corev1.ResourceStorage] |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this 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.
cmd/cdi-controller/controller.go
Outdated
@@ -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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: import populator
pkg/controller/clone/csi-clone.go
Outdated
return "CSIClone" | ||
} | ||
|
||
// Reconcile ensures a snapshot is created correctly |
There was a problem hiding this comment.
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/prep-claim.go
Outdated
return "PrepClaim" | ||
} | ||
|
||
// Reconcile ensures a snapshot is created correctly |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to be consistent with API types: https://github.com/mhenriks/containerized-data-importer/blob/clone-pop/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go#L829
It should never have been "network"
) | ||
|
||
// Planner plans clone operations | ||
type Planner struct { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
/retest-required |
There was a problem hiding this 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.
tests/clone-populator_test.go
Outdated
} | ||
}) | ||
|
||
It("should should do filesystem to filesystem clone", func() { |
There was a problem hiding this comment.
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)
tests/clone-populator_test.go
Outdated
Expect(targetHash).To(Equal(sourceHash)) | ||
}) | ||
|
||
It("should should do csi clone if possible", func() { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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>
other review comments verifier pod should bount readonly Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
/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>
There was a problem hiding this 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!
} | ||
|
||
// 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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
pkg/controller/clone/common.go
Outdated
} | ||
|
||
// MustGetStorageClassForClaim returns the storageclass for a PVC | ||
func MustGetStorageClassForClaim(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*storagev1.StorageClass, error) { |
There was a problem hiding this comment.
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
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fine
pkg/controller/clone/common.go
Outdated
return sc, nil | ||
} | ||
|
||
// GetCompatibleVolumeSnapshotClass returns a VolumeSNapshotClass name that works for all PVCs |
There was a problem hiding this comment.
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
.
pkg/controller/clone/common.go
Outdated
} | ||
} | ||
|
||
func claimBoundOrWFFC(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (bool, error) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
pkg/controller/clone/planner.go
Outdated
} | ||
|
||
if !exists { | ||
// TODO EVENT |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
pkg/controller/clone/planner.go
Outdated
return nil | ||
} | ||
|
||
func (p *Planner) strategyForSourcePVC(ctx context.Context, args *ChooseStrategyArgs) (*cdiv1.CDICloneStrategy, error) { |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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{ |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this 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 :)
pkg/controller/clone/common.go
Outdated
} | ||
|
||
// GetVolumeCloneSource returns the VolumeCloneSource dataSourceRef | ||
func GetVolumeCloneSource(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*cdiv1.VolumeCloneSource, error) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
pkg/controller/clone/common.go
Outdated
|
||
// GetVolumeCloneSource returns the VolumeCloneSource dataSourceRef | ||
func GetVolumeCloneSource(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (*cdiv1.VolumeCloneSource, error) { | ||
if !IsDataSourceVolumeClone(pvc.Spec.DataSourceRef) { |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
pkg/controller/clone/common.go
Outdated
} | ||
|
||
func claimBoundOrWFFC(ctx context.Context, c client.Client, pvc *corev1.PersistentVolumeClaim) (bool, error) { | ||
if pvc.Spec.VolumeName != "" { |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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..
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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'
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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..
There was a problem hiding this comment.
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
pkg/controller/clone/planner.go
Outdated
@@ -344,13 +345,20 @@ func (p *Planner) planHostAssistedFromPVC(ctx context.Context, args *PlanArgs) ( | |||
desiredClaim.Spec.Resources.Requests[corev1.ResourceStorage] = is | |||
} | |||
|
|||
ct := cdiv1.DataVolumeKubeVirt |
There was a problem hiding this comment.
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))
There was a problem hiding this comment.
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>
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 != ""
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
/lgtm |
/lgtm |
There was a problem hiding this 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.
return nil, fmt.Errorf("unknown strategy/source %s", string(args.Strategy)) | ||
} | ||
|
||
func (p *Planner) watchSnapshots(ctx context.Context, log logr.Logger) error { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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.
pkg/controller/clone/snap-clone.go
Outdated
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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>
/lgtm |
[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 |
/test pull-containerized-data-importer-e2e-nfs |
What this PR does / why we need it:
Overview
VolumeCloneSource
populator forPersistentVolumeClaim
sources.VolumeSnapshot
coming soon.The populator will do pretty much exactly the same work as a
DataVolume
with aPVC
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
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
, orcopy
).Plan
takes a given source, target, strategy and returns a chain ofPhases
. APhase
is typically responsible for doing a single operation like snapshot a PVC. When aPhase
is complete, it returnsnil, 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 thishost-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: