1a69fcfd04
- Updated the installation script to clarify that production wrappers do not include fixed test secrets, improving user guidance for local testing. - Modified the jiggablend-manager and jiggablend-runner scripts to remove fixed test configurations, emphasizing the use of local test credentials via `make init-test`. - Enhanced error handling in the runner script to ensure that an API key is provided, improving security and user feedback. - Added new flags and options for the runner, including sandboxing capabilities and GPU ray tracing control, enhancing flexibility for users. - Improved README documentation to reflect changes in usage and configuration, ensuring users have clear instructions for setup and execution.
122 lines
2.9 KiB
Go
122 lines
2.9 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const defaultPodmanImage = "registry.fedoraproject.org/fedora-minimal:41"
|
|
|
|
type podmanWrapper struct {
|
|
allowNetwork bool
|
|
image string
|
|
}
|
|
|
|
func (w *podmanWrapper) Name() string { return BackendPodman }
|
|
|
|
func (w *podmanWrapper) Available() error {
|
|
if _, err := LookPath("podman"); err != nil {
|
|
return fmt.Errorf("podman not found in PATH: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *podmanWrapper) Wrap(spec Spec) (*exec.Cmd, error) {
|
|
if err := w.Available(); err != nil {
|
|
return nil, err
|
|
}
|
|
bin := mustAbs(spec.BlenderBinary)
|
|
work := mustAbs(spec.WorkDir)
|
|
home := mustAbs(spec.HomeDir)
|
|
if home == "" {
|
|
home = filepath.Join(work, "home")
|
|
}
|
|
root := blenderRoot(bin)
|
|
|
|
args := []string{
|
|
"run", "--rm",
|
|
"--security-opt", "label=disable",
|
|
// Keep user groups for /dev/dri access (render/video)
|
|
"--group-add", "keep-groups",
|
|
}
|
|
if !w.allowNetwork {
|
|
args = append(args, "--network=none")
|
|
}
|
|
// Map to same UID so bind mounts are writable
|
|
uid := os.Getuid()
|
|
gid := os.Getgid()
|
|
args = append(args, "--user", fmt.Sprintf("%d:%d", uid, gid))
|
|
|
|
// Thin OS image + host Blender tree + job dir
|
|
args = append(args,
|
|
"-v", root+":"+root+":ro",
|
|
"-v", work+":"+work+":rw",
|
|
)
|
|
if home != work && !strings.HasPrefix(home, work+string(os.PathSeparator)) {
|
|
_ = os.MkdirAll(home, 0755)
|
|
args = append(args, "-v", home+":"+home+":rw")
|
|
}
|
|
|
|
// System libs for GPU ICDs / dynamic linker (Blender tarball is mostly self-contained)
|
|
for _, p := range []string{"/usr", "/lib", "/lib64", "/etc"} {
|
|
if pathExists(p) {
|
|
args = append(args, "-v", p+":"+p+":ro")
|
|
}
|
|
}
|
|
|
|
// GPU devices and extra lib roots
|
|
for _, b := range ExistingBinds(GPUMounts(spec.HasAMD, spec.HasNVIDIA, spec.HasIntel, spec.ForceCPU)) {
|
|
if !pathExists(b.Host) {
|
|
continue
|
|
}
|
|
if b.Dev {
|
|
// --device works for character devices; for /dev/dri use volume
|
|
info, err := os.Stat(b.Host)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if info.IsDir() {
|
|
args = append(args, "-v", b.Host+":"+b.Dest+":ro")
|
|
} else {
|
|
args = append(args, "--device", b.Host)
|
|
}
|
|
continue
|
|
}
|
|
mode := "ro"
|
|
if !b.ReadOnly {
|
|
mode = "rw"
|
|
}
|
|
args = append(args, "-v", b.Host+":"+b.Dest+":"+mode)
|
|
}
|
|
|
|
// Environment
|
|
for _, e := range spec.Env {
|
|
args = append(args, "-e", e)
|
|
}
|
|
if home != "" {
|
|
args = append(args, "-e", "HOME="+home)
|
|
}
|
|
|
|
args = append(args, "--workdir", work)
|
|
args = append(args, "--entrypoint", bin)
|
|
args = append(args, w.image)
|
|
// entrypoint is blender; remaining args are blender args
|
|
args = append(args, spec.Args...)
|
|
|
|
cmd := exec.Command("podman", args...)
|
|
cmd.Dir = work
|
|
return cmd, nil
|
|
}
|
|
|
|
// PodmanImageDefault returns the default thin runtime image name.
|
|
func PodmanImageDefault() string { return defaultPodmanImage }
|
|
|
|
// FormatUIDGID is a small helper for tests.
|
|
func FormatUIDGID(uid, gid int) string {
|
|
return strconv.Itoa(uid) + ":" + strconv.Itoa(gid)
|
|
}
|