include free ports calculation in SQL
This commit is contained in:
		| @@ -202,44 +202,6 @@ sub neighbor { | ||||
|     return eval { $row->neighbor_alias->device || undef }; | ||||
| } | ||||
|  | ||||
| =head2 is_free( $quantity, $unit ) | ||||
|  | ||||
| This method can be used to evaluate whether a device port could be considered | ||||
| unused, based on the last time it changed from the "up" state to a "down" | ||||
| state. | ||||
|  | ||||
| Pass in two parameters, first the C<$quantity> which must be an integer, and | ||||
| second the C<$unit> which must be a string of either C<days>, C<weeks>, | ||||
| C<months> or C<years>. | ||||
|  | ||||
| A True value is returned if the port is in a "down" state but administratively | ||||
| "up", yet last changed state at or further back than the parameters' time | ||||
| window. If the port is not in the correct state, or last changed state more | ||||
| recently, then a False value is returned. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub is_free { | ||||
|     my ($row, $num, $unit) = @_; | ||||
|     return unless $num =~ m/^\d+$/ | ||||
|               and $unit =~ m/(?:days|weeks|months|years)/; | ||||
|  | ||||
|     return 0 unless | ||||
|       ($row->up_admin and $row->up_admin eq 'up') | ||||
|       and ($row->up and $row->up eq 'down'); | ||||
|  | ||||
|     my $quan = { | ||||
|       days   => (60 * 60 * 24), | ||||
|       weeks  => (60 * 60 * 24 * 7), | ||||
|       months => (60 * 60 * 24 * 31), | ||||
|       years  => (60 * 60 * 24 * 365), | ||||
|     }; | ||||
|     my $total = $num * $quan->{$unit}; | ||||
|  | ||||
|     my $diff_sec = $row->lastchange / 100; | ||||
|     return ($diff_sec >= $total ? 1 : 0); | ||||
| } | ||||
|  | ||||
| =head1 ADDITIONAL COLUMNS | ||||
|  | ||||
| =head2 tagged_vlans_count | ||||
| @@ -265,4 +227,16 @@ between the date stamp and time stamp. That is: | ||||
|  | ||||
| sub lastchange_stamp { return (shift)->get_column('lastchange_stamp') } | ||||
|  | ||||
| =head2 is_free | ||||
|  | ||||
| This method can be used to evaluate whether a device port could be considered | ||||
| unused, based on the last time it changed from the "up" state to a "down" | ||||
| state. | ||||
|  | ||||
| See the C<with_is_free> and C<only_free_ports> modifiers to C<search()>. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub is_free { return (shift)->get_column('is_free') } | ||||
|  | ||||
| 1; | ||||
|   | ||||
| @@ -35,6 +35,75 @@ sub with_times { | ||||
|       }); | ||||
| } | ||||
|  | ||||
| =head2 with_free_ports | ||||
|  | ||||
| This is a modifier for any C<search()> (including the helpers below) which | ||||
| will add the following additional synthesized columns to the result set: | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item is_free | ||||
|  | ||||
| =back | ||||
|  | ||||
| In the C<$cond> hash (the first parameter) pass in the C<age_num> which must | ||||
| be an integer, and the C<age_unit> which must be a string of either C<days>, | ||||
| C<weeks>, C<months> or C<years>. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub with_is_free { | ||||
|   my ($rs, $cond, $attrs) = @_; | ||||
|  | ||||
|   my $interval = (delete $cond->{age_num}) .' '. (delete $cond->{age_unit}); | ||||
|  | ||||
|   return $rs | ||||
|     ->search_rs($cond, $attrs) | ||||
|     ->search({}, | ||||
|       { | ||||
|         '+select' => [ | ||||
|           \["up != 'up' and " | ||||
|               ."age(to_timestamp(extract(epoch from device.last_discover) " | ||||
|                 ."- (device.uptime - lastchange)/100)) " | ||||
|               ."> ?::interval", | ||||
|             [{} => $interval]], | ||||
|         ], | ||||
|         '+as' => [qw/ is_free /], | ||||
|         join => 'device', | ||||
|       }); | ||||
| } | ||||
|  | ||||
| =head2 only_free_ports | ||||
|  | ||||
| This is a modifier for any C<search()> (including the helpers below) which | ||||
| will restrict results based on whether the port is considered "free". | ||||
|  | ||||
| In the C<$cond> hash (the first parameter) pass in the C<age_num> which must | ||||
| be an integer, and the C<age_unit> which must be a string of either C<days>, | ||||
| C<weeks>, C<months> or C<years>. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub only_free_ports { | ||||
|   my ($rs, $cond, $attrs) = @_; | ||||
|  | ||||
|   my $interval = (delete $cond->{age_num}) .' '. (delete $cond->{age_unit}); | ||||
|  | ||||
|   return $rs | ||||
|     ->search_rs($cond, $attrs) | ||||
|     ->search( | ||||
|       { | ||||
|         'up' => { '!=' => 'up' }, | ||||
|       },{ | ||||
|         where => | ||||
|           \["age(to_timestamp(extract(epoch from device.last_discover) " | ||||
|                 ."- (device.uptime - lastchange)/100)) " | ||||
|               ."> ?::interval", | ||||
|             [{} => $interval]], | ||||
|       join => 'device' }, | ||||
|     ); | ||||
| } | ||||
|  | ||||
| =head2 with_vlan_count | ||||
|  | ||||
| This is a modifier for any C<search()> (including the helpers below) which | ||||
|   | ||||
| @@ -93,6 +93,13 @@ ajax '/ajax/content/device/ports' => sub { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     # filter for free ports if asked | ||||
|     my $free_filter = (param('free') ? 'only_free_ports' : 'with_is_free'); | ||||
|     $set = $set->$free_filter({ | ||||
|       age_num => (param('age_num') || 3), | ||||
|       age_unit => (param('age_unit') || 'months') | ||||
|     }); | ||||
|  | ||||
|     # make sure query asks for formatted timestamps when needed | ||||
|     $set = $set->with_times if param('c_lastchange'); | ||||
|  | ||||
| @@ -108,12 +115,8 @@ ajax '/ajax/content/device/ports' => sub { | ||||
|       prefetch => [{$nodes_name => 'ips'}, {neighbor_alias => 'device'}], | ||||
|     }) if param('c_connected'); | ||||
|  | ||||
|     # sort, and filter by free ports | ||||
|     # the filter could be in the template but here allows a 'no records' msg | ||||
|     my $results = [ sort { &netdisco::sort_port($a->port, $b->port) } | ||||
|                     grep { not param('free') | ||||
|                            or $_->is_free(param('age_num'), param('age_unit')) } $set->all ]; | ||||
|  | ||||
|     # sort ports (empty set would be a 'no records' msg) | ||||
|     my $results = [ sort { &netdisco::sort_port($a->port, $b->port) } $set->all ]; | ||||
|     return unless scalar @$results; | ||||
|  | ||||
|     content_type('text/html'); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user