-
Notifications
You must be signed in to change notification settings - Fork 270
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
Handle lost sparseness in non http data sources #3213
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ import ( | |
"context" | ||
"encoding/json" | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
|
@@ -284,24 +283,15 @@ func (f *Framework) VerifyBlankDisk(namespace *k8sv1.Namespace, pvc *k8sv1.Persi | |
} | ||
|
||
// VerifySparse checks a disk image being sparse after creation/resize. | ||
func (f *Framework) VerifySparse(namespace *k8sv1.Namespace, pvc *k8sv1.PersistentVolumeClaim, imagePath string) (bool, error) { | ||
func (f *Framework) VerifySparse(namespace *k8sv1.Namespace, pvc *k8sv1.PersistentVolumeClaim, imagePath string, originalVirtualSize int64) (bool, error) { | ||
var info image.ImgInfo | ||
var imageContentSize int64 | ||
err := f.GetImageInfo(namespace, pvc, imagePath, &info) | ||
if err != nil { | ||
return false, err | ||
} | ||
// qemu-img info gives us ActualSize but that is size on disk | ||
// which isn't important to us in this comparison; we compare content size | ||
err = f.GetImageContentSize(namespace, pvc, imagePath, &imageContentSize) | ||
if err != nil { | ||
return false, err | ||
} | ||
if info.ActualSize-imageContentSize >= units.MiB { | ||
return false, fmt.Errorf("Diff between content size %d and size on disk %d is significant, something's not right", imageContentSize, info.ActualSize) | ||
} | ||
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: VerifySparse comparison: Virtual: %d vs Content: %d\n", info.VirtualSize, imageContentSize) | ||
return info.VirtualSize >= imageContentSize, nil | ||
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: VerifySparse comparison: OriginalVirtual: %d vs SizeOnDisk: %d\n", originalVirtualSize, info.ActualSize) | ||
// The size on disk of a sparse image is significantly lower than the image's virtual size | ||
return originalVirtualSize-info.ActualSize >= units.MB, nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably intentional but why use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah intentional but it's been a while so I don't remember the exact reasoning, have to take a look There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the 1MB fudge factor all about? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its probably to ensure we align the size on 1Mib. qemu gets unhappy if the image is not aligned on the actual storage block size. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this check is a little too strict, wondering why current virtual size is not appropriate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I looked up the 1MiB->1MB switch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this check is specific to a particular image? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, you pass the virtual size of the used image as a parameter |
||
} | ||
|
||
// VerifyFSOverhead checks whether virtual size is smaller than actual size. That means FS Overhead has been accounted for. | ||
|
@@ -548,26 +538,6 @@ func (f *Framework) GetImageInfo(namespace *k8sv1.Namespace, pvc *k8sv1.Persiste | |
return err | ||
} | ||
|
||
// GetImageContentSize returns the content size (as opposed to size on disk) of an image | ||
func (f *Framework) GetImageContentSize(namespace *k8sv1.Namespace, pvc *k8sv1.PersistentVolumeClaim, imagePath string, imageSize *int64) error { | ||
cmd := fmt.Sprintf("du -s --apparent-size -B 1 %s | cut -f 1", imagePath) | ||
|
||
_, err := f.verifyInPod(namespace, pvc, cmd, func(output, stderr string) (bool, error) { | ||
fmt.Fprintf(ginkgo.GinkgoWriter, "CMD (%s) output %s\n", cmd, output) | ||
|
||
size, err := strconv.ParseInt(output, 10, 64) | ||
if err != nil { | ||
klog.Errorf("Invalid image content size:\n%s\n", output) | ||
return false, err | ||
} | ||
*imageSize = size | ||
|
||
return true, nil | ||
}) | ||
|
||
return err | ||
} | ||
|
||
func (f *Framework) startVerifierPod(namespace *k8sv1.Namespace, pvc *k8sv1.PersistentVolumeClaim) (*k8sv1.Pod, error) { | ||
var executorPod *k8sv1.Pod | ||
var err error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ import ( | |
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
|
||
"github.com/docker/go-units" | ||
"github.com/google/uuid" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
|
@@ -128,7 +129,7 @@ var _ = Describe("[rfe_id:1115][crit:high][vendor:[email protected]][level:compo | |
By("Verify the image contents") | ||
Expect(f.VerifyBlankDisk(f.Namespace, pvc)).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath, utils.UploadFileSize)).To(BeTrue()) | ||
By("Verifying permissions are 660") | ||
Expect(f.VerifyPermissions(f.Namespace, pvc)).To(BeTrue(), "Permissions on disk image are not 660") | ||
if utils.DefaultStorageCSIRespectsFsGroup { | ||
|
@@ -1636,7 +1637,11 @@ var _ = Describe("Import populator", func() { | |
tests.DisableWebhookPvcRendering(f.CrClient) | ||
}) | ||
|
||
DescribeTable("should import fileSystem PVC", func(expectedMD5 string, volumeImportSourceFunc func(cdiv1.DataVolumeContentType, bool) error, preallocation, webhookRendering bool) { | ||
DescribeTable("should import fileSystem PVC", func(expectedMD5 string, originalVirtualSize int, volumeImportSourceFunc func(cdiv1.DataVolumeContentType, bool) error, preallocation, webhookRendering bool) { | ||
// ImageIO raw images are not passed through any sparsification mechanism | ||
// VDDK ones do, but the fake plugin used for testing lies that they're not | ||
skipSparseCheckIDs := []string{"[test_id:11007]", "[test_id:11009]"} | ||
|
||
pvc = importPopulationPVCDefinition() | ||
|
||
if webhookRendering { | ||
|
@@ -1663,14 +1668,21 @@ var _ = Describe("Import populator", func() { | |
Expect(err).ToNot(HaveOccurred()) | ||
Expect(md5).To(Equal(expectedMD5)) | ||
|
||
var excluded bool | ||
for _, id := range skipSparseCheckIDs { | ||
if strings.Contains(CurrentSpecReport().LeafNodeText, id) { | ||
excluded = true | ||
break | ||
} | ||
} | ||
if preallocation { | ||
By("Verifying the image is preallocated") | ||
ok, err := f.VerifyImagePreallocated(f.Namespace, pvc) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(ok).To(BeTrue()) | ||
} else { | ||
} else if !excluded { | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath, int64(originalVirtualSize))).To(BeTrue()) | ||
} | ||
|
||
if utils.DefaultStorageCSIRespectsFsGroup { | ||
|
@@ -1695,17 +1707,17 @@ var _ = Describe("Import populator", func() { | |
return err != nil && k8serrors.IsNotFound(err) | ||
}, timeout, pollingInterval).Should(BeTrue()) | ||
}, | ||
Entry("[test_id:11001]with HTTP image and preallocation", utils.TinyCoreMD5, createHTTPImportPopulatorCR, true, false), | ||
Entry("[test_id:11002]with HTTP image without preallocation", utils.TinyCoreMD5, createHTTPImportPopulatorCR, false, false), | ||
Entry("[rfe_id:10985][crit:high][test_id:11003]with HTTP image and preallocation, with incomplete PVC webhook rendering", Serial, utils.TinyCoreMD5, createHTTPImportPopulatorCR, true, true), | ||
Entry("[test_id:11004]with Registry image and preallocation", utils.TinyCoreMD5, createRegistryImportPopulatorCR, true, false), | ||
Entry("[test_id:11005]with Registry image without preallocation", utils.TinyCoreMD5, createRegistryImportPopulatorCR, false, false), | ||
Entry("[test_id:11006]with ImageIO image with preallocation", Serial, utils.ImageioMD5, createImageIOImportPopulatorCR, true, false), | ||
Entry("[test_id:11007]with ImageIO image without preallocation", Serial, utils.ImageioMD5, createImageIOImportPopulatorCR, false, false), | ||
Entry("[test_id:11008]with VDDK image with preallocation", utils.VcenterMD5, createVDDKImportPopulatorCR, true, false), | ||
Entry("[test_id:11009]with VDDK image without preallocation", utils.VcenterMD5, createVDDKImportPopulatorCR, false, false), | ||
Entry("[test_id:11010]with Blank image with preallocation", utils.BlankMD5, createBlankImportPopulatorCR, true, false), | ||
Entry("[test_id:11011]with Blank image without preallocation", utils.BlankMD5, createBlankImportPopulatorCR, false, false), | ||
Entry("[test_id:11001]with HTTP image and preallocation", utils.TinyCoreMD5, utils.UploadFileSize, createHTTPImportPopulatorCR, true, false), | ||
Entry("[test_id:11002]with HTTP image without preallocation", utils.TinyCoreMD5, utils.UploadFileSize, createHTTPImportPopulatorCR, false, false), | ||
Entry("[rfe_id:10985][crit:high][test_id:11003]with HTTP image and preallocation, with incomplete PVC webhook rendering", Serial, utils.TinyCoreMD5, utils.UploadFileSize, createHTTPImportPopulatorCR, true, true), | ||
Entry("[test_id:11004]with Registry image and preallocation", utils.TinyCoreMD5, utils.UploadFileSize, createRegistryImportPopulatorCR, true, false), | ||
Entry("[test_id:11005]with Registry image without preallocation", utils.TinyCoreMD5, utils.UploadFileSize, createRegistryImportPopulatorCR, false, false), | ||
Entry("[test_id:11006]with ImageIO image with preallocation", Serial, utils.ImageioMD5, utils.CirrosRawFileSize, createImageIOImportPopulatorCR, true, false), | ||
Entry("[test_id:11007]with ImageIO image without preallocation", Serial, utils.ImageioMD5, utils.CirrosRawFileSize, createImageIOImportPopulatorCR, false, false), | ||
Entry("[test_id:11008]with VDDK image with preallocation", utils.VcenterMD5, utils.CirrosRawFileSize, createVDDKImportPopulatorCR, true, false), | ||
Entry("[test_id:11009]with VDDK image without preallocation", utils.VcenterMD5, utils.CirrosRawFileSize, createVDDKImportPopulatorCR, false, false), | ||
Entry("[test_id:11010]with Blank image with preallocation", utils.BlankMD5, units.MiB, createBlankImportPopulatorCR, true, false), | ||
Entry("[test_id:11011]with Blank image without preallocation", utils.BlankMD5, units.MiB, createBlankImportPopulatorCR, false, false), | ||
) | ||
|
||
DescribeTable("should import Block PVC", func(expectedMD5 string, volumeImportSourceFunc func(cdiv1.DataVolumeContentType, bool) error) { | ||
|
@@ -1733,7 +1745,7 @@ var _ = Describe("Import populator", func() { | |
Expect(err).ToNot(HaveOccurred()) | ||
Expect(md5).To(Equal(expectedMD5)) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultPvcMountPath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultPvcMountPath, utils.UploadFileSize)).To(BeTrue()) | ||
|
||
By("Verify 100.0% annotation") | ||
progress, ok, err := utils.WaitForPVCAnnotation(f.K8sClient, f.Namespace.Name, pvc, controller.AnnPopulatorProgress) | ||
|
@@ -1809,8 +1821,6 @@ var _ = Describe("Import populator", func() { | |
md5, err := f.GetMD5(f.Namespace, pvc, utils.DefaultImagePath, utils.MD5PrefixSize) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(md5).To(Equal(utils.TinyCoreMD5)) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
sourceMD5 := md5 | ||
|
||
By("Retaining PV") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -199,7 +199,7 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:[email protected]][level:compon | |
Expect(err).ToNot(HaveOccurred()) | ||
Expect(same).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath, utils.UploadFileSize)).To(BeTrue()) | ||
if utils.DefaultStorageCSIRespectsFsGroup { | ||
// CSI storage class, it should respect fsGroup | ||
By("Checking that disk image group is qemu") | ||
|
@@ -413,8 +413,6 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:[email protected]][level:compon | |
same, err := f.VerifyTargetPVCContentMD5(f.Namespace, archivePVC, pathInPvc, expectedMd5) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(same).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, archivePVC, pathInPvc)).To(BeTrue()) | ||
} | ||
} else { | ||
checkFailureNoValidToken(archivePVC) | ||
|
@@ -529,7 +527,7 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:[email protected]][level:compon | |
Expect(err).ToNot(HaveOccurred()) | ||
Expect(same).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath, utils.UploadFileSize)).To(BeTrue()) | ||
if utils.DefaultStorageCSIRespectsFsGroup { | ||
// CSI storage class, it should respect fsGroup | ||
By("Checking that disk image group is qemu") | ||
|
@@ -603,7 +601,7 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:[email protected]][level:compon | |
Expect(err).ToNot(HaveOccurred()) | ||
Expect(same).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath)).To(BeTrue()) | ||
Expect(f.VerifySparse(f.Namespace, pvc, utils.DefaultImagePath, utils.UploadFileSize)).To(BeTrue()) | ||
if utils.DefaultStorageCSIRespectsFsGroup { | ||
// CSI storage class, it should respect fsGroup | ||
By("Checking that disk image group is qemu") | ||
|
@@ -733,8 +731,6 @@ var _ = Describe("[rfe_id:138][crit:high][vendor:[email protected]][level:compon | |
same, err := f.VerifyTargetPVCContentMD5(f.Namespace, pvc, pathInPvc, expectedMd5) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(same).To(BeTrue()) | ||
By("Verifying the image is sparse") | ||
Expect(f.VerifySparse(f.Namespace, pvc, pathInPvc)).To(BeTrue()) | ||
} | ||
} else { | ||
checkFailureNoValidToken(pvcPrime) | ||
|
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 get rid of this function and check
!VerifyImagePreallocated()
?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.
Mainly because of the third point in the PR description
We could get rid of one of them by negating the other but those additions have to stay
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?
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.
Since current virtual size is post-resize you always end up comparing 1Gi or more (requested disk image size) versus a modest couple of megabytes, which is always going to pass as sort of a false negative