- 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.
213 lines
13 KiB
Markdown
213 lines
13 KiB
Markdown
# CLI и конфигурация
|
||
|
||
Имя команды: `gpu-rent`. Windows и Linux. Лицензия MIT, в репозитории нет секретов и имён личных чекпоинтов.
|
||
|
||
## Команды
|
||
|
||
| Команда | Поведение |
|
||
| --- | --- |
|
||
| `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 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) сервер |
|
||
| `gpu-rent up --flavor … --yes` | Без вопросов. `--flavor` бьёт список фоллбека. `--yes` без `--flavor` берёт первый доступный из `FLAVOR_PREFERENCE` |
|
||
| `gpu-rent tunnel` | Повторный SSH-проброс, если `up --no-tunnel` или туннель уже закрыли. Ctrl+C = закрыть туннель, GPU **оставить** |
|
||
| `gpu-rent tunnel --open` | Туннель + сразу открыть браузер на 17801 |
|
||
| `gpu-rent open` | Открыть браузер на `http://127.0.0.1:17801`. Туннель уже должен слушать порт |
|
||
| `gpu-rent status` | State + Nova + диск used/free + ₽/час + сколько до 24 ч preempt + killer/hold. Туннель не обязателен |
|
||
| `gpu-rent hold` | Отложить idle-killer на `IDLE_MINUTES` от сейчас |
|
||
| `gpu-rent hold --minutes 90` | Hold до now+90 мин (заменяет предыдущий, не складывает) |
|
||
| `gpu-rent hold --until <ISO>` | Hold до абсолютного времени |
|
||
| `gpu-rent hold --clear` | Снять hold |
|
||
| `gpu-rent stop` | Optional pull Output → удалить compute и FIP, диски оставить. С любой машины с `.env` |
|
||
| `gpu-rent stop --no-pull` | Не тянуть Output, даже если `PULL_OUTPUT=true` |
|
||
| `gpu-rent destroy` | `stop` + диски, только `--i-understand-data-loss` |
|
||
| `gpu-rent logs` | journalctl swarmui / cloud-init по SSH |
|
||
| `gpu-rent ssh` | Оболочка на VM |
|
||
| `gpu-rent seed-models` | Докачать новые строки манифеста Civitai на уже существующий диск |
|
||
| `gpu-rent push` | Инкремент `Models/` + `Wildcards/` + `CustomWorkflows/` (пустые skip) |
|
||
| `gpu-rent push-models` | Только `./Models` |
|
||
| `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` с 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`
|
||
|
||
Не создаёт сервер, не тратит GPU. Нужен до первого `up` и когда «вчера работало».
|
||
|
||
Проверки по порядку, все печатаются (не падать на первой, собрать отчёт):
|
||
|
||
1. Читается `.env`, обязательные `OS_*`.
|
||
2. Keystone: токен выдаётся.
|
||
3. Квота GPU > 0; иначе текст «напишите в поддержку Selectel».
|
||
4. В сегменте есть хотя бы один flavor из `FLAVOR_PREFERENCE` (не `disabled`).
|
||
5. Volume type сегмента существует; data 100 GB влезает в квоту дисков.
|
||
6. SSH-ключ: есть `<repo>/.gpu-rent/id_ed25519` или CLI сможет его создать.
|
||
7. Если задан `CIVITAI_API_TOKEN` — HEAD/лёгкий запрос к `CIVITAI_API_HOST` (дефолт `.red`); манифест парсится.
|
||
8. `extensions.yaml` парсится, если файл есть.
|
||
9. Локальные папки: предупреждение, если `Models/` огромный относительно свободного места на будущем диске.
|
||
|
||
Exit 0 — можно `up`. Exit 1 — нельзя, причина в отчёте.
|
||
|
||
## `status`
|
||
|
||
Без туннеля. Если SSH есть — ещё диск и killer; если нет — только OpenStack.
|
||
|
||
| Поле | Откуда |
|
||
| --- | --- |
|
||
| Фаза state / Nova status | `state.json` + compute |
|
||
| Flavor, ₽/час | extra specs / оценка с spike; нет цены в API — «см. панель», не выдумывать |
|
||
| Preempt window | create/unshelve timestamp + 24 ч; «осталось Hh Mm» или «не preemptible» |
|
||
| Data disk used/free | SSH `df` на `/mnt/swarm_data` |
|
||
| Idle-killer | armed / grace до … / hold до … / busy (очередь или качалка) / слеп (нет кредов) |
|
||
| Туннель | слушает ли локальный 17801 |
|
||
| Snapshot boot | есть ли `gpu-rent-boot-ok` |
|
||
|
||
## `hold`
|
||
|
||
Пишет на VM `/mnt/swarm_data/.gpu-rent-hold-until` (unix ts). Killer не удаляет compute, пока `now < ts`. Нужен SSH и живой сервер.
|
||
|
||
Без VM — ошибка, не «запомню на потом». После `unshelve` hold-файл на диске сохраняется.
|
||
|
||
## Что печатать при `up`
|
||
|
||
1. Preflight (тот же набор, что `doctor`, можно вызвать его внутри).
|
||
2. Если квота 0 — стоп с текстом «напишите в поддержку Selectel», не traceback.
|
||
3. Выбранный flavor (или фоллбек) + оценка: GPU ₽/час, диск ₽/мес, preemptible 24 ч, idle-killer через N мин.
|
||
4. Фазы: provisioning → bootstrap → clone extensions → autocomplete → seed Civitai → push локальных папок → waiting UI → backend Idle.
|
||
5. Если `NOTIFY_READY` — Windows toast + звук (и строка в лог).
|
||
6. Готово:
|
||
|
||
```text
|
||
SwarmUI на VM: 127.0.0.1:7801 (только через туннель)
|
||
Локально: gpu-rent tunnel
|
||
Браузер: gpu-rent open → http://127.0.0.1:17801
|
||
API: http://127.0.0.1:17801/API/
|
||
MCP: http://127.0.0.1:17801/mcp
|
||
Hold killer: gpu-rent hold
|
||
Стоп GPU: gpu-rent stop
|
||
```
|
||
|
||
Сниппет MCP для Cursor — в stdout, `mcp.json` не редактировать.
|
||
|
||
## Конфигурация
|
||
|
||
| Файл | Назначение |
|
||
| --- | --- |
|
||
| `.env` | Секреты и OpenStack (`OS_*`, токены). Не в git |
|
||
| `gpu-rent.vars` | Параметры запуска / несекретные дефолты. Читают `gpu-rent.ps1` / `.sh` / `.bat` и CLI. Пример: `gpu-rent.vars.example` |
|
||
| `models.yaml` / `extensions.yaml` | Манифесты |
|
||
|
||
`.env` в корне репозитория (рядом с `env.example`).
|
||
|
||
В `gpu-rent.vars` (создаётся из example при первом запуске):
|
||
|
||
```env
|
||
# Двойной клик / запуск без аргументов:
|
||
GPU_RENT_DEFAULT_ARGS=up --yes
|
||
|
||
# Дописать ко всем вызовам:
|
||
# GPU_RENT_EXTRA_ARGS=--no-update
|
||
|
||
UPDATE_GIT=true
|
||
```
|
||
|
||
```env
|
||
OS_AUTH_URL=https://cloud.api.selcloud.ru/identity/v3
|
||
OS_USER_DOMAIN_NAME=
|
||
OS_USERNAME=
|
||
OS_PASSWORD=
|
||
OS_PROJECT_ID=
|
||
OS_REGION_NAME=ru-7
|
||
GPU_RENT_AZ=ru-7a
|
||
|
||
SSH_PRIVATE_KEY_PATH=
|
||
SSH_USER=ubuntu
|
||
|
||
BOOT_VOLUME_ID=
|
||
DATA_VOLUME_ID=
|
||
DATA_VOLUME_SIZE_GB=100
|
||
BOOT_SNAPSHOT_NAME=gpu-rent-boot-ok
|
||
|
||
CIVITAI_API_TOKEN=
|
||
CIVITAI_API_HOST=civitai.red
|
||
MODELS_MANIFEST=
|
||
LOCAL_MODELS_DIR=
|
||
LOCAL_WILDCARDS_DIR=
|
||
LOCAL_WORKFLOWS_DIR=
|
||
LOCAL_OUTPUT_DIR=
|
||
EXTENSIONS_MANIFEST=
|
||
GIT_TOKEN=
|
||
|
||
AUTOCOMPLETE_ENABLED=true
|
||
AUTOCOMPLETE_GITHUB_REPO=DominikDoom/a1111-sd-webui-tagcomplete
|
||
AUTOCOMPLETE_GITHUB_PATH=tags/danbooru.csv
|
||
AUTOCOMPLETE_GITHUB_REF=main
|
||
AUTOCOMPLETE_FILENAME=danbooru.csv
|
||
|
||
SWARMUI_LOCAL_PORT=17801
|
||
|
||
DEFAULT_FLAVOR_ID=
|
||
FLAVOR_PREFERENCE=4090-24,4090-48,a5000,a100-40
|
||
FLAVOR_FALLBACK=true
|
||
DEFAULT_SPOT=true
|
||
KEEP_FLOATING_IP=false
|
||
IDLE_MINUTES=30
|
||
IDLE_GRACE_MINUTES=45
|
||
PULL_OUTPUT=false
|
||
NOTIFY_READY=true
|
||
```
|
||
|
||
Flavor id в git не хардкодить. `FLAVOR_PREFERENCE` — ярлыки; реальные uuid резолвятся в сегменте. `FLAVOR_FALLBACK=false` — только `DEFAULT_FLAVOR_ID` / `--flavor`, без следующего в списке.
|
||
|
||
Application credential для idle-killer CLI создаёт при bootstrap и кладёт на VM; в `.env` ноутбука его можно не дублировать.
|
||
|
||
Пути локальных папок по умолчанию — каталоги в корне приложения: `Models/`, `Wildcards/`, `CustomWorkflows/`, `Output/`.
|
||
|
||
## State
|
||
|
||
`<repo>/.gpu-rent/state.json` — ids, фаза (`idle` / `ready_cloud` / `ready_tunneled` / …), flavor, timestamps create/unshelve (для окна 24 ч). Без паролей. Lockfile там же, чтобы два `up` не создали два сервера.
|
||
|
||
## Ожидание готовности
|
||
|
||
Потолок ~20–40 мин на первый bootstrap, ~5–10 мин на unshelve:
|
||
|
||
1. Nova `ACTIVE`
|
||
2. TCP 22
|
||
3. SSH: cloud-init или `systemctl is-active swarmui`
|
||
4. HTTP `http://127.0.0.1:7801` **на VM** (через SSH), не путать с локальным 7801
|
||
5. Для MCP/API / toast — дождаться Idle backend.
|
||
|
||
## Windows
|
||
|
||
Лаунчеры в корне: `gpu-rent.bat` (cmd / двойной клик), `.\gpu-rent.ps1` (PowerShell). На Unix — `./gpu-rent.sh`. Они создают `.venv` в репозитории и вызывают `python -m gpu_rent`. Ключ генерирует CLI: `<repo>/.gpu-rent/id_ed25519`.
|
||
|
||
`NOTIFY_READY`: toast через WinRT / `win10toast` (что заработает на 10/11 без админ-прав) + системный звук. Если toast недоступен — только звук и лог, не падать.
|