1package App::Netdisco::Web::Plugin::AdminTask::OrphanedDevices; 2 3use strict; 4use warnings; 5use Dancer ':syntax'; 6use Dancer::Plugin::DBIC; 7use Dancer::Plugin::Auth::Extensible; 8 9use App::Netdisco::Web::Plugin; 10 11register_admin_task( 12 { tag => 'orphaned', 13 label => 'Orphaned Devices / Networks', 14 provides_csv => 1, 15 } 16); 17 18get '/ajax/content/admin/orphaned' => require_role admin => sub { 19 20 my @tree = schema('netdisco')->resultset('Virtual::UnDirEdgesAgg') 21 ->search( undef, { prefetch => 'device' } )->hri->all; 22 23 my @orphans 24 = schema('netdisco')->resultset('Virtual::OrphanedDevices')->search() 25 ->order_by('ip')->hri->all; 26 27 return unless ( scalar @tree || scalar @orphans ); 28 29 my @ordered; 30 31 if ( scalar @tree ) { 32 my %tree = map { $_->{'left_ip'} => $_ } @tree; 33 34 my $current_graph = 0; 35 my %visited = (); 36 my @to_visit = (); 37 foreach my $node ( keys %tree ) { 38 next if exists $visited{$node}; 39 40 $current_graph++; 41 @to_visit = ($node); 42 while (@to_visit) { 43 my $node_to_visit = shift @to_visit; 44 45 $visited{$node_to_visit} = $current_graph; 46 47 push @to_visit, 48 grep { !exists $visited{$_} } 49 @{ $tree{$node_to_visit}->{'links'} }; 50 } 51 } 52 53 my @graphs = (); 54 foreach my $key ( keys %visited ) { 55 push @{ $graphs[ $visited{$key} - 1 ] }, $tree{$key}->{'device'}; 56 } 57 58 @ordered = sort { scalar @{$b} <=> scalar @{$a} } @graphs; 59 } 60 61 return if ( scalar @ordered < 2 && !scalar @tree ); 62 63 if ( request->is_ajax ) { 64 template 'ajax/admintask/orphaned.tt', 65 { 66 orphans => \@orphans, 67 graphs => \@ordered, 68 }, 69 { layout => undef }; 70 } 71 else { 72 header( 'Content-Type' => 'text/comma-separated-values' ); 73 template 'ajax/admintask/orphaned_csv.tt', 74 { 75 orphans => \@orphans, 76 graphs => \@ordered, 77 }, 78 { layout => undef }; 79 } 80}; 81 821; 83