6.5 KiB
6.5 KiB
Device Profiles Implementation Status
Completed
Database Schema
- ✅ Created
device_profilestable for storing profile metadata - ✅ Created
profile_device_oidstable for device identification OIDs (serial, firmware, etc.) - ✅ Created
profile_sensor_oidstable for sensor discovery OIDs (temp, voltage, current, power) - ✅ Seeded MikroTik profile with all MIB symbolic names
Ecto Schemas
- ✅
Towerops.Profiles.DeviceProfile- Profile schema with associations - ✅
Towerops.Profiles.DeviceOid- Device identification OID schema - ✅
Towerops.Profiles.SensorOid- Sensor OID schema with divisor support
Context
- ✅
Towerops.Profilescontext for CRUD operationslist_profiles/0- Get all enabled profiles ordered by priorityget_profile/1- Get profile by name with associationsmatch_profile/1- Match device to profile based on sysDescr/sysObjectIDcreate_profile/1,update_profile/2,delete_profile/1add_device_oid/3,add_sensor_oid/2
Dynamic Profile
- ✅
Towerops.Snmp.Profiles.Dynamic- Runtime profile using database definitionsidentify_device/3- Polls device OIDs using MIB translationdiscover_sensors/2- Discovers sensors using MIB translationdiscover_interfaces/2- Delegates to Base profile
Discovery Integration
- ✅ Updated
Towerops.Snmp.Discoveryto support database profiles- Tries database profiles first via
Profiles.match_profile/1 - Falls back to hardcoded profiles (MikroTik, Cisco, etc.)
- Handles
{:dynamic, profile}tuples for database profiles
- Tries database profiles first via
Mix Task (Basic Structure)
- ✅ Created
Mix.Tasks.ImportProfileswith basic structure - ✅ Argument parsing (--source-path, --profiles filter)
- ✅ YAML file discovery and reading
Current Status
The core database-driven profile system is fully functional:
- MikroTik devices will be detected using the database profile
- Device info (serial, firmware, license) will be polled via MIB translation
- Sensors (temp, voltage, current, power) will be discovered via MIB translation
- Profiles can be updated without redeployment
Completed: LibreNMS Import Task
The mix import_profiles task has been implemented and tested successfully with LibreNMS YAML files.
LibreNMS File Structure
LibreNMS splits profile definitions across two files:
-
resources/definitions/os_detection/{os}.yaml- Detection and metadataos: routeros text: 'Mikrotik RouterOS' discovery: - sysObjectID: - .1.3.6.1.4.1.14988.1 -
resources/definitions/os_discovery/{os}.yaml- Device info and sensorsmodules: os: serial: MIKROTIK-MIB::mtxrSerialNumber.0 version: MIKROTIK-MIB::mtxrLicVersion.0 sensors: temperature: data: - oid: MIKROTIK-MIB::mtxrGaugeTable value: MIKROTIK-MIB::mtxrGaugeValue num_oid: '.1.3.6.1.4.1.14988.1.1.3.100.1.3.{{ $index }}' descr: MIKROTIK-MIB::mtxrGaugeName divisor: 10
Implementation Details
-
import_profile/2function ✅- Reads both
os_detection/{name}.yamlandos_discovery/{name}.yaml - Extracts detection patterns from os_detection file (sysObjectID)
- Extracts device OIDs from
modules.ossection (serial, version, hardware) - Extracts sensor OIDs from
modules.sensors.{type}.data[]arrays
- Reads both
-
Sensor handling ✅
- Only imports scalar sensors (with
.0suffix) - Skips table-based sensors with
{{ $index }}templates - Cleans up template syntax in descriptions
- Handles divisor values correctly
- Only imports scalar sensors (with
-
Supported sensor types ✅
temperature,voltage,current,power,fanspeed- Other types (
dbm,state,count) can be added as needed
-
Tested with real LibreNMS ✅
- Successfully imported
routerosprofile from~/dev/librenms/resources/definitions/ - Profile created with correct detection OID and device OIDs
- Scalar sensors imported (though routeros only has table-based sensors)
- Successfully imported
Usage
Import profiles from LibreNMS YAML definitions:
# Import all profiles
mix import_profiles --source-path ~/dev/librenms/resources/definitions
# Import specific profiles
mix import_profiles --source-path ~/dev/librenms/resources/definitions --profiles routeros,ios
# Import single profile
mix import_profiles --source-path ~/dev/librenms/resources/definitions --profiles routeros
Note: The task looks for files in:
{source-path}/os_detection/{profile}.yaml- Detection patterns{source-path}/os_discovery/{profile}.yaml- Device info and sensors
Current Limitations
-
Table-based sensors - Only scalar sensors (ending with
.0) are imported- Table sensors with
{{ $index }}templates are skipped - This excludes most interface-level sensors (POE ports, optical transceivers, etc.)
- Table sensors with
-
Complex templates - Template syntax in descriptions is removed
{{ MIKROTIK-MIB::mtxrPOEName }} POEbecomes just "POE"
-
Sensor types - Only common types are imported
- Supported: temperature, voltage, current, power, fanspeed
- Not supported: dbm, state, count (can be added as needed)
Next Steps
- Add more sensor types - Add dbm, state, count if needed
- Web UI for profiles - Build LiveView CRUD for managing profiles
- Table sensor support - Implement support for table-based sensors
- Import more profiles - Test with Cisco, Ubiquiti, etc.
Testing
To test the current implementation:
# Get the seeded MikroTik profile
profile = Towerops.Profiles.get_profile("mikrotik")
# Check device OIDs
profile.device_oids
# => [
# %{field: "serial_number", mib_name: "MIKROTIK-MIB::mtxrSerialNumber.0"},
# %{field: "firmware_version", mib_name: "MIKROTIK-MIB::mtxrFirmwareVersion.0"},
# ...
# ]
# Check sensor OIDs
profile.sensor_oids
# => [
# %{sensor_type: "temperature", mib_name: "MIKROTIK-MIB::mtxrHlTemperature.0", divisor: 10},
# %{sensor_type: "voltage", mib_name: "MIKROTIK-MIB::mtxrHlVoltage.0", divisor: 10},
# ...
# ]
# Match a device to a profile
system_info = %{
sys_descr: "RouterOS 7.16.1",
sys_object_id: ".1.3.6.1.4.1.14988.1"
}
matched = Towerops.Profiles.match_profile(system_info)
# => %DeviceProfile{name: "mikrotik", ...}
Next Steps
- Test with real MikroTik device - Verify dynamic profile works end-to-end
- Add Web UI - Build LiveView pages for managing profiles
- Improve import task - Parse LibreNMS YAML structure correctly
- Add more profiles - Cisco, Ubiquiti, etc.