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.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""User-facing prints: flavor list, cost warnings (no invented ₽)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
from gpu_rent.config import Config
|
||||
from gpu_rent.inventory import FlavorInfo, looks_like_gpu, rank_flavors, resolve_flavor
|
||||
|
||||
Log = Callable[[str], None]
|
||||
|
||||
|
||||
def list_ranked_flavors(flavors: list[Any], cfg: Config) -> list[FlavorInfo]:
|
||||
gpu = [f for f in flavors if looks_like_gpu(f)]
|
||||
return rank_flavors(gpu or flavors, cfg.flavor_preference)
|
||||
|
||||
|
||||
def format_flavor_lines(ranked: list[FlavorInfo], picked: FlavorInfo | None = None) -> list[str]:
|
||||
if not ranked:
|
||||
return ["flavors: пусто (проверь регион / FLAVOR_PREFERENCE)"]
|
||||
lines = ["flavors (по FLAVOR_PREFERENCE):"]
|
||||
for i, info in enumerate(ranked, 1):
|
||||
mark = " ← выберем" if picked and info.id == picked.id else ""
|
||||
ram = f"{info.ram_mb // 1024}GB" if info.ram_mb else "?"
|
||||
vcpu = str(info.vcpus) if info.vcpus is not None else "?"
|
||||
label = info.label or "—"
|
||||
lines.append(f" {i}. [{label}] {info.name} vCPU={vcpu} RAM={ram} id={info.id}{mark}")
|
||||
return lines
|
||||
|
||||
|
||||
def cost_and_risk_lines(cfg: Config, *, spot: bool, flavor_name: str) -> list[str]:
|
||||
"""Honest billing notes — OpenStack has no ₽ prices."""
|
||||
return [
|
||||
f"план: {'preemptible ' if spot else ''}{flavor_name}, data {cfg.data_volume_size_gb} GB",
|
||||
"₽: цены в OpenStack API нет — смотри панель Selectel (GPU ₽/час + диск ₽/мес).",
|
||||
"диск data тарифицируется 24/7, даже когда GPU выключен (stop).",
|
||||
f"idle-killer: {cfg.idle_grace_minutes} мин льготы после boot, потом "
|
||||
f"{cfg.idle_minutes} мин пустой очереди → delete compute. Отложить: gpu-rent hold",
|
||||
"preemptible: хостер может усыпить (~24 ч окно) → EXPIRED; tunnel сам unshelve, "
|
||||
"или gpu-rent up",
|
||||
"Ctrl+C на tunnel GPU не гасит — только gpu-rent stop или idle-killer",
|
||||
]
|
||||
|
||||
|
||||
def print_up_preview(
|
||||
cfg: Config,
|
||||
flavors: list[Any],
|
||||
*,
|
||||
picked: FlavorInfo,
|
||||
spot: bool,
|
||||
log: Log,
|
||||
) -> None:
|
||||
ranked = list_ranked_flavors(flavors, cfg)
|
||||
for line in format_flavor_lines(ranked, picked):
|
||||
log(line)
|
||||
log("")
|
||||
for line in cost_and_risk_lines(cfg, spot=spot, flavor_name=picked.name):
|
||||
log(f"! {line}")
|
||||
|
||||
|
||||
def resolve_and_preview(
|
||||
cfg: Config,
|
||||
flavors: list[Any],
|
||||
*,
|
||||
explicit: str | None,
|
||||
spot: bool,
|
||||
log: Log,
|
||||
) -> FlavorInfo:
|
||||
picked = resolve_flavor(
|
||||
flavors,
|
||||
cfg.flavor_preference,
|
||||
explicit=explicit,
|
||||
default_id=cfg.default_flavor_id or None,
|
||||
fallback=cfg.flavor_fallback,
|
||||
)
|
||||
print_up_preview(cfg, flavors, picked=picked, spot=spot, log=log)
|
||||
return picked
|
||||
Reference in New Issue
Block a user