update Node and NodeIp Result/ResultSet to have smarter value-add subs
This commit is contained in:
@@ -50,10 +50,20 @@ __PACKAGE__->set_primary_key("mac", "switch", "port");
|
||||
|
||||
__PACKAGE__->belongs_to( device => 'Netdisco::DB::Result::Device',
|
||||
{ 'foreign.ip' => 'self.switch' }, { join_type => 'LEFT' } );
|
||||
|
||||
# device port may have been deleted (reconfigured modules?) but node remains
|
||||
__PACKAGE__->belongs_to( device_port => 'Netdisco::DB::Result::DevicePort',
|
||||
{ 'foreign.ip' => 'self.switch', 'foreign.port' => 'self.port' }, { join_type => 'LEFT' } );
|
||||
{ 'foreign.ip' => 'self.switch', 'foreign.port' => 'self.port' },
|
||||
{ join_type => 'LEFT' }
|
||||
);
|
||||
|
||||
__PACKAGE__->has_many( ips => 'Netdisco::DB::Result::NodeIp',
|
||||
{ 'foreign.mac' => 'self.mac', 'foreign.active' => 'self.active' } );
|
||||
|
||||
__PACKAGE__->belongs_to( oui => 'Netdisco::DB::Result::Oui', 'oui' );
|
||||
|
||||
# accessors for custom formatted columns
|
||||
sub time_first_stamp { return (shift)->get_column('time_first_stamp') }
|
||||
sub time_last_stamp { return (shift)->get_column('time_last_stamp') }
|
||||
|
||||
1;
|
||||
|
||||
@@ -4,25 +4,62 @@ use base 'DBIx::Class::ResultSet';
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
||||
sub by_mac {
|
||||
my ($set, $archive, $mac) = @_;
|
||||
return $set unless $mac;
|
||||
=head1 search_by_mac( \%cond, \%attrs? )
|
||||
|
||||
return $set->search(
|
||||
{
|
||||
'me.mac' => $mac,
|
||||
($archive ? () : (active => 1)),
|
||||
},
|
||||
{
|
||||
order_by => {'-desc' => 'time_last'},
|
||||
columns => [qw/ mac switch port oui active device.dns /],
|
||||
'+select' => [
|
||||
\"to_char(time_first, 'YYYY-MM-DD HH24:MI')",
|
||||
\"to_char(time_last, 'YYYY-MM-DD HH24:MI')",
|
||||
],
|
||||
'+as' => [qw/ time_first time_last /],
|
||||
join => 'device',
|
||||
},
|
||||
my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55', active => 1});
|
||||
|
||||
Like C<search()>, this returns a C<$resultset> of matching rows from the Node
|
||||
table.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The C<cond> parameter must be a hashref containing a key C<mac> with
|
||||
the value to search for.
|
||||
|
||||
=item *
|
||||
|
||||
Results are ordered by time last seen.
|
||||
|
||||
=item *
|
||||
|
||||
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
||||
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
||||
|
||||
=item *
|
||||
|
||||
A JOIN is performed on the Device table and the Device C<dns> column
|
||||
prefetched.
|
||||
|
||||
=back
|
||||
|
||||
To limit results only to active nodes, set C<< {active => 1} >> in C<cond>.
|
||||
|
||||
=cut
|
||||
|
||||
sub search_by_mac {
|
||||
my ($rs, $cond, $attrs) = @_;
|
||||
|
||||
die "mac address required for search_by_mac\n"
|
||||
if ref {} ne ref $cond or !exists $cond->{mac};
|
||||
|
||||
$cond->{'me.mac'} = delete $cond->{mac};
|
||||
$attrs ||= {};
|
||||
|
||||
return $rs
|
||||
->search_rs($cond, %$attrs)
|
||||
->search({},
|
||||
{
|
||||
order_by => {'-desc' => 'time_last'},
|
||||
'+columns' => [qw/ device.dns /],
|
||||
'+select' => [
|
||||
\"to_char(time_first, 'YYYY-MM-DD HH24:MI')",
|
||||
\"to_char(time_last, 'YYYY-MM-DD HH24:MI')",
|
||||
],
|
||||
'+as' => [qw/ time_first_stamp time_last_stamp /],
|
||||
join => 'device',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,69 +13,176 @@ sub has_dns_col {
|
||||
|
||||
my $search_attr = {
|
||||
order_by => {'-desc' => 'time_last'},
|
||||
columns => [qw/ mac ip active oui.company /],
|
||||
'+columns' => [qw/ oui.company /],
|
||||
'+select' => [
|
||||
\"to_char(time_first, 'YYYY-MM-DD HH24:MI')",
|
||||
\"to_char(time_last, 'YYYY-MM-DD HH24:MI')",
|
||||
],
|
||||
'+as' => [qw/ time_first time_last /],
|
||||
'+as' => [qw/ time_first_stamp time_last_stamp /],
|
||||
join => 'oui'
|
||||
};
|
||||
|
||||
sub by_ip {
|
||||
my ($set, $archive, $ip) = @_;
|
||||
return $set unless $ip;
|
||||
=head1 search_by_ip( \%cond, \%attrs? )
|
||||
|
||||
my $op = '=';
|
||||
if ('NetAddr::IP::Lite' eq ref $ip) {
|
||||
$op = '<<=' if $ip->num > 1;
|
||||
my $set = $rs->search_by_ip({ip => '123.123.123.123', active => 1});
|
||||
|
||||
Like C<search()>, this returns a C<$resultset> of matching rows from the
|
||||
NodeIp table.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The C<cond> parameter must be a hashref containing a key C<ip> with the value
|
||||
to search for. Value can either be a simple string of IPv4 or IPv6, or a
|
||||
NetAddr::IP object in which case all results within the CIDR/Prefix will be
|
||||
retrieved.
|
||||
|
||||
=item *
|
||||
|
||||
Results are ordered by time last seen.
|
||||
|
||||
=item *
|
||||
|
||||
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
||||
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
||||
|
||||
=item *
|
||||
|
||||
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
||||
|
||||
=back
|
||||
|
||||
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
||||
|
||||
=cut
|
||||
|
||||
sub search_by_ip {
|
||||
my ($rs, $cond, $attrs) = @_;
|
||||
|
||||
die "ip address required for search_by_ip\n"
|
||||
if ref {} ne ref $cond or !exists $cond->{ip};
|
||||
$attrs ||= {};
|
||||
|
||||
# handle either plain text IP or NetAddr::IP (/32 or CIDR)
|
||||
my ($op, $ip) = ('=', delete $cond->{ip});
|
||||
|
||||
if ('NetAddr::IP::Lite' eq ref $ip and $ip->num > 1) {
|
||||
$op = '<<=';
|
||||
$ip = $ip->cidr;
|
||||
}
|
||||
$cond->{ip} = { $op => $ip };
|
||||
|
||||
return $set->search(
|
||||
{
|
||||
ip => { $op => $ip },
|
||||
($archive ? () : (active => 1)),
|
||||
},
|
||||
{
|
||||
%$search_attr,
|
||||
( $set->has_dns_col ? ('+columns' => 'dns') : () ),
|
||||
}
|
||||
);
|
||||
$rs = $rs->search_rs({}, {'+columns' => 'dns'})
|
||||
if $rs->has_dns_col;
|
||||
|
||||
return $rs
|
||||
->search_rs($cond, %$attrs)
|
||||
->search({}, $search_attr);
|
||||
}
|
||||
|
||||
sub by_name {
|
||||
my ($set, $archive, $name) = @_;
|
||||
return $set unless $name;
|
||||
die "do not call by_name unless you have a dns col on the node_ip table."
|
||||
if not $set->has_dns_col;
|
||||
=head1 search_by_name( \%cond, \%attrs? )
|
||||
|
||||
return $set->search(
|
||||
{
|
||||
dns => { '-ilike' => $name },
|
||||
($archive ? () : (active => 1)),
|
||||
},
|
||||
{
|
||||
%$search_attr,
|
||||
'+columns' => 'dns',
|
||||
}
|
||||
);
|
||||
my $set = $rs->search_by_name({dns => 'foo.example.com', active => 1});
|
||||
|
||||
Like C<search()>, this returns a C<$resultset> of matching rows from the
|
||||
NodeIp table.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The NodeIp table must have a C<dns> column for this search to work. Typically
|
||||
this column is the IP's DNS PTR record, cached at the time of Netdisco Arpnip.
|
||||
|
||||
=item *
|
||||
|
||||
The C<cond> parameter must be a hashref containing a key C<dns> with the value
|
||||
to search for. The value may optionally include SQL wildcard characters.
|
||||
|
||||
=item *
|
||||
|
||||
Results are ordered by time last seen.
|
||||
|
||||
=item *
|
||||
|
||||
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
||||
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
||||
|
||||
=item *
|
||||
|
||||
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
||||
|
||||
=back
|
||||
|
||||
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
||||
|
||||
=cut
|
||||
|
||||
sub search_by_dns {
|
||||
my ($rs, $cond, $attrs) = @_;
|
||||
|
||||
die "search_by_dns requires a dns col on the node_ip table.\n"
|
||||
if not $rs->has_dns_col;
|
||||
|
||||
die "dns field required for search_by_dns\n"
|
||||
if ref {} ne ref $cond or !exists $cond->{dns};
|
||||
|
||||
$cond->{dns} = { '-ilike' => delete $cond->{dns} };
|
||||
$attrs ||= {};
|
||||
|
||||
return $rs
|
||||
->search_rs($cond, %$attrs)
|
||||
->search_rs({}, {'+columns' => 'dns'})
|
||||
->search({}, $search_attr);
|
||||
}
|
||||
|
||||
sub by_mac {
|
||||
my ($set, $archive, $mac) = @_;
|
||||
return $set unless $mac;
|
||||
=head1 search_by_mac( \%cond, \%attrs? )
|
||||
|
||||
return $set->search(
|
||||
{
|
||||
mac => $mac,
|
||||
($archive ? () : (active => 1)),
|
||||
},
|
||||
{
|
||||
%$search_attr,
|
||||
( $set->has_dns_col ? ('+columns' => 'dns') : () ),
|
||||
}
|
||||
);
|
||||
my $set = $rs->search_by_mac({mac => '00:11:22:33:44:55', active => 1});
|
||||
|
||||
Like C<search()>, this returns a C<$resultset> of matching rows from the
|
||||
NodeIp table.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The C<cond> parameter must be a hashref containing a key C<mac> with the value
|
||||
to search for.
|
||||
|
||||
=item *
|
||||
|
||||
Results are ordered by time last seen.
|
||||
|
||||
=item *
|
||||
|
||||
Additional columns C<time_first_stamp> and C<time_last_stamp> provide
|
||||
preformatted timestamps of the C<time_first> and C<time_last> fields.
|
||||
|
||||
=item *
|
||||
|
||||
A JOIN is performed on the OUI table and the OUI C<company> column prefetched.
|
||||
|
||||
=back
|
||||
|
||||
To limit results only to active IPs, set C<< {active => 1} >> in C<cond>.
|
||||
|
||||
=cut
|
||||
|
||||
sub search_by_mac {
|
||||
my ($rs, $cond, $attrs) = @_;
|
||||
|
||||
die "mac address required for search_by_mac\n"
|
||||
if ref {} ne ref $cond or !exists $cond->{mac};
|
||||
$attrs ||= {};
|
||||
|
||||
$rs = $rs->search_rs({}, {'+columns' => 'dns'})
|
||||
if $rs->has_dns_col;
|
||||
|
||||
return $rs
|
||||
->search_rs($cond, %$attrs)
|
||||
->search({}, $search_attr);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -65,13 +65,15 @@ ajax '/ajax/content/search/node' => sub {
|
||||
content_type('text/html');
|
||||
|
||||
my $mac = Net::MAC->new(mac => $node, 'die' => 0, verbose => 0);
|
||||
my @active = (param('archived') ? () : (active => 1));
|
||||
|
||||
if (eval { $mac->as_IEEE }) {
|
||||
|
||||
my $sightings = schema('netdisco')->resultset('Node')
|
||||
->by_mac(param('archived'), $mac->as_IEEE);
|
||||
->search_by_mac({mac => $mac->as_IEEE, @active});
|
||||
|
||||
my $ips = schema('netdisco')->resultset('NodeIp')
|
||||
->by_mac(param('archived'), $mac->as_IEEE);
|
||||
->search_by_mac({mac => $mac->as_IEEE, @active});
|
||||
|
||||
my $ports = schema('netdisco')->resultset('DevicePort')
|
||||
->by_mac($mac->as_IEEE);
|
||||
@@ -90,9 +92,9 @@ ajax '/ajax/content/search/node' => sub {
|
||||
my $set;
|
||||
|
||||
if (my $ip = NetAddr::IP::Lite->new($node)) {
|
||||
# by_ip() will extract cidr notation if necessary
|
||||
# search_by_ip() will extract cidr notation if necessary
|
||||
$set = schema('netdisco')->resultset('NodeIp')
|
||||
->by_ip(param('archived'), $ip);
|
||||
->search_by_ip({ip => $ip, @active});
|
||||
}
|
||||
else {
|
||||
if (schema('netdisco')->resultset('NodeIp')->has_dns_col) {
|
||||
@@ -104,7 +106,7 @@ ajax '/ajax/content/search/node' => sub {
|
||||
if index($node, setting('domain_suffix')) == -1;
|
||||
}
|
||||
$set = schema('netdisco')->resultset('NodeIp')
|
||||
->by_name(param('archived'), $node);
|
||||
->search_by_dns({dns => $node, @active});
|
||||
}
|
||||
elsif (setting('domain_suffix')) {
|
||||
$node .= setting('domain_suffix')
|
||||
@@ -120,13 +122,16 @@ ajax '/ajax/content/search/node' => sub {
|
||||
return;
|
||||
}
|
||||
$set = schema('netdisco')->resultset('NodeIp')
|
||||
->by_ip(param('archived'), $node);
|
||||
->search_by_ip({ip => $node, @active});
|
||||
}
|
||||
}
|
||||
return unless $set and $set->count;
|
||||
|
||||
template 'ajax/search/node_by_ip.tt', {
|
||||
results => $set,
|
||||
macs => $set,
|
||||
# a callback for the templates, which
|
||||
# allows modification of the DB query before execution
|
||||
archive_filter => sub { (shift)->search({@active}) },
|
||||
}, { layout => undef };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
</tbody>
|
||||
[% WHILE (row = results.next) %]
|
||||
[% WHILE (row = macs.next) %]
|
||||
<tr>
|
||||
<td><a class="nd_linkcell"
|
||||
href="[% uri_for('/search') %]?[% vars.query_defaults.node %]&q=[% row.mac | uri %]">[% row.mac %]</a></td>
|
||||
@@ -27,11 +27,11 @@
|
||||
[% ' <span class="label warning">a</span>' IF NOT row.active %]
|
||||
</td>
|
||||
[% IF params.stamps %]
|
||||
<td>[% row.time_first %]</td>
|
||||
<td>[% row.time_last %]</td>
|
||||
<td>[% row.time_first_stamp %]</td>
|
||||
<td>[% row.time_last_stamp %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% FOREACH node IN row.node_sightings(params.archived) %]
|
||||
[% FOREACH node IN archive_filter(row.node_sightings) %]
|
||||
<tr>
|
||||
<td> </td>
|
||||
[% IF params.vendor %]
|
||||
@@ -43,12 +43,12 @@
|
||||
[% ' <span class="label warning">a</span>' IF NOT node.active %]
|
||||
</td>
|
||||
[% IF params.stamps %]
|
||||
<td>[% node.time_first %]</td>
|
||||
<td>[% node.time_last %]</td>
|
||||
<td>[% node.time_first_stamp %]</td>
|
||||
<td>[% node.time_last_stamp %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% END %]
|
||||
[% FOREACH nodeip IN row.ip_aliases(params.archived) %]
|
||||
[% FOREACH nodeip IN archive_filter(row.ip_aliases) %]
|
||||
<tr>
|
||||
<td> </td>
|
||||
[% IF params.vendor %]
|
||||
@@ -60,8 +60,8 @@
|
||||
[% ' <span class="label warning">a</span>' IF NOT nodeip.active %]
|
||||
</td>
|
||||
[% IF params.stamps %]
|
||||
<td>[% nodeip.time_first %]</td>
|
||||
<td>[% nodeip.time_last %]</td>
|
||||
<td>[% nodeip.time_first_stamp %]</td>
|
||||
<td>[% nodeip.time_last_stamp %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% END %]
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
[% ' <span class="label warning">a</span>' IF NOT row.active %]
|
||||
</td>
|
||||
[% IF params.stamps %]
|
||||
<td>[% row.time_first %]</td>
|
||||
<td>[% rw.time_last %]</td>
|
||||
<td>[% row.time_first_stamp %]</td>
|
||||
<td>[% rw.time_last_stamp %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% SET first_row = 0 %]
|
||||
@@ -71,8 +71,8 @@
|
||||
[% ' <span class="label warning">a</span>' IF NOT node.active %]
|
||||
</td>
|
||||
[% IF params.stamps %]
|
||||
<td>[% node.time_first %]</td>
|
||||
<td>[% node.time_last %]</td>
|
||||
<td>[% node.time_first_stamp %]</td>
|
||||
<td>[% node.time_last_stamp %]</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% SET first_row = 0 %]
|
||||
|
||||
Reference in New Issue
Block a user