1package App::Netdisco::Web::Plugin::AdminTask::PseudoDevice; 2 3use Dancer ':syntax'; 4use Dancer::Plugin::Ajax; 5use Dancer::Plugin::DBIC; 6use Dancer::Plugin::Auth::Extensible; 7 8use App::Netdisco::Web::Plugin; 9use NetAddr::IP::Lite ':lower'; 10 11register_admin_task({ 12 tag => 'pseudodevice', 13 label => 'Pseudo Devices', 14}); 15 16sub _sanity_ok { 17 return 0 unless param('dns') 18 and param('dns') =~ m/^[[:print:]]+$/ 19 and param('dns') !~ m/[[:space:]]/; 20 21 my $ip = NetAddr::IP::Lite->new(param('ip')); 22 return 0 unless ($ip and $ip->addr ne '0.0.0.0'); 23 24 return 0 unless param('ports') 25 and param('ports') =~ m/^[[:digit:]]+$/; 26 27 return 1; 28} 29 30ajax '/ajax/control/admin/pseudodevice/add' => require_role admin => sub { 31 send_error('Bad Request', 400) unless _sanity_ok(); 32 33 schema('netdisco')->txn_do(sub { 34 my $device = schema('netdisco')->resultset('Device') 35 ->create({ 36 ip => param('ip'), 37 dns => param('dns'), 38 vendor => 'netdisco', 39 layers => param('layers'), 40 last_discover => \'now()', 41 }); 42 return unless $device; 43 44 $device->ports->populate([ 45 [qw/port type/], 46 map {["Port$_", 'other']} @{[1 .. param('ports')]}, 47 ]); 48 49 # device_ip table is used to show whether topo is "broken" 50 schema('netdisco')->resultset('DeviceIp') 51 ->create({ 52 ip => param('ip'), 53 alias => param('ip'), 54 }); 55 }); 56}; 57 58ajax '/ajax/control/admin/pseudodevice/update' => require_role admin => sub { 59 send_error('Bad Request', 400) unless _sanity_ok(); 60 61 schema('netdisco')->txn_do(sub { 62 my $device = schema('netdisco')->resultset('Device') 63 ->with_port_count->find({ip => param('ip')}); 64 return unless $device; 65 my $count = $device->port_count; 66 67 if (param('ports') > $count) { 68 my $start = $count + 1; 69 $device->ports->populate([ 70 [qw/port type/], 71 map {["Port$_", 'other']} @{[$start .. param('ports')]}, 72 ]); 73 } 74 elsif (param('ports') < $count) { 75 my $start = param('ports') + 1; 76 77 foreach my $port ($start .. $count) { 78 $device->ports 79 ->single({port => "Port${port}"})->delete; 80 81 # clear outdated manual topology links 82 schema('netdisco')->resultset('Topology')->search({ 83 -or => [ 84 { dev1 => $device->ip, port1 => "Port${port}" }, 85 { dev2 => $device->ip, port2 => "Port${port}" }, 86 ], 87 })->delete; 88 } 89 } 90 91 # also set layers 92 $device->update({layers => param('layers')}); 93 }); 94}; 95 96ajax '/ajax/content/admin/pseudodevice' => require_role admin => sub { 97 my $set = schema('netdisco')->resultset('Device') 98 ->search( 99 {vendor => 'netdisco'}, 100 {order_by => { -desc => 'last_discover' }}, 101 )->with_port_count; 102 103 content_type('text/html'); 104 template 'ajax/admintask/pseudodevice.tt', { 105 results => $set, 106 }, { layout => undef }; 107}; 108 109true; 110