Skip to content

Commit 9b91552

Browse files
Yang Kaiyongimeoer
Yang Kaiyong
authored andcommitted
nydusify(feat): add crc32 in file attributes
Read CRC32 from external models' manifest and pass it to builder. Signed-off-by: Yang Kaiyong <yangkaiyong.yky@antgroup.com>
1 parent 96c3e55 commit 9b91552

File tree

7 files changed

+70
-4
lines changed

7 files changed

+70
-4
lines changed

contrib/nydusify/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ require (
3939
require (
4040
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
4141
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect
42-
github.com/BraveY/snapshotter-converter v0.0.5 // indirect
42+
github.com/BraveY/snapshotter-converter v0.0.6 // indirect
4343
github.com/CloudNativeAI/model-spec v0.0.2 // indirect
4444
github.com/Microsoft/go-winio v0.6.2 // indirect
4545
github.com/Microsoft/hcsshim v0.11.5 // indirect

contrib/nydusify/go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIS
55
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=
66
github.com/BraveY/snapshotter-converter v0.0.5 h1:h3zAB31u16EOkshS2J9Nx40RiWSjH6zd5baOSmjLCOg=
77
github.com/BraveY/snapshotter-converter v0.0.5/go.mod h1:nOVwsdXqdeltxr12x0t0JIbYDD+cdmdBx0HA2pYpxQY=
8+
github.com/BraveY/snapshotter-converter v0.0.6-0.20250409034316-66511579fa6d h1:00wAtig4otPLOMJN+CZHvG4MWm+g4NMY6j0K7eYEFNk=
9+
github.com/BraveY/snapshotter-converter v0.0.6-0.20250409034316-66511579fa6d/go.mod h1:nOVwsdXqdeltxr12x0t0JIbYDD+cdmdBx0HA2pYpxQY=
10+
github.com/BraveY/snapshotter-converter v0.0.6-0.20250409042404-e997e14906b7 h1:c9aFn0vSkXe1nrGe5mONSRs18/BXJKEiSiHvZyaXlBE=
11+
github.com/BraveY/snapshotter-converter v0.0.6-0.20250409042404-e997e14906b7/go.mod h1:nOVwsdXqdeltxr12x0t0JIbYDD+cdmdBx0HA2pYpxQY=
812
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
913
github.com/CloudNativeAI/model-spec v0.0.2 h1:uCO86kMk8wwadn8vKs0wT4petig5crByTIngdO3L2cQ=
1014
github.com/CloudNativeAI/model-spec v0.0.2/go.mod h1:3U/4zubBfbUkW59ATSg41HnkYyKrKUcKFH/cVdoPQnk=

contrib/nydusify/pkg/converter/converter.go

+1
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ func convertModelArtifact(ctx context.Context, opt Opt) error {
262262
ChunkSize: opt.ChunkSize,
263263
FromDir: contextDir,
264264
AttributesPath: attributesPath,
265+
Crc32: true,
265266
}
266267
_, externalBlobDigest, err := packWithAttributes(ctx, packOption, tmpDir)
267268
if err != nil {

contrib/nydusify/pkg/external/modctl/remote.go

+31
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ type RemoteHandler struct {
3838
blobs []backend.Blob
3939
}
4040

41+
type FileCrcList struct {
42+
Files []FileCrcInfo `json:"files"`
43+
}
44+
45+
type FileCrcInfo struct {
46+
FilePath string `json:"file_path"`
47+
ChunkCrcs string `json:"chunk_crcs"`
48+
}
49+
50+
const (
51+
filePathKey = "org.cnai.model.filepath"
52+
crcsKey = "org.cnai.nydus.crcs"
53+
)
54+
4155
func NewRemoteHandler(ctx context.Context, imageRef string, plainHTTP bool) (*RemoteHandler, error) {
4256
remoter, err := pkgPvd.DefaultRemote(imageRef, true)
4357
if err != nil {
@@ -154,13 +168,27 @@ func (handler *RemoteHandler) handle(ctx context.Context, layer ocispec.Descript
154168
return nil, errors.Wrap(err, "read tar blob failed")
155169
}
156170

171+
var fileCrcList = FileCrcList{}
172+
var fileCrcMap = make(map[string]string)
173+
if layer.Annotations != nil {
174+
if c, ok := layer.Annotations[crcsKey]; ok {
175+
if err := json.Unmarshal([]byte(c), &fileCrcList); err != nil {
176+
return nil, errors.Wrap(err, "unmarshal crcs failed")
177+
}
178+
for _, f := range fileCrcList.Files {
179+
fileCrcMap[f.FilePath] = f.ChunkCrcs
180+
}
181+
}
182+
}
183+
157184
blobInfo := handler.blobs[index].Config
158185
fileAttrs := make([]backend.FileAttribute, len(files))
159186
hackFile := os.Getenv("HACK_FILE")
160187
for idx, f := range files {
161188
if hackFile != "" && f.name == hackFile {
162189
hackFileWrapper(&f)
163190
}
191+
164192
fileAttrs[idx] = backend.FileAttribute{
165193
BlobID: blobInfo.Digest,
166194
BlobIndex: uint32(index),
@@ -172,6 +200,9 @@ func (handler *RemoteHandler) handle(ctx context.Context, layer ocispec.Descript
172200
Type: "external",
173201
Mode: f.mode,
174202
}
203+
if crcs, ok := fileCrcMap[f.name]; ok {
204+
fileAttrs[idx].Crcs = crcs
205+
}
175206
}
176207
return fileAttrs, nil
177208
}

contrib/nydusify/pkg/external/modctl/remote_test.go

+30-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/dragonflyoss/nydus/contrib/nydusify/pkg/snapshotter/external/backend"
1717
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1818
"github.com/stretchr/testify/assert"
19+
"github.com/stretchr/testify/require"
1920
)
2021

2122
type MockRemote struct {
@@ -95,13 +96,32 @@ func TestRemoteHandler_Handle(t *testing.T) {
9596
MaybeWithHTTPFunc: func(error) {},
9697
}
9798

99+
fileCrcInfo := &FileCrcInfo{
100+
ChunkCrcs: "0x1234,0x5678",
101+
FilePath: "file1.txt",
102+
}
103+
fileCrcList := &FileCrcList{
104+
Files: []FileCrcInfo{
105+
*fileCrcInfo,
106+
},
107+
}
108+
crcs, err := json.Marshal(fileCrcList)
109+
require.NoError(t, err)
110+
annotations := map[string]string{
111+
filePathKey: "file1.txt",
112+
crcsKey: string(crcs),
113+
}
98114
handler := &RemoteHandler{
99115
ctx: context.Background(),
100116
imageRef: "test-image",
101117
remoter: mockRemote,
102118
manifest: ocispec.Manifest{
103119
Layers: []ocispec.Descriptor{
104-
{MediaType: "test-media-type", Digest: "test-digest"},
120+
{
121+
MediaType: "test-media-type",
122+
Digest: "test-digest",
123+
Annotations: annotations,
124+
},
105125
},
106126
},
107127
blobs: []backend.Blob{
@@ -119,6 +139,15 @@ func TestRemoteHandler_Handle(t *testing.T) {
119139
assert.NotNil(t, backend)
120140
assert.NotEmpty(t, fileAttrs)
121141
assert.Equal(t, 3, len(fileAttrs))
142+
assert.Equal(t, fileCrcInfo.ChunkCrcs, fileAttrs[0].Crcs)
143+
assert.Equal(t, "", fileAttrs[1].Crcs)
144+
145+
handler.manifest.Layers[0].Annotations = map[string]string{
146+
filePathKey: "file1.txt",
147+
crcsKey: "0x1234,0x5678",
148+
}
149+
_, _, err = handler.Handle(context.Background())
150+
assert.Error(t, err)
122151
}
123152

124153
func TestGetModelConfig(t *testing.T) {

contrib/nydusify/pkg/snapshotter/external/backend/backend.go

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type FileAttribute struct {
4343
Chunk0CompressedOffset uint64
4444
Type string
4545
Mode uint32
46+
Crcs string
4647
}
4748

4849
type File struct {

contrib/nydusify/pkg/snapshotter/external/external.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ func RemoteHandle(ctx context.Context, opts Options) error {
9090
}
9191
attributes := []Attribute{}
9292
for _, file := range fileAttrs {
93-
p := fmt.Sprintf("/%s type=%s file_size=%d blob_index=%d blob_id=%s chunk_size=%s chunk_0_compressed_offset=%d compressed_size=%s",
94-
file.RelativePath, file.Type, file.FileSize, file.BlobIndex, file.BlobID, file.ChunkSize, file.Chunk0CompressedOffset, file.BlobSize)
93+
p := fmt.Sprintf("/%s type=%s file_size=%d blob_index=%d blob_id=%s chunk_size=%s chunk_0_compressed_offset=%d compressed_size=%s crcs=%s",
94+
file.RelativePath, file.Type, file.FileSize, file.BlobIndex, file.BlobID, file.ChunkSize, file.Chunk0CompressedOffset, file.BlobSize, file.Crcs)
9595
attributes = append(attributes, Attribute{
9696
Pattern: p,
9797
})

0 commit comments

Comments
 (0)