Главная идея: никто не дёргает железо напрямую. Только longfw-poller опрашивает SNMP/telnet/SSH, остальные читают snapshot'ы из Redis. До этого было ~5 систем дёргавших одни и те же устройства параллельно.
| Контейнер | longfw-poller (часть /opt/LoNGFW/docker-compose.yml) |
| Код | applications/LoNGFW/poller/poller.py |
| Scheduler | APScheduler в asyncio |
| Targets | автогенерация из BG inv_device_2 + bootstrap из targets/devices.yml |
| Переменная | Default | Что делает |
|---|---|---|
POLL_BASE_SEC |
60 | sysUpTime+sysName+sysDescr, alive — snmpget |
POLL_HEALTH_SEC |
120 | CPU%/mem (Eltex/DLink private MIB) |
POLL_MACS_SEC |
120 | mac-table + LLDP + классификация портов (BRIDGE-MIB + Q-BRIDGE-MIB + LLDP-MIB) |
POLL_OLT_SEC |
120 | RSSI+state всех ONT + env+uptime (telnet через OLTTelnetMini) |
| Vendor / устройство | Метод | Команды/OID'ы |
|---|---|---|
| Eltex MES (CSW + access switches) | SNMP v2c | private MIB CPU + standard BRIDGE-MIB |
| DLink DGS/DES | SNMP v2c | BRIDGE-MIB FDB walk |
| Eltex ESR-1000 (192.168.100.2) | SSH paramiko | show mac address-table bridge <N> + show arp |
| Eltex LTP-8X OLT (192.168.100.3) | telnet | show ont list verbose all + show system environment |
⚠️ ESR-1000 не отдаёт BRIDGE-MIB по SNMP (это маршрутизатор). FDB только через CLI. Поэтому отдельная функция poll_esr_fdb в poller'е (paramiko + bash через invoke_shell).
device:<host>:snmp:base — alive, uptime_ticks, sysName, sysDescr TTL=180s
device:<host>:snmp:health — cpu_pct, mem_free TTL=360s
device:<host>:mac_table — {macs: {mac→{port_idx, vlan, iface, bridge}},
ports: {port_idx→{kind, mac_count, lldp_neighbors, iface}}}
TTL=480s
mac:<mac> — hash {host → JSON} reverse-index TTL=480s
arp:<ip> — mac (от ESR `show arp`) TTL=480s
device:olt:onts — все ONT с RSSI/state TTL=360s
device:olt:health — env+uptime+version OLT TTL=360s
# agent-API кеши (доп. поверх poller'а):
agent:olt_status — обогащённый olt_status TTL=120s
agent:olt_health — parsed health TTL=60s
agent:capacity — capacity по сети TTL=300s
agent:tariffs — список тарифов TTL=600s
agent:ont_state:<id> — ONT state TTL=60s
В mac_table для каждого порта:
| kind | условие | смысл |
|---|---|---|
access |
mac_count < 5 (или ESR subif gi/te X/Y/Z.NNN) |
per-subscriber точка |
trunk_or_shared |
5 ≤ mac_count < 30 | общий хост / небольшой downstream |
trunk |
mac_count ≥ 30 ИЛИ (ESR vlan <N>) |
uplink/transit |
trunk_lldp |
есть LLDP-сосед | точно uplink (даже если 0 MAC) |
При поиске «где физически воткнут MAC» — приоритет access > trunk_or_shared > trunk_lldp > trunk > unknown.
fdpi_cli тут ни при чём. Используется invoke_shell paramiko к ESR:
ssh root@maxonnet@192.168.100.2
terminal datadump
show mac address-table bridge 11 # FTTB
show mac address-table bridge 500 # white IP/RTK
show arp # IP↔MAC для всех клиентских подсетей
Парсится регексом, кладётся в Redis. ARP пишется как arp:<ip> для быстрого reverse-lookup.
telnet 192.168.100.3
maxonnet
8c61210b2b037821 # password
show interface ont N configured # для всех 0..7 GPON портов
show system environment # CPU/temp/uptime/version
⚠️ terminal datadump ломает telnet-сессию OLT. Не использовать.
ONT с RSSI парсится регексом RSSI(?:\s*\([^)]*\))?\s*:\s*(-?[\d.]+).
/opt/LoNGFW/poller/targets/devices.yml:
defaults:
snmp:
community: public
version: 2c
timeout: 3
retries: 1
devices:
- host: 192.168.100.1
name: csw
vendor: eltex_mes
- host: 192.168.100.100
name: awg
vendor: eltex_mes
- host: 192.168.100.3
name: olt-1
vendor: eltex_ltp
- host: 192.168.100.2
name: border
vendor: eltex_esr
snmp:
community: nU2kUzqKGixTrnUEJk2X9 # special ESR community
# DLink DES/DGS — автогенерация из BG inv_device_2
После запуска — авто-добавляет всё что нашёл в bgbilling.inv_device_2.
docker logs longfw-poller -f — видно каждый poll: esr_fdb 192.168.100.2 mac=27 arp=80 9062msredis-cli KEYS "device:*" — должно быть >10redis-cli HGETALL "mac:<mac>" — где видится конкретный MACkind=access. Trunk-видимости — это просто транзит.failed, MAC не учится.fetch_olt_ont_macs.Changelog