diff --git a/lib/App/Netdisco/Web/Plugin/API/Device.pm b/lib/App/Netdisco/Web/Plugin/API/Device.pm new file mode 100644 index 00000000..32c34e3e --- /dev/null +++ b/lib/App/Netdisco/Web/Plugin/API/Device.pm @@ -0,0 +1,138 @@ +package App::Netdisco::Web::Plugin::API::Device; + +use Dancer ':syntax'; + +use Dancer::Plugin::Ajax; +use Dancer::Plugin::Auth::Extensible; +use Dancer::Plugin::DBIC; + +use App::Netdisco::Web::Plugin; + +sub api_array_json { + my $items = shift; + my @results; + foreach my $item (@{$items}) { + my $c = {}; + my $columns = $item->{_column_data}; + foreach my $col (keys %{$columns}) { + $c->{$col} = $columns->{$col}; + } + push @results, $c; + } + return (\@results); +}; + +ajax '/api/device/all' => require_login sub { + my @devices=schema('netdisco')->resultset('Device')->all; + return api_array_json(\@devices); +}; + +ajax '/api/device/search' => sub { + my $para = params; + my $search = {}; + foreach my $param (keys %{$para}) { + if ($param ne 'return_url') { + $search->{$param} = $para->{$param}; + } + } + my @devices; + try { + @devices=schema('netdisco')->resultset('Device')->search($search); + }; + return api_array_json(\@devices); +}; + +ajax '/api/device/:device' => require_login sub { + my $dev = params->{device}; + print "$dev\n"; + my $device = schema('netdisco')->resultset('Device') + ->search_for_device($dev) or send_error('Bad Device', 404); + return $device->{_column_data}; +}; + +ajax '/api/device/:device/modules' => require_login sub { + my $dev = params->{device}; + my $device = schema('netdisco')->resultset('Device') + ->search_for_device($dev) or send_error('Bad Device', 404); + my @modules = $device->modules; + return api_array_json(\@modules); + +}; + +ajax '/api/device/:device/vlans' => require_login sub { + my $dev = params->{device}; + my $device = schema('netdisco')->resultset('Device') + ->search_for_device($dev) or send_error('Bad Device', 404); + my @vlans = $device->vlans; + return api_array_json(\@vlans); +}; + +ajax '/api/device/:device/ports' => require_login sub { + my $dev = params->{device}; + my $device = schema('netdisco')->resultset('Device') + ->search_for_device($dev); + my @ports = $device->ports->all; + my @results; + foreach my $item (@ports) { + my $c = {}; + my $columns = $item->{_column_data}; + foreach my $col (keys %{$columns}) { + $c->{$col} = $columns->{$col}; + } + my @vlans = $item->vlans->all ; + my @pvlans; + my @vl = $item->port_vlans; + foreach my $item (@vlans) { + push @pvlans, $item->{_column_data}->{vlan}; + } + $c->{vlans}=\@pvlans; + push @results, $c; + } + return \@results; +}; + +ajax qr{/api/device/(?.*)/port/(?.*)/nodes$} => require_login sub { + my $param = captures; + my @ports = schema('netdisco')->resultset('Device') + ->search_for_device($$param{ip})->ports->search({port => $$param{port}}); + my @nodes = $ports[0]->nodes; + return api_array_json(\@nodes); +}; + +ajax qr{/api/device/(?.*)/port/(?.*)/neighbor$} => require_login sub { + my $param = captures; + my @ports = schema('netdisco')->resultset('Device') + ->search_for_device($$param{ip})->ports->search({port => $$param{port}}); + my @neighbors = $ports[0]->neighbor; + return api_array_json(\@neighbors); +}; + +ajax qr{/api/device/(?.*)/port/(?.*)/power$} => require_login sub { + my $param = captures; + my @ports = schema('netdisco')->resultset('Device') + ->search_for_device($$param{ip})->ports->search({port => $$param{port}}); + my @neighbors = $ports[0]->power; + return api_array_json(\@neighbors); +}; + +ajax qr{/api/device/(?.*)/port/(?.*)} => require_login sub { + my $param = captures; + my $port; + try { + my @ports = schema('netdisco')->resultset('Device') + ->search_for_device($$param{ip})->ports->search({port => $$param{port}}); + my @vlans = $ports[0]->vlans->all ; + my @pvlans; + foreach my $item (@vlans) { + push @pvlans, $item->{_column_data}->{vlan}; + } + $port = @{api_array_json(\@ports)}[0]; + $port->{vlans} = \@pvlans; + }; + + return $port if defined $port; + status 404; + return { message => "Port not found" }; +}; + +true; diff --git a/lib/App/Netdisco/Web/Plugin/API/Node.pm b/lib/App/Netdisco/Web/Plugin/API/Node.pm new file mode 100644 index 00000000..ccb5a5a4 --- /dev/null +++ b/lib/App/Netdisco/Web/Plugin/API/Node.pm @@ -0,0 +1,76 @@ +package App::Netdisco::Web::Plugin::API::Node; + +use Dancer ':syntax'; + +use Dancer::Plugin::Ajax; +use Dancer::Plugin::Auth::Extensible; +use Dancer::Plugin::DBIC; + +use App::Netdisco::Web::Plugin; + +sub api_array_json { + my $items = shift; + my @results; + foreach my $item (@{$items}) { + my $c = {}; + my $columns = $item->{_column_data}; + foreach my $col (keys %{$columns}) { + $c->{$col} = $columns->{$col}; + } + push @results, $c; + } + return (\@results); +}; + +ajax '/api/node/search' => require_login sub { + my $para = params; + my $search = {}; + # Generate a hashref of search terms. + foreach my $param (keys %{$para}) { + if ($param ne 'return_url') { + $search->{$param} = $para->{$param}; + } + } + my @ips; + try { + @ips = schema('netdisco')->resultset('Node')->search($search); + }; + return api_array_json(\@ips); +}; + +ajax '/api/node/:node/:method' => require_login sub { + my $node = params->{node}; + my $method = params->{method}; + # Make sure $node is actually a mac address in the proper format. + # TODO change to NetAddr::MAC + if (!($node =~ m/([0-9a-f]{2}:){5}([0-9a-f]{2})/)){ + status 400; + return ({ error => "Not a MAC Address. Address must follow the format aa:bb:cc:dd:ee:ff." }); + } + try { + my @nodesearch = schema('netdisco')->resultset('Node')->search({ mac => $node}); + # Searching by mac there should be only one result + my $node = $nodesearch[0]->$method; + + # ResultSets need to be converted to an array of hashes before being returned. + # Dancer's JSON serializer doesn't like the objects + if (ref($node) =~ m/ResultSet/) { + my @nodes = $node->all; + return api_array_json(\@nodes); + } + else { + my $nodes = $node; + return $nodes->{_column_data}; + } + } catch { + my ($exception) = @_; + if ($exception =~ m/Can\'t call method "$method" on an undefined value/) { + status 404; + return ({ error => "MAC Address not found."}); + } + status 400; + return ({ error => "Invalid collection $method." }); + }; +}; + +true; diff --git a/share/config.yml b/share/config.yml index ceb5db5b..548b69f2 100644 --- a/share/config.yml +++ b/share/config.yml @@ -39,6 +39,8 @@ api_token_lifetime: 3600 path: '/' web_plugins: - Inventory + - API::Node + - API::Device - Report::PortVLANMismatch - Report::PortAdminDown - Report::PortBlocking