package App::Netdisco::Web::Plugin::Device::Neighbors; use Dancer ':syntax'; use Dancer::Plugin::Ajax; use Dancer::Plugin::DBIC; use Dancer::Plugin::Auth::Extensible; use App::Netdisco::Web::Plugin; register_device_tab({ tag => 'netmap', label => 'Neighbors' }); ajax '/ajax/content/device/netmap' => require_login sub { content_type('text/html'); template 'ajax/device/netmap.tt', {}, { layout => undef }; }; sub _get_name { my $ip = shift; my $domain = quotemeta( setting('domain_suffix') || '' ); (my $dns = (var('devices')->{$ip} || '')) =~ s/$domain$//; return ($dns || $ip); } sub _add_children { my ($ptr, $childs, $step, $limit) = @_; return $step if $limit and $step > $limit; my @legit = (); my $max = $step; foreach my $c (@$childs) { next if exists var('seen')->{$c}; var('seen')->{$c}++; push @legit, $c; push @{$ptr}, { ip => $c, name => _get_name($c), }; } for (my $i = 0; $i < @legit; $i++) { $ptr->[$i]->{children} = []; my $nm = _add_children($ptr->[$i]->{children}, var('links')->{$legit[$i]}, ($step + 1), $limit); $max = $nm if $nm > $max; } return $max; } # d3 seems not to use proper ajax semantics, so get instead of ajax get '/ajax/data/device/netmap' => require_login sub { my $q = param('q'); my $vlan = param('vlan'); undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/); my $depth = (param('depth') || 8); undef $depth if (defined $depth and $depth !~ m/^\d+$/); my $device = schema('netdisco')->resultset('Device') ->search_for_device($q) or send_error('Bad device', 400); my $start = $device->ip; my @devices = schema('netdisco')->resultset('Device')->search({}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator', columns => ['ip', 'dns', 'name'], })->all; var(devices => { map { $_->{ip} => lc($_->{dns} || $_->{name} || '') } @devices }); var(links => {}); my $rs = schema('netdisco')->resultset('Virtual::DeviceLinks')->search({}, { columns => [qw/left_ip right_ip/], result_class => 'DBIx::Class::ResultClass::HashRefInflator', }); if ($vlan) { $rs = $rs->search({ 'left_vlans.vlan' => $vlan, 'right_vlans.vlan' => $vlan, }, { join => [qw/left_vlans right_vlans/], }); } while (my $l = $rs->next) { var('links')->{ $l->{left_ip} } ||= []; push @{ var('links')->{ $l->{left_ip} } }, $l->{right_ip}; } my %tree = ( ip => $start, name => _get_name($start), # dns or sysname or ip children => [], ); var(seen => {$start => 1}); my $max = _add_children($tree{children}, var('links')->{$start}, 1, $depth); $tree{scale} = $max; content_type('application/json'); to_json(\%tree); }; ajax '/ajax/data/device/alldevicelinks' => require_login sub { my $rs = schema('netdisco')->resultset('Virtual::DeviceLinks')->search({}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator', }); my %tree = (); while (my $l = $rs->next) { push @{ $tree{ $l->{left_ip} } }, $l->{right_ip}; } content_type('application/json'); to_json(\%tree); }; true;