Managed ComfyUI picks up Comfy-Desktop shared models/input/output automatically
This commit is contained in:
@@ -15,6 +15,8 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"gpu-turnstile/internal/supervise"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Name matches the Windows service name; the systemd unit is Name + ".service".
|
// Name matches the Windows service name; the systemd unit is Name + ".service".
|
||||||
@@ -66,7 +68,8 @@ func Run(run func(ctx context.Context) error) error {
|
|||||||
// BindPaths hole through ProtectHome/ProtectSystem: it reads its venv and
|
// BindPaths hole through ProtectHome/ProtectSystem: it reads its venv and
|
||||||
// writes output/temp/user data under COMFY_DIR. A venv whose base
|
// writes output/temp/user data under COMFY_DIR. A venv whose base
|
||||||
// interpreter (pyvenv.cfg home) lives outside COMFY_DIR gets an additional
|
// interpreter (pyvenv.cfg home) lives outside COMFY_DIR gets an additional
|
||||||
// read-only bind.
|
// read-only bind, and a Comfy-Desktop shared data dir (models, input,
|
||||||
|
// output) a read-write one.
|
||||||
func renderUnit(exePath, configPath, comfyDir string) string {
|
func renderUnit(exePath, configPath, comfyDir string) string {
|
||||||
bind := ""
|
bind := ""
|
||||||
if comfyDir != "" {
|
if comfyDir != "" {
|
||||||
@@ -74,6 +77,9 @@ func renderUnit(exePath, configPath, comfyDir string) string {
|
|||||||
if home := comfyVenvHome(comfyDir); home != "" {
|
if home := comfyVenvHome(comfyDir); home != "" {
|
||||||
bind += "BindReadOnlyPaths=" + home + "\n"
|
bind += "BindReadOnlyPaths=" + home + "\n"
|
||||||
}
|
}
|
||||||
|
if shared := supervise.DesktopSharedDir(comfyDir); shared != "" {
|
||||||
|
bind += "BindPaths=" + shared + "\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`[Unit]
|
return fmt.Sprintf(`[Unit]
|
||||||
Description=gpu-turnstile GPU arbitration proxy for Ollama and ComfyUI
|
Description=gpu-turnstile GPU arbitration proxy for Ollama and ComfyUI
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import (
|
|||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
"golang.org/x/sys/windows/svc/mgr"
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
|
||||||
|
"gpu-turnstile/internal/supervise"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Name is the Windows service name.
|
// Name is the Windows service name.
|
||||||
@@ -382,6 +384,13 @@ func grantAll(exe, configPath string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Comfy-Desktop keeps models/input/output in a shared dir next
|
||||||
|
// to the install; the managed instance writes output there.
|
||||||
|
if shared := supervise.DesktopSharedDir(comfyDir); shared != "" {
|
||||||
|
if err := grantAccessTree(shared, "(OI)(CI)(M)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ func ComfyLayout(goos, dir string) (python, script string) {
|
|||||||
// DefaultComfyCommand builds the launch command for the standard venv
|
// DefaultComfyCommand builds the launch command for the standard venv
|
||||||
// layout (see ComfyLayout): the script is passed relative to dir so dir
|
// layout (see ComfyLayout): the script is passed relative to dir so dir
|
||||||
// stays the working directory, and --port is taken from comfyURL when the
|
// stays the working directory, and --port is taken from comfyURL when the
|
||||||
// URL carries one.
|
// URL carries one. On a Comfy-Desktop standalone install the shared data
|
||||||
|
// directory (models, input, output) is added as --*-directory flags so the
|
||||||
|
// managed instance sees the desktop app's models.
|
||||||
func DefaultComfyCommand(goos, dir, comfyURL string) string {
|
func DefaultComfyCommand(goos, dir, comfyURL string) string {
|
||||||
python, script := ComfyLayout(goos, dir)
|
python, script := ComfyLayout(goos, dir)
|
||||||
rel, err := filepath.Rel(dir, script)
|
rel, err := filepath.Rel(dir, script)
|
||||||
@@ -55,9 +57,34 @@ func DefaultComfyCommand(goos, dir, comfyURL string) string {
|
|||||||
if u, err := url.Parse(comfyURL); err == nil && u.Port() != "" {
|
if u, err := url.Parse(comfyURL); err == nil && u.Port() != "" {
|
||||||
cmd += " --port " + u.Port()
|
cmd += " --port " + u.Port()
|
||||||
}
|
}
|
||||||
|
if shared := DesktopSharedDir(dir); shared != "" {
|
||||||
|
for _, sub := range []string{"models", "input", "output"} {
|
||||||
|
p := filepath.Join(shared, sub)
|
||||||
|
if st, err := os.Stat(p); err == nil && st.IsDir() {
|
||||||
|
cmd += ` --` + sub + `-directory "` + p + `"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DesktopSharedDir returns the Comfy-Desktop shared data directory
|
||||||
|
// (<root>/ComfyUI-Shared) when dir looks like a desktop standalone install
|
||||||
|
// (<root>/ComfyUI-Installs/<name>/ComfyUI) and the shared models directory
|
||||||
|
// exists; "" otherwise. The desktop app keeps models, input and output
|
||||||
|
// there rather than inside the ComfyUI tree.
|
||||||
|
func DesktopSharedDir(dir string) string {
|
||||||
|
installs := filepath.Dir(filepath.Dir(dir))
|
||||||
|
if filepath.Base(installs) != "ComfyUI-Installs" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
shared := filepath.Join(filepath.Dir(installs), "ComfyUI-Shared")
|
||||||
|
if st, err := os.Stat(filepath.Join(shared, "models")); err == nil && st.IsDir() {
|
||||||
|
return shared
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Process is one managed child process.
|
// Process is one managed child process.
|
||||||
type Process struct {
|
type Process struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -253,3 +253,24 @@ func TestStripANSI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDesktopSharedDir(t *testing.T) {
|
||||||
|
root := t.TempDir()
|
||||||
|
comfy := filepath.Join(root, "ComfyUI-Installs", "rtx5080", "ComfyUI")
|
||||||
|
if err := os.MkdirAll(comfy, 0o755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got := DesktopSharedDir(comfy); got != "" {
|
||||||
|
t.Fatalf("no shared dir yet: got %q, want empty", got)
|
||||||
|
}
|
||||||
|
shared := filepath.Join(root, "ComfyUI-Shared")
|
||||||
|
if err := os.MkdirAll(filepath.Join(shared, "models"), 0o755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got := DesktopSharedDir(comfy); got != shared {
|
||||||
|
t.Fatalf("got %q, want %q", got, shared)
|
||||||
|
}
|
||||||
|
if got := DesktopSharedDir(filepath.Join(root, "plain", "ComfyUI")); got != "" {
|
||||||
|
t.Fatalf("non-desktop layout: got %q, want empty", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user