Add Floating IP scanning and a durable address registry with configurable history depth
Adds POST /api/v1/admin/ips/scan (plus an optional periodic ticker) to
discover free Floating IPs in the OpenStack project and feed them straight
into the check queue. More importantly, decouples check/event history from
ip_queue's lifecycle: a new ip_registry table (migration 0007) gives every
address ever submitted a durable identity, so deleting it from the queue no
longer destroys its history — it's still reachable via the new
GET /api/v1/admin/registry[/{ip}] endpoints and the dashboard's /registry
pages, with retention depth configurable in check cycles per address
(history_retention_cycles, 0 = unlimited).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
78b20fa5be
commit
582b44f314
47 files changed
+1781
-107
No files matched your search
+128
-22
@@ -28,6 +28,7 @@ JSON, базовый префикс прикладных методов — `/ap
|
||||
- [Методы для prober](#методы-для-prober)
|
||||
- [Служебные и административные методы](#служебные-и-административные-методы)
|
||||
- [Управление очередью и конфигурацией](#управление-очередью-и-конфигурацией)
|
||||
- [Реестр адресов и история проверок](#реестр-адресов-и-история-проверок)
|
||||
- [Модель состояний и связь методов с ней](#модель-состояний-и-связь-методов-с-ней)
|
||||
- [Сквозной пример работы (curl)](#сквозной-пример-работы-curl)
|
||||
|
||||
@@ -416,12 +417,18 @@ YAML для этой секции больше не перечитывается
|
||||
|
||||
### `DELETE /api/v1/admin/ips/{ip}`, `POST /api/v1/admin/ips/delete`, `POST /api/v1/admin/ips/clear`
|
||||
|
||||
**Безвозвратное удаление**, в отличие от `cancel` выше: строка `ip_queue`
|
||||
и вся её история (`checks`, `events`) стираются физически, без возможности
|
||||
восстановления. Работает из любого состояния, включая активно
|
||||
проверяемое — если Floating IP привязан, он отвязывается тем же
|
||||
best-effort способом, что и при `cancel`/обычном завершении, владеющий
|
||||
валидатор освобождается.
|
||||
Удаляет строку `ip_queue` — адрес пропадает из очереди/`GET
|
||||
/api/v1/admin/ips*` — безвозвратно, без возможности восстановить именно
|
||||
эту строку. Работает из любого состояния, включая активно проверяемое —
|
||||
если Floating IP привязан, он отвязывается тем же best-effort способом,
|
||||
что и при `cancel`/обычном завершении, владеющий валидатор освобождается.
|
||||
|
||||
**Накопленная история адреса при этом не теряется**: `checks`/`events`
|
||||
остаются в реестре (`ip_registry`, см. раздел [«Реестр
|
||||
адресов»](#реестр-адресов-и-история-проверок) ниже) и доступны через `GET
|
||||
/api/v1/admin/registry/{ip}` даже после удаления строки из очереди — в
|
||||
отличие от `ip_queue`, реестровая запись никогда не удаляется этими
|
||||
методами.
|
||||
|
||||
| Метод | Путь | Тело | Успех | Ошибки |
|
||||
|---|---|---|---|---|
|
||||
@@ -433,7 +440,95 @@ best-effort способом, что и при `cancel`/обычном заве
|
||||
идут в `not_found`, не ошибка — тот же терпимый стиль, что у `POST
|
||||
/api/v1/admin/ips`). `POST .../clear` удаляет **вообще всё**, что сейчас в
|
||||
очереди, включая адреса в процессе проверки — самая опасная операция
|
||||
этого API, используйте с осторожностью.
|
||||
этого API, используйте с осторожностью (и, опять же, ничья история при
|
||||
этом физически не стирается — см. выше).
|
||||
|
||||
### `POST /api/v1/admin/ips/scan`
|
||||
|
||||
Сканирует текущий проект OpenStack на предмет свободных (не привязанных ни
|
||||
к одному порту) Floating IP и сразу передаёт найденный список в `POST
|
||||
/api/v1/admin/ips` — тот же add/requeue/reorder-вызов, как если бы
|
||||
оператор ввёл эти адреса вручную. Не принимает тело запроса.
|
||||
|
||||
Ответ (`200`):
|
||||
```json
|
||||
{
|
||||
"scanned_free": 3,
|
||||
"added": ["203.0.113.20"],
|
||||
"requeued": [],
|
||||
"reordered": ["203.0.113.10", "203.0.113.11"],
|
||||
"skipped_in_progress": []
|
||||
}
|
||||
```
|
||||
|
||||
`scanned_free` — сколько свободных Floating IP нашлось в проекте всего
|
||||
(включая уже стоящие в очереди — они попадут в `reordered`, а не
|
||||
`added`). Если свободных адресов нет вообще, это не ошибка: ответ будет
|
||||
`{"scanned_free": 0, "added": [], ...}`.
|
||||
|
||||
Помимо ручного вызова, сканирование можно включить по расписанию —
|
||||
`orchestrator.fip_scan_interval_seconds` в `control-api.yaml` (0, по
|
||||
умолчанию, — только по запросу через эту ручку или кнопку «Сканировать
|
||||
Floating IP» в дашборде).
|
||||
|
||||
## Реестр адресов и история проверок
|
||||
|
||||
В отличие от `ip_queue` (текущая рабочая очередь, см. выше), реестр —
|
||||
`ip_registry` — это накопительная запись **обо всех адресах, когда-либо
|
||||
поставленных на проверку**, вне зависимости от того, стоят ли они сейчас в
|
||||
очереди. Запись в реестре переживает удаление адреса из `ip_queue` (`DELETE
|
||||
/api/v1/admin/ips/{ip}` и т.п.) и повторное добавление того же адреса
|
||||
позже — обе истории (до и после) остаются доступны и не перекрывают друг
|
||||
друга (каждой постановке на проверку соответствует свой `cycle_id`,
|
||||
уникальный в пределах адреса на всё время).
|
||||
|
||||
### `GET /api/v1/admin/registry`
|
||||
|
||||
Список всех адресов реестра с краткой сводкой по каждому.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"ip_address": "203.0.113.10",
|
||||
"first_seen_at": "2026-01-10T12:00:00Z",
|
||||
"last_seen_at": "2026-02-01T09:00:00Z",
|
||||
"total_cycles": 4,
|
||||
"last_result": "pass",
|
||||
"last_checked_at": "2026-02-01T09:05:00Z",
|
||||
"in_queue": true,
|
||||
"current_state": "done"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
`in_queue`/`current_state` отражают, есть ли у адреса сейчас живая строка в
|
||||
`ip_queue`, а не только в реестре.
|
||||
|
||||
### `GET /api/v1/admin/registry/{ip}`
|
||||
|
||||
Реестровая запись по одному адресу плюс вся сохранённая история проверок
|
||||
по нему, по всем циклам (не только текущему — в отличие от `GET
|
||||
/api/v1/admin/ips/{ip}`, который отдаёт проверки только текущей попытки).
|
||||
Порядок — от новых циклов к старым.
|
||||
|
||||
```json
|
||||
{
|
||||
"registry": { "ip_address": "203.0.113.10", "total_cycles": 4, "...": "..." },
|
||||
"checks": [
|
||||
{"CycleID": 4, "Source": "egress", "CheckType": "https", "Success": true, "...": "..."},
|
||||
{"CycleID": 3, "Source": "egress", "CheckType": "https", "Success": false, "...": "..."}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`404`, если адрес никогда не ставился на проверку.
|
||||
|
||||
**Глубина хранения.** Сколько последних циклов на адрес хранится в
|
||||
`checks` (и синхронно — в `events`), управляется полем
|
||||
`history_retention_cycles` в `GET`/`PUT /api/v1/admin/config/orchestrator`
|
||||
(0, по умолчанию, — без ограничения). Сама реестровая запись (`ip_address`,
|
||||
`first_seen_at`, счётчик циклов) не удаляется никогда, независимо от этой
|
||||
настройки — она лишь ограничивает глубину детальной истории проверок.
|
||||
|
||||
```bash
|
||||
curl -s -X DELETE "$BASE/api/v1/admin/ips/203.0.113.10"
|
||||
@@ -497,25 +592,33 @@ curl -s -X POST "$BASE/api/v1/admin/ips/clear"
|
||||
|
||||
### Настройки оркестратора: `/api/v1/admin/config/orchestrator`
|
||||
|
||||
Единственный на сегодня параметр — `fip_settle_seconds`: пауза между
|
||||
привязкой Floating IP к валидатору и моментом, когда self-check по этому
|
||||
адресу становится доступен агенту (`GET
|
||||
/api/v1/agents/{id}/assignment` до истечения паузы отдаёт `204`, как если
|
||||
бы валидатору просто нечего было делать — никаких изменений в протоколе
|
||||
агента). Нужна, чтобы дать data plane OpenStack время реально начать
|
||||
пропускать трафик через только что привязанный адрес, прежде чем
|
||||
запускать по нему проверки. `0` — без паузы (поведение по умолчанию, как
|
||||
до появления этого параметра).
|
||||
Два параметра:
|
||||
|
||||
- `fip_settle_seconds` — пауза между привязкой Floating IP к валидатору и
|
||||
моментом, когда self-check по этому адресу становится доступен агенту
|
||||
(`GET /api/v1/agents/{id}/assignment` до истечения паузы отдаёт `204`,
|
||||
как если бы валидатору просто нечего было делать — никаких изменений в
|
||||
протоколе агента). Нужна, чтобы дать data plane OpenStack время реально
|
||||
начать пропускать трафик через только что привязанный адрес, прежде чем
|
||||
запускать по нему проверки. `0` — без паузы (поведение по умолчанию, как
|
||||
до появления этого параметра).
|
||||
- `history_retention_cycles` — сколько последних циклов проверки хранить
|
||||
на адрес в реестре (`GET /api/v1/admin/registry/{ip}`, см.
|
||||
[«Реестр адресов»](#реестр-адресов-и-история-проверок)). `0` — без
|
||||
ограничения (поведение по умолчанию).
|
||||
|
||||
| Метод | Путь | Тело | Успех | Ошибки |
|
||||
|---|---|---|---|---|
|
||||
| GET | `/api/v1/admin/config/orchestrator` | — | `{"fip_settle_seconds":N}` | |
|
||||
| PUT | `/api/v1/admin/config/orchestrator` | `{"fip_settle_seconds":N}` | `200` | `400`, если `N < 0`, или если `fip_settle_seconds + self_check_timeout_seconds >= lease_ttl_seconds` (пауза не должна съедать весь лизинг адреса — иначе self-check не успеет пройти до истечения `lease_ttl_seconds`, и адрес будет вечно возвращаться в очередь) |
|
||||
| GET | `/api/v1/admin/config/orchestrator` | — | `{"fip_settle_seconds":N,"history_retention_cycles":M}` | |
|
||||
| PUT | `/api/v1/admin/config/orchestrator` | `{"fip_settle_seconds":N,"history_retention_cycles":M}` | `200` | `400`, если `N < 0` или `M < 0`, или если `fip_settle_seconds + self_check_timeout_seconds >= lease_ttl_seconds` (пауза не должна съедать весь лизинг адреса — иначе self-check не успеет пройти до истечения `lease_ttl_seconds`, и адрес будет вечно возвращаться в очередь) |
|
||||
|
||||
Как и остальные разделы этой группы, YAML-поле `orchestrator.
|
||||
fip_settle_seconds` в `control-api.yaml` — только одноразовый bootstrap
|
||||
для пустой БД; дальше источник истины — сама база, менять значение нужно
|
||||
через `PUT` выше (или страницу `/settings` в дашборде).
|
||||
`history_retention_cycles` не имеет YAML-эквивалента вообще — управляется
|
||||
только через `PUT` выше/дашборд, значение по умолчанию `0` всегда
|
||||
применяется на пустой БД.
|
||||
|
||||
### Типы проверок пробера: `/api/v1/admin/config/inbound-checks`
|
||||
|
||||
@@ -633,12 +736,15 @@ queued ──(control-api сам, без вызова API)──▶ assigning_fi
|
||||
"cancelled"`)** — `POST /api/v1/admin/ips/{ip}/cancel`;
|
||||
- **`done`/`failed`/`occupied` → `queued` (новая попытка)** — `POST
|
||||
/api/v1/admin/ips` с уже завершённым (или занятым) адресом в списке;
|
||||
- **любое состояние → адрес физически исчезает из очереди**, вместе со
|
||||
всей историей — `DELETE /api/v1/admin/ips/{ip}`, `POST
|
||||
/api/v1/admin/ips/delete`, `POST /api/v1/admin/ips/clear` (см.
|
||||
- **любое состояние → адрес физически исчезает из очереди** — `DELETE
|
||||
/api/v1/admin/ips/{ip}`, `POST /api/v1/admin/ips/delete`, `POST
|
||||
/api/v1/admin/ips/clear` (см.
|
||||
[выше](#delete-apiv1adminipsip-post-apiv1adminipsdelete-post-apiv1adminipsclear)).
|
||||
Не путать с cancel — cancel сохраняет запись как историю (`failed`/
|
||||
`cancelled`), delete стирает её целиком без возможности восстановления.
|
||||
`cancelled`) прямо в `ip_queue`; delete убирает саму строку `ip_queue`
|
||||
безвозвратно, но накопленная история проверок остаётся в реестре (`GET
|
||||
/api/v1/admin/registry/{ip}`) — см.
|
||||
[«Реестр адресов»](#реестр-адресов-и-история-проверок).
|
||||
|
||||
## Сквозной пример работы (curl)
|
||||
|
||||
|
||||
Reference in new issue
Block a user