towerops/lib/towerops/profiles.ex

113 lines
2.6 KiB
Elixir

defmodule Towerops.Profiles do
@moduledoc """
Context for managing device profiles.
Profiles are stored in the database and can be updated without deployment.
"""
import Ecto.Query
alias Towerops.Profiles.DeviceOid
alias Towerops.Profiles.DeviceProfile
alias Towerops.Profiles.SensorOid
alias Towerops.Repo
@doc """
Lists all enabled profiles ordered by priority.
"""
def list_profiles do
DeviceProfile
|> where([p], p.enabled == true)
|> order_by([p], asc: p.priority)
|> Repo.all()
end
@doc """
Gets a profile by name with associations loaded.
"""
def get_profile(name) do
DeviceProfile
|> where([p], p.name == ^name)
|> preload([:device_oids, :sensor_oids])
|> Repo.one()
end
@doc """
Matches a profile based on sysDescr and sysObjectID.
Returns the first matching profile based on priority.
"""
def match_profile(system_info) do
sys_descr = Map.get(system_info, :sys_descr, "")
sys_object_id = Map.get(system_info, :sys_object_id, "")
profiles = list_profiles()
Enum.find(profiles, fn profile ->
matches_detection_pattern?(profile, sys_descr) ||
matches_detection_oid?(profile, sys_object_id)
end)
end
@doc """
Creates a new profile.
"""
def create_profile(attrs) do
%DeviceProfile{}
|> DeviceProfile.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a profile.
"""
def update_profile(%DeviceProfile{} = profile, attrs) do
profile
|> DeviceProfile.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a profile.
"""
def delete_profile(%DeviceProfile{} = profile) do
Repo.delete(profile)
end
@doc """
Adds a device OID to a profile.
"""
def add_device_oid(profile_id, field, mib_name) do
%DeviceOid{}
|> DeviceOid.changeset(%{
profile_id: profile_id,
field: field,
mib_name: mib_name
})
|> Repo.insert()
end
@doc """
Adds a sensor OID to a profile.
"""
def add_sensor_oid(profile_id, attrs) do
%SensorOid{}
|> SensorOid.changeset(Map.put(attrs, :profile_id, profile_id))
|> Repo.insert()
end
# Private functions
defp matches_detection_pattern?(%{detection_pattern: nil}, _sys_descr), do: false
defp matches_detection_pattern?(%{detection_pattern: pattern}, sys_descr) do
case Regex.compile(pattern) do
{:ok, regex} -> Regex.match?(regex, sys_descr)
{:error, _} -> false
end
end
defp matches_detection_oid?(%{detection_oid: nil}, _sys_object_id), do: false
defp matches_detection_oid?(%{detection_oid: pattern}, sys_object_id) do
String.starts_with?(sys_object_id, pattern)
end
end