From 2ecc2082e67c7c9cf205801904e74cacf55f53aa Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 18 Jan 2026 11:30:27 -0600 Subject: [PATCH] fix(imports): skip sensors without OIDs and truncate long MIB values Fixed two profile import issues: 1. Skip sensors without OIDs: - Some profiles have sensors with null/missing OID fields - These can't be used for SNMP polling anyway - Added check to skip importing sensors without oid or num_oid - Prevents Ecto.Changeset validation errors 2. Truncate MIB values to 255 characters: - ERROR 22001 (string_data_right_truncation) - MIB field is varchar(255) but some values exceed this - Added truncation to first 255 chars before saving - Location: lib/towerops/device_profiles/importer.ex:229-236 Both errors were causing profile imports to fail with crashes. --- lib/towerops/device_profiles/importer.ex | 58 ++++++++++++++---------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/towerops/device_profiles/importer.ex b/lib/towerops/device_profiles/importer.ex index 523d0e53..0e21a3c8 100644 --- a/lib/towerops/device_profiles/importer.ex +++ b/lib/towerops/device_profiles/importer.ex @@ -224,9 +224,16 @@ defmodule Towerops.DeviceProfiles.Importer do end defp import_discovery_definitions(profile, data) do - # Import MIB if specified + # Import MIB if specified (truncate to 255 chars if needed) if data["mib"] do - DeviceProfiles.update_profile(profile, %{mib: data["mib"]}) + mib = + if String.length(data["mib"]) > 255 do + String.slice(data["mib"], 0, 255) + else + data["mib"] + end + + DeviceProfiles.update_profile(profile, %{mib: mib}) end modules = data["modules"] || %{} @@ -311,29 +318,32 @@ defmodule Towerops.DeviceProfiles.Importer do defp import_sensors_of_class(profile_id, sensor_class, sensors) do Enum.each(sensors, fn sensor -> - attrs = %{ - device_profile_id: profile_id, - sensor_class: sensor_class, - oid: sensor["oid"], - num_oid: sensor["num_oid"], - index: to_string(sensor["index"] || ""), - descr: sensor["descr"], - divisor: calculate_divisor(sensor["precision"]), - precision: sensor["precision"], - sensor_type: sensor["type"], - low_limit: parse_float(sensor["low_limit"]), - low_warn_limit: parse_float(sensor["low_warn_limit"]), - warn_limit: parse_float(sensor["warn_limit"]), - high_limit: parse_float(sensor["high_limit"]), - skip_value_lt: parse_float(sensor["skip_value_lt"]), - skip_value_gt: parse_float(sensor["skip_value_gt"]), - user_func: sensor["user_func"], - entPhysicalIndex: sensor["entPhysicalIndex"], - group: sensor["group"], - options: extract_sensor_options(sensor) - } + # Skip sensors without a valid OID (required for SNMP polling) + if sensor["oid"] || sensor["num_oid"] do + attrs = %{ + device_profile_id: profile_id, + sensor_class: sensor_class, + oid: sensor["oid"], + num_oid: sensor["num_oid"], + index: to_string(sensor["index"] || ""), + descr: sensor["descr"], + divisor: calculate_divisor(sensor["precision"]), + precision: sensor["precision"], + sensor_type: sensor["type"], + low_limit: parse_float(sensor["low_limit"]), + low_warn_limit: parse_float(sensor["low_warn_limit"]), + warn_limit: parse_float(sensor["warn_limit"]), + high_limit: parse_float(sensor["high_limit"]), + skip_value_lt: parse_float(sensor["skip_value_lt"]), + skip_value_gt: parse_float(sensor["skip_value_gt"]), + user_func: sensor["user_func"], + entPhysicalIndex: sensor["entPhysicalIndex"], + group: sensor["group"], + options: extract_sensor_options(sensor) + } - import_sensor_with_states(attrs, sensor["states"]) + import_sensor_with_states(attrs, sensor["states"]) + end end) end