Add read-only Debug API support and update documentation
- Introduced a local read-only Debug API accessible at `http://127.0.0.1:17821` for diagnostics and agent interactions. - Updated CLI commands to include `gpu-rent debug` for launching the Debug API. - Enhanced documentation to reflect the new Debug API features and usage. - Modified configuration to include `DEBUG_LOCAL_PORT` for easier customization. - Added tests to ensure Debug API links are correctly generated in access card outputs.
This commit is contained in:
+69
-8
@@ -529,9 +529,12 @@ def up(
|
||||
"""Create/unshelve GPU; SwarmUI и/или LLM; по умолчанию туннель."""
|
||||
cfg = None
|
||||
up_ok = False
|
||||
debug_srv = None
|
||||
active_log = log
|
||||
try:
|
||||
from dataclasses import replace
|
||||
|
||||
from gpu_rent.debug_api import start_debug_server, stop_debug_server
|
||||
from gpu_rent.llm_runtime import (
|
||||
decide_runtime,
|
||||
ensure_ollama_manifest_from_example,
|
||||
@@ -543,13 +546,23 @@ def up(
|
||||
from gpu_rent.varsfile import upsert_vars
|
||||
|
||||
clock_reset()
|
||||
log("запускаю проверку…")
|
||||
# Sidecar before doctor so an agent can watch installer hang from second 0.
|
||||
early_cfg = load_config(require_auth=False)
|
||||
debug_srv = start_debug_server(early_cfg, log=log, print_urls=True)
|
||||
if debug_srv is not None:
|
||||
active_log = debug_srv.wrap_log(log)
|
||||
debug_srv.set_step("doctor")
|
||||
|
||||
active_log("запускаю проверку…")
|
||||
checks = run_doctor()
|
||||
log(f"проверка заняла {format_duration(clock_elapsed())}")
|
||||
active_log(f"проверка заняла {format_duration(clock_elapsed())}")
|
||||
code = _print_checks(checks, quiet=not verbose)
|
||||
if code != 0:
|
||||
raise typer.Exit(1)
|
||||
cfg = load_config(require_auth=True)
|
||||
if debug_srv is not None:
|
||||
debug_srv.hub.cfg = cfg
|
||||
debug_srv.set_step("up")
|
||||
|
||||
try:
|
||||
runtime = decide_runtime(
|
||||
@@ -618,7 +631,7 @@ def up(
|
||||
ollama_preset_menu(include_keep=False),
|
||||
default="recommended",
|
||||
ask=_ask,
|
||||
show=log,
|
||||
show=active_log,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise GpuRentError(str(exc)) from exc
|
||||
@@ -640,7 +653,7 @@ def up(
|
||||
ollama_preset_menu(include_keep=True),
|
||||
default="keep",
|
||||
ask=_ask2,
|
||||
show=log,
|
||||
show=active_log,
|
||||
)
|
||||
if key not in {"keep", "example", ""}:
|
||||
write_ollama_models_preset(cfg.ollama_models_manifest, key)
|
||||
@@ -654,6 +667,8 @@ def up(
|
||||
)
|
||||
|
||||
cfg = replace(cfg, llm_runtime=runtime, enable_swarmui=enable_swarm)
|
||||
if debug_srv is not None:
|
||||
debug_srv.hub.cfg = cfg
|
||||
if enable_swarm:
|
||||
ok("стек: SwarmUI" + (f" + {runtime}" if runtime != "none" else ""))
|
||||
else:
|
||||
@@ -665,6 +680,8 @@ def up(
|
||||
def ask(msg: str, default: str = "") -> str:
|
||||
return typer.prompt(msg, default=default)
|
||||
|
||||
if debug_srv is not None:
|
||||
debug_srv.set_step("provisioning")
|
||||
state = cmd_up(
|
||||
cfg,
|
||||
no_spot=no_spot,
|
||||
@@ -674,13 +691,17 @@ def up(
|
||||
update=(False if no_update else True if force_update else None),
|
||||
confirm=confirm,
|
||||
ask=None if yes else ask,
|
||||
log=log,
|
||||
log=active_log,
|
||||
)
|
||||
up_ok = True
|
||||
if no_tunnel:
|
||||
from gpu_rent.access_card import print_access_card
|
||||
|
||||
print_access_card(cfg, tunneled=False, host=state.floating_ip)
|
||||
console.print(
|
||||
f"[bold]готово[/bold] (без туннеля). "
|
||||
f"Доступы: gpu-rent tunnel --open | stop: gpu-rent stop"
|
||||
f"Доступы: gpu-rent tunnel --open | stop: gpu-rent stop | "
|
||||
f"debug: gpu-rent debug"
|
||||
)
|
||||
if state.floating_ip:
|
||||
console.print(f"FIP {state.floating_ip}")
|
||||
@@ -691,11 +712,13 @@ def up(
|
||||
|
||||
if not state.floating_ip:
|
||||
raise GpuRentError("нет floating IP после up — туннель не открыть")
|
||||
if debug_srv is not None:
|
||||
debug_srv.set_step("tunnel")
|
||||
run_tunnel(
|
||||
cfg,
|
||||
state.floating_ip,
|
||||
open_browser=open_browser,
|
||||
log=log,
|
||||
log=active_log,
|
||||
)
|
||||
except KeyboardInterrupt as exc:
|
||||
if (
|
||||
@@ -716,6 +739,11 @@ def up(
|
||||
):
|
||||
_stop_after_failed_up(cfg, exc)
|
||||
_die(exc)
|
||||
finally:
|
||||
if debug_srv is not None:
|
||||
from gpu_rent.debug_api import stop_debug_server
|
||||
|
||||
stop_debug_server(debug_srv)
|
||||
|
||||
|
||||
@app.command()
|
||||
@@ -816,19 +844,52 @@ def tunnel(
|
||||
open_browser: bool = typer.Option(False, "--open", help="Открыть браузер на 17801"),
|
||||
) -> None:
|
||||
"""SSH localhost:17801 -> VM :7801. Ctrl+C / Ctrl+D — stop GPU (диски остаются)."""
|
||||
debug_srv = None
|
||||
try:
|
||||
from gpu_rent.debug_api import start_debug_server, stop_debug_server
|
||||
|
||||
cfg = load_config(require_auth=True)
|
||||
state = load_state()
|
||||
if not state.floating_ip:
|
||||
raise GpuRentError("нет floating IP — сначала gpu-rent up")
|
||||
debug_srv = start_debug_server(cfg, log=log, print_urls=True)
|
||||
active_log = debug_srv.wrap_log(log) if debug_srv is not None else log
|
||||
if debug_srv is not None:
|
||||
debug_srv.set_step("tunnel")
|
||||
run_tunnel(
|
||||
cfg,
|
||||
state.floating_ip,
|
||||
open_browser=open_browser,
|
||||
log=log,
|
||||
log=active_log,
|
||||
)
|
||||
except GpuRentError as exc:
|
||||
_die(exc)
|
||||
finally:
|
||||
if debug_srv is not None:
|
||||
from gpu_rent.debug_api import stop_debug_server
|
||||
|
||||
stop_debug_server(debug_srv)
|
||||
|
||||
|
||||
@app.command("debug")
|
||||
def debug_cmd(
|
||||
port: Optional[int] = typer.Option(
|
||||
None,
|
||||
"--port",
|
||||
"-p",
|
||||
help="Локальный порт (по умолчанию DEBUG_LOCAL_PORT / 17821)",
|
||||
),
|
||||
) -> None:
|
||||
"""Локальный read-only Debug API (для агента), пока VM уже есть / после --no-tunnel."""
|
||||
try:
|
||||
from gpu_rent.debug_api import run_debug_blocking
|
||||
|
||||
cfg = load_config(require_auth=False)
|
||||
run_debug_blocking(cfg, port=port, log=log)
|
||||
except RuntimeError as exc:
|
||||
_die(GpuRentError(str(exc)))
|
||||
except GpuRentError as exc:
|
||||
_die(exc)
|
||||
|
||||
|
||||
@app.command()
|
||||
|
||||
Reference in New Issue
Block a user