Повторный анализ кодовой базы (docs/reviews/2026-09-26-codebase-review-2.md) и доработки:
025 Ёмкость префикса — размер его подсети (а не сумма листьев); «Обзор» считает ёмкость
по корневым активным IPv4-префиксам и адреса внутри них.
026 Политика блокировки входа: 5 неудач на логин+IP, 20 на IP, 50 на логин со всех IP,
кроме известных IP (known_logins, миграция 0009) — владельца нельзя заблокировать анонимно.
027 Сериализация попыток входа по IP (advisory-lock после блокировки логина).
028 UI «Префиксы»: загрузка всех страниц (до 20 000), счётчики по total, предупреждение об усечении.
029 Advisory-lock по VRF для операций, меняющих дерево префиксов и раскладку адресов.
030 Исправление замечаний ревью 025-029: _lock_prefix (VRF блокируется до чтения префикса,
409 при одновременном переносе), константы политики входа перенесены в app/services.py.
Тесты: 14 passed (проверка ёмкости родителя приведена к семантике 025); сквозные сценарии
и гонки — docs/reviews/2026-09-26-changes-025-029-review.md, 2026-09-27-changes-030-review.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 lines
3.6 KiB
Markdown
31 lines
3.6 KiB
Markdown
# Ёмкость и загрузка частично разбитого префикса (изменение 025)
|
||
|
||
Находка № 1 из `docs/reviews/2026-09-26-codebase-review-2.md`, серьёзность — средняя. Выполняется первым.
|
||
|
||
## Context
|
||
`_capacities` (`app/api/v1/prefixes.py`) считает ёмкость родителя как сумму ёмкостей его листьев, а `used` (`_usage`) — по всем адресам поддерева,
|
||
включая адреса самого родителя вне дочерних префиксов. После автовыделения подсетей (изменение 010) частичное разбиение стало обычным сценарием.
|
||
Воспроизведено: `172.20.0.0/24` с 40 адресами → `40/254, 16 %`; после выделения одного `/30` → `40/2, 100 %`. Экран адресов того же префикса показывает ёмкость 254.
|
||
«Обзор» (`app/api/v1/overview.py`) искажён той же причиной: `assigned` — все IPv4-адреса, `capacity` — сумма только листьев.
|
||
|
||
## Решение
|
||
1. **Ёмкость префикса — размер его собственной подсети.** `capacity(str(prefix))` из `app/services.py` (IPv4 без адреса сети/broadcast для ≤ /30, ограничение `MAX_CAPACITY`).
|
||
`_capacities` удалить; в `_prefix_outs` — `cap = capacity(str(r.prefix))`. `used` (`_usage`, по поддереву CIDR того же VRF) не меняется: дублей нет благодаря изменению 011.
|
||
Так числа в списке префиксов совпадут с `summary.capacity` экрана адресов.
|
||
2. **«Обзор»:**
|
||
- «корни» — активные IPv4-префиксы, не содержащиеся ни в одном другом активном IPv4-префиксе того же VRF (по CIDR, не по `parent_id`);
|
||
- `capacity` = сумма `capacity()` корней;
|
||
- `assigned` / `reserved` = IPv4-адреса со статусом assigned/reserved, лежащие внутри какого-либо корня того же VRF (адреса в неактивных ветках не учитываются) — один SQL-запрос с `EXISTS`/`JOIN` по `address <<= root.prefix`;
|
||
- `utilization` — через `utilization()`;
|
||
- `top_prefixes` («Высокая загрузка») — как сейчас: листья IPv4 с `capacity > 1`, по убыванию загрузки (формула загрузки листа не меняется);
|
||
- `prefixes`, `vrfs`, `recent_changes` — без изменений.
|
||
3. Формат ответов API не меняется. UI не меняется.
|
||
4. `README.md`, раздел «Модель данных»: строку «Ёмкость листового префикса — размер подсети…; родителя — сумма вложенных листьев» заменить новым правилом; описать расчёт «Обзора».
|
||
|
||
## Файлы
|
||
`app/api/v1/prefixes.py`, `app/api/v1/overview.py`, `README.md`.
|
||
|
||
## Проверка
|
||
- Сценарий из Context: после выделения `/30` ёмкость родителя остаётся 254, загрузка — 16 %.
|
||
- «Обзор» на демо-данных: `capacity` равна сумме корней (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 и т.п. — только активные, IPv4), загрузка не больше 100 %.
|