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>
47 lines
6.3 KiB
Markdown
47 lines
6.3 KiB
Markdown
# План: 004 — колонки Upgrade ROS / Upgrade FW и меню действий «⋯» в UI
|
||
|
||
## Context
|
||
|
||
Дашборд показывает только текущие версии; доступные для обновления версии видны лишь мелким текстом под ROS/FW и для ROS почти никогда не заполнены. Причины:
|
||
- `latest-version` в `/rest/system/package/update` появляется только после `check-for-updates` — приложение его при опросе статуса не вызывает (`app/ros/operations.py::get_status`).
|
||
- `ros_version` из `system/resource` имеет вид `7.24.4 (stable)`, а `latest-version` — `7.24.4`; прямое сравнение в шаблоне всегда даёт «отличаются».
|
||
- В строке устройства пять кнопок в ряд (Статус, Бэкап, ROS, FW, Изменить) — таблица перегружена.
|
||
|
||
Цель: отдельные колонки **Upgrade ROS** и **Upgrade FW** с версией, до которой можно обновиться, и все действия строки — в выпадающем меню под иконкой «⋯».
|
||
|
||
## Изменения
|
||
|
||
**1. Статус: проверка обновлений** — `app/ros/operations.py::get_status`
|
||
- Перед чтением `system/package/update` выполнять `POST system/package/update/check-for-updates` (таймаут ~30 с). Ошибка проверки (нет интернета на устройстве, таймаут) не ломает опрос: остаётся то, что вернул `GET`, в статус пишется `ros_check_error`.
|
||
- В статус добавить `ros_installed` (`installed-version`, без суффикса «(stable)») — именно с ним сравнивается `ros_latest`.
|
||
- `get_status(c, check_updates=True)`: параметр нужен только чтобы тест мог отключить проверку.
|
||
- `set_channel` уже вызывает `refresh_status`, значит после смены канала доступная версия пересчитается сама. Инструмент `install_ros_update` (`check-for-updates` + `install`) не меняется.
|
||
|
||
**2. Шаблон `app/ui/templates/_devices.html`**
|
||
- Колонки: `…, ROS, Upgrade ROS, FW, Upgrade FW, …`. Убрать мелкие подсказки «доступна X» из колонок ROS/FW.
|
||
- Upgrade ROS: `ros_latest`, если он есть и `!= ros_installed` → выделенный бейдж с версией; равен → «✓ актуально»; нет данных → «—» (в `title` — `ros_check_error`).
|
||
- Upgrade FW: `fw_upgrade`, если `!= fw_current` → бейдж; равен → «✓ актуально»; нет RouterBOARD (CHR) → «—».
|
||
- Колонка «Действия» → компактная колонка с кнопкой `⋯`; меню на `<details class="menu"><summary aria-label="Действия">⋯</summary>…</details>` (без внешних библиотек). Пункты те же, что были кнопками: Обновить статус, Бэкап, Обновить ROS, Обновить FW, Изменить. Атрибуты `hx-post` / `hx-target` / `hx-confirm` переносятся как есть.
|
||
- `colspan` пустой строки 9 → 10.
|
||
|
||
**3. Стили и поведение** — `app/ui/static/style.css`, `app/ui/templates/base.html`
|
||
- CSS: `.menu` (relative), `.menu-list` (absolute, справа, тень, границы под тёмную и светлую темы, `z-index`), пункты-кнопки на всю ширину, опасные (ROS/FW) — акцентным цветом; `.badge` для Upgrade-версий (цвет `--warn`), «актуально» — `--ok`.
|
||
- ~6 строк JS в `base.html`: закрывать открытое меню по клику вне его, по `Esc` и после выбора пункта (нужно, потому что действия с `hx-target="#jobs"` таблицу не перерисовывают и меню иначе останется открытым).
|
||
|
||
**4. Артефакты проекта (CLAUDE.md)**
|
||
- `docs/changes/004-upgrade-columns-and-actions-menu/plan.md` (копия этого плана) и `summary.md` в конце.
|
||
- `README.md`: описание колонок и меню, строка в «Историю изменений».
|
||
- Тесты: без новых; в существующем `test_status_parsing` (`tests/test_app.py`) добавить обработку `POST …/check-for-updates` в моке и проверку `ros_installed`/`ros_latest`.
|
||
|
||
## Проверка
|
||
|
||
- `pytest` (4 теста).
|
||
- `docker compose up -d --build --force-recreate`, затем `POST /api/v1/devices/1/refresh`: в статусе появились `ros_installed`, `ros_latest`; время опроса с проверкой обновлений замерить — при заметном замедлении оставить `check_updates` только в кнопке «Обновить статус», а не при каждом опросе.
|
||
- Визуально в браузере (`http://localhost:8000`): колонки Upgrade ROS/FW, меню «⋯» открывается/закрывается (клик вне, Esc, выбор пункта), пункты работают (Статус, Бэкап, ROS/FW — с подтверждением, Изменить), светлая и тёмная тема, узкое окно.
|
||
- Обновления ROS/FW фактически **не запускаются** (перезагрузка устройства); проверяется только отображение и подтверждение.
|
||
|
||
## Риски
|
||
|
||
- `check-for-updates` ходит с устройства на серверы MikroTik: без интернета вернётся ошибка/таймаут → «—» с подсказкой, статус остаётся `online`.
|
||
- Проверка добавляет секунды к опросу каждого устройства; параллелизм ограничен `MAX_CONCURRENCY` (см. пункт проверки выше).
|