register_device_tab({
tag
=>
'snmp'
,
label
=>
'SNMP'
,
render_if
=>
sub
{ schema(vars->{
'tenant'
})->resultset(
'DeviceBrowser'
)->count() } });
get
'/ajax/content/device/snmp'
=> require_login
sub
{
my
$device
=
try
{ schema(vars->{
'tenant'
})->resultset(
'Device'
)
->search_for_device( param(
'q'
) ) }
or send_error(
'Bad Device'
, 404);
template
'ajax/device/snmp.tt'
, {
device
=>
$device
->ip },
{
layout
=>
'noop'
};
};
ajax
'/ajax/data/device/:ip/snmptree/:base'
=> require_login
sub
{
my
$device
=
try
{ schema(vars->{
'tenant'
})->resultset(
'Device'
)
->find( param(
'ip'
) ) }
or send_error(
'Bad Device'
, 404);
my
$base
= param(
'base'
);
$base
=~ m/^\.1(\.\d+)*$/ or send_error(
'Bad OID Base'
, 404);
content_type
'application/json'
;
return
to_json [{
text
=>
'No data for this device. You can request a snapshot in the Details tab.'
,
children
=> \0,
state
=> {
disabled
=> \1 },
icon
=>
'icon-search'
,
}]
unless
$device
->oids->count;
return
to_json [{
text
=>
'No MIB data. Please run `~/bin/netdisco-do loadmibs`.'
,
children
=> \0,
state
=> {
disabled
=> \1 },
icon
=>
'icon-search'
,
}]
unless
schema(vars->{
'tenant'
})->resultset(
'SNMPObject'
)->count();
my
$items
= _get_snmp_data(
$device
->ip,
$base
);
to_json
$items
;
};
ajax
'/ajax/data/snmp/typeahead'
=> require_login
sub
{
my
$term
= param(
'term'
) or
return
to_json [];
my
$device
= param(
'ip'
);
my
$deviceonly
= param(
'deviceonly'
);
my
$table
= (
$deviceonly
?
'DeviceBrowser'
:
'SNMPObject'
);
my
@found
= schema(vars->{
'tenant'
})->resultset(
$table
)
->search({
-or
=> [
'me.oid'
=>
$term
,
'me.oid'
=> {
-like
=> (
$term
.
'.%'
) },
'me.leaf'
=> {
-ilike
=> (
'%'
.
$term
.
'%'
) } ],
((
$deviceonly
and
$device
) ? (
ip
=>
$device
) : ()), },
{
select
=> [
((
$deviceonly
and
$device
) ? \
q{ oid_fields.mib || '::' || me.leaf }
: \
q{ me.mib || '::' || me.leaf }
),
],
as
=> [
'qleaf'
],
((
$deviceonly
and
$device
) ? (
join
=>
'oid_fields'
) : ()),
rows
=> 25,
order_by
=>
'me.oid_parts'
})
->get_column(
'qleaf'
)->all;
return
to_json []
unless
scalar
@found
;
content_type
'application/json'
;
to_json [
sort
@found
];
};
ajax
'/ajax/data/snmp/nodesearch'
=> require_login
sub
{
my
$to_match
= param(
'str'
) or
return
to_json [];
my
$partial
= param(
'partial'
);
my
$found
=
undef
;
if
(
$partial
) {
$found
= schema(vars->{
'tenant'
})->resultset(
'SNMPObject'
)
->search({
-or
=> [
oid
=>
$to_match
,
oid
=> {
-like
=> (
$to_match
.
'.%'
) },
leaf
=> {
-ilike
=> (
$to_match
.
'%'
) } ] },
{
rows
=> 1,
order_by
=>
'oid_parts'
})->first;
}
else
{
my
(
$mib
,
$leaf
) =
split
m/::/,
$to_match
;
$found
= schema(vars->{
'tenant'
})->resultset(
'SNMPObject'
)
->search({
((
$mib
and
$leaf
) ? (
-and
=> [
mib
=>
$mib
,
leaf
=>
$leaf
])
: (
-or
=> [
oid
=>
$to_match
,
leaf
=> {
-ilike
=>
$to_match
}])),
},{
rows
=> 1,
order_by
=>
'oid_parts'
})->first;
}
return
to_json []
unless
$found
;
$found
=
$found
->oid;
$found
=~ s/^\.1\.?//;
my
@results
= (
'.1'
);
foreach
my
$part
(
split
m/\./,
$found
) {
my
$last
=
$results
[-1];
push
@results
,
"${last}.${part}"
;
}
content_type
'application/json'
;
to_json \
@results
;
};
ajax
'/ajax/content/device/:ip/snmpnode/:oid'
=> require_login
sub
{
my
$device
=
try
{ schema(vars->{
'tenant'
})->resultset(
'Device'
)
->find( param(
'ip'
) ) }
or send_error(
'Bad Device'
, 404);
my
$oid
= param(
'oid'
);
$oid
=~ m/^\.1(\.\d+)*$/ or send_error(
'Bad OID'
, 404);
my
$object
= schema(vars->{
'tenant'
})->resultset(
'DeviceBrowser'
)
->with_snmp_object(
$device
->ip)->find({
'snmp_object.oid'
=>
$oid
})
or send_error(
'Bad OID'
, 404);
my
$munge
= (param(
'munge'
) and
exists
$ALL_MUNGERS
{param(
'munge'
)})
? param(
'munge'
) :
$object
->munge;
my
%data
= (
$object
->get_columns,
snmp_object
=> {
$object
->snmp_object->get_columns },
value
=> decode_and_munge(
$munge
,
$object
->value ),
);
template
'ajax/device/snmpnode.tt'
,
{
node
=> \
%data
,
munge
=>
$munge
,
mungers
=> [
sort
keys
%ALL_MUNGERS
] },
{
layout
=>
'noop'
};
};
sub
_get_snmp_data {
my
(
$ip
,
$base
,
$recurse
) =
@_
;
my
@parts
=
grep
{
length
}
split
m/\./,
$base
;
my
%meta
=
map
{ (
'.'
.
join
'.'
, @{
$_
->{oid_parts}}) =>
$_
}
schema(vars->{
'tenant'
})->resultset(
'Virtual::FilteredSNMPObject'
)
->search({}, {
bind
=> [
$ip
,
(
scalar
@parts
+ 1),
(
scalar
@parts
+ 1),
$base
,
] })->hri->all;
my
@items
=
map
{{
id
=>
$_
,
mib
=>
$meta
{
$_
}->{mib},
leaf
=>
$meta
{
$_
}->{leaf},
text
=> (
$meta
{
$_
}->{leaf} .
' ('
.
$meta
{
$_
}->{oid_parts}->[-1] .
')'
),
(
$meta
{
$_
}->{browser} ? (
icon
=>
'icon-folder-close text-info'
)
: (
icon
=>
'icon-folder-close-alt muted'
)),
(
scalar
@{
$meta
{
$_
}->{
index
}}
? (
icon
=>
'icon-th'
.(
$meta
{
$_
}->{browser} ?
' text-info'
:
' muted'
)) : ()),
((
$meta
{
$_
}->{num_children} == 0 and (
$meta
{
$_
}->{type}
or
$meta
{
$_
}->{access} =~ m/^(?:
read
|
write
)/
or
$meta
{
$_
}->{oid_parts}->[-1] == 0))
? (
icon
=>
'icon-leaf'
.(
$meta
{
$_
}->{browser} ?
' text-info'
:
' muted'
)) : ()),
children
=> (
$meta
{
$_
}->{num_children} ? \1 : \0),
state
=> {
opened
=> ((
$meta
{
$_
}->{browser} and
$meta
{
$_
}->{num_children} == 1) ? \1 : \0 ) },
}}
sort
{
$meta
{
$a
}->{oid_parts}->[-1] <=>
$meta
{
$b
}->{oid_parts}->[-1]}
keys
%meta
;
return
\
@items
;
}
true;