avoid use of DNS when looking up devices in DB by IP
This commit is contained in:
		| @@ -43,21 +43,26 @@ sub with_times { | ||||
|       }); | ||||
| } | ||||
|  | ||||
| =head2 search_aliases( $name or $ip or $prefix ) | ||||
| =head2 search_aliases( {$name or $ip or $prefix}, \%options? ) | ||||
|  | ||||
| Tries to find devices in Netdisco which have an identity corresponding to | ||||
| C<$name>, C<$ip> or C<$prefix>. The name can be partial, in which case an | ||||
| automatic case-insensitive partial-match search is performed. | ||||
| C<$name>, C<$ip> or C<$prefix>. | ||||
|  | ||||
| The search is across all aliases of the device, as well as its "root IP" | ||||
| identity. Note that this search will try B<not> to use DNS, in case the current | ||||
| name for an IP does not correspond to the data within Netdisco. | ||||
|  | ||||
| Passing a zero value to the C<partial> key of the C<options> hashref will | ||||
| prevent partial matching of a host name. Otherwise the default is to perform | ||||
| a partial, case-insensitive search on the host name fields. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub search_aliases { | ||||
|     my ($rs, $q) = @_; | ||||
|     my ($rs, $q, $options) = @_; | ||||
|     $q ||= '255.255.255.255'; # hack to return empty resultset on error | ||||
|     $options ||= {}; | ||||
|     $options->{partial} = 1 if !defined $options->{partial}; | ||||
|  | ||||
|     # rough approximation of IP addresses (v4 in v6 not supported). | ||||
|     # this helps us avoid triggering any DNS. | ||||
| @@ -72,8 +77,9 @@ sub search_aliases { | ||||
|         ]; | ||||
|     } | ||||
|     else { | ||||
|         $q = "\%$q\%" if $q !~ m/\%/; | ||||
|         $q = "\%$q\%" if ($options->{partial} and $q !~ m/\%/); | ||||
|         $clause = [ | ||||
|             'me.name' => { '-ilike' => $q }, | ||||
|             'me.dns'  => { '-ilike' => $q }, | ||||
|             'device_ips.dns' => { '-ilike' => $q }, | ||||
|         ]; | ||||
| @@ -91,6 +97,33 @@ sub search_aliases { | ||||
|     ); | ||||
| } | ||||
|  | ||||
| =head2 search_for_device( $name or $ip or $prefix ) | ||||
|  | ||||
| This is a wrapper for C<search_aliases> which: | ||||
|  | ||||
| =over 4 | ||||
|  | ||||
| =item * | ||||
|  | ||||
| Disables partial matching on host names | ||||
|  | ||||
| =item * | ||||
|  | ||||
| Returns only the first result of any found devices | ||||
|  | ||||
| =back | ||||
|  | ||||
| If not matching devices are found, C<undef> is returned. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub search_for_device { | ||||
|     my ($rs, $q, $options) = @_; | ||||
|     $options ||= {}; | ||||
|     $options->{partial} = 0; | ||||
|     return $rs->search_aliases($q, $options)->first(); | ||||
| } | ||||
|  | ||||
| =head2 search_by_field( \%cond, \%attrs? ) | ||||
|  | ||||
| This variant of the standard C<search()> method returns a ResultSet of Device | ||||
|   | ||||
| @@ -27,8 +27,8 @@ NodeIp table. | ||||
|  | ||||
| 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. | ||||
| L<NetAddr::IP::Lite> object in which case all results within the CIDR/Prefix | ||||
| will be retrieved. | ||||
|  | ||||
| =item * | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,7 @@ package App::Netdisco::Util::DeviceProperties; | ||||
| use Dancer qw/:syntax :script/; | ||||
| use Dancer::Plugin::DBIC 'schema'; | ||||
|  | ||||
| use NetAddr::IP::Lite; | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use base 'Exporter'; | ||||
| our @EXPORT = (); | ||||
| @@ -38,16 +38,19 @@ Returns false if the host is not permitted to discover the target device. | ||||
| =cut | ||||
|  | ||||
| sub is_discoverable { | ||||
|   my $ip = shift; | ||||
|   my $q = shift; | ||||
|  | ||||
|   my $device = schema('netdisco')->resultset('Device') | ||||
|     ->search_for_device($q) or return 0; | ||||
|   my $addr = NetAddr::IP::Lite->new($device->ip); | ||||
|  | ||||
|   my $device = NetAddr::IP::Lite->new($ip) or return 0; | ||||
|   my $discover_no   = setting('discover_no') || []; | ||||
|   my $discover_only = setting('discover_only') || []; | ||||
|  | ||||
|   if (scalar @$discover_no) { | ||||
|       foreach my $item (@$discover_no) { | ||||
|           my $ip = NetAddr::IP::Lite->new($item) or return 0; | ||||
|           return 0 if $ip->contains($device); | ||||
|           return 0 if $ip->contains($addr); | ||||
|       } | ||||
|   } | ||||
|  | ||||
| @@ -55,7 +58,7 @@ sub is_discoverable { | ||||
|       my $okay = 0; | ||||
|       foreach my $item (@$discover_only) { | ||||
|           my $ip = NetAddr::IP::Lite->new($item) or return 0; | ||||
|           ++$okay if $ip->contains($device); | ||||
|           ++$okay if $ip->contains($addr); | ||||
|       } | ||||
|       return 0 if not $okay; | ||||
|   } | ||||
|   | ||||
| @@ -4,8 +4,6 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| hook 'before' => sub { | ||||
|   # list of port detail columns | ||||
|   var('port_columns' => [ | ||||
|   | ||||
| @@ -4,19 +4,18 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use App::Netdisco::Web::Plugin; | ||||
|  | ||||
| register_device_tab({ id => 'addresses', label => 'Addresses' }); | ||||
|  | ||||
| # device interface addresses | ||||
| ajax '/ajax/content/device/addresses' => sub { | ||||
|     my $ip = NetAddr::IP::Lite->new(param('q')); | ||||
|     return unless $ip; | ||||
|     my $q = param('q'); | ||||
|  | ||||
|     my $set = schema('netdisco')->resultset('DeviceIp') | ||||
|                 ->search({ip => $ip->addr}, {order_by => 'alias'}); | ||||
|     my $device = schema('netdisco')->resultset('Device') | ||||
|       ->search_for_device($q) or return; | ||||
|  | ||||
|     my $set = $device->device_ips->search({}, {order_by => 'alias'}); | ||||
|     return unless $set->count; | ||||
|  | ||||
|     content_type('text/html'); | ||||
|   | ||||
| @@ -4,20 +4,15 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use App::Netdisco::Web::Plugin; | ||||
|  | ||||
| register_device_tab({ id => 'details', label => 'Details' }); | ||||
|  | ||||
| # device details table | ||||
| ajax '/ajax/content/device/details' => sub { | ||||
|     my $ip = NetAddr::IP::Lite->new(param('q')); | ||||
|     return unless $ip; | ||||
|  | ||||
|     my $q = param('q'); | ||||
|     my $device = schema('netdisco')->resultset('Device') | ||||
|                    ->with_times()->find($ip->addr); | ||||
|     return unless $device; | ||||
|       ->with_times()->search_for_device($q) or return; | ||||
|  | ||||
|     content_type('text/html'); | ||||
|     template 'ajax/device/details.tt', { | ||||
|   | ||||
| @@ -4,8 +4,6 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use App::Netdisco::Web::Plugin; | ||||
|  | ||||
| register_device_tab({ id => 'netmap', label => 'Neighbors' }); | ||||
| @@ -42,9 +40,11 @@ sub _add_children { | ||||
|  | ||||
| # d3 seems not to use proper ajax semantics, so get instead of ajax | ||||
| get '/ajax/data/device/netmap' => sub { | ||||
|     my $ip = NetAddr::IP::Lite->new(param('q')); | ||||
|     return unless $ip; | ||||
|     my $start = $ip->addr; | ||||
|     my $q = param('q'); | ||||
|  | ||||
|     my $device = schema('netdisco')->resultset('Device') | ||||
|       ->search_for_device($q) or return; | ||||
|     my $start = $device->ip; | ||||
|  | ||||
|     my @devices = schema('netdisco')->resultset('Device')->search({}, { | ||||
|       result_class => 'DBIx::Class::ResultClass::HashRefInflator', | ||||
|   | ||||
| @@ -4,43 +4,41 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
| use App::Netdisco::Util::Web (); # for sort_port | ||||
|  | ||||
| use App::Netdisco::Web::Plugin; | ||||
|  | ||||
| register_device_tab({ id => 'ports', label => 'Ports' }); | ||||
|  | ||||
| # device ports with a description (er, name) matching | ||||
| ajax '/ajax/content/device/ports' => sub { | ||||
|     my $ip = NetAddr::IP::Lite->new(param('q')); | ||||
|     return unless $ip; | ||||
|     my $q = param('q'); | ||||
|  | ||||
|     my $set = schema('netdisco')->resultset('DevicePort') | ||||
|                 ->search({'me.ip' => $ip->addr}); | ||||
|     my $device = schema('netdisco')->resultset('Device') | ||||
|       ->search_for_device($q) or return; | ||||
|     my $set = $device->ports; | ||||
|  | ||||
|     # refine by ports if requested | ||||
|     my $q = param('f'); | ||||
|     if ($q) { | ||||
|         if ($q =~ m/^\d+$/) { | ||||
|     my $f = param('f'); | ||||
|     if ($f) { | ||||
|         if ($f =~ m/^\d+$/) { | ||||
|             $set = $set->search({ | ||||
|               -or => { | ||||
|                 'me.vlan' => $q, | ||||
|                 'port_vlans_tagged.vlan' => $q, | ||||
|                 'me.vlan' => $f, | ||||
|                 'port_vlans_tagged.vlan' => $f, | ||||
|               }, | ||||
|             }, { join => 'port_vlans_tagged' }); | ||||
|             return unless $set->count; | ||||
|         } | ||||
|         else { | ||||
|             $q =~ s/\*/%/g if index($q, '*') >= 0; | ||||
|             $q =~ s/\?/_/g if index($q, '?') >= 0; | ||||
|             $q = { '-ilike' => $q }; | ||||
|             $f =~ s/\*/%/g if index($f, '*') >= 0; | ||||
|             $f =~ s/\?/_/g if index($f, '?') >= 0; | ||||
|             $f = { '-ilike' => $f }; | ||||
|  | ||||
|             if ($set->search({'me.port' => $q})->count) { | ||||
|                 $set = $set->search({'me.port' => $q}); | ||||
|             if ($set->search({'me.port' => $f})->count) { | ||||
|                 $set = $set->search({'me.port' => $f}); | ||||
|             } | ||||
|             else { | ||||
|                 $set = $set->search({'me.name' => $q}); | ||||
|                 $set = $set->search({'me.name' => $f}); | ||||
|                 return unless $set->count; | ||||
|             } | ||||
|         } | ||||
| @@ -79,7 +77,7 @@ ajax '/ajax/content/device/ports' => sub { | ||||
|     template 'ajax/device/ports.tt', { | ||||
|       results => $results, | ||||
|       nodes => $nodes_name, | ||||
|       device => $ip->addr, | ||||
|       device => $device->ip, | ||||
|     }, { layout => undef }; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -4,8 +4,6 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| hook 'before' => sub { | ||||
|   # view settings for node options | ||||
|   var('node_options' => [ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user