1package App::Netdisco::Web::Plugin::AdminTask::Topology; 2 3use Dancer ':syntax'; 4use Dancer::Plugin::Ajax; 5use Dancer::Plugin::DBIC; 6use Dancer::Plugin::Auth::Extensible; 7 8use App::Netdisco::Web::Plugin; 9use App::Netdisco::Util::Device 'get_device'; 10 11use Try::Tiny; 12use NetAddr::IP::Lite ':lower'; 13 14register_admin_task({ 15 tag => 'topology', 16 label => 'Manual Device Topology', 17}); 18 19sub _sanity_ok { 20 my $dev1 = NetAddr::IP::Lite->new(param('dev1')); 21 return 0 unless ($dev1 and $dev1->addr ne '0.0.0.0'); 22 23 my $dev2 = NetAddr::IP::Lite->new(param('dev2')); 24 return 0 unless ($dev2 and $dev2->addr ne '0.0.0.0'); 25 26 return 0 unless param('port1'); 27 return 0 unless param('port2'); 28 29 return 0 if 30 (($dev1->addr eq $dev2->addr) and (param('port1') eq param('port2'))); 31 32 return 1; 33} 34 35ajax '/ajax/control/admin/topology/add' => require_any_role [qw(admin port_control)] => sub { 36 send_error('Bad Request', 400) unless _sanity_ok(); 37 38 my $device = schema('netdisco')->resultset('Topology') 39 ->create({ 40 dev1 => param('dev1'), 41 port1 => param('port1'), 42 dev2 => param('dev2'), 43 port2 => param('port2'), 44 }); 45 46 # re-set remote device details in affected ports 47 # could fail for bad device or port names 48 try { 49 schema('netdisco')->txn_do(sub { 50 # only work on root_ips 51 my $left = get_device(param('dev1')); 52 my $right = get_device(param('dev2')); 53 54 # skip bad entries 55 return unless ($left->in_storage and $right->in_storage); 56 57 $left->ports 58 ->search({port => param('port1')}, {for => 'update'}) 59 ->single() 60 ->update({ 61 remote_ip => param('dev2'), 62 remote_port => param('port2'), 63 remote_type => undef, 64 remote_id => undef, 65 is_uplink => \"true", 66 manual_topo => \"true", 67 }); 68 69 $right->ports 70 ->search({port => param('port2')}, {for => 'update'}) 71 ->single() 72 ->update({ 73 remote_ip => param('dev1'), 74 remote_port => param('port1'), 75 remote_type => undef, 76 remote_id => undef, 77 is_uplink => \"true", 78 manual_topo => \"true", 79 }); 80 }); 81 }; 82}; 83 84ajax '/ajax/control/admin/topology/del' => require_any_role [qw(admin port_control)] => sub { 85 send_error('Bad Request', 400) unless _sanity_ok(); 86 87 schema('netdisco')->txn_do(sub { 88 my $device = schema('netdisco')->resultset('Topology') 89 ->search({ 90 dev1 => param('dev1'), 91 port1 => param('port1'), 92 dev2 => param('dev2'), 93 port2 => param('port2'), 94 })->delete; 95 }); 96 97 # re-set remote device details in affected ports 98 # could fail for bad device or port names 99 try { 100 schema('netdisco')->txn_do(sub { 101 # only work on root_ips 102 my $left = get_device(param('dev1')); 103 my $right = get_device(param('dev2')); 104 105 # skip bad entries 106 return unless ($left->in_storage and $right->in_storage); 107 108 $left->ports 109 ->search({port => param('port1')}, {for => 'update'}) 110 ->single() 111 ->update({ 112 remote_ip => undef, 113 remote_port => undef, 114 remote_type => undef, 115 remote_id => undef, 116 is_uplink => \"false", 117 manual_topo => \"false", 118 }); 119 120 $right->ports 121 ->search({port => param('port2')}, {for => 'update'}) 122 ->single() 123 ->update({ 124 remote_ip => undef, 125 remote_port => undef, 126 remote_type => undef, 127 remote_id => undef, 128 is_uplink => \"false", 129 manual_topo => \"false", 130 }); 131 }); 132 }; 133}; 134 135ajax '/ajax/content/admin/topology' => require_any_role [qw(admin port_control)] => sub { 136 my $set = schema('netdisco')->resultset('Topology') 137 ->search({},{order_by => [qw/dev1 dev2 port1/]}); 138 139 content_type('text/html'); 140 template 'ajax/admintask/topology.tt', { 141 results => $set, 142 }, { layout => undef }; 143}; 144 145true; 146