Update configuration and documentation for LLM support and local watchdog
- Added `ollama-models.yaml` to .gitignore and implemented logic to copy it in gpu-rent.ps1 and gpu-rent.sh. - Enhanced env.example to include new variables for LLM runtime options and local watchdog configuration. - Updated CLI commands to support LLM options during setup and execution, including new flags for Ollama and llama.cpp. - Improved documentation in cli.md and README.md to reflect changes in LLM integration and local watchdog functionality. - Adjusted architecture and decisions documentation to clarify the role of LLMs and local watchdog in the system.
This commit is contained in:
@@ -19,6 +19,7 @@ CLI-оркестратор: поднимает прерываемый GPU-сер
|
||||
| [autocomplete.md](autocomplete.md) | Word-list промптов, Settings.fds, проверка версии |
|
||||
| [local-folders.md](local-folders.md) | `Models/` / `Wildcards/` / `CustomWorkflows/` push, optional `Output/` pull |
|
||||
| [swarmui.md](swarmui.md) | Нативный install, порт 7801, API, MCP |
|
||||
| [llm.md](llm.md) | Opt-in Ollama / llama.cpp, `ollama-models.yaml`, порты 17811/17812 |
|
||||
| [cli.md](cli.md) | Команды, конфиг, локальный state |
|
||||
| [roadmap.md](roadmap.md) | Порядок реализации |
|
||||
| [open-questions.md](open-questions.md) | Ещё не закрыто |
|
||||
|
||||
+28
-26
@@ -34,23 +34,22 @@
|
||||
|
||||
| Модуль | Ответственность |
|
||||
| --- | --- |
|
||||
| `cli` | Typer: `up`, `tunnel`, `open`, `status`, `stop`, `destroy`, `logs`, `ssh`, `doctor`, `hold`, `seed-*`, `push-models`, `pull-output`, `resize-data`, `dry-run` |
|
||||
| `config` | `.env`, валидация, пути к ключам |
|
||||
| `cli` | Typer: `up`, `setup`, `tunnel`, `open`, `status`, `stop`, `destroy`, `logs`, `ssh`, `doctor`, `hold`, `seed-*`, `push` / `pull-output`, `resize-data`, `watchdog`, `dry-run` |
|
||||
| `config` / `varsfile` | `.env` + `gpu-rent.vars`, пути |
|
||||
| `state` | JSON сессии: ids, фаза, timestamps |
|
||||
| `os_client` | `openstacksdk`, refresh IAM-токена |
|
||||
| `inventory` | Flavors/images в сегменте, квоты, **фоллбек flavor** |
|
||||
| `bootstrap` | Идемпотентный first-boot; после успеха — snapshot boot volume |
|
||||
| `os_client` / `cloud` / `pools` | openstacksdk, ресурсы, скан пулов |
|
||||
| `inventory` | Flavors/images, квоты, фоллбек flavor |
|
||||
| `session` | `cmd_up` / `cmd_stop` / adopt |
|
||||
| `bootstrap` + `remote/bootstrap.sh` | Идемпотентный first-boot; light без apt |
|
||||
| `provision` | extensions, autocomplete, civitai seed, push, idle-killer arm, start SwarmUI |
|
||||
| `doctor` | Preflight без mutating compute |
|
||||
| `civitai_seed` | Манифест + Civitai API на `.red` |
|
||||
| `models_push` | SFTP `./Models`, `./Wildcards`, `./CustomWorkflows` |
|
||||
| `output_pull` | Опциональный SFTP с VM `Output/` |
|
||||
| `git_seed` | Clone `extensions.yaml` |
|
||||
| `autocomplete_seed` | Word-list + Settings.fds |
|
||||
| `sync_files` | SFTP `Models` / Wildcards / workflows / Output |
|
||||
| `notify` | Toast/звук при backend Idle |
|
||||
| `tunnel` | paramiko / sshtunnel, порт **17801** |
|
||||
| `watchdog` | EXPIRED → unshelve, пока туннель жив |
|
||||
| `idle_killer` | systemd на VM + hold-файл + «качалка занята» |
|
||||
| `reconcile` | Сироты по state и тегу `gpu-rent` |
|
||||
| `tunnel` | sshtunnel + Nova EXPIRED watchdog |
|
||||
| `local_watchdog` | Опциональный локальный тик → stop при unclean exit |
|
||||
| `llm_runtime` / `setup_wizard` | Opt-in Ollama/llama.cpp + `ollama-models.yaml` |
|
||||
| `idle_killer` / `hold` | systemd на VM + hold-файл |
|
||||
| `ready` / `snapshot` | Idle backend + boot snapshot |
|
||||
|
||||
Каталог сервисов — из Keystone, не из выдуманного `api.selectel.ru/v3/`.
|
||||
|
||||
@@ -82,29 +81,32 @@
|
||||
|
||||
## Стейт-машина
|
||||
|
||||
Фазы в `state.json` (код пишет только эти):
|
||||
|
||||
```
|
||||
idle
|
||||
│ gpu-rent up
|
||||
▼
|
||||
provisioning → bootstrapping → seeding_extensions → seeding_autocomplete → seeding_models → waiting_ui
|
||||
provisioning ← create volumes / server
|
||||
│
|
||||
▼
|
||||
ready_cloud ← compute жив, idle-killer вооружён
|
||||
bootstrapping ← SSH + bootstrap + seed (пока не ready)
|
||||
│
|
||||
│ gpu-rent tunnel (опционально, пока ноут онлайн)
|
||||
▼
|
||||
ready_tunneled ← localhost:17801
|
||||
ready_cloud ← compute жив, idle-killer вооружён
|
||||
│
|
||||
│ хостер: EXPIRED
|
||||
│ gpu-rent tunnel (или up с туннелем)
|
||||
▼
|
||||
restoring (unshelve) → ready_cloud / ready_tunneled
|
||||
ready_tunneled ← localhost:17801
|
||||
│
|
||||
│ stop | idle-killer | destroy
|
||||
│ stop | idle-killer | local-watchdog | destroy
|
||||
▼
|
||||
stopping → idle
|
||||
idle
|
||||
```
|
||||
|
||||
`ready_cloud` ≠ Nova `ACTIVE`. ACTIVE бывает раньше SSH и UI.
|
||||
Подшаги seed (extensions / autocomplete / models) идут внутри `bootstrapping`, отдельными фазами в state не пишутся. `ready_cloud` ≠ Nova `ACTIVE` (ACTIVE бывает раньше SSH и UI).
|
||||
|
||||
На EXPIRED туннель сам делает unshelve → снова `bootstrapping`/`ready_*`.
|
||||
|
||||
## Idle-killer (на VM)
|
||||
|
||||
@@ -118,7 +120,7 @@ Killer молчит:
|
||||
- пока существует hold: файл `/mnt/swarm_data/.gpu-rent-hold-until` с unix ts (пишет `gpu-rent hold`);
|
||||
- пока SwarmUI качает модель в UI (Model Downloader / активный download — точный JSON на spike). Нет сигнала — пользователь жмёт `hold`.
|
||||
|
||||
`gpu-rent hold` без аргументов = +`IDLE_MINUTES` от сейчас. `--minutes 90` — абсолютное продление. `--until` ISO опционально. `hold --clear` снимает.
|
||||
`gpu-rent hold` без аргументов = +`IDLE_MINUTES` от сейчас. `--minutes 90` — hold до now+90 мин (заменяет предыдущий, не складывает). `--until` ISO опционально. `hold --clear` снимает.
|
||||
|
||||
Потом счётчик 30 минут пустой очереди.
|
||||
|
||||
@@ -167,7 +169,7 @@ Reconcile: сервер с тегом `gpu-rent` есть, локального
|
||||
|
||||
| Слой | Выбор |
|
||||
| --- | --- |
|
||||
| Python 3.11+ | openstacksdk, paramiko, Typer, Rich, questionary, dotenv |
|
||||
| Python 3.11+ | openstacksdk, paramiko, sshtunnel, Typer, Rich, dotenv, httpx, pyyaml |
|
||||
| SSH | paramiko + sshtunnel (Windows без системного `ssh -L`) |
|
||||
| Конфиг | `<repo>/.env` + runtime в `<repo>/.gpu-rent/` |
|
||||
| Конфиг | `<repo>/.env` + `gpu-rent.vars` + runtime в `<repo>/.gpu-rent/` |
|
||||
| Лицензия | MIT |
|
||||
|
||||
+20
-2
@@ -8,7 +8,9 @@
|
||||
| --- | --- |
|
||||
| `gpu-rent flavors` | Скан `SCAN_POOLS` (ru-6 multizone…) × `FLAVOR_PREFERENCE`, затем список в текущем `OS_REGION_NAME` |
|
||||
| `gpu-rent doctor` | Preflight **без** create: Keystone, квота GPU, flavor в AZ, диски, Civitai token+`.red`, манифесты, SSH-ключ. Код выхода ≠ 0, если сессию нельзя начать |
|
||||
| `gpu-rent up` / `up --yes` | Preflight → create/unshelve → bootstrap → git update SwarmUI/extensions → **туннель** `localhost:17801`; Ctrl+C закрывает туннель |
|
||||
| `gpu-rent setup` | Wizard: `.env`/манифесты, `LLM_RUNTIME`, пресет ollama-models, опционально local-watchdog |
|
||||
| `gpu-rent up` / `up --yes` | Preflight → create/unshelve → bootstrap → git update → optional LLM → **туннель** `localhost:17801`; Ctrl+C закрывает туннель |
|
||||
| `gpu-rent up --ollama` / `--llamacpp` / `--llm …` | Поднять LLM рядом со SwarmUI (см. [llm.md](llm.md)) |
|
||||
| `gpu-rent up --no-update` | Без `git pull` SwarmUI и extensions (только недостающие clone) |
|
||||
| `gpu-rent up --no-tunnel` | Только облако + bootstrap, без локального проброса |
|
||||
| `gpu-rent up --no-spot` | Обычный (не preemptible) сервер |
|
||||
@@ -32,13 +34,29 @@
|
||||
| `gpu-rent pull-output` | Забрать новые файлы с VM `Output/` в `./Output` (сервер не чистим) |
|
||||
| `gpu-rent seed-extensions` | Доклонировать/обновить git-репы; если VM жива — `systemctl restart swarmui` |
|
||||
| `gpu-rent resize-data --gb 400` | Увеличить data volume вверх (Selectel online resize). Вниз нельзя |
|
||||
| `gpu-rent watchdog install` | Локальный тик (Task Scheduler / systemd user / launchd): аварийное закрытие туннеля → `stop` после grace |
|
||||
| `gpu-rent watchdog uninstall` | Снять локальный сервис |
|
||||
| `gpu-rent watchdog status` | Установлен ли сервис + local lease |
|
||||
| `gpu-rent watchdog tick` | Один тик (для планировщика; `--dry-run` без delete) |
|
||||
| `gpu-rent dry-run` | План без mutating-вызовов |
|
||||
|
||||
Второй `up` при живой VM: не создавать второй GPU; сделать autocomplete-check и **push** локальных папок; если `PULL_OUTPUT` — подтянуть Output; напомнить про `tunnel` / `stop`. `--adopt` если нашли тег без state.
|
||||
|
||||
Нет команды `generate`. Нет зеркала каталога локального SwarmUI — только папки приложения, см. [local-folders.md](local-folders.md).
|
||||
|
||||
Сейчас в коде: после seed/`start swarmui` — idle-killer, Idle backend, boot snapshot, toast/MCP-сниппет, `resize-data`. `tunnel` с watchdog: EXPIRED → unshelve + reconnect FIP/SSH. UX-полировка flavors/цен ещё впереди.
|
||||
Сейчас в коде: после seed/`start swarmui` — idle-killer, Idle backend, boot snapshot, toast/MCP-сниппет, `resize-data`. `tunnel` с Nova-watchdog: EXPIRED → unshelve + reconnect. Опционально `watchdog install` — локальный safety net. UX-полировка flavors/цен ещё впереди.
|
||||
|
||||
## Local watchdog
|
||||
|
||||
Опционально. **Idle-killer на VM** остаётся основным: ноут можно закрыть, GPU живёт до простоя. Local watchdog — если хочешь гасить GPU при «убили окно / ребут» без `stop`.
|
||||
|
||||
1. `gpu-rent watchdog install` (раз на машине, в корне репо).
|
||||
2. Пока крутится `up`/`tunnel`, пишется heartbeat в `.gpu-rent/local-lease.json`.
|
||||
3. **Ctrl+C** → detach, GPU **не** трогаем (как раньше).
|
||||
4. Процесс умер / ребут → через `LOCAL_WATCHDOG_GRACE_MINUTES` (дефолт 10) тик вызывает `stop` (диски остаются).
|
||||
5. `gpu-rent stop` чистит lease сам.
|
||||
|
||||
Без `install` поведение прежнее. Без открытого туннеля (`up --no-tunnel`) lease не вооружается — работает только VM idle-killer.
|
||||
|
||||
## `doctor`
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ GPU в облаке дорогой. Веса для генерации карт
|
||||
1. Арендовать **прерываемый** облачный сервер Selectel с GPU (~70% дешевле обычного, без SLA).
|
||||
2. Хранить ОС, бинарники SwarmUI, модели, ComfyUI и результаты на **сетевых дисках**. Они переживают удаление и остановку VM.
|
||||
3. Локальный CLI создаёт (или восстанавливает) сервер и отдельно, когда нужно, пробрасывает SwarmUI на `localhost:17801`.
|
||||
4. GPU гасится командой `stop` **или** idle-killer на самой VM (пустая очередь). Диски остаются. Ноут можно закрыть — compute от этого не умирает.
|
||||
4. GPU гасится командой `stop`, idle-killer на VM, или (опционально) local-watchdog при unclean exit. Диски остаются. Без watchdog ноут можно закрыть — compute не умирает.
|
||||
|
||||
Пользователь открывает браузер на `http://127.0.0.1:17801`, переключает Cursor MCP на этот URL или бьёт в HTTP API SwarmUI. Локальный SwarmUI на `7801` не трогаем.
|
||||
|
||||
|
||||
+3
-2
@@ -5,7 +5,7 @@
|
||||
| Тема | Решение |
|
||||
| --- | --- |
|
||||
| Аудитория | Личный инструмент, репозиторий можно показать другим: MIT, без аккаунтных id и без имён локальных чекпоинтов |
|
||||
| Сессия | GPU живёт до `stop` **или** простоя (idle-killer **на VM**). Ноут можно закрыть — compute не обязан умереть |
|
||||
| Сессия | GPU живёт до `stop` **или** простоя (idle-killer **на VM**). Ноут можно закрыть — compute не обязан умереть. Опционально: `gpu-rent watchdog install` — локальный тик на Windows/macOS/Linux; если туннель умер без Ctrl+C/`stop`, после `LOCAL_WATCHDOG_GRACE_MINUTES` (дефолт 10) → `stop` |
|
||||
| Модели | Пустой `./Models` → не грузим ничего. Появились веса + метадата → на `up` выгрузить эту пару. Civitai-seed отдельно. С сервера не удаляем |
|
||||
| Civitai хост | Дефолт API `civitai.red` (полный каталог). `.com` — SFW-витрина, NSFW с неё часто 404. Ссылки `.com`/`.red`/`.green` в манифесте принимаем. 404 → один retry на второй хост. Один токен на оба домена |
|
||||
| Пул GPU | Перед `up`/`flavors` сканируем `SCAN_POOLS` (дефолт `ru-6,ru-7`). `ru-6` — мультизональный: ходим на `https://ru-6.cloud.api.selcloud.ru/compute/` тем же токеном (SDK-каталог часто знает только RC-пул). Собираем типы GPU из extra_specs и совпадения с `FLAVOR_PREFERENCE`. Автоматом `.env` не пишем — печатаем рекомендацию `OS_REGION_NAME` / `GPU_RENT_AZ` |
|
||||
@@ -21,6 +21,7 @@
|
||||
| Льгота после boot | Killer молчит во время clone/seed/push, hold, качалки в UI SwarmUI, пока backend не Idle, и 45 мин после ACTIVE/unshelve |
|
||||
| `up` / `tunnel` | `up` по умолчанию после ready открывает туннель `:17801`, печатает URL и ждёт. `--no-tunnel` — только облако. Ctrl+C на туннеле GPU не гасит (`stop` отдельно). Команда `tunnel` остаётся для повторного входа |
|
||||
| Git update | На каждом `up` по умолчанию: `git pull` SwarmUI + репы из `extensions.yaml` + уже установленные на data (`Extensions`/`DLNodes`). `--no-update` или `UPDATE_GIT=false` — не тянуть |
|
||||
| LLM (opt-in) | `none` по умолчанию. `ollama` / `llamacpp` — флаг `--ollama`/`--llamacpp`/`--llm`, `LLM_RUNTIME` в vars, или вопрос в interactive `up`/`setup`. Ollama-модели из `ollama-models.yaml`. Порты: Ollama 17811, llama.cpp 17812. Назначение: помощь с промптами, не замена SwarmUI |
|
||||
| Data-диск | Старт **100 GB**, рост через resize вверх (вниз Selectel не умеет) |
|
||||
| SSH | CLI генерирует `<repo>/.gpu-rent/id_ed25519` без passphrase и сам регистрирует keypair |
|
||||
| Локальные файлы | Всё в корне репозитория: `.env`, `models.yaml`, `extensions.yaml`; runtime (`state.json`, lock, SSH) в `<repo>/.gpu-rent/`. Не `%USERPROFILE%\.gpu-rent` |
|
||||
@@ -41,6 +42,6 @@
|
||||
|
||||
1. **Туннель ≠ жизнь GPU.** `stop` и idle-killer не зависят от того, открыт ли SSH с ноутбука.
|
||||
2. **Локальный SwarmUI на 7801 не трогаем.** Туннель по умолчанию на **17801** (на VM по-прежнему 7801 на loopback).
|
||||
3. **`Ctrl+C` на туннеле не удаляет VM.** Иначе «закрыл ноут» невозможно. Чтобы убить GPU — `gpu-rent stop` или простой.
|
||||
3. **`Ctrl+C` на туннеле не удаляет VM.** Иначе «закрыл ноут» невозможно. Чтобы убить GPU — `gpu-rent stop` или простой. При установленном **local-watchdog** Ctrl+C по-прежнему detach; убийство процесса/ребут без detach → stop после grace.
|
||||
4. Idle-killer на VM **не может** быть `shutdown -h`: у Selectel остановленная изнутри VM часто продолжает тарифицировать ресурсы. Нужен вызов OpenStack: удалить **этот** compute, диски оставить.
|
||||
5. Для этого на VM — OpenStack **application credential** с правом удалить/shelve сервер в проекте (не пароль владельца аккаунта). Компрометация SwarmUI в худшем случае сносит GPU-сессию, а не создаёт новые дорогие машины, если роль без `compute:create`.
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# LLM рядом со SwarmUI (opt-in)
|
||||
|
||||
По умолчанию поднимается только SwarmUI. Ollama или llama.cpp — по флагу, `LLM_RUNTIME` в `gpu-rent.vars` / `.env`, или через wizard.
|
||||
|
||||
## Включение
|
||||
|
||||
```text
|
||||
gpu-rent setup # спросит none/ollama/llamacpp + пресет моделей
|
||||
gpu-rent up --ollama # разово
|
||||
gpu-rent up --llm llamacpp
|
||||
# или в gpu-rent.vars:
|
||||
LLM_RUNTIME=ollama
|
||||
```
|
||||
|
||||
Без параметров `gpu-rent` / `gpu-rent up` (без `--yes`) спросит про LLM, если в vars ещё `none`.
|
||||
|
||||
## Порты (только loopback + туннель)
|
||||
|
||||
| Сервис | VM | localhost |
|
||||
| --- | --- | --- |
|
||||
| SwarmUI | 7801 | 17801 |
|
||||
| Ollama | 11434 | 17811 |
|
||||
| llama.cpp | 8080 | 17812 |
|
||||
|
||||
```text
|
||||
gpu-rent tunnel
|
||||
gpu-rent open --llm # http://127.0.0.1:17811 (Ollama)
|
||||
# клиент:
|
||||
set OLLAMA_HOST=http://127.0.0.1:17811
|
||||
```
|
||||
|
||||
## Ollama models
|
||||
|
||||
Как Civitai `models.yaml`:
|
||||
|
||||
- `ollama-models.example.yaml` — в git
|
||||
- `ollama-models.yaml` — локальный (gitignore)
|
||||
|
||||
На `up` при `LLM_RUNTIME=ollama` CLI делает `ollama pull` по списку. Уже скачанные не трогает; лишние на диске не удаляет.
|
||||
|
||||
### Пресеты setup
|
||||
|
||||
| preset | tag | зачем |
|
||||
| --- | --- | --- |
|
||||
| **recommended** | `huihui_ai/qwen2.5-abliterate:7b` | RU/EN, ~5GB, мало отказов — помощь с промптами |
|
||||
| light | `qwen2.5:3b` | быстрее, слабее |
|
||||
| stock | `qwen2.5:7b` | официальный, больше цензуры |
|
||||
| alt | `richardyoung/qwen2.5-7b-instruct-abliterated` | другой abliterate |
|
||||
| empty | `[]` | только runtime |
|
||||
|
||||
Community abliterate-модели без гарантий безопасности — для личного prompt-help / NSFW-тегов рядом со SwarmUI.
|
||||
|
||||
## llama.cpp
|
||||
|
||||
Ставит `llama-server` и systemd. GGUF клади вручную в `/mnt/swarm_data/llamacpp/models` на data-диске (или через SSH), затем `systemctl restart gpu-rent-llamacpp`.
|
||||
|
||||
## Idle-killer
|
||||
|
||||
Busy также если идёт `ollama pull`, в Ollama есть loaded model, или llama.cpp занимает слоты.
|
||||
@@ -7,7 +7,7 @@
|
||||
- Качалка модели в UI: отдельного poll-API нет (`DoModelDownloadWS` только WS) → v1 считает busy через `waiting_gens` / `live_gens` / `loading_models` / backend≠idle; иначе пользователь жмёт `hold`.
|
||||
- Реальная цена 100 GB сетевого диска в выбранном сегменте и цена 1×4090 preemptible ₽/час (в OpenStack API нет).
|
||||
- Имя GPU-образа (без Docker) и flavor id в твоём пуле (в git не класть); какие из списка фоллбека реально есть.
|
||||
- Хватает ли application credential с правами сервисного `member`, или Selectel отдаёт более узкую роль «только delete».
|
||||
- Хватает ли application credential с access_rules (delete/GET server) на Selectel — при отказе CLI падает назад на unrestricted cred и пишет в лог.
|
||||
- Snapshot attached boot volume после Idle: время и можно ли сразу create from snapshot.
|
||||
|
||||
Если spike покажет, что 45 минут льготы мало на первую установку ComfyUI — поднять `IDLE_GRACE_MINUTES`, не отключать killer.
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
# Project Review — 2026-08-21 (1)
|
||||
|
||||
## Prior Reviews Summary
|
||||
|
||||
> Based on the last 3 review files analysed in Phase 0.
|
||||
|
||||
### Still Open (carried forward)
|
||||
None.
|
||||
|
||||
### Resolved Since Last Review
|
||||
None.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Code Quality
|
||||
|
||||
### SOLID
|
||||
- `session.cmd_up` / `_bind_access` orchestrate cloud, SSH, bootstrap, provision, snapshot, notify — god-flow (`src/gpu_rent/session.py`).
|
||||
- Docs name separate modules (`civitai_seed`, `models_push`, `git_seed`, `watchdog`, `reconcile`) that do not exist as packages; logic is folded into `provision.py`, `sync_files.py`, `tunnel.py`, `cli.status`.
|
||||
- `Config` dataclass is a wide bag of unrelated settings (auth, paths, idle, autocomplete, civitai).
|
||||
|
||||
### Performance
|
||||
- `push_tree` / `pull_tree`: per-file `remote_sha256` + `put_file` each open a new SSH (`sync_files.py`, `ssh_ops.py`).
|
||||
- Every `up` re-runs full `bootstrap.sh` (apt-get) via `_bind_access` even when already bootstrapped.
|
||||
- `scan_pools` on every `up`: extra Keystone authorize + per-flavor HTTP extra_specs (ThreadPool 16).
|
||||
- Tunnel watchdog: `connect()` / Keystone authorize every ~30s.
|
||||
|
||||
### Correctness & Bugs
|
||||
- `wait_ssh` aborts after 3 `AuthenticationException`s (~15s) while cloud-init may still be injecting keys (`ssh_ops.py` ~114–120).
|
||||
- `cmd_stop` leaves `bootstrapped=True` (`session.py` ~397–400) → next ACTIVE path mis-labeled / wrong branch when FIP cleared.
|
||||
- `phase` set to `ready_cloud` before bootstrap finishes (`session.py` ~344–346).
|
||||
- Application credential created without role/access_rules restriction (`idle_killer.py` ~52–57) vs architecture “delete/shelve only”.
|
||||
- `GIT_TOKEN` embedded in git remote URL and never stripped (`clone_ext.py` `with_token` / clone).
|
||||
- SG rules accumulate old CIDRs; never prune (`cloud.py` `ensure_security_group`).
|
||||
- Session tests out of sync: no `bootstrapped`+FIP setup for “second GPU”; `run_bootstrap` mock missing `update=` (`tests/test_session.py`).
|
||||
|
||||
### Code Quality
|
||||
- State machine phases in docs (`bootstrapping`, `seeding_*`, `waiting_ui`) never written by code (only `idle` / `provisioning` / `ready_*`).
|
||||
- `os_client.connect` reports `app_version="0.1.0"` while package is `0.2.0`.
|
||||
- Duplicated SwarmUI busy/Idle polling logic in `ready.py` and `remote/idle_killer.py`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Logical Consistency
|
||||
|
||||
### Domain & Application Layer
|
||||
- Architecture table invents module names; actual layout is flatter (`cli` → `session`/`doctor`/`tunnel` → `cloud`/`provision`/`ssh_ops`).
|
||||
|
||||
### Data Flow
|
||||
- Config sources: `.env` (dotenv override=False) then `gpu-rent.vars` (override empty only) — OK.
|
||||
- Volume IDs: `state` preferred over `BOOT_VOLUME_ID` / `DATA_VOLUME_ID` env — OK; AZ not re-validated on reuse.
|
||||
|
||||
### State Management
|
||||
- `bootstrapped` not cleared on `stop`.
|
||||
- `bootstrapped` True only at end of `_bind_access`; failure mid-bind leaves `ready_cloud` + `bootstrapped=False`.
|
||||
- Marker files on VM (`/opt/swarmui/.gpu-rent-bootstrapped`) independent of local `state.bootstrapped`.
|
||||
|
||||
### Consistency
|
||||
- Error handling: mostly `GpuRentError` / `CloudError`; some soft-log (`wait_backend_idle`, snapshot, idle-killer arm).
|
||||
- Civitai bad token is **blocking** in doctor → blocks `up` even if user only needs default SwarmUI models.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: UI/UX (CLI)
|
||||
|
||||
### Usability
|
||||
- `up` always prints full doctor table (noisy).
|
||||
- Invalid/expired `CIVITAI_API_TOKEN` blocks entire session start.
|
||||
- `destroy` has no `--no-pull` (always respects `PULL_OUTPUT` via `cmd_stop`).
|
||||
|
||||
### Visual & Consistency
|
||||
- N/A (CLI). Mixed RU/EN messages by design.
|
||||
|
||||
### Interaction & Feedback
|
||||
- Confirm on `up` without `--yes` is good; `--yes` skips.
|
||||
- Tunnel Ctrl+C messaging is clear.
|
||||
- `logs` only tails cloud-init + `is-active`, not `journalctl -u swarmui` as docs imply.
|
||||
|
||||
### Accessibility
|
||||
- N/A.
|
||||
|
||||
---
|
||||
|
||||
## Full exploration notes (sections 1–10)
|
||||
|
||||
See chat report for narrative. Tasks below are actionable.
|
||||
|
||||
---
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1. [Bug] Soften `wait_ssh` early auth abort (retry until timeout / distinguish “sshd up, keys not ready”) — `src/gpu_rent/ssh_ops.py` line 114
|
||||
- [x] 2. [Bug] Clear `bootstrapped=False` (and align phase) in `cmd_stop` — `src/gpu_rent/session.py` line 397
|
||||
- [x] 3. [Security] Restrict idle-killer application credential (access_rules / roles delete-only) — `src/gpu_rent/idle_killer.py` line 52
|
||||
- [x] 4. [Security] Strip `GIT_TOKEN` from git `origin` after clone/fetch — `src/gpu_rent/remote/clone_ext.py` line 30
|
||||
- [x] 5. [Security] Stop accumulating stale SSH SG CIDRs; replace or prune old /32 — `src/gpu_rent/cloud.py` line 154
|
||||
- [x] 6. [Security] Revisit default `GPU_RENT_SSH_CIDR=0.0.0.0/0` in `env.example` — `env.example` line 16
|
||||
- [x] 7. [Performance] Reuse one SSH/SFTP session in `push_tree` / `pull_tree` / hash checks — `src/gpu_rent/sync_files.py` line 15
|
||||
- [x] 8. [Performance] Skip full bootstrap (or apt) when VM already marked bootstrapped — `src/gpu_rent/session.py` line 87
|
||||
- [x] 9. [Logic] Do not set `phase=ready_cloud` before `_bind_access` succeeds — `src/gpu_rent/session.py` line 344
|
||||
- [x] 10. [Logic] Make doctor Civitai failure non-blocking when seed is optional — `src/gpu_rent/doctor.py` line 271
|
||||
- [x] 11. [CodeQuality] Fix `tests/test_session.py` mocks (`bootstrapped`+FIP; `run_bootstrap(..., update=)`) — `tests/test_session.py` line 40
|
||||
- [x] 12. [UX] `logs` should include `journalctl -u swarmui` as docs claim — `src/gpu_rent/cli.py` line 404
|
||||
- [x] 13. [Logic] Update `docs/architecture.md` module names, phases, questionary, hold `--minutes` wording — `docs/architecture.md` line 37
|
||||
|
||||
## Closure notes (2026-08-21)
|
||||
|
||||
- `wait_ssh`: auth streak give-up after 180s continuous AuthenticationException (not 3 attempts).
|
||||
- Idle-killer: access_rules for GET/DELETE server; fallback without rules if Keystone rejects.
|
||||
- Bootstrap light path: `GPU_RENT_BOOTSTRAP_LIGHT=1` skips apt when marker present.
|
||||
- Also fixed `os_client` `app_version` → package `__version__` (noted in Phase 1, not a numbered task).
|
||||
Reference in New Issue
Block a user