Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3aff5dd
test(e2e): source VirtualDiskCreation from the custom e2e-br image
Isteb4k Jul 10, 2026
35aa1be
test(e2e): shrink VirtualDiskCreation disks to 50Mi
Isteb4k Jul 10, 2026
b50c33a
test(e2e): source all blockdevice tests from the custom e2e-br image
Isteb4k Jul 11, 2026
365a64a
test(e2e): source quota_exhausted from the custom e2e-br image
Isteb4k Jul 11, 2026
f334237
test(e2e): source data_exports from the custom e2e-br image
Isteb4k Jul 11, 2026
9957a84
test(e2e): rewrite virtual_disk_resizing on custom image with observers
Isteb4k Jul 11, 2026
e49b76d
test(e2e): source importer_network_policy from custom image, observers
Isteb4k Jul 11, 2026
f6f25f6
test(e2e): convert virtual_disk_provisioning to observers
Isteb4k Jul 11, 2026
7e31557
test(e2e): convert vd_snapshots to custom image and observers
Isteb4k Jul 11, 2026
e2006c0
test(e2e): convert data_exports to custom image, root guest-fs, obser…
Isteb4k Jul 11, 2026
b6a3400
test(e2e): rewrite ISO/format tests for the custom EFI ISO
Isteb4k Jul 11, 2026
36c158e
fix(vm): tolerate concurrent finalizer changes when releasing PVC pro…
Isteb4k Jul 11, 2026
39a1bf4
test(e2e): SIG labels, VPD serial device resolution, off-cluster expo…
Isteb4k Jul 11, 2026
60f124c
test(e2e): drop the REPEAT option from the run task
Isteb4k Jul 11, 2026
e98d082
test(e2e): refresh the ttl.sh container-disk image (24h TTL expired)
Isteb4k Jul 11, 2026
a00a696
Merge remote-tracking branch 'origin/main' into e2e/virtual-disk-crea…
Isteb4k Jul 11, 2026
5286f9c
test(e2e): fix go-lint findings and write export artifacts to a temp dir
Isteb4k Jul 13, 2026
33362fe
test(e2e): allow LongTimeout for data-disk deletion after export
Isteb4k Jul 13, 2026
83c704f
test(e2e): revert data-disk deletion to MiddleTimeout
Isteb4k Jul 13, 2026
4fe34b3
test(e2e): drop the pointless delete-and-wait of the original data di…
Isteb4k Jul 13, 2026
229bf51
test(e2e): wait for the disk to detach, not for the VM to be deleted,…
Isteb4k Jul 13, 2026
9904a2e
Merge branch 'main' into e2e/virtual-disk-creation-custom-image
Isteb4k Jul 14, 2026
72bcf9c
test(e2e): stop ignoring fixed PVC/VD protection finalizer errors
Isteb4k Jul 14, 2026
d0dc653
test(e2e): drop stale comment about the original data disk in DataExp…
Isteb4k Jul 14, 2026
db3f882
test(e2e): observe Project via a typed observer instead of the generi…
Isteb4k Jul 14, 2026
acbb26a
test(e2e): restore the REPEAT option in the run task
Isteb4k Jul 14, 2026
cd0fbc8
test(e2e): skip flaky concurrent VirtualDiskSnapshots test
Isteb4k Jul 14, 2026
af45e4d
test(e2e): skip the entire VirtualDiskSnapshots suite
Isteb4k Jul 14, 2026
9ec12a1
test(e2e): stop skipping VirtualDiskProvisioning on NFS
Isteb4k Jul 14, 2026
552b2fd
test(e2e): enrich the blockdevice failure debug bundle for guest boot…
Isteb4k Jul 14, 2026
2e9705a
test(e2e): drop redundant WithProvisioning(nil) in data_exports
Isteb4k Jul 14, 2026
4293726
test(e2e): pin the StorageClass on all blockdevice disks
Isteb4k Jul 14, 2026
e2a3a64
test(e2e): raise VMBDA attach waits in blockdevice to LongTimeout
Isteb4k Jul 14, 2026
827432e
test(e2e): raise VDSnapshot ready waits in blockdevice to LongTimeout
Isteb4k Jul 14, 2026
91f9d2d
test(e2e): surface the failure cause when a VirtualDiskSnapshot fails
Isteb4k Jul 14, 2026
269d1d9
test(e2e): size every blockdevice disk at vdCreationImageSize (50Mi)
Isteb4k Jul 14, 2026
9874ce7
fix(dvcr): stop double-counting the probed header in raw image size
Isteb4k Jul 14, 2026
411c096
test(e2e): use 52Mi disks in blockdevice and double sizes on resize
Isteb4k Jul 14, 2026
c78c0ed
test(e2e): size only source and blank disks, derive the rest
Isteb4k Jul 14, 2026
6059ee6
test(e2e): oversize disks cloned from a VirtualImage on PVC to 52Mi
Isteb4k Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions images/dvcr-artifact/pkg/registry/imageinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func getImageInfo(ctx context.Context, sourceReader io.ReadCloser) (ImageInfo, e
return getImageInfoVMDK(ctx, formatSourceReaders.TopReader(), headerBuf)
}

return getImageInfoStandard(ctx, formatSourceReaders, headerBuf)
return getImageInfoStandard(ctx, formatSourceReaders)
}

// getImageInfoVMDK obtains information about the VMDK image using a synthetic file.
Expand Down Expand Up @@ -147,7 +147,7 @@ func getImageInfoVMDK(ctx context.Context, sourceReader io.Reader, headerBuf []b
}

// getImageInfoStandard handles non-VMDK formats using the first 64MB of the file.
func getImageInfoStandard(ctx context.Context, formatSourceReaders *importer.FormatReaders, headerBuf []byte) (ImageInfo, error) {
func getImageInfoStandard(ctx context.Context, formatSourceReaders *importer.FormatReaders) (ImageInfo, error) {
var tempImageInfoFile *os.File
var err error
var bytesWrittenToTemp int64
Expand All @@ -160,20 +160,15 @@ func getImageInfoStandard(ctx context.Context, formatSourceReaders *importer.For
}
defer os.Remove(tempImageInfoFile.Name())

n, err := tempImageInfoFile.Write(headerBuf)
if err != nil {
return ImageInfo{}, fmt.Errorf("error writing header to temp file: %w", err)
}
bytesWrittenToTemp = int64(n)

remaining := imageInfoSize - int64(len(headerBuf))
if remaining > 0 {
n, err := io.CopyN(tempImageInfoFile, formatSourceReaders.TopReader(), remaining)
if err != nil && !errors.Is(err, io.EOF) {
return ImageInfo{}, fmt.Errorf("error writing remaining data to temp file: %w", err)
}
bytesWrittenToTemp += n
// The reader already starts with the header bytes (getImageInfo prepends
// the probed header to the rest of the source), so sample straight from
// it. Writing headerBuf separately would both duplicate the first bytes
// in the sample and count them twice in the raw VirtualSize below.
n, err := io.CopyN(tempImageInfoFile, formatSourceReaders.TopReader(), imageInfoSize)
if err != nil && !errors.Is(err, io.EOF) {
return ImageInfo{}, fmt.Errorf("error writing image data to temp file: %w", err)
}
bytesWrittenToTemp = n

if err = tempImageInfoFile.Close(); err != nil {
return ImageInfo{}, fmt.Errorf("error closing temp file: %w", err)
Expand Down
85 changes: 85 additions & 0 deletions images/dvcr-artifact/pkg/registry/imageinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
Copyright 2026 Flant JSC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package registry

import (
"context"
"io"
"os/exec"
"testing"
)

// patternReader yields a deterministic non-zero byte stream of a given size.
// The pattern matches no known image header, so qemu-img classifies it as raw.
type patternReader struct {
size int64
off int64
}

func (r *patternReader) Read(p []byte) (int, error) {
if r.off >= r.size {
return 0, io.EOF
}
n := len(p)
if remaining := r.size - r.off; int64(n) > remaining {
n = int(remaining)
}
for i := 0; i < n; i++ {
p[i] = byte((r.off + int64(i)) % 251)
}
r.off += int64(n)
return n, nil
}

// TestGetImageInfoRawVirtualSize pins the raw-source size accounting: every
// source byte must be counted exactly once. A regression that double-counts
// the probed header (the first syntheticHeadSize bytes are prepended to the
// stream again by getImageInfo) inflates VirtualSize by exactly 10 MiB, which
// in turn inflates VirtualImage unpackedSize for block-device sources and
// breaks size validation of disks cloned from such images.
func TestGetImageInfoRawVirtualSize(t *testing.T) {
if _, err := exec.LookPath("qemu-img"); err != nil {
t.Skip("qemu-img is not available")
}

cases := []struct {
name string
size int64
}{
{name: "smaller than the probed header", size: 3*1024*1024 + 17},
{name: "larger than the probed header", size: syntheticHeadSize + 5*1024*1024 + 123},
{name: "larger than the sampled temp file", size: imageInfoSize + 6*1024*1024 + 7},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
src := io.NopCloser(&patternReader{size: tc.size})

info, err := getImageInfo(context.Background(), src)
if err != nil {
t.Fatalf("getImageInfo failed: %v", err)
}
if info.Format != "raw" {
t.Fatalf("unexpected format: got %q, want %q", info.Format, "raw")
}
if info.VirtualSize != uint64(tc.size) {
t.Fatalf("VirtualSize miscounted: got %d, want %d (diff %d)",
info.VirtualSize, tc.size, int64(info.VirtualSize)-tc.size)
}
})
}
}
Loading
Loading