towerops/priv/repo/migrations/20260118000250_create_device_profiles.exs
Graham McIntire 007adcc489
feat: add database-driven SNMP device profiles
Implement dynamic device profile system using LibreNMS YAML definitions:

- Create 7 database tables for device profiles, detection rules, sensors, processors, memory pools
- Add DeviceProfiles context module with profile matching logic
- Add YAML importer to parse LibreNMS os_detection and os_discovery files
- Add mix task for importing profiles from LibreNMS repository
- Create Dynamic profile module to interpret database definitions at runtime
- Update discovery.ex to check database profiles before hard-coded modules
- Fix Redis PubSub configuration to support unnamed nodes for Mix tasks

Imported 5 Ubiquiti/Cambium profiles: epmp, airos-af, airos-af-ltu, airos-af60, unifi

The system now supports 671+ device profiles from LibreNMS without requiring
code changes for each device type.
2026-01-17 18:13:53 -06:00

162 lines
5.1 KiB
Elixir

defmodule Towerops.Repo.Migrations.CreateDeviceProfiles do
use Ecto.Migration
def change do
# Main device profile table - stores high-level device type information
create table(:device_profiles, primary_key: false) do
add :id, :binary_id, primary_key: true
add :os, :string, null: false
add :text, :string, null: false
add :type, :string
add :icon, :string
add :group, :string
add :mib, :string
add :snmp_bulk, :boolean, default: true
add :mib_dir, :string
add :enabled, :boolean, default: true
add :priority, :integer, default: 100
timestamps(type: :utc_datetime)
end
create unique_index(:device_profiles, [:os])
create index(:device_profiles, [:enabled])
create index(:device_profiles, [:type])
create index(:device_profiles, [:priority])
# Detection rules - how to identify which profile to use
create table(:profile_detection_rules, primary_key: false) do
add :id, :binary_id, primary_key: true
add :device_profile_id,
references(:device_profiles, type: :binary_id, on_delete: :delete_all), null: false
add :rule_type, :string, null: false
add :oid, :text
add :operator, :string
add :value, :text
add :pattern, :text
add :priority, :integer, default: 0
timestamps(type: :utc_datetime)
end
create index(:profile_detection_rules, [:device_profile_id])
create index(:profile_detection_rules, [:rule_type])
# Sensor definitions - OID mappings for different sensor types
create table(:profile_sensor_definitions, primary_key: false) do
add :id, :binary_id, primary_key: true
add :device_profile_id,
references(:device_profiles, type: :binary_id, on_delete: :delete_all), null: false
add :sensor_class, :string, null: false
add :oid, :string
add :num_oid, :string
add :index, :string
add :descr, :string
add :divisor, :integer, default: 1
add :multiplier, :integer, default: 1
add :precision, :integer
add :sensor_type, :string
add :unit, :string
add :low_limit, :float
add :low_warn_limit, :float
add :warn_limit, :float
add :high_limit, :float
add :skip_value_lt, :float
add :skip_value_gt, :float
add :user_func, :string
add :entPhysicalIndex, :string
add :group, :string
add :options, :map
timestamps(type: :utc_datetime)
end
create index(:profile_sensor_definitions, [:device_profile_id])
create index(:profile_sensor_definitions, [:sensor_class])
# State definitions - for enumerated state sensors
create table(:profile_sensor_states, primary_key: false) do
add :id, :binary_id, primary_key: true
add :sensor_definition_id,
references(:profile_sensor_definitions, type: :binary_id, on_delete: :delete_all),
null: false
add :value, :integer, null: false
add :descr, :string, null: false
add :generic, :integer, null: false
add :graph, :integer, null: false
timestamps(type: :utc_datetime)
end
create index(:profile_sensor_states, [:sensor_definition_id])
# Processor (CPU) definitions
create table(:profile_processor_definitions, primary_key: false) do
add :id, :binary_id, primary_key: true
add :device_profile_id,
references(:device_profiles, type: :binary_id, on_delete: :delete_all), null: false
add :oid, :string, null: false
add :num_oid, :string, null: false
add :index, :string
add :descr, :string
add :precision, :integer, default: 1
add :type, :string
add :warn_percent, :integer
add :entPhysicalIndex, :string
timestamps(type: :utc_datetime)
end
create index(:profile_processor_definitions, [:device_profile_id])
# Memory pool definitions
create table(:profile_mempool_definitions, primary_key: false) do
add :id, :binary_id, primary_key: true
add :device_profile_id,
references(:device_profiles, type: :binary_id, on_delete: :delete_all), null: false
add :index, :string
add :descr, :string
add :total_oid, :string
add :used_oid, :string
add :free_oid, :string
add :percent_used_oid, :string
add :precision, :integer, default: 1
add :type, :string
add :class, :string
add :warn_percent, :integer
timestamps(type: :utc_datetime)
end
create index(:profile_mempool_definitions, [:device_profile_id])
# OS-specific metadata (version, serial, hardware info)
create table(:profile_os_definitions, primary_key: false) do
add :id, :binary_id, primary_key: true
add :device_profile_id,
references(:device_profiles, type: :binary_id, on_delete: :delete_all), null: false
add :field, :string, null: false
add :oid, :string
add :regex, :string
add :template, :text
add :value, :string
timestamps(type: :utc_datetime)
end
create index(:profile_os_definitions, [:device_profile_id])
create unique_index(:profile_os_definitions, [:device_profile_id, :field])
end
end