Squashed commit of the following:

commit 4b6f3de36cbf508c05fbf7f18acee1758bc838ed
Merge: 94ed8b8 200dd2d
Author: Eric A. Miller <emiller@cpan.org>
Date:   Mon Nov 4 19:30:04 2013 -0500

    Merge branch 'master' into em-poe-report

commit 94ed8b8cf01963030a40829fd71bff529750719e
Author: Eric A. Miller <emiller@cpan.org>
Date:   Sun Nov 3 23:34:07 2013 -0500

    Show PoE module statistics in device details if available

commit 652974b312c11d6017cf6f3c0693d62085774e80
Author: Eric A. Miller <emiller@cpan.org>
Date:   Sun Nov 3 23:31:02 2013 -0500

    Move PoE statistics to model from controller
    Add missing div in PoE status report

commit f94f68b1c84d23b2f252d985509757d95be5c0d0
Author: Eric A. Miller <emiller@cpan.org>
Date:   Tue Oct 22 22:38:45 2013 -0400

    Device PoE status report
This commit is contained in:
Eric A. Miller
2013-11-04 19:45:49 -05:00
parent 200dd2d3d1
commit 9f29204676
9 changed files with 252 additions and 2 deletions

View File

@@ -43,4 +43,15 @@ __PACKAGE__->belongs_to( port => 'App::Netdisco::DB::Result::DevicePort', {
'foreign.ip' => 'self.ip', 'foreign.port' => 'self.port',
});
=head2 device_module
Returns the entry from the C<device_power> table for which this Power entry
applies.
=cut
__PACKAGE__->belongs_to( device_module => 'App::Netdisco::DB::Result::DevicePower', {
'foreign.ip' => 'self.ip', 'foreign.module' => 'self.module',
});
1;

View File

@@ -35,5 +35,15 @@ Returns the entry from the C<device> table on which this power module was discov
__PACKAGE__->belongs_to( device => 'App::Netdisco::DB::Result::Device', 'ip' );
=head2 ports
Returns the set of PoE ports associated with a power module.
=cut
__PACKAGE__->has_many( ports => 'App::Netdisco::DB::Result::DevicePortPower', {
'foreign.ip' => 'self.ip', 'foreign.module' => 'self.module',
} );
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;

View File

@@ -575,4 +575,94 @@ sub delete {
return $self->next::method();
}
=head2 with_poestats_as_hashref
This is a modifier for C<search()> which returns a hash reference with the
power_modules hash augmented with the following statistics as keys:
=over 4
=item capable_ports
Count of ports which have the ability to supply PoE.
=item disabled_ports
Count of ports with PoE administratively disabled.
=item powered_ports
Count of ports which are delivering power.
=item errored_ports
Count of ports either reporting a fault or in test mode.
=item pwr_committed
Total power that has been negotiated and therefore committed on ports
actively supplying power.
=item pwr_delivering
Total power as measured on ports actively supplying power.
=back
=cut
sub with_poestats_as_hashref {
my ( $rs, $cond, $attrs ) = @_;
my @return = $rs->search(
{},
{ result_class => 'DBIx::Class::ResultClass::HashRefInflator',
prefetch => { power_modules => 'ports' },
order_by => { -asc => [qw/me.ip power_modules.module/] }
})->all;
my $poemax = {
'class0' => 15.4,
'class1' => 4.0,
'class2' => 7.0,
'class3' => 15.4,
'class4' => 30.0
};
foreach my $device (@return) {
foreach my $module (@{$device->{power_modules}}) {
$module->{capable_ports} = 0;
$module->{disabled_ports} = 0;
$module->{powered_ports} = 0;
$module->{errored_ports} = 0;
$module->{pwr_committed} = 0;
$module->{pwr_delivering} = 0;
foreach my $port ( @{$module->{ports}} ) {
$module->{capable_ports}++;
if ( $port->{admin} eq 'false' ) {
$module->{disabled_ports}++;
}
elsif ( $port->{status} ne 'searching'
and $port->{status} ne 'deliveringPower' )
{
$module->{errored_ports}++;
}
elsif ( $port->{status} eq 'deliveringPower' ) {
$module->{powered_ports}++;
if ( defined $port->{power} and $port->{power} ) {
$module->{pwr_delivering} += int( $port->{power} / 1000 );
$module->{pwr_committed} += $poemax->{ $port->{class} };
}
else {
$module->{pwr_committed} += $poemax->{ $port->{class} };
}
}
}
}
}
return \@return;
}
1;

View File

@@ -13,11 +13,16 @@ register_device_tab({ tag => 'details', label => 'Details' });
ajax '/ajax/content/device/details' => require_login sub {
my $q = param('q');
my $device = schema('netdisco')->resultset('Device')
->with_times()->search_for_device($q) or send_error('Bad device', 400);
->search_for_device($q) or send_error('Bad device', 400);
my $results
= schema('netdisco')->resultset('Device')
->search( { 'me.ip' => $device->ip } )->with_times()
->with_poestats_as_hashref;
content_type('text/html');
template 'ajax/device/details.tt', {
d => $device,
d => $results->[0],
}, { layout => undef };
};

View File

@@ -0,0 +1,35 @@
package App::Netdisco::Web::Plugin::Report::DevicePoeStatus;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
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' => require_login sub {
my $results = schema('netdisco')->resultset('Device')
->with_poestats_as_hashref;
return unless scalar $results;
if ( request->is_ajax ) {
template 'ajax/report/devicepoestatus.tt', { results => $results, },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/devicepoestatus_csv.tt',
{ results => $results, },
{ layout => undef };
}
};
1;