Update documentation and CLI behavior for GPU management
- Clarified the behavior of `Ctrl+C` and `Ctrl+D` in the README and other documentation, specifying that `Ctrl+C` only stops the tunnel while keeping the GPU active, and `Ctrl+D` stops the GPU while preserving disk data. - Enhanced the CLI documentation to reflect these changes, ensuring users understand the implications of these commands during GPU operations. - Improved the handling of data bindings and remounting logic in the codebase to prevent issues with empty model tabs in the UI. - Added tests to validate the new command behaviors and ensure proper documentation alignment.
This commit is contained in:
+110
-1
@@ -1,4 +1,9 @@
|
||||
from gpu_rent.tunnel import decide_watch, tunnel_forwards
|
||||
import sys
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from gpu_rent.tunnel import decide_watch, poll_ctrl_d, run_tunnel, tunnel_forwards
|
||||
|
||||
|
||||
def test_decide_ok_active():
|
||||
@@ -71,3 +76,107 @@ def test_resolve_llm_uses_cfg_only(monkeypatch):
|
||||
llm_runtime = "ollama"
|
||||
|
||||
assert resolve_llm_runtime(Cfg2()) == "ollama"
|
||||
|
||||
|
||||
def test_poll_ctrl_d_skips_when_not_tty(monkeypatch):
|
||||
monkeypatch.setattr("gpu_rent.tunnel.sys.stdin.isatty", lambda: False)
|
||||
t0 = time.time()
|
||||
assert poll_ctrl_d(0.02) is False
|
||||
assert time.time() - t0 < 0.5
|
||||
|
||||
|
||||
def test_poll_ctrl_d_windows_eot(monkeypatch):
|
||||
class Msvcrt:
|
||||
def kbhit(self) -> bool:
|
||||
return True
|
||||
|
||||
def getch(self) -> bytes:
|
||||
return b"\x04"
|
||||
|
||||
monkeypatch.setattr("gpu_rent.tunnel.sys.stdin.isatty", lambda: True)
|
||||
monkeypatch.setattr("gpu_rent.tunnel.os.name", "nt")
|
||||
monkeypatch.setitem(sys.modules, "msvcrt", Msvcrt())
|
||||
assert poll_ctrl_d(0.2) is True
|
||||
|
||||
|
||||
def test_poll_ctrl_d_windows_ctrl_c(monkeypatch):
|
||||
class Msvcrt:
|
||||
def kbhit(self) -> bool:
|
||||
return True
|
||||
|
||||
def getch(self) -> bytes:
|
||||
return b"\x03"
|
||||
|
||||
monkeypatch.setattr("gpu_rent.tunnel.sys.stdin.isatty", lambda: True)
|
||||
monkeypatch.setattr("gpu_rent.tunnel.os.name", "nt")
|
||||
monkeypatch.setitem(sys.modules, "msvcrt", Msvcrt())
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
poll_ctrl_d(0.2)
|
||||
|
||||
|
||||
class _Fwd:
|
||||
is_active = True
|
||||
|
||||
def stop(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class _State:
|
||||
notes: dict = {}
|
||||
phase = ""
|
||||
floating_ip = "1.2.3.4"
|
||||
|
||||
|
||||
class _Cfg:
|
||||
ssh_user = "u"
|
||||
ssh_private_key_path = "k"
|
||||
swarmui_local_port = 17801
|
||||
ollama_local_port = 17811
|
||||
llm_runtime = "none"
|
||||
enable_swarmui = True
|
||||
|
||||
|
||||
def _stub_tunnel(monkeypatch) -> None:
|
||||
st = _State()
|
||||
monkeypatch.setattr("gpu_rent.tunnel._ssh_tunnel_forwarder", lambda: object)
|
||||
monkeypatch.setattr("gpu_rent.tunnel._start_forwarder", lambda *a, **k: _Fwd())
|
||||
monkeypatch.setattr("gpu_rent.ready.verify_stack_local", lambda *a, **k: [])
|
||||
monkeypatch.setattr("gpu_rent.tunnel.load_state", lambda: st)
|
||||
monkeypatch.setattr("gpu_rent.tunnel.save_state", lambda s: None)
|
||||
monkeypatch.setattr("gpu_rent.access_card.print_access_card", lambda *a, **k: None)
|
||||
monkeypatch.setattr("gpu_rent.local_watchdog.watchdog_installed", lambda: False)
|
||||
|
||||
|
||||
def test_run_tunnel_ctrl_d_stops_gpu(monkeypatch):
|
||||
_stub_tunnel(monkeypatch)
|
||||
logs: list[str] = []
|
||||
stopped: list[bool] = []
|
||||
run_tunnel(
|
||||
_Cfg(),
|
||||
"1.2.3.4",
|
||||
log=logs.append,
|
||||
stop_gpu=lambda: stopped.append(True),
|
||||
session_end_poll=lambda _t: True,
|
||||
poll_seconds=999,
|
||||
)
|
||||
assert stopped == [True]
|
||||
assert any("GPU остановлен" in x for x in logs)
|
||||
|
||||
|
||||
def test_run_tunnel_ctrl_c_keeps_gpu(monkeypatch):
|
||||
_stub_tunnel(monkeypatch)
|
||||
logs: list[str] = []
|
||||
stopped: list[bool] = []
|
||||
|
||||
def boom() -> None:
|
||||
raise KeyboardInterrupt
|
||||
|
||||
run_tunnel(
|
||||
_Cfg(),
|
||||
"1.2.3.4",
|
||||
log=logs.append,
|
||||
wait=boom,
|
||||
stop_gpu=lambda: stopped.append(True),
|
||||
)
|
||||
assert stopped == []
|
||||
assert any("GPU жив" in x for x in logs)
|
||||
|
||||
Reference in New Issue
Block a user