# Device Profiles Implementation Status ## Completed ### Database Schema - ✅ Created `device_profiles` table for storing profile metadata - ✅ Created `profile_device_oids` table for device identification OIDs (serial, firmware, etc.) - ✅ Created `profile_sensor_oids` table 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.Profiles` context for CRUD operations - `list_profiles/0` - Get all enabled profiles ordered by priority - `get_profile/1` - Get profile by name with associations - `match_profile/1` - Match device to profile based on sysDescr/sysObjectID - `create_profile/1`, `update_profile/2`, `delete_profile/1` - `add_device_oid/3`, `add_sensor_oid/2` ### Dynamic Profile - ✅ `Towerops.Snmp.Profiles.Dynamic` - Runtime profile using database definitions - `identify_device/3` - Polls device OIDs using MIB translation - `discover_sensors/2` - Discovers sensors using MIB translation - `discover_interfaces/2` - Delegates to Base profile ### Discovery Integration - ✅ Updated `Towerops.Snmp.Discovery` to 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 ### Mix Task (Basic Structure) - ✅ Created `Mix.Tasks.ImportProfiles` with 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: 1. **`resources/definitions/os_detection/{os}.yaml`** - Detection and metadata ```yaml os: routeros text: 'Mikrotik RouterOS' discovery: - sysObjectID: - .1.3.6.1.4.1.14988.1 ``` 2. **`resources/definitions/os_discovery/{os}.yaml`** - Device info and sensors ```yaml modules: 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 1. **`import_profile/2` function** ✅ - Reads both `os_detection/{name}.yaml` and `os_discovery/{name}.yaml` - Extracts detection patterns from os_detection file (sysObjectID) - Extracts device OIDs from `modules.os` section (serial, version, hardware) - Extracts sensor OIDs from `modules.sensors.{type}.data[]` arrays 2. **Sensor handling** ✅ - Only imports scalar sensors (with `.0` suffix) - Skips table-based sensors with `{{ $index }}` templates - Cleans up template syntax in descriptions - Handles divisor values correctly 3. **Supported sensor types** ✅ - `temperature`, `voltage`, `current`, `power`, `fanspeed` - Other types (`dbm`, `state`, `count`) can be added as needed 4. **Tested with real LibreNMS** ✅ - Successfully imported `routeros` profile from `~/dev/librenms/resources/definitions/` - Profile created with correct detection OID and device OIDs - Scalar sensors imported (though routeros only has table-based sensors) ### Usage Import profiles from LibreNMS YAML definitions: ```bash # 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 1. **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.) 2. **Complex templates** - Template syntax in descriptions is removed - `{{ MIKROTIK-MIB::mtxrPOEName }} POE` becomes just "POE" 3. **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 1. **Add more sensor types** - Add dbm, state, count if needed 2. **Web UI for profiles** - Build LiveView CRUD for managing profiles 3. **Table sensor support** - Implement support for table-based sensors 4. **Import more profiles** - Test with Cisco, Ubiquiti, etc. ## Testing To test the current implementation: ```elixir # 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 1. **Test with real MikroTik device** - Verify dynamic profile works end-to-end 2. **Add Web UI** - Build LiveView pages for managing profiles 3. **Improve import task** - Parse LibreNMS YAML structure correctly 4. **Add more profiles** - Cisco, Ubiquiti, etc.