Files
gpu-rent/src/gpu_rent/hold.py
T
Leonid Pershin a563ae06c4 Bump version to 0.2.0 and enhance documentation
- Updated version number in pyproject.toml and __init__.py to 0.2.0.
- Revised README.md to reflect the current state of the project, including usage instructions and setup steps.
- Improved CLI documentation in cli.md, adding details about new commands and their functionalities.
- Enhanced the quick start section in README.md for better clarity on initial setup.
- Updated local folder documentation to clarify file handling and commands.
- Added a new command for listing GPU flavors and improved error handling in the CLI.
- Implemented a watchdog feature in the tunnel to manage server states effectively.
2026-08-21 03:38:01 +03:00

73 lines
2.4 KiB
Python

"""gpu-rent hold: pause idle-killer via hold-until file on the data volume."""
from __future__ import annotations
from datetime import datetime, timezone
from collections.abc import Callable
from gpu_rent.config import Config
from gpu_rent.errors import GpuRentError
from gpu_rent.ssh_ops import put_text, remote_exists, run_ssh
Log = Callable[[str], None]
HOLD_PATH = "/mnt/swarm_data/.gpu-rent-hold-until"
def _parse_until(value: str) -> int:
text = value.strip()
if text.isdigit():
return int(text)
try:
dt = datetime.fromisoformat(text.replace("Z", "+00:00"))
except ValueError as exc:
raise GpuRentError(f"не разобрать --until {value!r}: нужен ISO или unix ts") from exc
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
return int(dt.timestamp())
def set_hold(
cfg: Config,
host: str,
*,
minutes: int | None = None,
until: str | None = None,
log: Log | None = None,
) -> int:
"""Write hold-until unix ts. Default = now + IDLE_MINUTES."""
if minutes is not None and until is not None:
raise GpuRentError("укажи либо --minutes, либо --until, не оба")
now = int(datetime.now(timezone.utc).timestamp())
if until:
ts = _parse_until(until)
else:
mins = minutes if minutes is not None else cfg.idle_minutes
if mins <= 0:
raise GpuRentError("--minutes должен быть > 0")
ts = now + mins * 60
if ts <= now:
raise GpuRentError("hold уже в прошлом — увеличь время или используй --clear")
put_text(cfg, host, HOLD_PATH, f"{ts}\n")
# readable by ubuntu + root
run_ssh(cfg, host, f"sudo -n chmod 644 {HOLD_PATH}", check=False)
iso = datetime.fromtimestamp(ts, tz=timezone.utc).isoformat()
if log:
log(f"hold до {iso} (unix {ts})")
return ts
def clear_hold(cfg: Config, host: str, log: Log | None = None) -> None:
run_ssh(cfg, host, f"sudo -n rm -f {HOLD_PATH}", check=False)
if log:
log("hold снят")
def read_hold(cfg: Config, host: str) -> int | None:
if not remote_exists(cfg, host, HOLD_PATH):
return None
raw = run_ssh(cfg, host, f"cat {HOLD_PATH}", check=False).strip()
try:
return int(float(raw.split()[0]))
except (ValueError, IndexError):
return None