relocate repo files so ND2 is the only code
This commit is contained in:
41
lib/App/Netdisco/Web/Plugin/Report/ApChannelDist.pm
Normal file
41
lib/App/Netdisco/Web/Plugin/Report/ApChannelDist.pm
Normal file
@@ -0,0 +1,41 @@
|
||||
package App::Netdisco::Web::Plugin::Report::ApChannelDist;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Wireless',
|
||||
tag => 'apchanneldist',
|
||||
label => 'Access Point Channel Distribution',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/apchanneldist' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('DevicePortWireless')->search(
|
||||
{ channel => { '!=', '0' } },
|
||||
{ select => [ 'channel', { count => 'channel' } ],
|
||||
as => [qw/ channel ch_count /],
|
||||
group_by => [qw/channel/],
|
||||
order_by => { -desc => [qw/count/] },
|
||||
},
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/apchanneldist.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/apchanneldist_csv.tt', { results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
51
lib/App/Netdisco/Web/Plugin/Report/ApClients.pm
Normal file
51
lib/App/Netdisco/Web/Plugin/Report/ApClients.pm
Normal file
@@ -0,0 +1,51 @@
|
||||
package App::Netdisco::Web::Plugin::Report::ApClients;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Wireless',
|
||||
tag => 'apclients',
|
||||
label => 'Access Point Client Count',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/apclients' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(
|
||||
{ 'nodes.time_last' => { '>=', \'me.last_macsuck' } },
|
||||
{ select => [ 'ip', 'dns', 'name', 'model', 'location' ],
|
||||
join => { 'ports' => { 'ssid' => 'nodes' } },
|
||||
'+columns' => [
|
||||
{ 'port' => 'ports.port' },
|
||||
{ 'description' => 'ports.name' },
|
||||
{ 'ssid' => 'ssid.ssid' },
|
||||
{ 'mac_count' => { count => 'nodes.mac' } },
|
||||
],
|
||||
group_by => [
|
||||
'me.ip', 'me.dns', 'me.name', 'me.model',
|
||||
'me.location', 'ports.port', 'ports.descr', 'ports.name', 'ssid.ssid',
|
||||
],
|
||||
order_by => { -desc => [qw/count/] },
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/apclients.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/apclients_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
58
lib/App/Netdisco/Web/Plugin/Report/ApRadioChannelPower.pm
Normal file
58
lib/App/Netdisco/Web/Plugin/Report/ApRadioChannelPower.pm
Normal file
@@ -0,0 +1,58 @@
|
||||
package App::Netdisco::Web::Plugin::Report::ApRadioChannelPower;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
use App::Netdisco::Util::ExpandParams 'expand_hash';
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Wireless',
|
||||
tag => 'apradiochannelpower',
|
||||
label => 'Access Point Radios Channel and Power',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/apradiochannelpower/data' => require_login sub {
|
||||
send_error( 'Missing parameter', 400 )
|
||||
unless ( param('draw') && param('draw') =~ /\d+/ );
|
||||
|
||||
my $rs = schema('netdisco')->resultset('Virtual::ApRadioChannelPower');
|
||||
my $exp_params = expand_hash( scalar params );
|
||||
my $recordsTotal = $rs->count;
|
||||
my @data = $rs->get_datatables_data($exp_params)->hri->all;
|
||||
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json(
|
||||
{ draw => int( param('draw') ),
|
||||
recordsTotal => int($recordsTotal),
|
||||
recordsFiltered => int($recordsFiltered),
|
||||
data => \@data,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
get '/ajax/content/report/apradiochannelpower' => require_login sub {
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
template 'ajax/report/apradiochannelpower.tt', {},
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
my @results
|
||||
= schema('netdisco')->resultset('Virtual::ApRadioChannelPower')
|
||||
->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/apradiochannelpower_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
42
lib/App/Netdisco/Web/Plugin/Report/DeviceAddrNoDNS.pm
Normal file
42
lib/App/Netdisco/Web/Plugin/Report/DeviceAddrNoDNS.pm
Normal file
@@ -0,0 +1,42 @@
|
||||
package App::Netdisco::Web::Plugin::Report::DeviceAddrNoDNS;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'deviceaddrnodns',
|
||||
label => 'Addresses without DNS Entries',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/deviceaddrnodns' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(
|
||||
{ 'device_ips.dns' => undef },
|
||||
{ select => [ 'ip', 'dns', 'name', 'location', 'contact' ],
|
||||
join => [qw/device_ips/],
|
||||
'+columns' => [ { 'alias' => 'device_ips.alias' }, ],
|
||||
order_by => { -asc => [qw/me.ip device_ips.alias/] },
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/deviceaddrnodns.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/deviceaddrnodns_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
38
lib/App/Netdisco/Web/Plugin/Report/DeviceByLocation.pm
Normal file
38
lib/App/Netdisco/Web/Plugin/Report/DeviceByLocation.pm
Normal file
@@ -0,0 +1,38 @@
|
||||
package App::Netdisco::Web::Plugin::Report::DeviceByLocation;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'devicebylocation',
|
||||
label => 'By Location',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/devicebylocation' => require_login sub {
|
||||
my @results
|
||||
= schema('netdisco')->resultset('Device')
|
||||
->columns( [qw/ ip dns name location vendor model /] )
|
||||
->order_by( [qw/ location name ip vendor model /] )->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/devicebylocation.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/devicebylocation_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
41
lib/App/Netdisco/Web/Plugin/Report/DeviceDnsMismatch.pm
Normal file
41
lib/App/Netdisco/Web/Plugin/Report/DeviceDnsMismatch.pm
Normal file
@@ -0,0 +1,41 @@
|
||||
package App::Netdisco::Web::Plugin::Report::DeviceDnsMismatch;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'devicednsmismatch',
|
||||
label => 'Device Name / DNS Mismatches',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/devicednsmismatch' => require_login sub {
|
||||
|
||||
my $suffix = setting('domain_suffix') || '';
|
||||
|
||||
my @results
|
||||
= schema('netdisco')->resultset('Virtual::DeviceDnsMismatch')
|
||||
->search( undef, { bind => [ $suffix, $suffix ] } )
|
||||
->columns( [qw/ ip dns name location contact /] )->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/devicednsmismatch.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/devicednsmismatch_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
58
lib/App/Netdisco/Web/Plugin/Report/DevicePoeStatus.pm
Normal file
58
lib/App/Netdisco/Web/Plugin/Report/DevicePoeStatus.pm
Normal file
@@ -0,0 +1,58 @@
|
||||
package App::Netdisco::Web::Plugin::Report::DevicePoeStatus;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
use App::Netdisco::Util::ExpandParams 'expand_hash';
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'devicepoestatus',
|
||||
label => 'Power over Ethernet (PoE) Status',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/devicepoestatus/data' => require_login sub {
|
||||
send_error( 'Missing parameter', 400 )
|
||||
unless ( param('draw') && param('draw') =~ /\d+/ );
|
||||
|
||||
my $rs = schema('netdisco')->resultset('Virtual::DevicePoeStatus');
|
||||
|
||||
my $exp_params = expand_hash( scalar params );
|
||||
my $recordsTotal = $rs->count;
|
||||
my @data = $rs->get_datatables_data($exp_params)->hri->all;
|
||||
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json(
|
||||
{ draw => int( param('draw') ),
|
||||
recordsTotal => int($recordsTotal),
|
||||
recordsFiltered => int($recordsFiltered),
|
||||
data => \@data,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
get '/ajax/content/report/devicepoestatus' => require_login sub {
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
template 'ajax/report/devicepoestatus.tt', {}, { layout => undef };
|
||||
}
|
||||
else {
|
||||
my @results
|
||||
= schema('netdisco')->resultset('Virtual::DevicePoeStatus')
|
||||
->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/devicepoestatus_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
36
lib/App/Netdisco/Web/Plugin/Report/DuplexMismatch.pm
Normal file
36
lib/App/Netdisco/Web/Plugin/Report/DuplexMismatch.pm
Normal file
@@ -0,0 +1,36 @@
|
||||
package App::Netdisco::Web::Plugin::Report::DuplexMismatch;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'duplexmismatch',
|
||||
label => 'Duplex Mismatches Between Devices',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/duplexmismatch' => require_login sub {
|
||||
my @results
|
||||
= schema('netdisco')->resultset('Virtual::DuplexMismatch')->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/duplexmismatch.tt', { results => $json, },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/duplexmismatch_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
44
lib/App/Netdisco/Web/Plugin/Report/HalfDuplex.pm
Normal file
44
lib/App/Netdisco/Web/Plugin/Report/HalfDuplex.pm
Normal file
@@ -0,0 +1,44 @@
|
||||
package App::Netdisco::Web::Plugin::Report::HalfDuplex;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'halfduplex',
|
||||
label => 'Ports in Half Duplex Mode',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/halfduplex' => require_login sub {
|
||||
my $format = param('format');
|
||||
my @results
|
||||
= schema('netdisco')->resultset('DevicePort')
|
||||
->columns( [qw/ ip port name duplex /] )->search(
|
||||
{ up => 'up', duplex => { '-ilike' => 'half' } },
|
||||
{ '+columns' => [qw/ device.dns device.name /],
|
||||
join => [qw/ device /],
|
||||
collapse => 1,
|
||||
}
|
||||
)->order_by( [qw/ device.dns port /] )->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/halfduplex.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/halfduplex_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
30
lib/App/Netdisco/Web/Plugin/Report/InventoryByModelByOS.pm
Normal file
30
lib/App/Netdisco/Web/Plugin/Report/InventoryByModelByOS.pm
Normal file
@@ -0,0 +1,30 @@
|
||||
package App::Netdisco::Web::Plugin::Report::InventoryByModelByOS;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'inventorybymodelbyos',
|
||||
label => 'Inventory by Model by OS',
|
||||
provides_csv => 0,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/inventorybymodelbyos' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(undef, {
|
||||
columns => [qw/vendor model os os_ver/],
|
||||
select => [ { count => 'os_ver' } ],
|
||||
as => [qw/ os_ver_count /],
|
||||
group_by => [qw/ vendor model os os_ver /],
|
||||
order_by => ['vendor', 'model', { -desc => 'count' }, 'os_ver'],
|
||||
})->hri->all;
|
||||
|
||||
template 'ajax/report/inventorybymodelbyos.tt', { results => \@results, },
|
||||
{ layout => undef };
|
||||
};
|
||||
|
||||
1;
|
||||
168
lib/App/Netdisco/Web/Plugin/Report/IpInventory.pm
Normal file
168
lib/App/Netdisco/Web/Plugin/Report/IpInventory.pm
Normal file
@@ -0,0 +1,168 @@
|
||||
package App::Netdisco::Web::Plugin::Report::IpInventory;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
|
||||
register_report(
|
||||
{ category => 'IP',
|
||||
tag => 'ipinventory',
|
||||
label => 'IP Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/ipinventory' => require_login sub {
|
||||
|
||||
# Default to something simple with no results to prevent
|
||||
# "Search failed!" error
|
||||
my $subnet = param('subnet') || '0.0.0.0/32';
|
||||
$subnet = NetAddr::IP::Lite->new($subnet);
|
||||
$subnet = NetAddr::IP::Lite->new('0.0.0.0/32')
|
||||
if (! $subnet) or ($subnet->addr eq '0.0.0.0');
|
||||
|
||||
my $agenot = param('age_invert') || '0';
|
||||
my ( $start, $end ) = param('daterange') =~ /(\d+-\d+-\d+)/gmx;
|
||||
|
||||
my $limit = param('limit') || 256;
|
||||
my $never = param('never') || '0';
|
||||
my $order = [{-desc => 'age'}, {-asc => 'ip'}];
|
||||
|
||||
# We need a reasonable limit to prevent a potential DoS, especially if
|
||||
# 'never' is true. TODO: Need better input validation, both JS and
|
||||
# server-side to provide user feedback
|
||||
$limit = 8192 if $limit > 8192;
|
||||
|
||||
my $rs1 = schema('netdisco')->resultset('DeviceIp')->search(
|
||||
undef,
|
||||
{ join => 'device',
|
||||
select => [
|
||||
'alias AS ip',
|
||||
\'NULL as mac',
|
||||
'creation AS time_first',
|
||||
'device.last_discover AS time_last',
|
||||
'dns',
|
||||
\'true AS active',
|
||||
\'false AS node',
|
||||
\qq/replace( date_trunc( 'minute', age( now(), device.last_discover ) ) ::text, 'mon', 'month') AS age/
|
||||
],
|
||||
as => [qw( ip mac time_first time_last dns active node age)],
|
||||
}
|
||||
)->hri;
|
||||
|
||||
my $rs2 = schema('netdisco')->resultset('NodeIp')->search(
|
||||
undef,
|
||||
{ columns => [qw( ip mac time_first time_last dns active)],
|
||||
'+select' => [ \'true AS node',
|
||||
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
|
||||
],
|
||||
'+as' => [ 'node', 'age' ],
|
||||
}
|
||||
)->hri;
|
||||
|
||||
my $rs3 = schema('netdisco')->resultset('NodeNbt')->search(
|
||||
undef,
|
||||
{ columns => [qw( ip mac time_first time_last )],
|
||||
'+select' => [
|
||||
'nbname AS dns', 'active',
|
||||
\'true AS node',
|
||||
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
|
||||
],
|
||||
'+as' => [ 'dns', 'active', 'node', 'age' ],
|
||||
}
|
||||
)->hri;
|
||||
|
||||
my $rs_union = $rs1->union( [ $rs2, $rs3 ] );
|
||||
|
||||
if ( $never ) {
|
||||
$subnet = NetAddr::IP::Lite->new('0.0.0.0/32') if ($subnet->bits ne 32);
|
||||
|
||||
my $rs4 = schema('netdisco')->resultset('Virtual::CidrIps')->search(
|
||||
undef,
|
||||
{ bind => [ $subnet->cidr ],
|
||||
columns => [qw( ip mac time_first time_last dns active)],
|
||||
'+select' => [ \'false AS node',
|
||||
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
|
||||
],
|
||||
'+as' => [ 'node', 'age' ],
|
||||
}
|
||||
)->hri;
|
||||
|
||||
$rs_union = $rs_union->union( [$rs4] );
|
||||
}
|
||||
|
||||
my $rs_sub = $rs_union->search(
|
||||
{ ip => { '<<' => $subnet->cidr } },
|
||||
{ select => [
|
||||
\'DISTINCT ON (ip) ip',
|
||||
'mac',
|
||||
'dns',
|
||||
\qq/date_trunc('second', time_last) AS time_last/,
|
||||
\qq/date_trunc('second', time_first) AS time_first/,
|
||||
'active',
|
||||
'node',
|
||||
'age'
|
||||
],
|
||||
as => [
|
||||
'ip', 'mac', 'dns', 'time_last', 'time_first',
|
||||
'active', 'node', 'age'
|
||||
],
|
||||
order_by => [{-asc => 'ip'}, {-desc => 'active'}],
|
||||
}
|
||||
)->as_query;
|
||||
|
||||
my $rs;
|
||||
if ( $start && $end ) {
|
||||
$start = $start . ' 00:00:00';
|
||||
$end = $end . ' 23:59:59';
|
||||
|
||||
if ( $agenot ) {
|
||||
$rs = $rs_union->search(
|
||||
{ -or => [
|
||||
time_first => [ undef ],
|
||||
time_last => [ { '<', $start }, { '>', $end } ]
|
||||
]
|
||||
},
|
||||
{ from => { me => $rs_sub }, }
|
||||
);
|
||||
}
|
||||
else {
|
||||
$rs = $rs_union->search(
|
||||
{ -or => [
|
||||
-and => [
|
||||
time_first => undef,
|
||||
time_last => undef,
|
||||
],
|
||||
-and => [
|
||||
time_last => { '>=', $start },
|
||||
time_last => { '<=', $end },
|
||||
],
|
||||
],
|
||||
},
|
||||
{ from => { me => $rs_sub }, }
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$rs = $rs_union->search( undef, { from => { me => $rs_sub }, } );
|
||||
}
|
||||
|
||||
my @results = $rs->order_by($order)->limit($limit)->all;
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/ipinventory.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/ipinventory_csv.tt', { results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
166
lib/App/Netdisco/Web/Plugin/Report/ModuleInventory.pm
Normal file
166
lib/App/Netdisco/Web/Plugin/Report/ModuleInventory.pm
Normal file
@@ -0,0 +1,166 @@
|
||||
package App::Netdisco::Web::Plugin::Report::ModuleInventory;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
use App::Netdisco::Util::ExpandParams 'expand_hash';
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
use List::MoreUtils ();
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'moduleinventory',
|
||||
label => 'Module Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
hook 'before' => sub {
|
||||
return
|
||||
unless (
|
||||
request->path eq uri_for('/report/moduleinventory')->path
|
||||
or index( request->path,
|
||||
uri_for('/ajax/content/report/moduleinventory')->path ) == 0
|
||||
);
|
||||
|
||||
# view settings
|
||||
var('module_options' => [
|
||||
{ name => 'fruonly',
|
||||
label => 'FRU Only',
|
||||
default => 'on'
|
||||
},
|
||||
{ name => 'matchall',
|
||||
label => 'Match All Options',
|
||||
default => 'on'
|
||||
},
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
hook 'before_template' => sub {
|
||||
my $tokens = shift;
|
||||
|
||||
return
|
||||
unless (
|
||||
request->path eq uri_for('/report/moduleinventory')->path
|
||||
or index( request->path,
|
||||
uri_for('/ajax/content/report/moduleinventory')->path ) == 0
|
||||
);
|
||||
|
||||
# used in the search sidebar template to set selected items
|
||||
foreach my $opt (qw/class/) {
|
||||
my $p = (
|
||||
ref [] eq ref param($opt)
|
||||
? param($opt)
|
||||
: ( param($opt) ? [ param($opt) ] : [] )
|
||||
);
|
||||
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
|
||||
}
|
||||
};
|
||||
|
||||
get '/ajax/content/report/moduleinventory/data' => require_login sub {
|
||||
send_error( 'Missing parameter', 400 )
|
||||
unless ( param('draw') && param('draw') =~ /\d+/ );
|
||||
|
||||
my $rs = schema('netdisco')->resultset('DeviceModule');
|
||||
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
|
||||
|
||||
if ( param('device') ) {
|
||||
my @ips = schema('netdisco')->resultset('Device')
|
||||
->search_fuzzy( param('device') )->get_column('ip')->all;
|
||||
|
||||
params->{'ips'} = \@ips;
|
||||
}
|
||||
|
||||
$rs = $rs->search_by_field( scalar params )->columns(
|
||||
[ 'ip', 'description', 'name', 'class',
|
||||
'type', 'serial', 'hw_ver', 'fw_ver',
|
||||
'sw_ver', 'model'
|
||||
]
|
||||
)->search(
|
||||
{},
|
||||
{ '+columns' => [qw/ device.dns device.name /],
|
||||
join => 'device',
|
||||
collapse => 1,
|
||||
}
|
||||
);
|
||||
|
||||
my $exp_params = expand_hash( scalar params );
|
||||
|
||||
my $recordsTotal = $rs->count;
|
||||
|
||||
my @data = $rs->get_datatables_data($exp_params)->hri->all;
|
||||
|
||||
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json(
|
||||
{ draw => int( param('draw') ),
|
||||
recordsTotal => int($recordsTotal),
|
||||
recordsFiltered => int($recordsFiltered),
|
||||
data => \@data,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
get '/ajax/content/report/moduleinventory' => require_login sub {
|
||||
|
||||
my $has_opt = List::MoreUtils::any { param($_) }
|
||||
qw/device description name type model serial class/;
|
||||
|
||||
my $rs = schema('netdisco')->resultset('DeviceModule');
|
||||
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
|
||||
my @results;
|
||||
|
||||
if ( $has_opt && !request->is_ajax ) {
|
||||
|
||||
if ( param('device') ) {
|
||||
my @ips = schema('netdisco')->resultset('Device')
|
||||
->search_fuzzy( param('device') )->get_column('ip')->all;
|
||||
|
||||
params->{'ips'} = \@ips;
|
||||
}
|
||||
|
||||
@results = $rs->search_by_field( scalar params )->columns(
|
||||
[ 'ip', 'description', 'name', 'class',
|
||||
'type', 'serial', 'hw_ver', 'fw_ver',
|
||||
'sw_ver', 'model'
|
||||
]
|
||||
)->search(
|
||||
{},
|
||||
{ '+columns' => [qw/ device.dns device.name /],
|
||||
join => 'device',
|
||||
collapse => 1,
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
}
|
||||
elsif ( !$has_opt ) {
|
||||
@results = $rs->search(
|
||||
{ class => { '!=', undef } },
|
||||
{ select => [ 'class', { count => 'class' } ],
|
||||
as => [qw/ class count /],
|
||||
group_by => [qw/ class /]
|
||||
}
|
||||
)->order_by( { -desc => 'count' } )->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
}
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/moduleinventory.tt',
|
||||
{ results => $json, opt => $has_opt },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/moduleinventory_csv.tt',
|
||||
{ results => \@results, opt => $has_opt },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
110
lib/App/Netdisco/Web/Plugin/Report/Netbios.pm
Normal file
110
lib/App/Netdisco/Web/Plugin/Report/Netbios.pm
Normal file
@@ -0,0 +1,110 @@
|
||||
package App::Netdisco::Web::Plugin::Report::Netbios;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
use App::Netdisco::Util::ExpandParams 'expand_hash';
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Node',
|
||||
tag => 'netbios',
|
||||
label => 'NetBIOS Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
hook 'before_template' => sub {
|
||||
my $tokens = shift;
|
||||
|
||||
return
|
||||
unless ( request->path eq uri_for('/report/netbios')->path
|
||||
or
|
||||
index( request->path, uri_for('/ajax/content/report/netbios')->path )
|
||||
== 0 );
|
||||
|
||||
# used in the search sidebar template to set selected items
|
||||
foreach my $opt (qw/domain/) {
|
||||
my $p = (
|
||||
ref [] eq ref param($opt)
|
||||
? param($opt)
|
||||
: ( param($opt) ? [ param($opt) ] : [] )
|
||||
);
|
||||
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
|
||||
}
|
||||
};
|
||||
|
||||
get '/ajax/content/report/netbios/data' => require_login sub {
|
||||
send_error( 'Missing parameter', 400 )
|
||||
unless ( param('draw') && param('draw') =~ /\d+/ );
|
||||
|
||||
my $domain = param('domain');
|
||||
|
||||
my $rs = schema('netdisco')->resultset('NodeNbt');
|
||||
|
||||
my $search = $domain eq 'blank' ? '' : $domain;
|
||||
$rs = $rs->search( { domain => $search } )
|
||||
->order_by( [ { -asc => 'domain' }, { -desc => 'time_last' } ] );
|
||||
|
||||
my $exp_params = expand_hash( scalar params );
|
||||
|
||||
my $recordsTotal = $rs->count;
|
||||
|
||||
my @data = $rs->get_datatables_data($exp_params)->hri->all;
|
||||
|
||||
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json(
|
||||
{ draw => int( param('draw') ),
|
||||
recordsTotal => int($recordsTotal),
|
||||
recordsFiltered => int($recordsFiltered),
|
||||
data => \@data,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
get '/ajax/content/report/netbios' => require_login sub {
|
||||
|
||||
my $domain = param('domain');
|
||||
|
||||
my $rs = schema('netdisco')->resultset('NodeNbt');
|
||||
my @results;
|
||||
|
||||
if ( defined $domain && !request->is_ajax ) {
|
||||
my $search = $domain eq 'blank' ? '' : $domain;
|
||||
@results
|
||||
= $rs->search( { domain => $search } )
|
||||
->order_by( [ { -asc => 'domain' }, { -desc => 'time_last' } ] )
|
||||
->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
}
|
||||
elsif ( !defined $domain ) {
|
||||
@results = $rs->search(
|
||||
{},
|
||||
{ select => [ 'domain', { count => 'domain' } ],
|
||||
as => [qw/ domain count /],
|
||||
group_by => [qw/ domain /]
|
||||
}
|
||||
)->order_by( { -desc => 'count' } )->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
}
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/netbios.tt',
|
||||
{ results => $json, opt => $domain },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/netbios_csv.tt',
|
||||
{ results => \@results, opt => $domain },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
51
lib/App/Netdisco/Web/Plugin/Report/NodeMultiIPs.pm
Normal file
51
lib/App/Netdisco/Web/Plugin/Report/NodeMultiIPs.pm
Normal file
@@ -0,0 +1,51 @@
|
||||
package App::Netdisco::Web::Plugin::Report::NodeMultiIPs;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Node',
|
||||
tag => 'nodemultiips',
|
||||
label => 'Nodes with multiple active IP addresses',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/nodemultiips' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Node')->search(
|
||||
{},
|
||||
{ select => [ 'mac', 'switch', 'port' ],
|
||||
join => [qw/device ips oui/],
|
||||
'+columns' => [
|
||||
{ 'dns' => 'device.dns' },
|
||||
{ 'name' => 'device.name' },
|
||||
{ 'ip_count' => { count => 'ips.ip' } },
|
||||
{ 'vendor' => 'oui.company' }
|
||||
],
|
||||
group_by => [
|
||||
qw/ me.mac me.switch me.port device.dns device.name oui.company/
|
||||
],
|
||||
having => \[ 'count(ips.ip) > ?', [ count => 1 ] ],
|
||||
order_by => { -desc => [qw/count/] },
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/nodemultiips.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/nodemultiips_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
133
lib/App/Netdisco/Web/Plugin/Report/NodeVendor.pm
Normal file
133
lib/App/Netdisco/Web/Plugin/Report/NodeVendor.pm
Normal file
@@ -0,0 +1,133 @@
|
||||
package App::Netdisco::Web::Plugin::Report::NodeVendor;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
use App::Netdisco::Util::ExpandParams 'expand_hash';
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Node',
|
||||
tag => 'nodevendor',
|
||||
label => 'Node Vendor Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
hook 'before_template' => sub {
|
||||
my $tokens = shift;
|
||||
|
||||
return
|
||||
unless (
|
||||
request->path eq uri_for('/report/nodevendor')->path
|
||||
or index( request->path,
|
||||
uri_for('/ajax/content/report/nodevendor')->path ) == 0
|
||||
);
|
||||
|
||||
# used in the search sidebar template to set selected items
|
||||
foreach my $opt (qw/vendor/) {
|
||||
my $p = (
|
||||
ref [] eq ref param($opt)
|
||||
? param($opt)
|
||||
: ( param($opt) ? [ param($opt) ] : [] )
|
||||
);
|
||||
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
|
||||
}
|
||||
};
|
||||
|
||||
get '/ajax/content/report/nodevendor/data' => require_login sub {
|
||||
send_error( 'Missing parameter', 400 )
|
||||
unless ( param('draw') && param('draw') =~ /\d+/ );
|
||||
|
||||
my $vendor = param('vendor');
|
||||
|
||||
my $rs = schema('netdisco')->resultset('Node');
|
||||
|
||||
my $match = $vendor eq 'blank' ? undef : $vendor;
|
||||
|
||||
$rs = $rs->search( { 'oui.abbrev' => $match },
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
|
||||
join => [qw/ oui device /],
|
||||
collapse => 1,
|
||||
});
|
||||
|
||||
unless ( param('archived') ) {
|
||||
$rs = $rs->search( { -bool => 'me.active' } );
|
||||
}
|
||||
|
||||
my $exp_params = expand_hash( scalar params );
|
||||
|
||||
my $recordsTotal = $rs->count;
|
||||
|
||||
my @data = $rs->get_datatables_data($exp_params)->hri->all;
|
||||
|
||||
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json(
|
||||
{ draw => int( param('draw') ),
|
||||
recordsTotal => int($recordsTotal),
|
||||
recordsFiltered => int($recordsFiltered),
|
||||
data => \@data,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
get '/ajax/content/report/nodevendor' => require_login sub {
|
||||
|
||||
my $vendor = param('vendor');
|
||||
|
||||
my $rs = schema('netdisco')->resultset('Node');
|
||||
my @results;
|
||||
|
||||
if ( defined $vendor && !request->is_ajax ) {
|
||||
|
||||
my $match = $vendor eq 'blank' ? undef : $vendor;
|
||||
|
||||
$rs = $rs->search( { 'oui.abbrev' => $match },
|
||||
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
|
||||
join => [qw/ oui device /],
|
||||
collapse => 1,
|
||||
});
|
||||
|
||||
unless ( param('archived') ) {
|
||||
$rs = $rs->search( { -bool => 'me.active' } );
|
||||
}
|
||||
|
||||
@results = $rs->hri->all;
|
||||
return unless scalar @results;
|
||||
}
|
||||
elsif ( !defined $vendor ) {
|
||||
$rs = $rs->search(
|
||||
{ },
|
||||
{ join => 'oui',
|
||||
select => [ 'oui.abbrev', { count => 'me.mac' } ],
|
||||
as => [qw/ vendor count /],
|
||||
group_by => [qw/ oui.abbrev /]
|
||||
}
|
||||
)->order_by( { -desc => 'count' } );
|
||||
|
||||
unless ( param('archived') ) {
|
||||
$rs = $rs->search( { -bool => 'me.active' } );
|
||||
}
|
||||
|
||||
@results = $rs->hri->all;
|
||||
return unless scalar @results;
|
||||
}
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/nodevendor.tt',
|
||||
{ results => $json, opt => $vendor },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/nodevendor_csv.tt',
|
||||
{ results => \@results, opt => $vendor },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
54
lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm
Normal file
54
lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm
Normal file
@@ -0,0 +1,54 @@
|
||||
package App::Netdisco::Web::Plugin::Report::NodesDiscovered;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
use App::Netdisco::Util::Web 'sql_match';
|
||||
|
||||
register_report(
|
||||
{ category => 'Node',
|
||||
tag => 'nodesdiscovered',
|
||||
label => 'Nodes discovered through LLDP/CDP',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/nodesdiscovered' => require_login sub {
|
||||
my $op = param('matchall') ? '-and' : '-or';
|
||||
|
||||
my @results = schema('netdisco')->resultset('Virtual::NodesDiscovered')
|
||||
->search({
|
||||
$op => [
|
||||
(param('aps') ?
|
||||
('me.remote_type' => { -ilike => 'AP:%' }) : ()),
|
||||
(param('phones') ?
|
||||
('me.remote_type' => { -ilike => '%ip_phone%' }) : ()),
|
||||
(param('remote_id') ?
|
||||
('me.remote_id' => { -ilike => scalar sql_match(param('remote_id')) }) : ()),
|
||||
(param('remote_type') ? ('-or' => [
|
||||
map {( 'me.remote_type' => { -ilike => scalar sql_match($_) } )}
|
||||
grep { $_ }
|
||||
(ref param('remote_type') ? @{param('remote_type')} : param('remote_type'))
|
||||
]) : ()),
|
||||
],
|
||||
})
|
||||
->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/nodesdiscovered.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/nodesdiscovered_csv.tt',
|
||||
{ results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
45
lib/App/Netdisco/Web/Plugin/Report/PortAdminDown.pm
Normal file
45
lib/App/Netdisco/Web/Plugin/Report/PortAdminDown.pm
Normal file
@@ -0,0 +1,45 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortAdminDown;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'portadmindown',
|
||||
label => 'Ports administratively disabled',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/portadmindown' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(
|
||||
{ 'up_admin' => 'down' },
|
||||
{ select => [ 'ip', 'dns', 'name' ],
|
||||
join => [ 'ports' ],
|
||||
'+columns' => [
|
||||
{ 'port' => 'ports.port' },
|
||||
{ 'description' => 'ports.name' },
|
||||
{ 'up_admin' => 'ports.up_admin' },
|
||||
]
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/portadmindown.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portadmindown_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
45
lib/App/Netdisco/Web/Plugin/Report/PortBlocking.pm
Normal file
45
lib/App/Netdisco/Web/Plugin/Report/PortBlocking.pm
Normal file
@@ -0,0 +1,45 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortBlocking;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'portblocking',
|
||||
label => 'Ports that are blocking',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/portblocking' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(
|
||||
{ 'stp' => [ 'blocking', 'broken' ], 'up' => { '!=', 'down' } },
|
||||
{ select => [ 'ip', 'dns', 'name' ],
|
||||
join => ['ports'],
|
||||
'+columns' => [
|
||||
{ 'port' => 'ports.port' },
|
||||
{ 'description' => 'ports.name' },
|
||||
{ 'stp' => 'ports.stp' },
|
||||
]
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/portblocking.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portblocking_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
66
lib/App/Netdisco/Web/Plugin/Report/PortLog.pm
Normal file
66
lib/App/Netdisco/Web/Plugin/Report/PortLog.pm
Normal file
@@ -0,0 +1,66 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortLog;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report({
|
||||
tag => 'portlog',
|
||||
label => 'Port Control Log',
|
||||
category => 'Port', # not used
|
||||
hidden => true,
|
||||
});
|
||||
|
||||
sub _sanity_ok {
|
||||
return 0 unless
|
||||
param('ip') =~ m/^[[:print:]]+$/
|
||||
and param('port') =~ m/^[[:print:]]+$/
|
||||
and param('log') =~ m/^[[:print:]]+$/;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ajax '/ajax/control/report/portlog/add' => require_login sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $user = schema('netdisco')->resultset('DevicePortLog')
|
||||
->create({
|
||||
ip => param('ip'),
|
||||
port => param('port'),
|
||||
reason => 'other',
|
||||
log => param('log'),
|
||||
username => session('logged_in_user'),
|
||||
userip => request->remote_address,
|
||||
action => 'comment',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/content/report/portlog' => require_login sub {
|
||||
my $device = param('q');
|
||||
my $port = param('f');
|
||||
send_error('Bad Request', 400) unless $device and $port;
|
||||
|
||||
$device = schema('netdisco')->resultset('Device')
|
||||
->search_for_device($device);
|
||||
return unless $device;
|
||||
|
||||
my $set = schema('netdisco')->resultset('DevicePortLog')->search({
|
||||
ip => $device->ip,
|
||||
port => $port,
|
||||
}, {
|
||||
order_by => { -desc => [qw/creation/] },
|
||||
rows => 200,
|
||||
})->with_times;
|
||||
|
||||
content_type('text/html');
|
||||
template 'ajax/report/portlog.tt', {
|
||||
results => $set,
|
||||
}, { layout => undef };
|
||||
};
|
||||
|
||||
true;
|
||||
53
lib/App/Netdisco/Web/Plugin/Report/PortMultiNodes.pm
Normal file
53
lib/App/Netdisco/Web/Plugin/Report/PortMultiNodes.pm
Normal file
@@ -0,0 +1,53 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortMultiNodes;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'portmultinodes',
|
||||
label => 'Ports with multiple nodes attached',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/portmultinodes' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('Device')->search(
|
||||
{ 'ports.remote_ip' => undef,
|
||||
(param('vlan') ?
|
||||
('ports.vlan' => param('vlan'), 'nodes.vlan' => param('vlan')) : ()),
|
||||
'nodes.active' => 1,
|
||||
'wireless.port' => undef
|
||||
},
|
||||
{ select => [ 'ip', 'dns', 'name' ],
|
||||
join => { 'ports' => [ 'wireless', 'nodes' ] },
|
||||
'+columns' => [
|
||||
{ 'port' => 'ports.port' },
|
||||
{ 'description' => 'ports.name' },
|
||||
{ 'mac_count' => { count => 'nodes.mac' } },
|
||||
],
|
||||
group_by => [qw/me.ip me.dns me.name ports.port ports.name/],
|
||||
having => \[ 'count(nodes.mac) > ?', [ count => 1 ] ],
|
||||
order_by => { -desc => [qw/count/] },
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/portmultinodes.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portmultinodes_csv.tt',
|
||||
{ results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
79
lib/App/Netdisco/Web/Plugin/Report/PortSsid.pm
Normal file
79
lib/App/Netdisco/Web/Plugin/Report/PortSsid.pm
Normal file
@@ -0,0 +1,79 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortSsid;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Port',
|
||||
tag => 'portssid',
|
||||
label => 'Port SSID Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
hook 'before_template' => sub {
|
||||
my $tokens = shift;
|
||||
|
||||
return
|
||||
unless (
|
||||
request->path eq uri_for('/report/portssid')->path
|
||||
or index(
|
||||
request->path, uri_for('/ajax/content/report/portssid')->path
|
||||
) == 0
|
||||
);
|
||||
|
||||
# used in the search sidebar template to set selected items
|
||||
foreach my $opt (qw/ssid/) {
|
||||
my $p = (
|
||||
ref [] eq ref param($opt)
|
||||
? param($opt)
|
||||
: ( param($opt) ? [ param($opt) ] : [] )
|
||||
);
|
||||
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
|
||||
}
|
||||
};
|
||||
|
||||
get '/ajax/content/report/portssid' => require_login sub {
|
||||
|
||||
my $ssid = param('ssid');
|
||||
|
||||
my $rs = schema('netdisco')->resultset('DevicePortSsid');
|
||||
|
||||
if ( defined $ssid ) {
|
||||
|
||||
$rs = $rs->search(
|
||||
{ ssid => $ssid },
|
||||
{ '+columns' => [
|
||||
qw/ device.dns device.name device.model device.vendor port.port/
|
||||
],
|
||||
join => [qw/ device port /],
|
||||
collapse => 1,
|
||||
}
|
||||
)->order_by( [qw/ port.ip port.port /] )->hri;
|
||||
}
|
||||
else {
|
||||
$rs = $rs->get_ssids->hri;
|
||||
|
||||
}
|
||||
|
||||
my @results = $rs->all;
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/portssid.tt',
|
||||
{ results => $json, opt => $ssid },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portssid_csv.tt',
|
||||
{ results => \@results, opt => $ssid },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
33
lib/App/Netdisco/Web/Plugin/Report/PortUtilization.pm
Normal file
33
lib/App/Netdisco/Web/Plugin/Report/PortUtilization.pm
Normal file
@@ -0,0 +1,33 @@
|
||||
package App::Netdisco::Web::Plugin::Report::PortUtilization;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Device',
|
||||
tag => 'portutilization',
|
||||
label => 'Port Utilization',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/portutilization' => require_login sub {
|
||||
return unless schema('netdisco')->resultset('Device')->count;
|
||||
my @results = schema('netdisco')->resultset('Virtual::PortUtilization')->hri->all;
|
||||
|
||||
if (request->is_ajax) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/portutilization.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portutilization_csv.tt', { results => \@results, },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
35
lib/App/Netdisco/Web/Plugin/Report/SsidInventory.pm
Normal file
35
lib/App/Netdisco/Web/Plugin/Report/SsidInventory.pm
Normal file
@@ -0,0 +1,35 @@
|
||||
package App::Netdisco::Web::Plugin::Report::SsidInventory;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'Wireless',
|
||||
tag => 'ssidinventory',
|
||||
label => 'SSID Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/ssidinventory' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('DevicePortSsid')
|
||||
->get_ssids->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json( \@results );
|
||||
template 'ajax/report/portssid.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/portssid_csv.tt', { results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
42
lib/App/Netdisco/Web/Plugin/Report/SubnetUtilization.pm
Normal file
42
lib/App/Netdisco/Web/Plugin/Report/SubnetUtilization.pm
Normal file
@@ -0,0 +1,42 @@
|
||||
package App::Netdisco::Web::Plugin::Report::SubnetUtilization;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report({
|
||||
category => 'IP',
|
||||
tag => 'subnets',
|
||||
label => 'Subnet Utilization',
|
||||
provides_csv => 1,
|
||||
});
|
||||
|
||||
get '/ajax/content/report/subnets' => require_login sub {
|
||||
my $subnet = param('subnet') || '0.0.0.0/32';
|
||||
my $agenot = param('age_invert') || '0';
|
||||
my ( $start, $end ) = param('daterange') =~ /(\d+-\d+-\d+)/gmx;
|
||||
|
||||
$start = $start . ' 00:00:00';
|
||||
$end = $end . ' 23:59:59';
|
||||
|
||||
my @results = schema('netdisco')->resultset('Virtual::SubnetUtilization')
|
||||
->search(undef,{
|
||||
bind => [ $subnet, $start, $end, $start, $subnet, $start, $start ],
|
||||
})->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
template 'ajax/report/subnets.tt', { results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/subnets_csv.tt', { results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
46
lib/App/Netdisco/Web/Plugin/Report/VlanInventory.pm
Normal file
46
lib/App/Netdisco/Web/Plugin/Report/VlanInventory.pm
Normal file
@@ -0,0 +1,46 @@
|
||||
package App::Netdisco::Web::Plugin::Report::VlanInventory;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::DBIC;
|
||||
use Dancer::Plugin::Auth::Extensible;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_report(
|
||||
{ category => 'VLAN',
|
||||
tag => 'vlaninventory',
|
||||
label => 'VLAN Inventory',
|
||||
provides_csv => 1,
|
||||
}
|
||||
);
|
||||
|
||||
get '/ajax/content/report/vlaninventory' => require_login sub {
|
||||
my @results = schema('netdisco')->resultset('DeviceVlan')->search(
|
||||
{ 'me.description' => { '!=', 'NULL' } },
|
||||
{ join => { 'ports' => 'vlan' },
|
||||
select => [
|
||||
'me.vlan',
|
||||
'me.description',
|
||||
{ count => { distinct => 'me.ip' } },
|
||||
{ count => 'ports.vlan' }
|
||||
],
|
||||
as => [qw/ vlan description dcount pcount /],
|
||||
group_by => [qw/ me.vlan me.description /],
|
||||
}
|
||||
)->hri->all;
|
||||
|
||||
return unless scalar @results;
|
||||
|
||||
if ( request->is_ajax ) {
|
||||
my $json = to_json (\@results);
|
||||
template 'ajax/report/vlaninventory.tt', { results => $json },
|
||||
{ layout => undef };
|
||||
}
|
||||
else {
|
||||
header( 'Content-Type' => 'text/comma-separated-values' );
|
||||
template 'ajax/report/vlaninventory_csv.tt', { results => \@results },
|
||||
{ layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
true;
|
||||
Reference in New Issue
Block a user