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

Annotation to check for statically provisioned PVs when creating DataVolumes #2583

Merged
merged 10 commits into from
Feb 22, 2023

Conversation

mhenriks
Copy link
Member

@mhenriks mhenriks commented Feb 12, 2023

What this PR does / why we need it:

This PR basically does the following if a DataVolume that has the cdi.kubevirt.io/storage.checkStaticVolume annotation is created:

  1. Check if there is PV explicitly provisioned (has claimRef name+namespace set) for the target PVC
  2. If so, the "base" controller will create the target PVC in syncCommon()
  3. The target PVC will initially have an annotation cdi.kubevirt.io/storage.persistentVolumeList that contains the names of the PVCs from step 1
  4. When the target PVC gets bound to a PV, syncCommon() will check that the PVC is bound to one of the PVs in the persistentVolumeList annotation
  5. If the bind works as expected, cdi.kubevirt.io/storage.persistentVolumeList is removed and cdi.kubevirt.io/storage.populatedFor is added to the PVC
  6. If the PVC does not bind to one of the expected PVs, the PVC is deleted and we go back to step 1

The motivation for this PR is KubeVirt integration with a specific "Metro DR" solution. That solution bundles:

RamenDR
volume-replication-operator
OCM

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:

TODO

  • import
  • upload
  • pvc clone
  • snapshot clone
  • external populator

I've taken the liberty to do some minor refactoring along the way.

This has not been addressed and is bumming me out bigtime

Release note:

cdi.kubevirt.io/storage.checkStaticVolume annotation skips volume population step if a static PV is configured for target DataVOlume PVC

@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 Feb 12, 2023
@mhenriks
Copy link
Member Author

/hold

@kubevirt-bot kubevirt-bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 12, 2023
@@ -101,12 +101,29 @@ func NewImportController(
return datavolumeController, nil
}

// TODO find a better place for this
Copy link
Collaborator

@akalenyu akalenyu Feb 13, 2023

Choose a reason for hiding this comment

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

There's

key, err := cache.MetaNamespaceKeyFunc(snapshot)
But I might be missing a reason that it's not suitable for us

Copy link
Member Author

Choose a reason for hiding this comment

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

problem is that pv claimRef is not a metav1.Object so have to sonstruct from namespace/name

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 put a common func in pkg/controller/common and get rid of the following:

datasource-controller.go:        getKey := func(namespace, name string) string {
datavolume/clone-controller-base.go:     getKey := func(namespace, name string) string {
datavolume/pvc-clone-controller.go:      getKey := func(namespace, name string) string {

}
var pvNames []string
for _, pv := range pvList.Items {
// TODO - should we be more specific here, like do the actual matching in pv controller?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

unfortunately that package is not as fleshed out in k8s 23 but using it anyway

@mhenriks mhenriks force-pushed the replicated-volume-annotation branch 4 times, most recently from dc54297 to 626abd1 Compare February 15, 2023 14:22
@mhenriks
Copy link
Member Author

/retest-required

@mhenriks mhenriks force-pushed the replicated-volume-annotation branch 3 times, most recently from 9f43eae to 3288da2 Compare February 18, 2023 00:59

pvc, err := f.K8sClient.CoreV1().PersistentVolumeClaims(dv.Namespace).Get(context.TODO(), dv.Name, metav1.GetOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(pvc.Spec.VolumeName).To(Equal(pvName))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test is great, just one consideration, maybe we should make sure pv.CreationTimestamp < dv.CreationTimestamp

Copy link
Member Author

Choose a reason for hiding this comment

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

sure

Copy link
Collaborator

Choose a reason for hiding this comment

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

I am a broken record about this by now, but, maybe we would sleep better if there is an md5 check at the end of this test

Copy link
Member Author

Choose a reason for hiding this comment

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

not a bad idea

@@ -317,6 +317,30 @@ func NewDataVolumeWithHTTPImportToBlockPV(dataVolumeName string, size string, ht

// NewDataVolumeWithExternalPopulation initializes a DataVolume struct meant to be externally populated
func NewDataVolumeWithExternalPopulation(dataVolumeName, size, storageClassName string, volumeMode corev1.PersistentVolumeMode, dataSource, dataSourceRef *corev1.TypedLocalObjectReference) *cdiv1.DataVolume {
dataVolume := &cdiv1.DataVolume{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you explain what happened here?
Usually, I thought we shift towards using the storage API mostly

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 storage api obscures the matching a bit, just have to be consistent either way (all pvc or all storage). I took the PVC route to be explicit as possible. Basically when I originally wrote the test I was using pvc to create the source then didn't get a match I used storage for target.

Copy link
Collaborator

Choose a reason for hiding this comment

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

gotcha

@mhenriks
Copy link
Member Author

@akalenyu @arnongilboa what do you think?

@mhenriks
Copy link
Member Author

/unhold

@kubevirt-bot kubevirt-bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 20, 2023

func shouldSetPending(pvc *corev1.PersistentVolumeClaim, dv *cdiv1.DataVolume) bool {
return checkStaticProvisionPending(pvc, dv) ||
(pvc == nil && dv.Status.Phase == cdiv1.PhaseUnset)
Copy link
Collaborator

@arnongilboa arnongilboa Feb 21, 2023

Choose a reason for hiding this comment

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

I would add && dv != nil, as checkStaticProvisionPending() returns false if pvc == nil || dv == nil.

Copy link
Member Author

Choose a reason for hiding this comment

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

dv will never be nil in either case and shouldSetPending kind of assumes the dv exists

// CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
// and PersistentVolumeClaims
// TODO - later versions of k8s.io/component-helpers have this function
func CheckVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's strange k8s (and you) choose Mismatches instead of being positive

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'd like to stick with k8s on this

Comment on lines +419 to +420
_, ok := pvModesMap[mode]
if !ok {
Copy link
Collaborator

@arnongilboa arnongilboa Feb 21, 2023

Choose a reason for hiding this comment

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

I think it's more clear to write it as:
if hasMode := pvModesMap[mode]; hasMode {

Copy link
Member Author

Choose a reason for hiding this comment

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

eh, would rather do exactly what the lib does

…lt as a parameter

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>
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>
…cto common index creation

Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
…ions)

even if source does not exist or user has no permission

BUT no token is added so this is really just for the static/prepopulate cases

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

cloneSourceHandler, err := newCloneSourceHandler(dataVolume, wh.cdiClient)
if err != nil {
if k8serrors.IsNotFound(err) && noTokenOkay {
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 continue with the following code when noTokenOkay and not just return?

Copy link
Member Author

Choose a reason for hiding this comment

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

Want to add the token if possible. Still have to handle initial provisioning case where DataVolume has static pv annotation but the pv does not exist

Expect(err).ToNot(HaveOccurred())
err = utils.DeleteVerifierPod(f.K8sClient, f.Namespace.Name)
Expect(err).ToNot(HaveOccurred())
sourceMD5 = md5
Copy link
Collaborator

Choose a reason for hiding this comment

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

Really not big deal but I think you can get rid of this and use the md5 const

// UploadFileMD5 is the expected MD5 of the uploaded file
UploadFileMD5 = "2a7a52285c846314d1dbd79e9818270d"

@mhenriks
Copy link
Member Author

/retest-required

By("Creating source DV")
// source here shouldn't matter
dvDef := importDef()
controller.AddAnnotation(dvDef, controller.AnnDeleteAfterCompletion, "false")
Copy link
Collaborator

Choose a reason for hiding this comment

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

why GC needs to be disabled?

@arnongilboa
Copy link
Collaborator

/lgtm

@kubevirt-bot kubevirt-bot added the lgtm Indicates that a PR is ready to be merged. label Feb 22, 2023
@arnongilboa
Copy link
Collaborator

/retest

@akalenyu
Copy link
Collaborator

/lgtm

@mhenriks
Copy link
Member Author

/approve

@kubevirt-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mhenriks

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 Feb 22, 2023
@kubevirt-bot kubevirt-bot merged commit 496efbc into kubevirt:main Feb 22, 2023
@mhenriks
Copy link
Member Author

/cherrypick release-v1.56

@kubevirt-bot
Copy link
Contributor

@mhenriks: new pull request created: #2605

In response to this:

/cherrypick release-v1.56

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

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.

5 participants