Skip to content

Conversation

@gaohoward
Copy link
Collaborator

@gaohoward gaohoward commented Sep 10, 2025

When cloning from a source, the host cloner should check the requested size for the target tmp pvc if the tmp source pvc is of block volume mode and the target pvc is of filesystem volume mode because it should take filesystem overhead into consideration and enlarge the original request size accordingly
before creating the tmp pvc.

Because currently the check is missing the cloning will fail on validation.

What this PR does / why we need it:

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 #

https://issues.redhat.com/browse/CNV-44140

Special notes for your reviewer:

Release note:

Fix: Host assisted clone should adjust requested storage when cloning from block to filesystem volume mode

@kubevirt-bot kubevirt-bot added dco-signoff: yes Indicates the PR's author has DCO signed all their commits. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Sep 10, 2025
@kubevirt-bot
Copy link
Contributor

Hi @gaohoward. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

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-sigs/prow repository.

@kubevirt-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign aglitke for approval. For more information see the Code Review Process.

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

Details 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 release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Sep 10, 2025
@akalenyu
Copy link
Collaborator

/test all

@coveralls
Copy link

coveralls commented Sep 11, 2025

Coverage Status

coverage: 49.428% (+0.04%) from 49.388%
when pulling b606f62 on gaohoward:cnv-44140
into c5480cc on kubevirt:main.

@gaohoward gaohoward force-pushed the cnv-44140 branch 2 times, most recently from 4942c4d to 3869e6a Compare September 15, 2025 02:53
@gaohoward gaohoward force-pushed the cnv-44140 branch 2 times, most recently from af4abed to 6a01cfa Compare October 13, 2025 09:13
@awels
Copy link
Member

awels commented Oct 13, 2025

I am probably missing something, but didn't #3384 fix this particular issue? Or did I miss a particular case with that PR?

@gaohoward
Copy link
Collaborator Author

I am probably missing something, but didn't #3384 fix this particular issue? Or did I miss a particular case with that PR?

Yeah I think it goes a different path. In this case it falls back to host-clone from smart-clone (supported by provisioner), and in that case it didn't take the fs overhead into account.

@awels
Copy link
Member

awels commented Oct 13, 2025

Gotcha, okay, let me know if you need a review on the PR.

@gaohoward
Copy link
Collaborator Author

Gotcha, okay, let me know if you need a review on the PR.

Yes pleas review. Thanks @awels !

@gaohoward gaohoward force-pushed the cnv-44140 branch 2 times, most recently from d00ad6c to 95f11c4 Compare October 23, 2025 08:53
@gaohoward
Copy link
Collaborator Author

/retest

2 similar comments
@gaohoward
Copy link
Collaborator Author

/retest

@gaohoward
Copy link
Collaborator Author

/retest

@gaohoward
Copy link
Collaborator Author

/retest

@gaohoward
Copy link
Collaborator Author

/retest

1 similar comment
@gaohoward
Copy link
Collaborator Author

/retest

@gaohoward gaohoward force-pushed the cnv-44140 branch 3 times, most recently from 379d8bd to c83e112 Compare December 8, 2025 11:50
@gaohoward
Copy link
Collaborator Author

/retest

Copy link
Collaborator

@akalenyu akalenyu left a comment

Choose a reason for hiding this comment

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

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.

I am a little confused that we have to inflate in the populator layer;
usually we do this in the mutating pvc webhook (on by default)/dv controllers

@gaohoward
Copy link
Collaborator Author

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.

I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are:
https://issues.redhat.com/browse/CNV-44140

Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

@akalenyu
Copy link
Collaborator

akalenyu commented Dec 11, 2025

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140

Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

@akalenyu
Copy link
Collaborator

Also note that bug describes a separate issue that may still exist

$ oc create  -f dv-hpp-cloned-from-datasource.yaml
Error from server: error when creating "dv-hpp-cloned-from-datasource.yaml": admission webhook "datavolume-validate.cdi.kubevirt.io" denied the request:  Storage size is missing

@akalenyu
Copy link
Collaborator

/cc @jpeimer

@kubevirt-bot
Copy link
Contributor

@akalenyu: GitHub didn't allow me to request PR reviews from the following users: jpeimer.

Note that only kubevirt members and repo collaborators can review this PR, and authors cannot review their own PRs.

Details

In response to this:

/cc @jpeimer

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-sigs/prow repository.

@gaohoward
Copy link
Collaborator Author

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140
Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

No the target PVC doesn't get inflated when doing snapshot clone. When the controller plans the clone it finds out the storage class is different from the volume snapshot's one and then it fall back to host assisted clone. When doing host clone phase it create the tmp target PVC, if we don't check here then it will report the failure because the target size is not enough (for this to happen the tmp target PVC volume mode must be filesystem).

@gaohoward
Copy link
Collaborator Author

dv-hpp-cloned-from-datasource.yaml

It doesn't happen for me on upstream. Can you share your yaml file?

@akalenyu
Copy link
Collaborator

akalenyu commented Dec 16, 2025

dv-hpp-cloned-from-datasource.yaml

It doesn't happen for me on upstream. Can you share your yaml file?

Yeah I don't see it either, may have to do with an older version

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140
Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

No the target PVC doesn't get inflated when doing snapshot clone. When the controller plans the clone it finds out the storage class is different from the volume snapshot's one and then it fall back to host assisted clone. When doing host clone phase it create the tmp target PVC, if we don't check here then it will report the failure because the target size is not enough (for this to happen the tmp target PVC volume mode must be filesystem).

I was pretty sure we inflate filesystem target PVCs here -

func renderPvcSpecVolumeSize(client client.Client, pvcSpec *v1.PersistentVolumeClaimSpec, isClone bool, log *logr.Logger) error {
Sorry for poking I just think we have a problem elsewhere and that inflating the temp PVC in the populator will just cover that up

@gaohoward
Copy link
Collaborator Author

dv-hpp-cloned-from-datasource.yaml

It doesn't happen for me on upstream. Can you share your yaml file?

Yeah I don't see it either, may have to do with an older version

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140
Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

No the target PVC doesn't get inflated when doing snapshot clone. When the controller plans the clone it finds out the storage class is different from the volume snapshot's one and then it fall back to host assisted clone. When doing host clone phase it create the tmp target PVC, if we don't check here then it will report the failure because the target size is not enough (for this to happen the tmp target PVC volume mode must be filesystem).

I was pretty sure we inflate filesystem target PVCs here -

func renderPvcSpecVolumeSize(client client.Client, pvcSpec *v1.PersistentVolumeClaimSpec, isClone bool, log *logr.Logger) error {

Sorry for poking I just think we have a problem elsewhere and that inflating the target in the populator will just cover that up

This method is never called in this case. Actually the webhook rendering is not enabled. For snapshot cloning it basically fallback to host-assisted during the planning phase, and when the host-clone phase is handling the temp target pvc creation, it has a chance to make sure the target size is right (inflate if necessary).

@akalenyu
Copy link
Collaborator

dv-hpp-cloned-from-datasource.yaml

It doesn't happen for me on upstream. Can you share your yaml file?

Yeah I don't see it either, may have to do with an older version

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140
Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

No the target PVC doesn't get inflated when doing snapshot clone. When the controller plans the clone it finds out the storage class is different from the volume snapshot's one and then it fall back to host assisted clone. When doing host clone phase it create the tmp target PVC, if we don't check here then it will report the failure because the target size is not enough (for this to happen the tmp target PVC volume mode must be filesystem).

I was pretty sure we inflate filesystem target PVCs here -

func renderPvcSpecVolumeSize(client client.Client, pvcSpec *v1.PersistentVolumeClaimSpec, isClone bool, log *logr.Logger) error {

Sorry for poking I just think we have a problem elsewhere and that inflating the target in the populator will just cover that up

This method is never called in this case. Actually the webhook rendering is not enabled. For snapshot cloning it basically fallback to host-assisted during the planning phase, and when the host-clone phase is handling the temp target pvc creation, it has a chance to make sure the target size is right (inflate if necessary).

Webhook rendering is enabled since a few releases now, but anyway renderPvcSpecVolumeSize existed prior to it for the DV storage API. How come the target doesn't get inflated?

@Acedus
Copy link
Contributor

Acedus commented Dec 17, 2025

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

@gaohoward
Copy link
Collaborator Author

gaohoward commented Dec 17, 2025

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

I rerun the test again and yes the webhook rendering is enabled. However the issue is that if the snapshot clone going as normal (doesn't fall back to host assisted) the target will get inflated as you said. But when it falls back to host clone, (clone strategy is copy), when the host-clone phase prepares the target tmp PVC, it didn't check the size
and do inflate if necessary. Here we added it so that the host clone won't get size problem.

csr, err := r.getCloneStrategy(ctx, log, pvc, vcs)

After this point the host clone takes over. If it doesn't fall back to host clone, the methods you mentioned get called and works. But if it go through host clone phase, we need this fix to take care of the size issue.

@Acedus
Copy link
Contributor

Acedus commented Dec 17, 2025

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

I rerun the test again and yes the webhook rendering is enabled. However the issue is that if the snapshot clone going as normal (doesn't fall back to host assisted) the target will get inflated as you said. But when it falls back to host clone, (clone strategy is copy), when the host-clone phase prepares the target tmp PVC, it didn't check the size and do inflate if necessary. Here we added it so that the host clone won't get size problem.

csr, err := r.getCloneStrategy(ctx, log, pvc, vcs)

After this point the host clone takes over. If it doesn't fall back to host clone, the methods you mentioned get called and works. But if it go through host clone phase, we need this fix to take care of the size issue.

Even if it does fall back to host clone the target PVC is created so it should be mutated according to the logic I wrote above, shouldn't we fix that logic instead?

@gaohoward
Copy link
Collaborator Author

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

I rerun the test again and yes the webhook rendering is enabled. However the issue is that if the snapshot clone going as normal (doesn't fall back to host assisted) the target will get inflated as you said. But when it falls back to host clone, (clone strategy is copy), when the host-clone phase prepares the target tmp PVC, it didn't check the size and do inflate if necessary. Here we added it so that the host clone won't get size problem.

csr, err := r.getCloneStrategy(ctx, log, pvc, vcs)

After this point the host clone takes over. If it doesn't fall back to host clone, the methods you mentioned get called and works. But if it go through host clone phase, we need this fix to take care of the size issue.

Not sure that's another issue or not but this doesn't help the host assisted clone. The host clone will create a temp target PVC based on its clone source (in this case a volume snapshot). The temp targetPVC must satisfy the size requirement (infalted if necessary)

@gaohoward
Copy link
Collaborator Author

dv-hpp-cloned-from-datasource.yaml

It doesn't happen for me on upstream. Can you share your yaml file?

Yeah I don't see it either, may have to do with an older version

Thank you for tackling this! I would appreciate a link to the bug so I can do some testing and see the origin of the issue.
I am a little confused that we have to inflate in the populator layer; usually we do this in the mutating pvc webhook (on by default)/dv controllers

Here you are: https://issues.redhat.com/browse/CNV-44140
Yes the issue happens at the very late stage where the snapshot clone falls back to host assisted clone.

I see, though I am still confused by inflating this far into the process. Doesn't the target PVC get inflated anyhow by the webhook/DV controller (and thus so does the temp)?

No the target PVC doesn't get inflated when doing snapshot clone. When the controller plans the clone it finds out the storage class is different from the volume snapshot's one and then it fall back to host assisted clone. When doing host clone phase it create the tmp target PVC, if we don't check here then it will report the failure because the target size is not enough (for this to happen the tmp target PVC volume mode must be filesystem).

I was pretty sure we inflate filesystem target PVCs here -

func renderPvcSpecVolumeSize(client client.Client, pvcSpec *v1.PersistentVolumeClaimSpec, isClone bool, log *logr.Logger) error {

Sorry for poking I just think we have a problem elsewhere and that inflating the target in the populator will just cover that up

This method is never called in this case. Actually the webhook rendering is not enabled. For snapshot cloning it basically fallback to host-assisted during the planning phase, and when the host-clone phase is handling the temp target pvc creation, it has a chance to make sure the target size is right (inflate if necessary).

Webhook rendering is enabled since a few releases now, but anyway renderPvcSpecVolumeSize existed prior to it for the DV storage API. How come the target doesn't get inflated?

Yes webhook rendering is enabled. Please see my reply to @Acedus for explanation why it is happening

@akalenyu
Copy link
Collaborator

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

This path is not exercised though if a size exists

func renderClonePvcVolumeSizeFromSource(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if size, exists := pvc.Spec.Resources.Requests[v1.ResourceStorage]; exists && !size.IsZero() {
return nil
}

@Acedus
Copy link
Contributor

Acedus commented Dec 17, 2025

I think the real issue here is that we don't inflate the PVC during mutation if it has a data source:

func RenderPvc(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if pvc.Spec.VolumeMode != nil &&
*pvc.Spec.VolumeMode == cdiv1.PersistentVolumeFromStorageProfile {
pvc.Spec.VolumeMode = nil
}
dvContentType := cc.GetPVCContentType(pvc)
if err := renderPvcSpecVolumeModeAndAccessModesAndStorageClass(client, nil, nil, nil, &pvc.Spec, dvContentType); err != nil {
return err
}
if hasCloneSourceRef(pvc) {
return renderClonePvcVolumeSizeFromSource(ctx, client, pvc)
}
// Skip size inflation for PVCs restoring from VolumeSnapshots.
// The PVC size must not exceed what the snapshot can provide; inflating it
// causes strict CSI drivers (e.g., NetApp Trident) to reject the restore.
if hasVolumeSnapshotDataSource(pvc) {
return nil
}
return renderPvcSpecVolumeSize(client, &pvc.Spec, false, nil)
}

if source.Kind == "VolumeSnapshot" && source.Name != "" {
sourceSnapshot := &snapshotv1.VolumeSnapshot{}
if err := client.Get(ctx, types.NamespacedName{Namespace: sourceNamespace, Name: source.Name}, sourceSnapshot); err != nil {
return err
}
if sourceSnapshot.Status != nil && sourceSnapshot.Status.RestoreSize != nil {
setRequestedVolumeSize(&pvc.Spec, *sourceSnapshot.Status.RestoreSize)
}
return nil
}

We simply set the restore size if it's available and leave it as is otherwise.

This path is not exercised though if a size exists

func renderClonePvcVolumeSizeFromSource(ctx context.Context, client client.Client, pvc *v1.PersistentVolumeClaim) error {
if size, exists := pvc.Spec.Resources.Requests[v1.ResourceStorage]; exists && !size.IsZero() {
return nil
}

Result is the same, if we would hit the latter path (renderPvcSpecVolumeSize) we'd correctly inflate the size.

EDIT: The target tmp PVC doesn't have a dataSource so in theory it should just hit the standard path and inflate properly.

when cloning from block to filesystem volume mode (kubevirt#3900)

When cloning from a source, the host cloner should
check the requested size for the target tmp pvc if
the tmp source pvc is of block volume mode and the
target pvc is of filesystem volume mode because it
should take filesystem overhead into consideration
and enlarge the original request size accordingly
before creating the tmp pvc.

Because currently the check is missing the cloning
will fail on validation.

Signed-off-by: Howard Gao <howard.gao@gmail.com>
@kubevirt-bot
Copy link
Contributor

@gaohoward: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-cdi-linter b606f62 link false /test pull-cdi-linter
Details

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-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has DCO signed all their commits. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants