fix agent discovery system OIDs returning no_such_name
gosnmp returns OIDs with leading dots (e.g., ".1.3.6.1.2.1.1.1.0") but the Replay adapter did exact-match lookups without the dot. Walks already normalized both sides, so interfaces worked. GETs did not, breaking all system OID resolution (sysDescr, sysName, etc).
This commit is contained in:
parent
d36fcbe628
commit
10d1157ec3
3 changed files with 62 additions and 3 deletions
|
|
@ -73,16 +73,27 @@ defmodule Towerops.Snmp.Adapters.Replay do
|
|||
def get(opts, oid) when is_binary(oid) do
|
||||
oid_map = Keyword.fetch!(opts, :oid_map)
|
||||
|
||||
case Map.fetch(oid_map, oid) do
|
||||
case lookup_oid(oid_map, oid) do
|
||||
{:ok, value} ->
|
||||
{:ok, parse_value(value)}
|
||||
|
||||
:error ->
|
||||
# Mimic SNMP "no such name" error
|
||||
{:error, :no_such_name}
|
||||
end
|
||||
end
|
||||
|
||||
# Normalize OID lookup to handle leading dot differences.
|
||||
# gosnmp returns OIDs with leading dots (e.g., ".1.3.6.1.2.1.1.1.0")
|
||||
# but server code uses OIDs without (e.g., "1.3.6.1.2.1.1.1.0").
|
||||
defp lookup_oid(oid_map, oid) do
|
||||
normalized = String.trim_leading(oid, ".")
|
||||
|
||||
with :error <- Map.fetch(oid_map, oid),
|
||||
:error <- Map.fetch(oid_map, normalized) do
|
||||
Map.fetch(oid_map, "." <> normalized)
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def walk(opts, base_oid) when is_binary(base_oid) do
|
||||
oid_map = Keyword.fetch!(opts, :oid_map)
|
||||
|
|
|
|||
|
|
@ -1865,7 +1865,10 @@
|
|||
<p>
|
||||
Raw SNMP OID values collected during the last discovery run at
|
||||
<%= if @snmp_device.last_discovery_at do %>
|
||||
{ToweropsWeb.TimeHelpers.format_iso8601(@snmp_device.last_discovery_at, @timezone)}
|
||||
{ToweropsWeb.TimeHelpers.format_iso8601(
|
||||
@snmp_device.last_discovery_at,
|
||||
@timezone
|
||||
)}
|
||||
<% else %>
|
||||
unknown time
|
||||
<% end %>.
|
||||
|
|
|
|||
|
|
@ -229,6 +229,51 @@ defmodule Towerops.Snmp.Adapters.ReplayTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "leading dot normalization (gosnmp format)" do
|
||||
test "get/2 finds value when map has leading-dot keys" do
|
||||
# gosnmp returns OIDs like ".1.3.6.1.2.1.1.1.0" (with leading dot)
|
||||
# but server code looks up "1.3.6.1.2.1.1.1.0" (without leading dot)
|
||||
oid_map = %{".1.3.6.1.2.1.1.1.0" => "RouterOS CHR"}
|
||||
opts = Replay.new(oid_map)
|
||||
|
||||
assert {:ok, "RouterOS CHR"} = Replay.get(opts, "1.3.6.1.2.1.1.1.0")
|
||||
end
|
||||
|
||||
test "get/2 finds value when map has no-dot keys but lookup has dot" do
|
||||
oid_map = %{"1.3.6.1.2.1.1.1.0" => "Cisco IOS"}
|
||||
opts = Replay.new(oid_map)
|
||||
|
||||
assert {:ok, "Cisco IOS"} = Replay.get(opts, ".1.3.6.1.2.1.1.1.0")
|
||||
end
|
||||
|
||||
test "get_multiple/2 finds values with mixed dot formats" do
|
||||
oid_map = %{
|
||||
".1.3.6.1.2.1.1.1.0" => "RouterOS CHR",
|
||||
".1.3.6.1.2.1.1.5.0" => "mikrotik-router"
|
||||
}
|
||||
|
||||
opts = Replay.new(oid_map)
|
||||
|
||||
oids = ["1.3.6.1.2.1.1.1.0", "1.3.6.1.2.1.1.5.0"]
|
||||
|
||||
assert {:ok, results} = Replay.get_multiple(opts, oids)
|
||||
assert results["1.3.6.1.2.1.1.1.0"] == "RouterOS CHR"
|
||||
assert results["1.3.6.1.2.1.1.5.0"] == "mikrotik-router"
|
||||
end
|
||||
|
||||
test "walk/2 handles leading-dot keys in map" do
|
||||
oid_map = %{
|
||||
".1.3.6.1.2.1.2.2.1.1.1" => "1",
|
||||
".1.3.6.1.2.1.2.2.1.1.2" => "2"
|
||||
}
|
||||
|
||||
opts = Replay.new(oid_map)
|
||||
|
||||
assert {:ok, results} = Replay.walk(opts, "1.3.6.1.2.1.2.2.1.1")
|
||||
assert length(results) == 2
|
||||
end
|
||||
end
|
||||
|
||||
describe "type inference edge cases" do
|
||||
test "parses MAC address with hyphens" do
|
||||
oid_map = %{"oid" => "AA-BB-CC-DD-EE-FF"}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue