diff --git a/.github/issue_template.md b/.github/issue_template.md index c5d80b4b..c6ab9ac8 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,5 +1,12 @@ - + + + + + + + + ## Expected Behavior diff --git a/Changes b/Changes index ef370116..0c6b0392 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ [ENHANCEMENTS] * Add note on D-Link LLDP config (H. Erasmus) + * New "stats" command for netdisco-do to update statistics 2.036009 - 2017-08-01 diff --git a/bin/netdisco-do b/bin/netdisco-do index 446b6be9..c7682769 100755 --- a/bin/netdisco-do +++ b/bin/netdisco-do @@ -124,6 +124,12 @@ unless ($action) { return ('done', 'Generated monitor data.'); } + use App::Netdisco::Util::Statistics (); + sub stats { + App::Netdisco::Util::Statistics::update_stats(); + return ('done', 'Updated statistics.'); + } + sub show { my ($self, $job) = @_; my ($device, $port, $extra) = map {$job->$_} qw/device port extra/; @@ -397,6 +403,10 @@ pass an SQL statement in the C<-e> option then it will be executed. ~netdisco/bin/netdisco-do psql -e 'SELECT ip, dns FROM device' ~netdisco/bin/netdisco-do psql -e 'COPY (SELECT ip, dns FROM device) TO STDOUT WITH CSV HEADER' +=head2 stats + +Updates Netdisco's statistics on number of devices, nodes, etc, for today. + =head2 location Set the SNMP location field on the device (specified with C<-d>). Pass the diff --git a/lib/App/Netdisco.pm b/lib/App/Netdisco.pm index ad77c44c..0e31bc9d 100644 --- a/lib/App/Netdisco.pm +++ b/lib/App/Netdisco.pm @@ -222,6 +222,7 @@ run for each installation: # apply database schema updates, update MIBs and Vendor MACs ~/bin/netdisco-deploy + ~/bin/netdisco-do stats # restart web service (if you run it) ~/bin/netdisco-web restart diff --git a/lib/App/Netdisco/Backend/Worker/Poller/Expiry.pm b/lib/App/Netdisco/Backend/Worker/Poller/Expiry.pm index fa1f10a8..c1599084 100644 --- a/lib/App/Netdisco/Backend/Worker/Poller/Expiry.pm +++ b/lib/App/Netdisco/Backend/Worker/Poller/Expiry.pm @@ -3,8 +3,8 @@ package App::Netdisco::Backend::Worker::Poller::Expiry; use Dancer qw/:moose :syntax :script/; use Dancer::Plugin::DBIC 'schema'; -use Time::Piece; use App::Netdisco::Backend::Util ':all'; +use App::Netdisco::Util::Statistics 'update_stats'; use Role::Tiny; use namespace::clean; @@ -51,66 +51,12 @@ sub expire { }); } - # now update stats - my $schema = schema('netdisco'); - eval { require SNMP::Info }; - my $snmpinfo_ver = ($@ ? 'n/a' : $SNMP::Info::VERSION); - - # TODO: (when we have the capabilities table?) - # $stats{waps} = sql_scalar('device',['COUNT(*)'], {"model"=>"AIR%"}); - - $schema->txn_do(sub { - $schema->resultset('Statistics')->update_or_create({ - day => localtime->ymd, - - device_count => - $schema->resultset('Device')->count_rs->as_query, - device_ip_count => - $schema->resultset('DeviceIp')->count_rs->as_query, - device_link_count => - $schema->resultset('Virtual::DeviceLinks') - ->count_rs({'me.left_ip' => {'>', \'me.right_ip'}})->as_query, - device_port_count => - $schema->resultset('DevicePort')->count_rs->as_query, - device_port_up_count => - $schema->resultset('DevicePort')->count_rs({up => 'up'})->as_query, - ip_table_count => - $schema->resultset('NodeIp')->count_rs->as_query, - ip_active_count => - $schema->resultset('NodeIp')->search({-bool => 'active'}, - {columns => 'ip', distinct => 1})->count_rs->as_query, - node_table_count => - $schema->resultset('Node')->count_rs->as_query, - node_active_count => - $schema->resultset('Node')->search({-bool => 'active'}, - {columns => 'mac', distinct => 1})->count_rs->as_query, - - netdisco_ver => pretty_version($App::Netdisco::VERSION, 3), - snmpinfo_ver => $snmpinfo_ver, - schema_ver => $schema->schema_version, - perl_ver => pretty_version($], 3), - pg_ver => - pretty_version($schema->storage->dbh->{pg_server_version}, 2), - - }, { key => 'primary' }); - }); + # now update stats + update_stats(); return job_done("Checked expiry and updated stats"); } -# take perl or pg versions and make pretty -sub pretty_version { - my ($version, $seglen) = @_; - return unless $version and $seglen; - return $version if $version !~ m/^[0-9.]+$/; - $version =~ s/\.//g; - $version = (join '.', reverse map {scalar reverse} - unpack("(A${seglen})*", reverse $version)); - $version =~ s/\.000/.0/g; - $version =~ s/\.0+([1-9]+)/.$1/g; - return $version; -} - # expire nodes for a specific device sub expirenodes { my ($self, $job) = @_; diff --git a/lib/App/Netdisco/Manual/Vendors.pod b/lib/App/Netdisco/Manual/Vendors.pod index 336cd5c6..60160532 100644 --- a/lib/App/Netdisco/Manual/Vendors.pod +++ b/lib/App/Netdisco/Manual/Vendors.pod @@ -18,6 +18,12 @@ Add the following to your devices (changing the port numbers appropriately): config lldp ports 1-28 mgt_addr ipv4 enable +or + + config lldp ports 1-28 mgt_addr ipv4 1.2.3.4 enable + +Which you use will depend on the device OS version. + =head1 VRFs and NXOS Netdsico at this time does not support VRFs. In particular, overlapping IP diff --git a/lib/App/Netdisco/Util/Statistics.pm b/lib/App/Netdisco/Util/Statistics.pm new file mode 100644 index 00000000..1375f1f9 --- /dev/null +++ b/lib/App/Netdisco/Util/Statistics.pm @@ -0,0 +1,91 @@ +package App::Netdisco::Util::Statistics; + +use Dancer qw/:syntax :script/; +use Dancer::Plugin::DBIC 'schema'; + +use Time::Piece; # for OO localtime + +use base 'Exporter'; +our @EXPORT = (); +our @EXPORT_OK = qw/update_stats/; +our %EXPORT_TAGS = (all => \@EXPORT_OK); + +=head1 NAME + +App::Netdisco::Util::Statistics + +=head1 DESCRIPTION + +Update the Netdisco statistics. + +There are no default exports, however the C<:all> tag will export all +subroutines. + +=head1 EXPORT_OK + +=head2 update_stats() + +Update the Netdisco statistics, either new for today or updating today's +figures. + +=cut + +sub update_stats { + my $schema = schema('netdisco'); + eval { require SNMP::Info }; + my $snmpinfo_ver = ($@ ? 'n/a' : $SNMP::Info::VERSION); + + # TODO: (when we have the capabilities table?) + # $stats{waps} = sql_scalar('device',['COUNT(*)'], {"model"=>"AIR%"}); + + $schema->txn_do(sub { + $schema->resultset('Statistics')->update_or_create({ + day => localtime->ymd, + + device_count => + $schema->resultset('Device')->count_rs->as_query, + device_ip_count => + $schema->resultset('DeviceIp')->count_rs->as_query, + device_link_count => + $schema->resultset('Virtual::DeviceLinks') + ->count_rs({'me.left_ip' => {'>', \'me.right_ip'}})->as_query, + device_port_count => + $schema->resultset('DevicePort')->count_rs->as_query, + device_port_up_count => + $schema->resultset('DevicePort')->count_rs({up => 'up'})->as_query, + ip_table_count => + $schema->resultset('NodeIp')->count_rs->as_query, + ip_active_count => + $schema->resultset('NodeIp')->search({-bool => 'active'}, + {columns => 'ip', distinct => 1})->count_rs->as_query, + node_table_count => + $schema->resultset('Node')->count_rs->as_query, + node_active_count => + $schema->resultset('Node')->search({-bool => 'active'}, + {columns => 'mac', distinct => 1})->count_rs->as_query, + + netdisco_ver => pretty_version($App::Netdisco::VERSION, 3), + snmpinfo_ver => $snmpinfo_ver, + schema_ver => $schema->schema_version, + perl_ver => pretty_version($], 3), + pg_ver => + pretty_version($schema->storage->dbh->{pg_server_version}, 2), + + }, { key => 'primary' }); + }); +} + +# take perl or pg versions and make pretty +sub pretty_version { + my ($version, $seglen) = @_; + return unless $version and $seglen; + return $version if $version !~ m/^[0-9.]+$/; + $version =~ s/\.//g; + $version = (join '.', reverse map {scalar reverse} + unpack("(A${seglen})*", reverse $version)); + $version =~ s/\.000/.0/g; + $version =~ s/\.0+([1-9]+)/.$1/g; + return $version; +} + +true;