Fixes three critical issues affecting agent-based SNMP polling:
1. MikroTik gauge sensors incorrectly showing 10x values (223°C instead of 22.3°C)
- Root cause: get_int_value() rejected zero values, causing mtxrGaugeUnit
to be treated as nil and bypassing divisor logic
- Fixed: Accept zero values and apply correct divisor=10 for temp/voltage/current/power
2. Empty SNMP community strings sent to agents causing authentication failures
- Root cause: Devices with source="device" but null community weren't falling
back to organization/site inheritance
- Fixed: Enhanced resolve_snmp_community() to fall back to inheritance chain
even when source="device" but community is empty
3. Continuous MikroTik API commands sent every 60s instead of once per 24h
- Root cause: MikroTik jobs built on every poll cycle, not just discovery
- Fixed: Only build MikroTik jobs during discovery phase
Migrations update existing data to fix incorrect divisor values and community
source tracking. Added comprehensive debug logging to diagnose future issues.
- Create firmware_releases table to store latest available firmware versions
- Create device_firmware_history table to track version changes over time
- Add FirmwareRelease and DeviceFirmwareHistory Ecto schemas with validations
- Add comprehensive tests for both schemas (23 tests, 100% coverage)
firmware_releases stores one record per vendor/product_line with latest version.
device_firmware_history is append-only audit log of device firmware changes.
Part of firmware version tracking system for MikroTik (extensible to other vendors).
Sets sensor_unit for all sensors that are missing it, fixing sensors
created before the discovery code was updated to set units properly.
Updates:
- Temperature sensors: set to '°C'
- Voltage sensors: set to 'V'
- Current sensors: set to 'mA'
- Power sensors: set to 'W'
- dBm sensors: set to 'dBm'
This ensures the device detail page displays units correctly for all
sensor types (e.g., "27 °C" instead of "27" for temperature).
The discovery code already sets these units for new sensors, so this
migration only affects existing data.
Related to:
- lib/towerops/snmp/profiles/vendors/routeros.ex:690 (°C)
- lib/towerops/snmp/profiles/vendors/routeros.ex:709 (V)
- lib/towerops/snmp/profiles/base.ex:1473-1480 (sensor_type_to_unit)
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes voltage sensors that were incorrectly classified as temperature
sensors due to MikroTik devices reporting wrong mtxrGaugeUnit values.
Problem:
- Sensors with names like "psu1-voltage" and "psu2-voltage" were
classified as temperature sensors with divisor=1
- This caused voltage readings to display as 469V instead of 46.9V
- The RouterOS profile already has name-based override logic for new
discoveries, but existing sensors needed fixing
Solution:
- Migration identifies sensors by:
- OID pattern: 1.3.6.1.4.1.14988.1.1.3.100.1.3.%
- Type mismatch: sensor_type = 'temperature' but name contains 'voltage'
- Incorrect divisor: sensor_divisor = 1
- Updates sensor metadata: type, unit, divisor
- Corrects historical sensor_reading values by dividing by 10
Future discoveries are already protected by the name-based override
logic in lib/towerops/snmp/profiles/vendors/routeros.ex:620-630
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Mikrotik/RouterOS voltage sensors were showing incorrect values (469.0
instead of 46.9) because existing sensors in the database have
sensor_divisor=1 instead of the correct value of 10.
The RouterOS profile code was fixed in a previous commit to set
divisor=10 for new sensors, but existing sensors need to be updated.
Migration changes:
- Updates sensor_divisor from 1 to 10 for Mikrotik voltage sensors
- Identifies Mikrotik sensors by OID prefix: 1.3.6.1.4.1.14988.1.1.3.100.1.3
- Divides all historical sensor_reading values by 10 to correct the data
- Both up and down migrations included for full reversibility
After this migration:
- Voltage will show as 46.9V instead of 469.0V
- Historical graphs will show correct voltage values
Replaces etcd-based distributed locking with Oban's PostgreSQL-backed job queue.
This simplifies the architecture by eliminating the need for a separate etcd cluster
while providing better reliability and observability.
Changes:
- Add Oban dependency and migration (oban_jobs table)
- Create DevicePollerCoordinator and DeviceMonitorCoordinator Oban workers
- Remove EtcdCoordinator and EtcdLock modules
- Update application supervisor to start Oban
- Configure Oban with pollers (50 workers) and monitors (50 workers) queues
- Remove etcd StatefulSet from Kubernetes manifests
- Update monitoring supervisor documentation
Benefits:
- Simpler architecture (no etcd cluster to manage)
- PostgreSQL-based (uses existing database)
- Built-in uniqueness prevents duplicate jobs cluster-wide
- Better observability with Oban Web UI
- Automatic job rescue on node crashes
- Easier local development (no etcd required)
What was removed:
- etcd StatefulSet (3 pods)
- EtcdCoordinator module (320 lines)
- EtcdLock module (158 lines)
- eetcd dependency
All 3,686 tests passing.
- Create snmp_physical_entities table with migration
- Add PhysicalEntity schema with entity_class validation
- Support parent/child hierarchy via parent_entity_id
- Implement discover_physical_entities/1 in Base profile
- Discover chassis, modules, PSUs, fans from ENTITY-MIB
- Map entity class integers to string names
- Add 10 schema tests and 4 discovery tests
- Fix flaky AlertNotifier test with unique names and mailbox clearing
- Create snmp_ip_addresses table with migration
- Add IpAddress schema with ip_type validation (ipv4/ipv6)
- Add prefix_length validation based on ip_type
- Implement discover_ip_addresses/1 in Base profile
- Extract IP addresses from IP-MIB ipAdEntTable
- Support multiple IPs per interface with subnet masks
- Add 12 schema tests and 4 discovery tests