ros_control: централизованное управление парком MikroTik RouterOS

Control Server (FastAPI) с WEB UI (Jinja2 + HTMX) и JSON API для группового
администрирования устройств RouterOS 7 через REST.

- Устройства: список, статус (модель, канал, версии ROS/FW, uptime, доступные
  обновления), примечания, пароли шифруются (Fernet); фоновый опрос каждые 30 с
  и быстрое обнаружение недоступности (таймаут соединения 4 с).
- Группы устройств и фильтры (устройства, резервные копии).
- Резервные копии: .backup и .rsc (show-sensitive) создаются через REST,
  скачиваются сервером и загружаются в S3 (Yandex Object Storage).
- Обновление ROS/FW и выбор канала, групповые операции задачами.
- Интерфейс по утверждённому макету: светлая/тёмная темы, окна, шрифты IBM Plex
  локально. Docker Compose, SQLite в томе, минимальный набор тестов.
- Планы и итоги каждого изменения — в docs/changes/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ayurishchevandClaude Sonnet 5 committed 2026-09-19 13:13:29 +03:00
commit 4c1841b61b
85 files changed
+3579

No files matched your search

@@ -0,0 +1,76 @@
# План: ros_control — централизованное управление парком MikroTik RouterOS
## Context
Нужно приложение для группового администрирования множества устройств MikroTik RouterOS через API и WEB UI. Источник требований — `ros_control.svg` (draw.io): архитектура, список функций, ссылки на API.
Из схемы:
- **Control Server** связан двусторонне с **Local Metadata DB** (DB transactions), **S3 Bucket** (Yandex Object Storage: `ListObjectsV2`, `GetObject`, `PutObject`, `DeleteObject`) и **Admin Dashboard**.
- Dashboard ↔ Control Server: JSON payload, UI Forms (ввод), JSON payload render (вывод).
- Control Server ↔ **Endpoint API Server (on device)** = RouterOS REST API (`GET/PATCH/PUT/POST/DELETE`, JSON), N устройств.
Функции dashboard: список устройств и управление списком (добавить, изменить, удалить); статус (модель, канал обновлений, версия ROS, версия FW, uptime, время запроса бэкапа); бэкап по каждому устройству (бинарный `.backup` без шифрования + текстовый `.rsc`, загрузка в S3, удаление с устройства, скачивание из бакета, список бэкапов в бакете); выбор канала обновлений; обновление ROS до актуальной версии канала (перезагрузка после скачивания); обновление FW (перезагрузка сразу после обновления).
Принятые решения: Python FastAPI + Jinja2/HTMX, SQLite (SQLAlchemy), пароли устройств шифруются (Fernet), вход в UI по логину/паролю, API — Bearer-токен, Docker Compose для развёртывания + `venv` в корне проекта для разработки.
## Артефакты процесса (по CLAUDE.md проекта)
- `docs/changes/001-initial-implementation/plan.md` — копия этого плана (создаётся первым шагом реализации)
- `docs/changes/001-initial-implementation/summary.md` — итоги по выполненному (создаётся последним шагом)
- `README.md` — описание, запуск, конфигурация, ссылки на API; обновляется при каждом изменении
- Тесты — минимальный набор (см. Verification)
## Структура проекта
```
app/
main.py # FastAPI, роутинг, lifespan
config.py # настройки из env (pydantic-settings)
db.py, models.py # SQLAlchemy + SQLite: users, devices, backups, jobs
security.py # Fernet для паролей устройств, хэш пароля админа, API-токен
ros/client.py # httpx-клиент RouterOS REST (basic auth, verify_tls per device)
ros/operations.py # status, backup, update channel/install, firmware upgrade
s3.py # boto3: list/get(presigned)/put(presigned)/delete, endpoint Yandex
services/ # devices, backups, updates, jobs (фоновые задачи + batch)
api/v1.py # JSON API
ui/routes.py, templates/, static/ # Jinja2 + HTMX
tests/ # минимальный набор
Dockerfile, docker-compose.yml, requirements.txt, .env.example, README.md
docs/changes/001-initial-implementation/{plan,summary}.md
```
## Ключевые технические решения
1. **RouterOS REST** (`https://<host>/rest/...`, ROS ≥ 7.1, сервис `www-ssl`). Для самоподписанных сертификатов — флаг `verify_tls` на устройство. Ограничение: только ROS 7.
2. **Статус** — параллельный опрос (`asyncio.gather` + семафор): `/rest/system/resource` (модель, версия ROS, uptime), `/rest/system/routerboard` (current/upgrade firmware), `/rest/system/package/update` (channel, installed/latest version). Недоступное устройство отображается как offline, не ломает список.
3. **Бэкап**:
- `POST /rest/system/backup/save` (`dont-encrypt=yes`) и `POST /rest/export` (`.rsc`);
- REST не отдаёт содержимое крупных файлов, поэтому **устройство само загружает файлы в S3** через `/tool/fetch` (`http-method=put upload=yes src-path=…`) по **presigned PUT URL**, выданному Control Server. Ключи S3: `backups/<device>/<timestamp>.backup|.rsc`;
- после успешной загрузки — `DELETE /rest/file/<id>` на устройстве; время запроса пишется в БД;
- список — `ListObjectsV2` по префиксу, скачивание — presigned GET (редирект).
4. **Обновление ROS**: `POST /rest/system/package/update/set {channel}` → `check-for-updates` → `install` (устройство скачивает пакет и перезагружается само — соответствует требованию «перезагрузка после скачивания»).
5. **Обновление FW**: `POST /rest/system/routerboard/upgrade` → опрос до `current-firmware == upgrade-firmware` → `POST /rest/system/reboot`.
6. **Долгие операции** — таблица `jobs` + фоновые задачи; UI опрашивает статус через HTMX. Групповые операции: эндпоинты принимают список `device_ids`, выполняются параллельно с ограничением конкурентности.
7. **API v1**: `/api/v1/devices` (CRUD), `/devices/{id}/status`, `/devices/{id}/backups` (POST/GET), `/backups/download`, `/devices/{id}/update/channel` (PUT), `/devices/{id}/update/install`, `/devices/{id}/firmware/upgrade` (POST), `/jobs/{id}`. UI использует те же сервисы.
8. **Безопасность**: пароли устройств не возвращаются в API/UI; ключ шифрования и S3-ключи — только из env; UI — сессия после логина; API — Bearer-токен.
## Этапы реализации
1. Артефакты: `plan.md`, каркас проекта, `venv`, `requirements.txt`, `.env.example`.
2. Модели БД, security (Fernet, логин, токен), конфиг.
3. RouterOS-клиент и операции статуса; CRUD устройств; список со статусами (API + UI).
4. S3-модуль; бэкап (2 формата, загрузка с устройства, очистка), список и скачивание.
5. Каналы обновлений, обновление ROS, обновление FW; jobs и групповые операции.
6. Docker/compose, README, минимальные тесты, `summary.md`.
## Риски / проверить на реальном устройстве
- `/tool/fetch` с `http-method=put upload=yes` на целевой версии ROS (основной вариант). Запасной: устройство отправляет файл на эндпоинт Control Server.
- Синхронные REST-вызовы (`fetch`, `install`) могут упереться в таймаут — использовать `duration`/асинхронные задачи и опрос состояния.
- Сертификат `www-ssl` на устройствах и доступность 443 от Control Server; доступность S3 (`storage.yandexcloud.net`) с устройств.
## Verification
- **Автотесты (минимум, ~4)**: шифрование/расшифровка пароля; разбор статуса RouterOS (mock httpx); сценарий бэкапа с мокнутыми RouterOS и S3 (порядок: save → export → fetch → delete file → запись в БД); авторизация API (401 без токена).
- **Ручная проверка**: RouterOS CHR (ROS 7) в лаборатории + тестовый бакет Yandex Object Storage: добавить устройство → статус в списке → бэкап (оба файла в бакете, на устройстве удалены) → скачивание → смена канала → обновление ROS → обновление FW.
- `docker compose up` — приложение поднимается, UI на `:8000`, `/docs` показывает OpenAPI.