"""Upload and run the idempotent SwarmUI bootstrap on the VM.""" from __future__ import annotations from collections.abc import Callable from importlib.resources import files from gpu_rent.config import Config from gpu_rent.errors import CloudError from gpu_rent.ssh_ops import run_script_sudo Log = Callable[[str], None] def bootstrap_script() -> str: return files("gpu_rent.remote").joinpath("bootstrap.sh").read_text(encoding="utf-8") def run_bootstrap( cfg: Config, host: str, log: Log, *, update: bool = True, light: bool = False, ) -> None: skip_swarm = not bool(getattr(cfg, "enable_swarmui", True)) if skip_swarm: log("bootstrap llm-only (data disk, без SwarmUI)") elif light: log("bootstrap SwarmUI (light: без apt)") else: log("bootstrap SwarmUI на VM (идемпотентно, без Docker)") if not skip_swarm: if update: log("git update: SwarmUI on") else: log("git update: SwarmUI off (--no-update)") script = bootstrap_script() out = run_script_sudo( cfg, host, script, remote_path="/tmp/gpu-rent-bootstrap.sh", timeout=1800, env={ "SWARM_USER": cfg.ssh_user, "GPU_RENT_UPDATE_GIT": "1" if update else "0", "GPU_RENT_BOOTSTRAP_LIGHT": "1" if light else "0", "GPU_RENT_SKIP_SWARMUI": "1" if skip_swarm else "0", }, log=log, ) if "bootstrap ok" not in out: raise CloudError(f"bootstrap не подтвердил успех:\n{out[-800:]}") if skip_swarm: log("data disk готов — дальше LLM") else: log("диски и systemd unit готовы; дальше seed, потом start swarmui")