Enhance Settings.fds management and installation checks

- Introduced functions to ensure the `IsInstalled` flag is set in `Settings.fds`, preventing the UI from displaying the /Install wizard.
- Added logic to create or patch `Settings.fds` with installation details, including the installation date and version.
- Updated the `install_swarm_comfy.py` script to call the new function, ensuring the installation state is correctly managed during backend operations.
- Added tests to verify the presence of the `IsInstalled` flag in the relevant scripts and ensure proper functionality during installation checks.
This commit is contained in:
Leonid Pershin
2026-08-21 11:27:06 +03:00
parent 241ada62cb
commit fc60fef279
3 changed files with 204 additions and 2 deletions
+140 -2
View File
@@ -284,6 +284,7 @@ from __future__ import annotations
import os
import re
import sys
import time
from pathlib import Path
p = Path(os.environ.get("GPU_RENT_SETTINGS_FDS") or "/mnt/swarm_data/Data/Settings.fds")
@@ -292,8 +293,15 @@ if not fname:
print("no GPU_RENT_AUTOCOMPLETE_FILE", file=sys.stderr)
raise SystemExit(1)
installed_block = (
"IsInstalled: true\n"
f"InstallDate: {time.strftime('%Y-%m-%d')}\n"
"InstallVersion: gpu-rent\n"
)
block = (
"DefaultUser:\n"
installed_block
+ "DefaultUser:\n"
" AutoComplete:\n"
f" Source: {fname}\n"
" EscapeParens: true\n"
@@ -302,10 +310,20 @@ block = (
if not p.is_file():
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(block, encoding="utf-8")
print(f"created Settings.fds AutoComplete.Source={fname}")
print(f"created Settings.fds IsInstalled+AutoComplete.Source={fname}")
raise SystemExit(0)
text = p.read_text(encoding="utf-8", errors="replace")
# Never leave a Settings.fds that sends the UI to /Install.
if not re.search(r"(?im)^\s*IsInstalled:\s*true\s*$", text):
if re.search(r"(?im)^\s*IsInstalled:\s*", text):
text = re.sub(r"(?im)^(\s*IsInstalled:\s*).*$", r"\1true", text, count=1)
else:
text = installed_block + text
p.write_text(text, encoding="utf-8")
print("patched IsInstalled: true (was missing/false)")
text = p.read_text(encoding="utf-8", errors="replace")
if re.search(rf"^\s*Source:\s*{re.escape(fname)}\s*$", text, re.M):
print(f"AutoComplete.Source already {fname}")
raise SystemExit(0)
@@ -343,6 +361,98 @@ else:
'''
_ENSURE_INSTALLED_PY = r'''
#!/usr/bin/env python3
"""Ensure Settings.fds has IsInstalled: true so UI skips /Install wizard."""
from __future__ import annotations
import os
import re
import sys
import time
from pathlib import Path
paths = []
env = (os.environ.get("GPU_RENT_SETTINGS_FDS") or "").strip()
if env:
paths.append(Path(env))
paths.extend(
[
Path("/mnt/swarm_data/Data/Settings.fds"),
Path("/opt/swarmui/Data/Settings.fds"),
]
)
# Unique while preserving order
seen = set()
uniq: list[Path] = []
for p in paths:
key = str(p)
if key in seen:
continue
seen.add(key)
uniq.append(p)
changed = False
for p in uniq:
try:
same = False
if p.is_file():
for q in uniq:
if q is not p and q.is_file():
try:
if p.resolve() == q.resolve():
same = True
break
except OSError:
pass
if same and changed:
continue
if not p.is_file():
# Only create on data volume path
if "/mnt/swarm_data/" not in str(p):
continue
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(
"IsInstalled: true\n"
f"InstallDate: {time.strftime('%Y-%m-%d')}\n"
"InstallVersion: gpu-rent\n"
"DefaultUser:\n"
" Theme: modern_dark\n",
encoding="utf-8",
)
print(f"created {p} with IsInstalled")
changed = True
continue
text = p.read_text(encoding="utf-8", errors="replace")
if re.search(r"(?im)^\s*IsInstalled:\s*true\s*$", text):
print(f"ok {p}: IsInstalled true")
continue
if re.search(r"(?im)^\s*IsInstalled:\s*", text):
text = re.sub(r"(?im)^(\s*IsInstalled:\s*).*$", r"\1true", text, count=1)
else:
text = (
"IsInstalled: true\n"
f"InstallDate: {time.strftime('%Y-%m-%d')}\n"
"InstallVersion: gpu-rent\n"
+ text
)
if not re.search(r"(?im)^\s*InstallDate:\s*", text):
text = re.sub(
r"(?im)^(\s*IsInstalled:\s*true\s*\n)",
rf"\1InstallDate: {time.strftime('%Y-%m-%d')}\n",
text,
count=1,
)
p.write_text(text, encoding="utf-8")
print(f"patched {p}: IsInstalled true")
changed = True
except OSError as exc:
print(f"skip {p}: {exc}")
print("CHANGED" if changed else "NOOP")
'''
def _merge_autocomplete_into_settings(
cfg: Config, host: str, settings_path: str, filename: str, log: Log
) -> None:
@@ -364,6 +474,31 @@ def _merge_autocomplete_into_settings(
log(line.strip())
def ensure_settings_is_installed(cfg: Config, host: str, log: Log) -> bool:
"""Make sure Settings.fds has IsInstalled:true (UI /Install wizard).
Returns True if the file was created/patched (caller may need SwarmUI restart).
"""
out = run_python(
cfg,
host,
_ENSURE_INSTALLED_PY,
remote_path="/tmp/gpu-rent-ensure_installed.py",
timeout=60,
log=None,
env={"GPU_RENT_SETTINGS_FDS": f"{DATA}/Data/Settings.fds"},
)
changed = False
for line in (out or "").splitlines():
line = line.strip()
if not line:
continue
log(f"Settings: {line}")
if line == "CHANGED":
changed = True
return changed
def _download_url(host: str, version_id: int, file_info: dict) -> str:
raw = str(file_info.get("downloadUrl") or "")
if "civitai." in raw and "/api/download/" in raw:
@@ -801,6 +936,9 @@ def provision_vm(
)
if cfg.pull_output:
pull_tree(cfg, host, f"{DATA}/Output", cfg.local_output_dir, log)
# Avoid /Install wizard when backends already exist but Settings lack flag.
if ensure_settings_is_installed(cfg, host, log):
restart = True
else:
log("SwarmUI: skip (llm-only)")
run_ssh(