Point gpu-rent logs at gpu-rent-ollama and harden Assistent bin probes.
Stock ollama.service is disabled by install; journal aliases must use
gpu-rent-ollama. Prefer bin/{Debug,Release}/net* when locating the
extension DLL and Sqlite private deps.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,9 +30,17 @@ for root in roots:
|
|||||||
for p in sorted(root.iterdir()):
|
for p in sorted(root.iterdir()):
|
||||||
if "assistent" not in p.name.lower():
|
if "assistent" not in p.name.lower():
|
||||||
continue
|
continue
|
||||||
|
# Prefer TFM output dirs (Debug/Release net*), then any bin/** fallback
|
||||||
|
dlls = []
|
||||||
|
for cfg_name in ("Debug", "Release"):
|
||||||
|
dlls.extend(sorted(p.glob(f"bin/{cfg_name}/net*/SwarmAssistentExtension.dll")))
|
||||||
|
if not dlls:
|
||||||
dlls = sorted(p.glob("bin/**/SwarmAssistentExtension.dll"))
|
dlls = sorted(p.glob("bin/**/SwarmAssistentExtension.dll"))
|
||||||
if not dlls:
|
if not dlls:
|
||||||
# Older layout / alternate assembly name
|
# Older layout / alternate assembly name
|
||||||
|
for cfg_name in ("Debug", "Release"):
|
||||||
|
dlls.extend(sorted(p.glob(f"bin/{cfg_name}/net*/*Assistent*.dll")))
|
||||||
|
if not dlls:
|
||||||
dlls = sorted(p.glob("bin/**/*Assistent*.dll"))
|
dlls = sorted(p.glob("bin/**/*Assistent*.dll"))
|
||||||
dll = dlls[0] if dlls else None
|
dll = dlls[0] if dlls else None
|
||||||
dll_dir = dll.parent if dll else None
|
dll_dir = dll.parent if dll else None
|
||||||
@@ -335,9 +343,12 @@ def collect_assistent_extension(cfg: Config, *, fs: dict[str, Any] | None = None
|
|||||||
hints.append(f"{e.get('name')}: нет DLL — compile fail / Swarm не билдил")
|
hints.append(f"{e.get('name')}: нет DLL — compile fail / Swarm не билдил")
|
||||||
ok = False
|
ok = False
|
||||||
elif not e.get("sqlite_dll"):
|
elif not e.get("sqlite_dll"):
|
||||||
|
where = e.get("dll_dir") or "bin/{Debug,Release}/net*"
|
||||||
hints.append(
|
hints.append(
|
||||||
f"{e.get('name')}: DLL есть, но нет Microsoft.Data.Sqlite.dll — "
|
f"{e.get('name')}: DLL есть ({where}), но рядом нет "
|
||||||
"чат/memory API могут падать (нужен ≥0.13.1 + seed-extensions)"
|
"Microsoft.Data.Sqlite.dll (+ SQLitePCLRaw*) — чат/memory API упадут. "
|
||||||
|
"Нужен swarm-assistent ≥0.13.1 (CopyLocalLockFileAssemblies) + "
|
||||||
|
"gpu-rent seed-extensions + restart SwarmUI"
|
||||||
)
|
)
|
||||||
ok = False
|
ok = False
|
||||||
if not e.get("tab_html") or not e.get("bundle_js"):
|
if not e.get("tab_html") or not e.get("bundle_js"):
|
||||||
|
|||||||
@@ -237,6 +237,10 @@ for root in roots:
|
|||||||
for p in sorted(root.iterdir()):
|
for p in sorted(root.iterdir()):
|
||||||
if "assistent" not in p.name.lower():
|
if "assistent" not in p.name.lower():
|
||||||
continue
|
continue
|
||||||
|
dlls = []
|
||||||
|
for cfg_name in ("Debug", "Release"):
|
||||||
|
dlls.extend(sorted(p.glob(f"bin/{cfg_name}/net*/SwarmAssistentExtension.dll")))
|
||||||
|
if not dlls:
|
||||||
dlls = sorted(p.glob("bin/**/SwarmAssistentExtension.dll"))
|
dlls = sorted(p.glob("bin/**/SwarmAssistentExtension.dll"))
|
||||||
dll = dlls[0] if dlls else None
|
dll = dlls[0] if dlls else None
|
||||||
dll_dir = dll.parent if dll else None
|
dll_dir = dll.parent if dll else None
|
||||||
@@ -246,6 +250,7 @@ for root in roots:
|
|||||||
"path": str(p),
|
"path": str(p),
|
||||||
"name": p.name,
|
"name": p.name,
|
||||||
"dll": str(dll) if dll else None,
|
"dll": str(dll) if dll else None,
|
||||||
|
"dll_dir": str(dll_dir) if dll_dir else None,
|
||||||
"sqlite_dll": bool(sqlite and sqlite.is_file()),
|
"sqlite_dll": bool(sqlite and sqlite.is_file()),
|
||||||
"sqlitepcl": bool(pcl),
|
"sqlitepcl": bool(pcl),
|
||||||
})
|
})
|
||||||
@@ -330,8 +335,9 @@ def verify_assistent_sqlite_bins(cfg: Config, host: str, log: Log) -> bool:
|
|||||||
log(f"Assistent {name}: Microsoft.Data.Sqlite есть (SQLitePCLRaw не найден)")
|
log(f"Assistent {name}: Microsoft.Data.Sqlite есть (SQLitePCLRaw не найден)")
|
||||||
ok_any = True
|
ok_any = True
|
||||||
else:
|
else:
|
||||||
|
where = row.get("dll_dir") or "bin/{Debug,Release}/net*"
|
||||||
log(
|
log(
|
||||||
f"⚠ Assistent {name}: DLL есть, но нет Microsoft.Data.Sqlite.dll — "
|
f"⚠ Assistent {name}: DLL в {where}, но нет Microsoft.Data.Sqlite.dll — "
|
||||||
"чат/memory API упадут. Нужен ≥0.13.1 + seed-extensions + restart"
|
"чат/memory API упадут. Нужен ≥0.13.1 + seed-extensions + restart"
|
||||||
)
|
)
|
||||||
return ok_any
|
return ok_any
|
||||||
|
|||||||
+12
-9
@@ -13,20 +13,23 @@ Log = Callable[[str], None]
|
|||||||
DIGEST_LINES = 20
|
DIGEST_LINES = 20
|
||||||
FULL_LINES_DEFAULT = 80
|
FULL_LINES_DEFAULT = 80
|
||||||
|
|
||||||
|
# Stock `ollama.service` is disabled by install_ollama.sh; we run gpu-rent-ollama.
|
||||||
|
OLLAMA_UNIT = "gpu-rent-ollama"
|
||||||
|
KILLER_UNIT = "gpu-rent-idle-killer"
|
||||||
|
|
||||||
UNIT_ALIASES: dict[str, str] = {
|
UNIT_ALIASES: dict[str, str] = {
|
||||||
"all": "all",
|
"all": "all",
|
||||||
"swarm": "swarmui",
|
"swarm": "swarmui",
|
||||||
"swarmui": "swarmui",
|
"swarmui": "swarmui",
|
||||||
"ollama": "ollama",
|
"ollama": OLLAMA_UNIT,
|
||||||
"killer": "gpu-rent-idle-killer",
|
"gpu-rent-ollama": OLLAMA_UNIT,
|
||||||
"idle-killer": "gpu-rent-idle-killer",
|
"killer": KILLER_UNIT,
|
||||||
"idle": "gpu-rent-idle-killer",
|
"idle-killer": KILLER_UNIT,
|
||||||
|
"idle": KILLER_UNIT,
|
||||||
"cloud-init": "cloud-init",
|
"cloud-init": "cloud-init",
|
||||||
"cloud": "cloud-init",
|
"cloud": "cloud-init",
|
||||||
}
|
}
|
||||||
|
|
||||||
KILLER_UNIT = "gpu-rent-idle-killer"
|
|
||||||
|
|
||||||
|
|
||||||
def units_for(cfg: Config) -> list[str]:
|
def units_for(cfg: Config) -> list[str]:
|
||||||
"""Journal units enabled for this stack (no cloud-init)."""
|
"""Journal units enabled for this stack (no cloud-init)."""
|
||||||
@@ -34,7 +37,7 @@ def units_for(cfg: Config) -> list[str]:
|
|||||||
if bool(getattr(cfg, "enable_swarmui", True)):
|
if bool(getattr(cfg, "enable_swarmui", True)):
|
||||||
units.append("swarmui")
|
units.append("swarmui")
|
||||||
if normalize_runtime(getattr(cfg, "llm_runtime", "none")) == "ollama":
|
if normalize_runtime(getattr(cfg, "llm_runtime", "none")) == "ollama":
|
||||||
units.append("ollama")
|
units.append(OLLAMA_UNIT)
|
||||||
units.append(KILLER_UNIT)
|
units.append(KILLER_UNIT)
|
||||||
return units
|
return units
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ def journal_units_for_target(target: str, *, cfg: Config | None = None) -> list[
|
|||||||
if target == "all":
|
if target == "all":
|
||||||
if cfg is not None:
|
if cfg is not None:
|
||||||
return units_for(cfg)
|
return units_for(cfg)
|
||||||
return ["swarmui", "ollama", KILLER_UNIT]
|
return ["swarmui", OLLAMA_UNIT, KILLER_UNIT]
|
||||||
return [target]
|
return [target]
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +118,7 @@ def fetch_logs_for_cli(
|
|||||||
target = resolve_unit_alias(unit)
|
target = resolve_unit_alias(unit)
|
||||||
# Full dump keeps historical all=swarm+ollama+killer regardless of cfg.
|
# Full dump keeps historical all=swarm+ollama+killer regardless of cfg.
|
||||||
if target == "all":
|
if target == "all":
|
||||||
journal_units = ["swarmui", "ollama", KILLER_UNIT]
|
journal_units = ["swarmui", OLLAMA_UNIT, KILLER_UNIT]
|
||||||
else:
|
else:
|
||||||
journal_units = journal_units_for_target(target)
|
journal_units = journal_units_for_target(target)
|
||||||
cmd = build_logs_remote_cmd(
|
cmd = build_logs_remote_cmd(
|
||||||
|
|||||||
+11
-5
@@ -7,6 +7,7 @@ import pytest
|
|||||||
from gpu_rent.vm_logs import (
|
from gpu_rent.vm_logs import (
|
||||||
DIGEST_LINES,
|
DIGEST_LINES,
|
||||||
KILLER_UNIT,
|
KILLER_UNIT,
|
||||||
|
OLLAMA_UNIT,
|
||||||
build_logs_remote_cmd,
|
build_logs_remote_cmd,
|
||||||
fetch_unit_logs,
|
fetch_unit_logs,
|
||||||
resolve_unit_alias,
|
resolve_unit_alias,
|
||||||
@@ -23,7 +24,7 @@ class _Cfg:
|
|||||||
def test_units_for_swarm_and_ollama():
|
def test_units_for_swarm_and_ollama():
|
||||||
assert units_for(_Cfg(enable_swarmui=True, llm_runtime="ollama")) == [
|
assert units_for(_Cfg(enable_swarmui=True, llm_runtime="ollama")) == [
|
||||||
"swarmui",
|
"swarmui",
|
||||||
"ollama",
|
OLLAMA_UNIT,
|
||||||
KILLER_UNIT,
|
KILLER_UNIT,
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ def test_units_for_swarm_only():
|
|||||||
|
|
||||||
def test_units_for_llm_only():
|
def test_units_for_llm_only():
|
||||||
assert units_for(_Cfg(enable_swarmui=False, llm_runtime="ollama")) == [
|
assert units_for(_Cfg(enable_swarmui=False, llm_runtime="ollama")) == [
|
||||||
"ollama",
|
OLLAMA_UNIT,
|
||||||
KILLER_UNIT,
|
KILLER_UNIT,
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -51,7 +52,9 @@ def test_digest_cmd_has_journal_no_cloud_init():
|
|||||||
)
|
)
|
||||||
assert "cloud-init" not in cmd
|
assert "cloud-init" not in cmd
|
||||||
assert "journalctl -u swarmui" in cmd
|
assert "journalctl -u swarmui" in cmd
|
||||||
assert "journalctl -u ollama" in cmd
|
assert f"journalctl -u {OLLAMA_UNIT}" in cmd
|
||||||
|
# Stock ollama.service is disabled — digest must not query bare unit name
|
||||||
|
assert "journalctl -u ollama -n" not in cmd
|
||||||
assert f"journalctl -u {KILLER_UNIT}" in cmd
|
assert f"journalctl -u {KILLER_UNIT}" in cmd
|
||||||
assert f"-n {DIGEST_LINES}" in cmd
|
assert f"-n {DIGEST_LINES}" in cmd
|
||||||
assert "systemctl is-active swarmui" in cmd
|
assert "systemctl is-active swarmui" in cmd
|
||||||
@@ -61,15 +64,18 @@ def test_full_logs_cmd_includes_cloud_init():
|
|||||||
cmd = build_logs_remote_cmd(
|
cmd = build_logs_remote_cmd(
|
||||||
lines=80,
|
lines=80,
|
||||||
include_cloud_init=True,
|
include_cloud_init=True,
|
||||||
journal_units=["swarmui", "ollama", KILLER_UNIT],
|
journal_units=["swarmui", OLLAMA_UNIT, KILLER_UNIT],
|
||||||
)
|
)
|
||||||
assert "cloud-init-output.log" in cmd
|
assert "cloud-init-output.log" in cmd
|
||||||
assert "journalctl -u swarmui" in cmd
|
assert "journalctl -u swarmui" in cmd
|
||||||
|
assert f"journalctl -u {OLLAMA_UNIT}" in cmd
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_unit_alias():
|
def test_resolve_unit_alias():
|
||||||
assert resolve_unit_alias(None) == "all"
|
assert resolve_unit_alias(None) == "all"
|
||||||
assert resolve_unit_alias("swarm") == "swarmui"
|
assert resolve_unit_alias("swarm") == "swarmui"
|
||||||
|
assert resolve_unit_alias("ollama") == OLLAMA_UNIT
|
||||||
|
assert resolve_unit_alias("gpu-rent-ollama") == OLLAMA_UNIT
|
||||||
assert resolve_unit_alias("killer") == KILLER_UNIT
|
assert resolve_unit_alias("killer") == KILLER_UNIT
|
||||||
with pytest.raises(ValueError, match="неизвестный"):
|
with pytest.raises(ValueError, match="неизвестный"):
|
||||||
resolve_unit_alias("bogus")
|
resolve_unit_alias("bogus")
|
||||||
@@ -90,4 +96,4 @@ def test_fetch_unit_logs_uses_ssh(monkeypatch):
|
|||||||
assert "cloud-init" not in calls[0][1]
|
assert "cloud-init" not in calls[0][1]
|
||||||
assert "journalctl -u swarmui" in calls[0][1]
|
assert "journalctl -u swarmui" in calls[0][1]
|
||||||
assert f"journalctl -u {KILLER_UNIT}" in calls[0][1]
|
assert f"journalctl -u {KILLER_UNIT}" in calls[0][1]
|
||||||
assert "journalctl -u ollama" not in calls[0][1]
|
assert f"journalctl -u {OLLAMA_UNIT}" not in calls[0][1]
|
||||||
|
|||||||
Reference in New Issue
Block a user