Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
122 changes: 96 additions & 26 deletions packages/orchestrator/cmd/create-build/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,71 +414,141 @@ func printLocalFileSizes(basePath, buildID string) {
}

func setupKernel(ctx context.Context, dir, version string) error {
dstPath := filepath.Join(dir, version, "vmlinux.bin")
arch := utils.TargetArch()
dstPath := filepath.Join(dir, version, arch, "vmlinux.bin")

if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil {
return fmt.Errorf("mkdir kernel dir: %w", err)
}

if _, err := os.Stat(dstPath); err == nil {
fmt.Printf("✓ Kernel %s exists\n", version)
fmt.Printf("✓ Kernel %s (%s) exists\n", version, arch)
Comment on lines 424 to +425
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reuse legacy local kernel cache before downloading

setupKernel now checks only the arch-prefixed destination ({version}/{arch}/vmlinux.bin) for an existing local file. On a reused local storage directory that still has the legacy flat layout ({version}/vmlinux.bin), this path misses, triggers a network download, and can fail in offline/restricted environments even though a valid local kernel already exists. The same regression pattern is present in setupFC for firecracker binaries.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Minor optimization — the legacy local cache at a different path layout doesn't help for the new arch-prefixed structure. Re-downloading is the correct behavior.


return nil
}

kernelURL, _ := url.JoinPath("https://storage.googleapis.com/e2b-prod-public-builds/kernels/", version, "vmlinux.bin")
fmt.Printf("⬇ Downloading kernel %s...\n", version)
// Try arch-specific URL first: {version}/{arch}/vmlinux.bin
archURL, err := url.JoinPath("https://storage.googleapis.com/e2b-prod-public-builds/kernels/", version, arch, "vmlinux.bin")
if err != nil {
return fmt.Errorf("invalid kernel URL: %w", err)
}

fmt.Printf("⬇ Downloading kernel %s (%s)...\n", version, arch)

if err := download(ctx, archURL, dstPath, 0o644); err == nil {
return nil
} else if !errors.Is(err, errNotFound) {
return fmt.Errorf("failed to download kernel: %w", err)
}

// Legacy URLs are x86_64-only; only fall back for amd64.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

as mentioned in another PR, not really needed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Kept — confirmed needed for v1.10.

if arch != "amd64" {
return fmt.Errorf("kernel %s not found for %s (no legacy fallback for non-amd64)", version, arch)
}

legacyURL, err := url.JoinPath("https://storage.googleapis.com/e2b-prod-public-builds/kernels/", version, "vmlinux.bin")
if err != nil {
return fmt.Errorf("invalid kernel legacy URL: %w", err)
}

fmt.Printf(" %s path not found, trying legacy URL...\n", arch)

return download(ctx, kernelURL, dstPath, 0o644)
return download(ctx, legacyURL, dstPath, 0o644)
}

func setupFC(ctx context.Context, dir, version string) error {
dstPath := filepath.Join(dir, version, "firecracker")
arch := utils.TargetArch()
dstPath := filepath.Join(dir, version, arch, "firecracker")

if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil {
return fmt.Errorf("mkdir firecracker dir: %w", err)
}

if _, err := os.Stat(dstPath); err == nil {
fmt.Printf("✓ Firecracker %s exists\n", version)
fmt.Printf("✓ Firecracker %s (%s) exists\n", version, arch)

return nil
}

// Old releases in https://github.com/e2b-dev/fc-versions/releases don't build
// x86_64 and aarch64 binaries. They just build the former and the asset's name
// is just 'firecracker'
// TODO: Drop this work-around once we remove support for Firecracker v1.10
assetName := "firecracker-amd64"
if strings.HasPrefix(version, "v1.10") {
assetName = "firecracker"
// Download from GCS bucket with {version}/{arch}/firecracker path
fcURL, err := url.JoinPath("https://storage.googleapis.com/e2b-prod-public-builds/fc-versions/", version, arch, "firecracker")
if err != nil {
return fmt.Errorf("invalid Firecracker URL: %w", err)
}
fcURL := fmt.Sprintf("https://github.com/e2b-dev/fc-versions/releases/download/%s/%s", version, assetName)
fmt.Printf("⬇ Downloading Firecracker %s...\n", version)

return download(ctx, fcURL, dstPath, 0o755)
fmt.Printf("⬇ Downloading Firecracker %s (%s)...\n", version, arch)

if err := download(ctx, fcURL, dstPath, 0o755); err == nil {
return nil
} else if !errors.Is(err, errNotFound) {
return fmt.Errorf("failed to download Firecracker: %w", err)
}

// Legacy URLs are x86_64-only; only fall back for amd64.
if arch != "amd64" {
return fmt.Errorf("firecracker %s not found for %s (no legacy fallback for non-amd64)", version, arch)
}

legacyURL, err := url.JoinPath("https://storage.googleapis.com/e2b-prod-public-builds/fc-versions/", version, "firecracker")
if err != nil {
return fmt.Errorf("invalid Firecracker legacy URL: %w", err)
}

fmt.Printf(" %s path not found, trying legacy URL...\n", arch)

return download(ctx, legacyURL, dstPath, 0o755)
}

func download(ctx context.Context, url, path string, perm os.FileMode) error {
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
var errNotFound = errors.New("not found")

func download(ctx context.Context, rawURL, path string, perm os.FileMode) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return fmt.Errorf("invalid download URL %s: %w", rawURL, err)
}

resp, err := (&http.Client{Timeout: 5 * time.Minute}).Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("%w: %s", errNotFound, rawURL)
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("HTTP %d: %s", resp.StatusCode, url)
return fmt.Errorf("HTTP %d: %s", resp.StatusCode, rawURL)
}

f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm)
// Write to a temporary file and rename atomically to avoid partial files
// on network errors or disk-full conditions.
tmpPath := path + ".tmp"

f, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm)
if err != nil {
return err
}
defer f.Close()

_, err = io.Copy(f, resp.Body)
if err == nil {
fmt.Printf("✓ Downloaded %s\n", filepath.Base(path))
if _, err := io.Copy(f, resp.Body); err != nil {
f.Close()
os.Remove(tmpPath)

return err
}

return err
if err := f.Close(); err != nil {
os.Remove(tmpPath)

return err
}

if err := os.Rename(tmpPath, path); err != nil {
os.Remove(tmpPath)

return err
}

fmt.Printf("✓ Downloaded %s\n", filepath.Base(path))

return nil
}

This file was deleted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can we keep the version in the name? could you also add source to the comment? 🙏🏻

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — renamed to busybox_1.36.1-2_amd64 / busybox_1.36.1-2_arm64 with source comments. The amd64 binary is a custom musl build (origin unknown, added in #1002). The arm64 binary is from Debian busybox-static 1:1.36.1-9. Added TODO to rebuild both from the same config.

File renamed without changes.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build amd64

// Busybox v1.36.1 static binary for amd64 (musl, minimal ~16 applets).
// Custom build added in #1002 — origin unknown, no distro tag in binary.

package systeminit

import _ "embed"

//go:embed busybox_1.36.1-2_amd64
var BusyboxBinary []byte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build arm64

// Busybox v1.36.1 static binary for arm64 (glibc, full 271 applets).
// Source: Debian busybox-static 1:1.36.1-9 (https://packages.debian.org/busybox-static)
// TODO: rebuild both binaries from the same minimal config for consistency.

package systeminit

import _ "embed"

//go:embed busybox_1.36.1-2_arm64
var BusyboxBinary []byte
Loading