diff --git a/Netdisco/Changes b/Netdisco/Changes index 781e3fff..4a63b7e2 100644 --- a/Netdisco/Changes +++ b/Netdisco/Changes @@ -1,3 +1,33 @@ +2.029008 + + [ENHANCEMENTS] + + * Setting for items in number of records per table page menu (table_showrecordsmenu). + +2.029007 - 2014-09-12 + + [ENHANCEMENTS] + + * [#123] Allow devices with no LLDP/CDP to be found as Nodes + * Accept host names to netdisco-do show + * [#139] Add PaloAlto and IOS-XR support to netdisco-sshcollector + + [BUG FIXES] + + * Skip device aliases which cannot be parsed as IPs + * [#137] do not attempt DNS resolution on bad IPs + +2.029006 - 2014-08-25 + + [NEW FEATURES] + + * netdisco-sshcollector script to get ARP data on devices without SNMP (C. Ramseyer) + * Add Nodes discovered through LLDP/CDP report (replaces IP Phones report) + + [ENHANCEMENTS] + + * Port search also searches on the Remote ID and Type + 2.029005 - 2014-08-13 [ENHANCEMENTS] diff --git a/Netdisco/MANIFEST b/Netdisco/MANIFEST index 8ef8ad38..e1080c3c 100644 --- a/Netdisco/MANIFEST +++ b/Netdisco/MANIFEST @@ -6,6 +6,7 @@ bin/netdisco-db-deploy bin/netdisco-deploy bin/netdisco-do bin/netdisco-rancid-export +bin/netdisco-sshcollector bin/netdisco-web bin/netdisco-web-fg Changes @@ -79,9 +80,9 @@ lib/App/Netdisco/DB/Result/Virtual/DevicePoeStatus.pm lib/App/Netdisco/DB/Result/Virtual/DuplexMismatch.pm lib/App/Netdisco/DB/Result/Virtual/GenericReport.pm lib/App/Netdisco/DB/Result/Virtual/NodeMonitor.pm +lib/App/Netdisco/DB/Result/Virtual/NodesDiscovered.pm lib/App/Netdisco/DB/Result/Virtual/NodeWithAge.pm lib/App/Netdisco/DB/Result/Virtual/OrphanedDevices.pm -lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm lib/App/Netdisco/DB/Result/Virtual/PollerPerformance.pm lib/App/Netdisco/DB/Result/Virtual/PortUtilization.pm lib/App/Netdisco/DB/Result/Virtual/SlowDevices.pm @@ -148,6 +149,11 @@ lib/App/Netdisco/Manual/Deployment.pod lib/App/Netdisco/Manual/Developing.pod lib/App/Netdisco/Manual/ReleaseNotes.pod lib/App/Netdisco/Manual/WritingPlugins.pod +lib/App/Netdisco/SSHCollector/Platform/ACE.pm +lib/App/Netdisco/SSHCollector/Platform/BigIP.pm +lib/App/Netdisco/SSHCollector/Platform/IOS.pm +lib/App/Netdisco/SSHCollector/Platform/IOSXR.pm +lib/App/Netdisco/SSHCollector/Platform/PaloAlto.pm lib/App/Netdisco/Util/Daemon.pm lib/App/Netdisco/Util/Device.pm lib/App/Netdisco/Util/DNS.pm @@ -198,8 +204,8 @@ lib/App/Netdisco/Web/Plugin/Report/IpInventory.pm lib/App/Netdisco/Web/Plugin/Report/ModuleInventory.pm lib/App/Netdisco/Web/Plugin/Report/Netbios.pm lib/App/Netdisco/Web/Plugin/Report/NodeMultiIPs.pm +lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm lib/App/Netdisco/Web/Plugin/Report/NodeVendor.pm -lib/App/Netdisco/Web/Plugin/Report/PhonesDiscovered.pm lib/App/Netdisco/Web/Plugin/Report/PortAdminDown.pm lib/App/Netdisco/Web/Plugin/Report/PortBlocking.pm lib/App/Netdisco/Web/Plugin/Report/PortLog.pm @@ -341,10 +347,10 @@ share/views/ajax/report/netbios.tt share/views/ajax/report/netbios_csv.tt share/views/ajax/report/nodemultiips.tt share/views/ajax/report/nodemultiips_csv.tt +share/views/ajax/report/nodesdiscovered.tt +share/views/ajax/report/nodesdiscovered_csv.tt share/views/ajax/report/nodevendor.tt share/views/ajax/report/nodevendor_csv.tt -share/views/ajax/report/phonesdiscovered.tt -share/views/ajax/report/phonesdiscovered_csv.tt share/views/ajax/report/portadmindown.tt share/views/ajax/report/portadmindown_csv.tt share/views/ajax/report/portblocking.tt @@ -388,6 +394,7 @@ share/views/sidebar/device/ports.tt share/views/sidebar/report/ipinventory.tt share/views/sidebar/report/moduleinventory.tt share/views/sidebar/report/netbios.tt +share/views/sidebar/report/nodesdiscovered.tt share/views/sidebar/report/nodevendor.tt share/views/sidebar/report/portlog.tt share/views/sidebar/report/portssid.tt diff --git a/Netdisco/META.yml b/Netdisco/META.yml index 2d7e34e7..f593b944 100644 --- a/Netdisco/META.yml +++ b/Netdisco/META.yml @@ -22,8 +22,10 @@ no_index: - share - t recommends: + Expect: 0 Graph: 0 GraphViz: 0 + Net::OpenSSH: 0 requires: Algorithm::Cron: 0.07 AnyEvent: 7.05 @@ -89,4 +91,4 @@ resources: homepage: http://netdisco.org/ license: http://opensource.org/licenses/bsd-license.php repository: git://git.code.sf.net/p/netdisco/netdisco-ng -version: 2.029005 +version: 2.029007 diff --git a/Netdisco/Makefile.PL b/Netdisco/Makefile.PL index 8e818eb4..5f1aa25b 100644 --- a/Netdisco/Makefile.PL +++ b/Netdisco/Makefile.PL @@ -70,6 +70,8 @@ if ( $^O eq 'linux' ) { recommends 'Graph' => 0; recommends 'GraphViz' => 0; +recommends 'Net::OpenSSH' => 0; +recommends 'Expect' => 0; install_share 'share'; @@ -82,6 +84,7 @@ install_script 'bin/netdisco-daemon'; install_script 'bin/netdisco-web-fg'; install_script 'bin/netdisco-web'; install_script 'bin/netdisco-rancid-export'; +install_script 'bin/netdisco-sshcollector'; resources homepage => 'http://netdisco.org/', diff --git a/Netdisco/bin/netdisco-do b/Netdisco/bin/netdisco-do index 4b2e0d53..724892b6 100755 --- a/Netdisco/bin/netdisco-do +++ b/Netdisco/bin/netdisco-do @@ -113,7 +113,17 @@ unless ($action) { } use App::Netdisco::Util::SNMP (); + use App::Netdisco::Util::Device 'get_device'; + use NetAddr::IP::Lite ':lower'; + use Scalar::Util 'blessed'; sub show { + my $ip = NetAddr::IP::Lite->new($device) + or return ('error', "Bad host or IP: $device"); + my $dev = get_device($ip->addr); + unless (blessed $dev and $dev->in_storage) { + return ('error', "Don't know device: $device"); + } + $extra ||= 'interfaces'; my $class = undef; ($class, $extra) = split(/::([^:]+)$/, $extra); if ($class and $extra) { @@ -123,7 +133,7 @@ unless ($action) { $extra = $class; undef $class; } - my $i = App::Netdisco::Util::SNMP::snmp_connect($device, $class); + my $i = App::Netdisco::Util::SNMP::snmp_connect($dev, $class); Data::Printer::p($i->$extra); return ('done', "Showed $extra response from $device."); } diff --git a/Netdisco/bin/netdisco-sshcollector b/Netdisco/bin/netdisco-sshcollector new file mode 100644 index 00000000..033fea04 --- /dev/null +++ b/Netdisco/bin/netdisco-sshcollector @@ -0,0 +1,274 @@ +#!/usr/bin/env perl + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +netdisco-sshcollector - Collect ARP data for Netdisco from devices without +full SNMP support + +=head1 DESCRIPTION + +Collects ARP data for Netdisco from devices without full SNMP support. +Currently, ARP tables can be retrieved from the following device classes: + +=over 4 + +=item * L - Cisco ACE (Application Control Engine) + +=item * L - F5 Networks BigIP + +=item * L - Cisco IOS + +=item * L - Cisco IOS XR + +=item * L - PaloAlto devices + +=back + +The collected arp entries are then directly stored in the netdisco database. + +=head1 CONFIGURATION + +The following should go into your Netdisco 2 configuration file, "C<< +~/environments/deployment.yml >>" + +=over 4 + +=item C + +Data is collected from the machines specified in this setting. The format is a +list of dictionaries. The keys C, C, C, and C +are required. Optionally the C key can be used instead of the +C. For example: + + sshcollector: + - ip: '192.0.2.1' + user: oliver + password: letmein + platform: IOS + - hostname: 'core-router.example.com' + user: oliver + password: letmein + platform: IOS + +Platform is the final part of the classname to be instantiated to query the +host, e.g. platform B will be queried using +C. + +If the password is "-", public key authentication will be attempted. + +=back + +=head1 ADDING DEVICES + +Additional device classes can be easily integrated just by adding and +additonal class to the C namespace. +This class must implement an C method which returns +an array of hashrefs in the format + + @result = ({ ip => IPADDR, mac => MACADDR }, ...) + +The parameter C<$ssh> is an active C connection to the host. +Depending on the target system, it can be queried using simple methods like + + my @data = $ssh->capture("show whatever") + +or automated via Expect - this is mostly useful for non-Linux appliances which +don't support command execution via ssh: + + my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command"; + my $expect = Expect->init($pty); + my $prompt = qr/#/; + my ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + $expect->send("terminal length 0\n"); + # etc... + +The returned IP and MAC addresses should be in a format that the respective +B and B datatypes in PostgreSQL can handle. + +=head1 DEPENDENCIES + +=over 4 + +=item L + +=item L + +=item L + +=back + +=head1 COPYRIGHT AND LICENSE + + Copyright (C) 2013 by the Netdisco Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Netdisco Project nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE NETDISCO DEVELOPER TEAM BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Initial Version for Netdisco 1.x + Copyright (C) 2013 by Christian Ramseyer (ramseyer@netnea.com) + I hereby grant full ownership of the code to the Netdisco Project + +=cut + +use warnings; +use strict; + +our $VERSION = 2.001000; +our $home; + +BEGIN { + use FindBin; + FindBin::again(); + + $home = ($ENV{NETDISCO_HOME} || $ENV{HOME}); + + # try to find a localenv if one isn't already in place. + if (!exists $ENV{PERL_LOCAL_LIB_ROOT}) { + use File::Spec; + my $localenv = File::Spec->catfile($FindBin::RealBin, 'localenv'); + exec($localenv, $0, @ARGV) if -f $localenv; + $localenv = File::Spec->catfile($home, 'perl5', 'bin', 'localenv'); + exec($localenv, $0, @ARGV) if -f $localenv; + + die "Sorry, can't find libs required for App::Netdisco.\n" + if !exists $ENV{PERLBREW_PERL}; + } +} + +BEGIN { + use Path::Class; + + # stuff useful locations into @INC and $PATH + unshift @INC, + dir($FindBin::RealBin)->parent->subdir('lib')->stringify, + dir($FindBin::RealBin, 'lib')->stringify; + + unshift @INC, + split m/:/, ($ENV{NETDISCO_INC} || ''); + + use Config; + $ENV{PATH} = $FindBin::RealBin . $Config{path_sep} . $ENV{PATH}; +} + +use App::Netdisco; +use App::Netdisco::Core::Arpnip 'store_arp'; +use App::Netdisco::Util::Node 'check_mac'; +use App::Netdisco::Util::DNS 'hostnames_resolve_async'; +use Dancer ':script'; + +use Data::Printer; +use Module::Load (); +use Net::OpenSSH; +use MCE::Loop Sereal => 1; + +#this may be helpful with SSH issues: +#$Net::OpenSSH::debug = ~0; + +MCE::Loop::init { chunk_size => 1 }; +my %stats; + +exit main(); + +sub main { + my @input = @{ setting('sshcollector') }; + + my @mce_result = mce_loop { + my ($mce, $chunk_ref, $chunk_id) = @_; + my $host = $chunk_ref->[0]; + + my $hostlabel = (!defined $host->{hostname} or $host->{hostname} eq "-") + ? $host->{ip} : $host->{hostname}; + + if ($hostlabel) { + my $ssh = Net::OpenSSH->new( + $hostlabel, + user => $host->{user}, + password => $host->{password}, + timeout => 30, + async => 0, + master_opts => [ + -o => "StrictHostKeyChecking=no", + -o => "BatchMode=no" + ], + ); + + MCE->gather( process($hostlabel, $ssh, $host) ); + } + } \@input; + + return 0 unless scalar @mce_result; + + foreach my $host (@mce_result) { + $stats{host}++; + info sprintf ' [%s] arpnip - retrieved %s entries', + $host->[0], scalar @{$host->[1]}; + store_arpentries($host->[1]); + } + + info sprintf 'arpnip - processed %s ARP Cache entries from %s devices', + $stats{entry}, $stats{host}; + return 0; +} + +sub process { + my ($hostlabel, $ssh, $args) = @_; + + my $class = "App::Netdisco::SSHCollector::Platform::".$args->{platform}; + Module::Load::load $class; + + my $device = $class->new(); + my $arpentries = [ $device->arpnip($hostlabel, $ssh, $args) ]; + + # debug p $arpentries; + if (scalar @$arpentries) { + hostnames_resolve_async($arpentries); + return [$hostlabel, $arpentries]; + } + else { + warning "WARNING: no entries received from <$hostlabel>"; + } +} + +sub store_arpentries { + my ($arpentries) = @_; + + foreach my $arpentry ( @$arpentries ) { + # skip broadcast/vrrp/hsrp and other wierdos + next unless check_mac( undef, $arpentry->{mac} ); + + debug sprintf ' arpnip - stored entry: %s / %s', + $arpentry->{mac}, $arpentry->{ip}; + store_arp({ + node => $arpentry->{mac}, + ip => $arpentry->{ip}, + dns => $arpentry->{dns}, + }); + + $stats{entry}++; + } +} + +__END__ + diff --git a/Netdisco/lib/App/Netdisco.pm b/Netdisco/lib/App/Netdisco.pm index c0acaf1c..18b750fa 100644 --- a/Netdisco/lib/App/Netdisco.pm +++ b/Netdisco/lib/App/Netdisco.pm @@ -4,7 +4,7 @@ use strict; use warnings; use 5.010_000; -our $VERSION = '2.029005'; +our $VERSION = '2.029007'; use App::Netdisco::Configuration; use Module::Find (); diff --git a/Netdisco/lib/App/Netdisco/Core/Arpnip.pm b/Netdisco/lib/App/Netdisco/Core/Arpnip.pm index 3480f792..d52d7801 100644 --- a/Netdisco/lib/App/Netdisco/Core/Arpnip.pm +++ b/Netdisco/lib/App/Netdisco/Core/Arpnip.pm @@ -96,14 +96,21 @@ sub _get_arps { return $resolved_ips; } -=head2 store_arp( $mac, $ip, $name, $now? ) +=head2 store_arp( \%host, $now? ) Stores a new entry to the C table with the given MAC, IP (v4 or v6) -and DNS host name. +and DNS host name. Host details are provided in a Hash ref: -Will mark old entries for this IP as no longer C. + { + ip => '192.0.2.1', + node => '00:11:22:33:44:55', + dns => 'myhost.example.com', + } -Optionally a literal string can be passed in the fourth argument for the +The C entry is optional. The update will mark old entries for this IP as +no longer C. + +Optionally a literal string can be passed in the second argument for the C timestamp, otherwise the current timestamp (C) is used. =cut diff --git a/Netdisco/lib/App/Netdisco/Core/Discover.pm b/Netdisco/lib/App/Netdisco/Core/Discover.pm index f4def41d..29acbac6 100644 --- a/Netdisco/lib/App/Netdisco/Core/Discover.pm +++ b/Netdisco/lib/App/Netdisco/Core/Discover.pm @@ -120,7 +120,8 @@ sub store_device { # build device aliases suitable for DBIC my @aliases; foreach my $entry (keys %$ip_index) { - my $ip = NetAddr::IP::Lite->new($entry); + my $ip = NetAddr::IP::Lite->new($entry) + or next; my $addr = $ip->addr; next if $addr eq '0.0.0.0'; diff --git a/Netdisco/lib/App/Netdisco/Core/Macsuck.pm b/Netdisco/lib/App/Netdisco/Core/Macsuck.pm index 8f0bdce5..042f28e9 100644 --- a/Netdisco/lib/App/Netdisco/Core/Macsuck.pm +++ b/Netdisco/lib/App/Netdisco/Core/Macsuck.pm @@ -346,6 +346,8 @@ sub _walk_fwtable { next; } + my $vlan = $fw_vlan->{$idx} || $comm_vlan || '0'; + # check to see if the port is connected to another device # and if we have that device in the database. @@ -371,12 +373,13 @@ sub _walk_fwtable { debug sprintf ' [%s] macsuck %s - port %s is detected uplink - skipping.', $device->ip, $mac, $port; + + $skiplist->{$port} = [ $vlan, $mac ] # remember for later + if exists $port_macs->{$mac}; next; } } - my $vlan = $fw_vlan->{$idx} || $comm_vlan || '0'; - if (exists $port_macs->{$mac}) { my $switch_ip = $port_macs->{$mac}; if ($device->ip eq $switch_ip) { @@ -395,7 +398,8 @@ sub _walk_fwtable { if (not setting('macsuck_bleed')) { debug sprintf ' [%s] macsuck %s - adding port %s to skiplist', $device->ip, $mac, $port; - $skiplist->{$port} = delete $cache->{$vlan}->{$port}; + + $skiplist->{$port} = [ $vlan, $mac ]; # remember for later next; } } @@ -410,6 +414,15 @@ sub _walk_fwtable { ++$cache->{$vlan}->{$port}->{$mac}; } + # restore MACs of neighbor devices. + # this is when we have a "possible uplink" detected but we still want to + # record the single MAC of the neighbor device so it works in Node search. + foreach my $port (keys %$skiplist) { + my ($vlan, $mac) = @{ $skiplist->{$port} }; + delete $cache->{$_}->{$port} for keys %$cache; # nuke nodes on all VLANs + ++$cache->{$vlan}->{$port}->{$mac}; + } + return $cache; } diff --git a/Netdisco/lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm b/Netdisco/lib/App/Netdisco/DB/Result/Virtual/NodesDiscovered.pm similarity index 84% rename from Netdisco/lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm rename to Netdisco/lib/App/Netdisco/DB/Result/Virtual/NodesDiscovered.pm index 8aa265e5..1b8a39b4 100644 --- a/Netdisco/lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm +++ b/Netdisco/lib/App/Netdisco/DB/Result/Virtual/NodesDiscovered.pm @@ -1,4 +1,4 @@ -package App::Netdisco::DB::Result::Virtual::PhonesDiscovered; +package App::Netdisco::DB::Result::Virtual::NodesDiscovered; use strict; use warnings; @@ -7,7 +7,7 @@ use base 'DBIx::Class::Core'; __PACKAGE__->table_class('DBIx::Class::ResultSource::View'); -__PACKAGE__->table('phones_discovered'); +__PACKAGE__->table('nodes_discovered'); __PACKAGE__->result_source_instance->is_virtual(1); __PACKAGE__->result_source_instance->view_definition(<" if you MUST maintain backwards compatibility with the Netdisco Value: Number. Default: 10. -The number of rows in a table page. +The default number of rows in a table page. + +=head3 C + +Value: Number. Default: + + table_showrecordsmenu: + - [10, 25, 50, 100, '-1'] + - [10, 25, 50, 100, 'All'] + +The choices available to users for selecting the number of rows per page. The +format is two lists: one of the values and one of the labels in the web +interface. You can see in the default that a value of "C<-1>" means Show All +Records. =head2 Netdisco Core diff --git a/Netdisco/lib/App/Netdisco/Manual/Deployment.pod b/Netdisco/lib/App/Netdisco/Manual/Deployment.pod index e6906029..2917750a 100644 --- a/Netdisco/lib/App/Netdisco/Manual/Deployment.pod +++ b/Netdisco/lib/App/Netdisco/Manual/Deployment.pod @@ -164,7 +164,7 @@ Then run the web daemon with the environment variable to enable the feature: DANCER_DEBUG=1 ~/bin/netdisco-web restart -=head2 Database Backups +=head1 Database Backups We recommend you backup the Netdisco database regularly. You could put the following commands into a shell script and call it nightly from C: diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/ACE.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/ACE.pm new file mode 100644 index 00000000..9cb1b1b8 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/ACE.pm @@ -0,0 +1,87 @@ +package App::Netdisco::SSHCollector::Platform::ACE; + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +App::Netdisco::SSHCollector::Platform::ACE + +=head1 DESCRIPTION + +Collect ARP entries from Cisco ACE load balancers. ACEs have multiple +virtual contexts with individual ARP tables. Contexts are enumerated +with C, afterwards the commands C and +C must be executed for every context. + +The IOS shell does not permit to combine mulitple commands in a single +line, and Net::OpenSSH uses individual connections for individual commands, +so we need to use Expect to execute the changeto and show commands in +the same context. + +=cut + +use strict; +use warnings; + +use Moo; +use Expect; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }. + +=cut + +sub arpnip{ + my ($self, $hostlabel, $ssh, @args) = @_; + + debug "$hostlabel $$ arpnip()"; + + my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command"; + my $expect = Expect->init($pty); + + my ($pos, $error, $match, $before, $after); + my $prompt = qr/#/; + + ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + + $expect->send("terminal length 0\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + + $expect->send("show context | include Name\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + + my @ctx; + my @arpentries; + + for (split(/\n/, $before)){ + if (m/Name: (\S+)/){ + push(@ctx, $1); + $expect->send("changeto $1\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + $expect->send("show arp\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + for (split(/\n/, $before)){ + my ($ip, $mac) = split(/\s+/); + if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/ && $mac =~ m/[0-9a-f.]+/i) { + push(@arpentries, { ip => $ip, mac => $mac }); + } + } + + } + } + + $expect->send("exit\n"); + $expect->soft_close(); + + return @arpentries; +} + +1; diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/BigIP.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/BigIP.pm new file mode 100644 index 00000000..7feb553b --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/BigIP.pm @@ -0,0 +1,66 @@ +package App::Netdisco::SSHCollector::Platform::BigIP; + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +NApp::etdisco::SSHCollector::Platform::BigIP + +=head1 DESCRIPTION + +Collect ARP entries from F5 BigIP load balancers. These are Linux boxes, +but feature an additional, proprietary IP stack which does not show +up in the standard SNMP ipNetToMediaTable. + +These devices also feature a CLI interface similar to IOS, which can +either be set as the login shell of the user, or be called from an +ordinary shell. This module assumes the former, and if "show net arp" +can't be executed, falls back to the latter. + +=cut + +use strict; +use warnings; + +use Moo; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }. + +=cut +sub arpnip { + my ($self, $hostlabel, $ssh, @args) = @_; + + debug "$hostlabel $$ arpnip()"; + + my @data = $ssh->capture("show net arp"); + unless (@data){ + @data = $ssh->capture('tmsh -c "show net arp"'); + } + + chomp @data; + my @arpentries; + + foreach (@data){ + if (m/\d{1,3}\..*resolved/){ + my (undef, $ip, $mac) = split(/\s+/); + + # ips can look like 172.19.254.143%10, clean + $ip =~ s/%\d+//; + + push(@arpentries, {mac => $mac, ip => $ip}); + } + } + + return @arpentries; +} + +1; diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOS.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOS.pm new file mode 100644 index 00000000..1165e6d5 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOS.pm @@ -0,0 +1,55 @@ +package App::Netdisco::SSHCollector::Platform::IOS; + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +App::Netdisco::SSHCollector::Platform::IOS + +=head1 DESCRIPTION + +Collect ARP entries from Cisco IOS devices. + +=cut + +use strict; +use warnings; + +use Dancer ':script'; +use Data::Printer; +use Moo; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }. + +=cut + +sub arpnip { + my ($self, $hostlabel, $ssh, @args) = @_; + + debug "$hostlabel $$ arpnip()"; + my @data = $ssh->capture("show ip arp"); + + chomp @data; + my @arpentries; + + # Internet 172.16.20.15 13 0024.b269.867d ARPA FastEthernet0/0.1 + foreach my $line (@data) { + next unless $line =~ m/^Internet/; + my @fields = split m/\s+/, $line; + + push @arpentries, { mac => $fields[3], ip => $fields[1] }; + } + + return @arpentries; +} + +1; diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOSXR.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOSXR.pm new file mode 100644 index 00000000..04404342 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/IOSXR.pm @@ -0,0 +1,68 @@ +package App::Netdisco::SSHCollector::Platform::IOSXR; + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +App::Netdisco::SSHCollector::Platform::IOSXR + +=head1 DESCRIPTION + +Collect ARP entries from Cisco IOS XR devices. + +=cut + +use strict; +use warnings; + +use Dancer ':script'; +use Data::Printer; +use Moo; +use Expect; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }. + +=cut + +sub arpnip { + my ($self, $hostlabel, $ssh, @args) = @_; + + debug "$hostlabel $$ arpnip()"; + + my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command"; + my $expect = Expect->init($pty); + + my ($pos, $error, $match, $before, $after); + my $prompt = qr/#/; + + ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + + $expect->send("terminal length 0\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + + my @arpentries; + + $expect->send("show arp vrf all\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + + # 0.0.0.0 00:00:00 0000.0000.0000 Dynamic ARPA GigabitEthernet0/0/0/0 + for (split(/\n/, $before)){ + my ($ip, $age, $mac, $state, $t, $iface) = split(/\s+/); + if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/ && $mac =~ m/[0-9a-f.]+/i) { + push(@arpentries, { ip => $ip, mac => $mac }); + } + } + + return @arpentries; +} + +1; diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/PaloAlto.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/PaloAlto.pm new file mode 100644 index 00000000..67ba10dc --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/PaloAlto.pm @@ -0,0 +1,66 @@ +package App::Netdisco::SSHCollector::Platform::PaloAlto; + +# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4: + +=head1 NAME + +App::Netdisco::SSHCollector::Platform::PaloAlto + +=head1 DESCRIPTION + +Collect ARP entries from PaloAlto devices. + +=cut + +use strict; +use warnings; + +use Dancer ':script'; +use Data::Printer; +use Moo; +use Expect; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns an array of hashrefs in the format { mac => MACADDR, ip => IPADDR }. + +=cut + +sub arpnip{ + my ($self, $hostlabel, $ssh, @args) = @_; + + debug "$hostlabel $$ arpnip()"; + + my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command"; + my $expect = Expect->init($pty); + my ($pos, $error, $match, $before, $after); + my $prompt = qr/> \r?$/; + + ($pos, $error, $match, $before, $after) = $expect->expect(20, -re, $prompt); + $expect->send("set cli pager off\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + $expect->send("show arp all\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + + my @arpentries; + for (split(/\r\n/, $before)){ + next unless $_ =~ m/(\d{1,3}\.){3}\d{1,3}/; + my ($tmp, $ip, $mac) = split(/\s+/); + if ($ip =~ m/(\d{1,3}\.){3}\d{1,3}/ && $mac =~ m/([0-9a-f]{2}:){5}[0-9a-f]{2}/i) { + push(@arpentries, { ip => $ip, mac => $mac }); + } + } + $expect->send("exit\n"); + $expect->soft_close(); + + return @arpentries; +} + +1; diff --git a/Netdisco/lib/App/Netdisco/Util/DNS.pm b/Netdisco/lib/App/Netdisco/Util/DNS.pm index d55b2e42..914024eb 100644 --- a/Netdisco/lib/App/Netdisco/Util/DNS.pm +++ b/Netdisco/lib/App/Netdisco/Util/DNS.pm @@ -166,7 +166,8 @@ sub no_resolve { my $config = setting('dns')->{no} || []; return 0 if not scalar @$config; - my $addr = NetAddr::IP::Lite->new($ip); + my $addr = NetAddr::IP::Lite->new($ip) + or return 1; foreach my $item (@$config) { my $c_ip = NetAddr::IP::Lite->new($item) diff --git a/Netdisco/lib/App/Netdisco/Web.pm b/Netdisco/lib/App/Netdisco/Web.pm index 711b10d1..07c403c2 100644 --- a/Netdisco/lib/App/Netdisco/Web.pm +++ b/Netdisco/lib/App/Netdisco/Web.pm @@ -76,6 +76,10 @@ hook 'before_template' => sub { # create date ranges from within templates $tokens->{to_daterange} = sub { interval_to_daterange(@_) }; + # data structure for DataTables records per page menu + $tokens->{table_showrecordsmenu} = + to_json( setting('table_showrecordsmenu') ); + # fix Plugin Template Variables to be only path+query $tokens->{$_} = $tokens->{$_}->path_query for qw/search_node search_device device_ports/; diff --git a/Netdisco/lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm b/Netdisco/lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm new file mode 100644 index 00000000..b5a697a2 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm @@ -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; diff --git a/Netdisco/lib/App/Netdisco/Web/Plugin/Report/PhonesDiscovered.pm b/Netdisco/lib/App/Netdisco/Web/Plugin/Report/PhonesDiscovered.pm deleted file mode 100644 index 130f2718..00000000 --- a/Netdisco/lib/App/Netdisco/Web/Plugin/Report/PhonesDiscovered.pm +++ /dev/null @@ -1,36 +0,0 @@ -package App::Netdisco::Web::Plugin::Report::PhonesDiscovered; - -use Dancer ':syntax'; -use Dancer::Plugin::DBIC; -use Dancer::Plugin::Auth::Extensible; - -use App::Netdisco::Web::Plugin; - -register_report( - { category => 'Node', - tag => 'phonesdiscovered', - label => 'IP Phones discovered through LLDP/CDP', - provides_csv => 1, - } -); - -get '/ajax/content/report/phonesdiscovered' => require_login sub { - my @results = schema('netdisco')->resultset('Virtual::PhonesDiscovered') - ->hri->all; - - return unless scalar @results; - - if ( request->is_ajax ) { - my $json = to_json( \@results ); - template 'ajax/report/phonesdiscovered.tt', { results => $json }, - { layout => undef }; - } - else { - header( 'Content-Type' => 'text/comma-separated-values' ); - template 'ajax/report/phonesdiscovered_csv.tt', - { results => \@results }, - { layout => undef }; - } -}; - -1; diff --git a/Netdisco/lib/App/Netdisco/Web/Plugin/Search/Port.pm b/Netdisco/lib/App/Netdisco/Web/Plugin/Search/Port.pm index eb1c38fb..37ab2f75 100644 --- a/Netdisco/lib/App/Netdisco/Web/Plugin/Search/Port.pm +++ b/Netdisco/lib/App/Netdisco/Web/Plugin/Search/Port.pm @@ -37,6 +37,8 @@ get '/ajax/content/search/port' => require_login sub { ? { "me.mac" => $q } : \[ 'me.mac::text ILIKE ?', $likeval ] ), + { "me.remote_id" => $likeclause }, + { "me.remote_type" => $likeclause }, ] }, { '+columns' => [qw/ device.dns device.name port_vlans.vlan /], diff --git a/Netdisco/lib/App/Netdisco/Web/Report.pm b/Netdisco/lib/App/Netdisco/Web/Report.pm index 2a27fe7c..740cd950 100644 --- a/Netdisco/lib/App/Netdisco/Web/Report.pm +++ b/Netdisco/lib/App/Netdisco/Web/Report.pm @@ -8,7 +8,7 @@ get '/report/*' => require_login sub { my ($tag) = splat; # used in the report search sidebar to populate select inputs - my ( $domain_list, $class_list, $ssid_list, $vendor_list ); + my ( $domain_list, $class_list, $ssid_list, $type_list, $vendor_list ); if ( $tag eq 'netbios' ) { $domain_list = [ schema('netdisco')->resultset('NodeNbt') @@ -31,6 +31,10 @@ get '/report/*' => require_login sub { $ssid_list = [ schema('netdisco')->resultset('DevicePortSsid') ->get_distinct_col('ssid') ]; } + elsif ( $tag eq 'nodesdiscovered' ) { + $type_list = [ schema('netdisco')->resultset('DevicePort') + ->get_distinct_col('remote_type') ]; + } elsif ( $tag eq 'nodevendor' ) { $vendor_list = [ schema('netdisco')->resultset('Node')->search( @@ -54,6 +58,7 @@ get '/report/*' => require_login sub { domain_list => $domain_list, class_list => $class_list, ssid_list => $ssid_list, + type_list => $type_list, vendor_list => $vendor_list, }; }; diff --git a/Netdisco/share/config.yml b/Netdisco/share/config.yml index 55d5a453..019caae8 100644 --- a/Netdisco/share/config.yml +++ b/Netdisco/share/config.yml @@ -54,7 +54,7 @@ web_plugins: - Report::Netbios - Report::NodeMultiIPs - Report::NodeVendor - - Report::PhonesDiscovered + - Report::NodesDiscovered - Report::SsidInventory - Report::VlanInventory - Report::SubnetUtilization @@ -82,6 +82,9 @@ jobqueue_refresh: 10 safe_password_store: true reports: [] table_pagesize: 10 +table_showrecordsmenu: + - [10, 25, 50, 100, '-1'] + - [10, 25, 50, 100, 'All'] # ------------- # NETDISCO CORE diff --git a/Netdisco/share/public/css/netdisco.css b/Netdisco/share/public/css/netdisco.css index 9f053d48..03adcbc3 100644 --- a/Netdisco/share/public/css/netdisco.css +++ b/Netdisco/share/public/css/netdisco.css @@ -657,6 +657,7 @@ form .clearfix.success input { } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* dataTables */ /* Clear div for DataTables ColVis plugin */ div.nd_clear-both { diff --git a/Netdisco/share/views/ajax/admintask/nodemonitor.tt b/Netdisco/share/views/ajax/admintask/nodemonitor.tt index c80419f5..dcd47e3e 100644 --- a/Netdisco/share/views/ajax/admintask/nodemonitor.tt +++ b/Netdisco/share/views/ajax/admintask/nodemonitor.tt @@ -71,11 +71,6 @@ diff --git a/Netdisco/share/views/ajax/admintask/pseudodevice.tt b/Netdisco/share/views/ajax/admintask/pseudodevice.tt index 2184f163..51e6ee56 100644 --- a/Netdisco/share/views/ajax/admintask/pseudodevice.tt +++ b/Netdisco/share/views/ajax/admintask/pseudodevice.tt @@ -63,17 +63,12 @@ diff --git a/Netdisco/share/views/ajax/admintask/slowdevices.tt b/Netdisco/share/views/ajax/admintask/slowdevices.tt index 256cb412..f2c5ebe8 100644 --- a/Netdisco/share/views/ajax/admintask/slowdevices.tt +++ b/Netdisco/share/views/ajax/admintask/slowdevices.tt @@ -33,7 +33,7 @@ $(document).ready(function() { "searching": false, "info": false, "order": [[ 4, 'desc' ], [ 0, 'asc' ], [ 1, 'asc' ] ], - "pageLength": [% settings.table_pagesize %], - } ); + "pageLength": 12 + }); } ); diff --git a/Netdisco/share/views/ajax/admintask/topology.tt b/Netdisco/share/views/ajax/admintask/topology.tt index 50f57731..0dcec0aa 100644 --- a/Netdisco/share/views/ajax/admintask/topology.tt +++ b/Netdisco/share/views/ajax/admintask/topology.tt @@ -89,17 +89,12 @@ diff --git a/Netdisco/share/views/ajax/admintask/undiscoveredneighbors.tt b/Netdisco/share/views/ajax/admintask/undiscoveredneighbors.tt index f1071460..204b04f8 100644 --- a/Netdisco/share/views/ajax/admintask/undiscoveredneighbors.tt +++ b/Netdisco/share/views/ajax/admintask/undiscoveredneighbors.tt @@ -27,13 +27,8 @@ diff --git a/Netdisco/share/views/ajax/admintask/userlog.tt b/Netdisco/share/views/ajax/admintask/userlog.tt index d4f04c65..65bc50e4 100644 --- a/Netdisco/share/views/ajax/admintask/userlog.tt +++ b/Netdisco/share/views/ajax/admintask/userlog.tt @@ -17,12 +17,6 @@ diff --git a/Netdisco/share/views/ajax/admintask/users.tt b/Netdisco/share/views/ajax/admintask/users.tt index 89db1e5c..a17bd45a 100644 --- a/Netdisco/share/views/ajax/admintask/users.tt +++ b/Netdisco/share/views/ajax/admintask/users.tt @@ -78,12 +78,6 @@ diff --git a/Netdisco/share/views/ajax/datatabledefaults.tt b/Netdisco/share/views/ajax/datatabledefaults.tt new file mode 100644 index 00000000..55b3ed82 --- /dev/null +++ b/Netdisco/share/views/ajax/datatabledefaults.tt @@ -0,0 +1,11 @@ + + "processing": true, + "stateSave": true, + "pageLength": [% settings.table_pagesize %], + "lengthMenu": [% table_showrecordsmenu %], + "dom": '<"top"l<"nd_datatables-pager"p>f>rt<"bottom"><"clear">', + "language": { + "search": '_INPUT_', + "searchPlaceholder": 'Filter records...', + "lengthMenu": "Show _MENU_ records." + } diff --git a/Netdisco/share/views/ajax/device/addresses.tt b/Netdisco/share/views/ajax/device/addresses.tt index d392ae17..448bc385 100644 --- a/Netdisco/share/views/ajax/device/addresses.tt +++ b/Netdisco/share/views/ajax/device/addresses.tt @@ -13,12 +13,6 @@ diff --git a/Netdisco/share/views/ajax/device/ports.tt b/Netdisco/share/views/ajax/device/ports.tt index 4c5cd117..2efeee9e 100644 --- a/Netdisco/share/views/ajax/device/ports.tt +++ b/Netdisco/share/views/ajax/device/ports.tt @@ -31,16 +31,6 @@ $(document).ready(function() { var freeDate = moment().subtract( [% params.age_num %], '[% params.age_unit %]' ); var table = $('#dp-data-table').dataTable({ - "processing": true, - "stateSave": true, - "pageLength": [% settings.table_pagesize %], - "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ], - "dom": '<"top"l<"nd_datatables-pager"p>f>rt<"bottom"><"clear">', - "language": { - "search": '_INPUT_', - "searchPlaceholder": 'Filter records...', - "lengthMenu": "Show _MENU_ records." - }, "deferRender": true, "order": [[ 1, "asc" ]], "colVis": { @@ -601,7 +591,8 @@ $(document).ready(function() { [% END %] [% END %] ], - "data": [% results %] + "data": [% results %], +[% INCLUDE 'ajax/datatabledefaults.tt' -%] }); // display the column show/hide buttons in the sidebar diff --git a/Netdisco/share/views/ajax/report/apchanneldist.tt b/Netdisco/share/views/ajax/report/apchanneldist.tt index 4abc7f3c..22f16d74 100644 --- a/Netdisco/share/views/ajax/report/apchanneldist.tt +++ b/Netdisco/share/views/ajax/report/apchanneldist.tt @@ -10,12 +10,6 @@ diff --git a/Netdisco/share/views/ajax/report/apradiochannelpower.tt b/Netdisco/share/views/ajax/report/apradiochannelpower.tt index aab21a89..3a283562 100644 --- a/Netdisco/share/views/ajax/report/apradiochannelpower.tt +++ b/Netdisco/share/views/ajax/report/apradiochannelpower.tt @@ -38,12 +38,6 @@ function groupString(d) { $(document).ready(function() { var table = $('#data-table').DataTable({ - "processing": true, - "stateSave": true, - "pageLength": [% settings.table_pagesize %], - "language": { - "search": 'Filter records: ' - }, "serverSide": true, "ajax": "[% uri_for('/ajax/content/report/apradiochannelpower/data') %]", "order": [[ 0, 'asc' ]], @@ -103,7 +97,8 @@ $(document).ready(function() { last = group; } } ); - } + }, +[% INCLUDE 'ajax/datatabledefaults.tt' -%] } ); // Order by the grouping diff --git a/Netdisco/share/views/ajax/report/deviceaddrnodns.tt b/Netdisco/share/views/ajax/report/deviceaddrnodns.tt index 94b17416..08b7c4da 100644 --- a/Netdisco/share/views/ajax/report/deviceaddrnodns.tt +++ b/Netdisco/share/views/ajax/report/deviceaddrnodns.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/devicebylocation.tt b/Netdisco/share/views/ajax/report/devicebylocation.tt index 07a3c6a6..6c563d5f 100644 --- a/Netdisco/share/views/ajax/report/devicebylocation.tt +++ b/Netdisco/share/views/ajax/report/devicebylocation.tt @@ -13,12 +13,6 @@ diff --git a/Netdisco/share/views/ajax/report/devicepoestatus.tt b/Netdisco/share/views/ajax/report/devicepoestatus.tt index bdcaecdf..76e0ec33 100644 --- a/Netdisco/share/views/ajax/report/devicepoestatus.tt +++ b/Netdisco/share/views/ajax/report/devicepoestatus.tt @@ -64,12 +64,6 @@ function groupString(d) { $(document).ready(function() { var table = $('#data-table').DataTable({ - "processing": true, - "stateSave": true, - "pageLength": [% settings.table_pagesize %], - "language": { - "search": 'Filter records: ' - }, "serverSide": true, "ajax": "[% uri_for('/ajax/content/report/devicepoestatus/data') %]", "order": [[ 0, 'asc' ]], @@ -168,7 +162,8 @@ $(document).ready(function() { last = group; } } ); - } + }, +[% INCLUDE 'ajax/datatabledefaults.tt' -%] } ); // Order by the grouping diff --git a/Netdisco/share/views/ajax/report/duplexmismatch.tt b/Netdisco/share/views/ajax/report/duplexmismatch.tt index 2cda1424..17548fc3 100644 --- a/Netdisco/share/views/ajax/report/duplexmismatch.tt +++ b/Netdisco/share/views/ajax/report/duplexmismatch.tt @@ -14,12 +14,6 @@ diff --git a/Netdisco/share/views/ajax/report/generic_report.tt b/Netdisco/share/views/ajax/report/generic_report.tt index 7d3aac74..d2a27386 100644 --- a/Netdisco/share/views/ajax/report/generic_report.tt +++ b/Netdisco/share/views/ajax/report/generic_report.tt @@ -20,12 +20,7 @@ diff --git a/Netdisco/share/views/ajax/report/halfduplex.tt b/Netdisco/share/views/ajax/report/halfduplex.tt index c0601263..4427ce99 100644 --- a/Netdisco/share/views/ajax/report/halfduplex.tt +++ b/Netdisco/share/views/ajax/report/halfduplex.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/ipinventory.tt b/Netdisco/share/views/ajax/report/ipinventory.tt index 5eeadd61..53f859f7 100644 --- a/Netdisco/share/views/ajax/report/ipinventory.tt +++ b/Netdisco/share/views/ajax/report/ipinventory.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/moduleinventory.tt b/Netdisco/share/views/ajax/report/moduleinventory.tt index be393121..19c0ab6c 100644 --- a/Netdisco/share/views/ajax/report/moduleinventory.tt +++ b/Netdisco/share/views/ajax/report/moduleinventory.tt @@ -30,12 +30,6 @@ diff --git a/Netdisco/share/views/ajax/report/netbios.tt b/Netdisco/share/views/ajax/report/netbios.tt index 964d949b..6134b412 100644 --- a/Netdisco/share/views/ajax/report/netbios.tt +++ b/Netdisco/share/views/ajax/report/netbios.tt @@ -26,12 +26,6 @@ diff --git a/Netdisco/share/views/ajax/report/nodemultiips.tt b/Netdisco/share/views/ajax/report/nodemultiips.tt index b3a8279d..1d70e853 100644 --- a/Netdisco/share/views/ajax/report/nodemultiips.tt +++ b/Netdisco/share/views/ajax/report/nodemultiips.tt @@ -13,12 +13,6 @@ diff --git a/Netdisco/share/views/ajax/report/phonesdiscovered.tt b/Netdisco/share/views/ajax/report/nodesdiscovered.tt similarity index 80% rename from Netdisco/share/views/ajax/report/phonesdiscovered.tt rename to Netdisco/share/views/ajax/report/nodesdiscovered.tt index 3826f539..98db813e 100644 --- a/Netdisco/share/views/ajax/report/phonesdiscovered.tt +++ b/Netdisco/share/views/ajax/report/nodesdiscovered.tt @@ -14,12 +14,6 @@ diff --git a/Netdisco/share/views/ajax/report/phonesdiscovered_csv.tt b/Netdisco/share/views/ajax/report/nodesdiscovered_csv.tt similarity index 100% rename from Netdisco/share/views/ajax/report/phonesdiscovered_csv.tt rename to Netdisco/share/views/ajax/report/nodesdiscovered_csv.tt diff --git a/Netdisco/share/views/ajax/report/nodevendor.tt b/Netdisco/share/views/ajax/report/nodevendor.tt index dade6972..0f6f70b0 100644 --- a/Netdisco/share/views/ajax/report/nodevendor.tt +++ b/Netdisco/share/views/ajax/report/nodevendor.tt @@ -26,12 +26,6 @@ diff --git a/Netdisco/share/views/ajax/report/portadmindown.tt b/Netdisco/share/views/ajax/report/portadmindown.tt index 1eb25fa3..9a8c516c 100644 --- a/Netdisco/share/views/ajax/report/portadmindown.tt +++ b/Netdisco/share/views/ajax/report/portadmindown.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/portblocking.tt b/Netdisco/share/views/ajax/report/portblocking.tt index 241545dd..5ff08dc9 100644 --- a/Netdisco/share/views/ajax/report/portblocking.tt +++ b/Netdisco/share/views/ajax/report/portblocking.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/portlog.tt b/Netdisco/share/views/ajax/report/portlog.tt index 1616980c..777e32d1 100644 --- a/Netdisco/share/views/ajax/report/portlog.tt +++ b/Netdisco/share/views/ajax/report/portlog.tt @@ -30,12 +30,7 @@ diff --git a/Netdisco/share/views/ajax/report/portmultinodes.tt b/Netdisco/share/views/ajax/report/portmultinodes.tt index d359ffc1..8482edfd 100644 --- a/Netdisco/share/views/ajax/report/portmultinodes.tt +++ b/Netdisco/share/views/ajax/report/portmultinodes.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/report/portssid.tt b/Netdisco/share/views/ajax/report/portssid.tt index ce8270ee..23e5e9e8 100644 --- a/Netdisco/share/views/ajax/report/portssid.tt +++ b/Netdisco/share/views/ajax/report/portssid.tt @@ -26,12 +26,6 @@ diff --git a/Netdisco/share/views/ajax/report/portutilization.tt b/Netdisco/share/views/ajax/report/portutilization.tt index 822f0bee..cb1ec9d7 100644 --- a/Netdisco/share/views/ajax/report/portutilization.tt +++ b/Netdisco/share/views/ajax/report/portutilization.tt @@ -13,12 +13,6 @@ diff --git a/Netdisco/share/views/ajax/report/vlaninventory.tt b/Netdisco/share/views/ajax/report/vlaninventory.tt index a7aee16e..5b27c15d 100644 --- a/Netdisco/share/views/ajax/report/vlaninventory.tt +++ b/Netdisco/share/views/ajax/report/vlaninventory.tt @@ -12,12 +12,6 @@ diff --git a/Netdisco/share/views/ajax/search/device.tt b/Netdisco/share/views/ajax/search/device.tt index b36f61b8..b9f11a2a 100644 --- a/Netdisco/share/views/ajax/search/device.tt +++ b/Netdisco/share/views/ajax/search/device.tt @@ -17,12 +17,6 @@ diff --git a/Netdisco/share/views/ajax/search/node_by_ip.tt b/Netdisco/share/views/ajax/search/node_by_ip.tt index 879c6967..e91df02d 100644 --- a/Netdisco/share/views/ajax/search/node_by_ip.tt +++ b/Netdisco/share/views/ajax/search/node_by_ip.tt @@ -175,12 +175,6 @@ tr.group:hover { diff --git a/Netdisco/share/views/ajax/search/vlan.tt b/Netdisco/share/views/ajax/search/vlan.tt index 010d54b8..aa75ce85 100644 --- a/Netdisco/share/views/ajax/search/vlan.tt +++ b/Netdisco/share/views/ajax/search/vlan.tt @@ -14,12 +14,6 @@ diff --git a/Netdisco/share/views/sidebar/report/nodesdiscovered.tt b/Netdisco/share/views/sidebar/report/nodesdiscovered.tt new file mode 100644 index 00000000..b3fd7381 --- /dev/null +++ b/Netdisco/share/views/sidebar/report/nodesdiscovered.tt @@ -0,0 +1,52 @@ + +

Node Search Options

+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ + +
+

+
+ + +
+