WIP: Add snapshot export import#152
Open
kwonkwonn wants to merge 4 commits into
Open
Conversation
|
|
||
| // UploadToPresignedURL uploads the file at filePath via an S3-compatible presigned PUT URL. | ||
| func UploadToPresignedURL(ctx context.Context, filePath, presignedURL string) error { | ||
| f, err := os.Open(filePath) |
| } | ||
| req.ContentLength = info.Size() | ||
|
|
||
| resp, err := http.DefaultClient.Do(req) |
Contributor
Author
|
요약: |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds presigned-URL based image fetch and snapshot upload capabilities to support “snapshot export/import” workflows, while keeping existing snapshot APIs for backward compatibility.
Changes:
- Extends VM creation request/types with
presignedImageUrland downloads missing base images via presigned GET beforeqemu-img create. - Introduces
POST /TakeExternalSnapshotto create an external snapshot and upload it via presigned PUT in one call. - Adds helper utilities + unit tests for base-image download and presigned uploads; updates CPU status to use atomic operations.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
services/snapshot/external_snap/upload_ext.go |
Adds SnapshotFilePath and UploadToPresignedURL helper functions for snapshot upload flows. |
services/snapshot/external_snap/upload_ext_test.go |
Adds httptest-based unit coverage for presigned upload + path helper. |
services/creation/generate_files.go |
Adds ensureBaseImage and wires presigned base image download into disk image creation. |
services/creation/generate_files_test.go |
Adds unit tests for ensureBaseImage behaviors (exists/missing/download/error cleanup). |
pkg/types/vm.go |
Adds presignedImageUrl to VM_Init_Info for downstream creation flow. |
api/Create/model.go |
Adds presignedImageUrl to /createVM request and maps it into VM_Init_Info. |
api/Snapshot/model.go |
Adds request/response types for TakeExternalSnapshot. |
api/Snapshot/Snapshot.go |
Implements TakeExternalSnapshot handler (snapshot + presigned PUT upload). |
api/Snapshot/snapshot_test.go |
Adds handler tests for request decode/validation and domain lookup failure. |
internal/server/server.go |
Registers POST /TakeExternalSnapshot route. |
DomCon/domainList_status/cpu_status.go |
Switches CPU status bookkeeping to atomic operations and simplifies idle calc. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+42
to
+44
| if _, err := os.Stat(path); err == nil { | ||
| return nil | ||
| } |
Comment on lines
+54
to
+77
| tmpPath := path + ".tmp" | ||
|
|
||
| ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) | ||
| defer cancel() | ||
|
|
||
| req, err := http.NewRequestWithContext(ctx, http.MethodGet, presignedURL, nil) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to build download request: %w", err) | ||
| } | ||
|
|
||
| resp, err := http.DefaultClient.Do(req) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to download base image: %w", err) | ||
| } | ||
| defer resp.Body.Close() | ||
|
|
||
| if resp.StatusCode < 200 || resp.StatusCode >= 300 { | ||
| return fmt.Errorf("download base image returned status %d", resp.StatusCode) | ||
| } | ||
|
|
||
| tmp, err := os.Create(tmpPath) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create temp file: %w", err) | ||
| } |
Comment on lines
+323
to
+328
| snapName, err := externalsnapshot.CreateExternalSnapshot(dom, param.SnapKey, &externalsnapshot.ExternalSnapshotOptions{}) | ||
| if err != nil { | ||
| resp.ResponseWriteErr(w, err, http.StatusInternalServerError) | ||
| h.Logger.Error("take external snapshot failed - create snapshot", zap.String("uuid", param.UUID), zap.Error(err)) | ||
| return | ||
| } |
Comment on lines
+70
to
+74
| got := SnapshotFilePath("/var/lib/kws", "vm-uuid", "snap1", "vda") | ||
| want := "/var/lib/kws/vm-uuid/snapshots/snap1/vda.qcow2" | ||
| if got != want { | ||
| t.Errorf("got %q, want %q", got, want) | ||
| } |
Comment on lines
+39
to
+48
| type TakeExternalSnapshotRequest struct { | ||
| UUID string `json:"uuid"` | ||
| SnapKey string `json:"snapKey"` | ||
| PresignedURL string `json:"presignedUrl"` | ||
| } | ||
|
|
||
| type TakeExternalSnapshotResponse struct { | ||
| UUID string `json:"uuid"` | ||
| SnapKey string `json:"snapKey"` | ||
| } |
kwonkwonn
force-pushed
the
add_snapshot_export_import
branch
from
June 28, 2026 07:49
13948a0 to
75da5bc
Compare
This was referenced Jun 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
presignedImageUrl필드 추가 (/createVM): 베이스 이미지가 로컬에 없을 때 presigned GET URL로 RustFS에서 자동 다운로드 후 VM 생성. 이미 이미지가 존재하면 기존 경로 그대로 사용하므로 하위 호환성 유지.POST /TakeExternalSnapshot신규 엔드포인트: 외부 스냅샷 생성과 RustFS presigned PUT 업로드를 단일 요청으로 처리. 기존/CreateExternalSnapshot은 변경 없이 유지 (WKS_Control 이전 버전과의 하위 호환성 보장)..tmp→ rename 패턴으로 중간 실패 시 불완전한 파일이 남지 않도록 처리.ensureBaseImage,UploadToPresignedURL,TakeExternalSnapshot핸들러에 대한 httptest 기반 테스트.Changes
pkg/types/vm.goVM_Init_Info에presignedImageUrl필드 추가api/Create/model.goCreateVMRequest에 동일 필드 추가 및toVMInitInfo()연결services/creation/generate_files.goensureBaseImage()구현 — 로컬 확인 → presigned GET 다운로드api/Snapshot/model.goTakeExternalSnapshotRequest/Response타입 추가services/snapshot/external_snap/upload_ext.goUploadToPresignedURL(),SnapshotFilePath()구현api/Snapshot/Snapshot.goTakeExternalSnapshot핸들러 추가internal/server/server.goPOST /TakeExternalSnapshot라우트 등록WIP / Known Limitations
TakeExternalSnapshot은vda하드코딩. WKS_Control의TakeSnapshotRequest가 단일presignedUrl을 전달하는 구조에 맞춘 것으로, 멀티 디스크 VM은 미지원.Test Plan
/createVM(이미지 있을 때) —/var/lib/kws/baseimg/{os}파일 존재 확인 후 기존 동작 유지 확인/createVM+presignedImageUrl(이미지 없을 때) — 호출 후/var/lib/kws/baseimg/{os}파일 생성 확인POST /TakeExternalSnapshot— 호출 후/var/lib/kws/{uuid}/snapshots/{snapKey}/vda.qcow2파일 생성 확인 + RustFS 버킷에 업로드됨 확인/CreateExternalSnapshot— 기존 동작 회귀 없음 확인