diff --git a/internal/envdclient/client.go b/internal/envdclient/client.go index d20ffd5..0567cf1 100644 --- a/internal/envdclient/client.go +++ b/internal/envdclient/client.go @@ -268,6 +268,30 @@ func (c *Client) ReadFile(ctx context.Context, path string) ([]byte, error) { return data, nil } +// PostInit calls envd's POST /init endpoint, which triggers a re-read of +// Firecracker MMDS metadata. This updates WRENN_SANDBOX_ID, WRENN_TEMPLATE_ID +// env vars and the corresponding files under /run/wrenn/ inside the guest. +// Must be called after snapshot restore so envd picks up the new sandbox's metadata. +func (c *Client) PostInit(ctx context.Context) error { + req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.base+"/init", nil) + if err != nil { + return fmt.Errorf("create request: %w", err) + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return fmt.Errorf("post init: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusNoContent { + body, _ := io.ReadAll(resp.Body) + return fmt.Errorf("post init: status %d: %s", resp.StatusCode, string(body)) + } + + return nil +} + // ListDir lists directory contents inside the sandbox. func (c *Client) ListDir(ctx context.Context, path string, depth uint32) (*envdpb.ListDirResponse, error) { req := connect.NewRequest(&envdpb.ListDirRequest{ diff --git a/internal/sandbox/manager.go b/internal/sandbox/manager.go index e920476..74df2a2 100644 --- a/internal/sandbox/manager.go +++ b/internal/sandbox/manager.go @@ -697,6 +697,11 @@ func (m *Manager) Resume(ctx context.Context, sandboxID string, timeoutSec int) return nil, fmt.Errorf("wait for envd: %w", err) } + // Trigger envd to re-read MMDS so it picks up the new sandbox/template IDs. + if err := client.PostInit(waitCtx); err != nil { + slog.Warn("post-init failed after resume, metadata files may be stale", "sandbox", sandboxID, "error", err) + } + now := time.Now() sb := &sandboxState{ Sandbox: models.Sandbox{ @@ -1098,6 +1103,11 @@ func (m *Manager) createFromSnapshot(ctx context.Context, sandboxID string, team return nil, fmt.Errorf("wait for envd: %w", err) } + // Trigger envd to re-read MMDS so it picks up the new sandbox/template IDs. + if err := client.PostInit(waitCtx); err != nil { + slog.Warn("post-init failed after template restore, metadata files may be stale", "sandbox", sandboxID, "error", err) + } + now := time.Now() sb := &sandboxState{ Sandbox: models.Sandbox{