App-Netdisco

 view release on metacpan or  search on metacpan

lib/App/Netdisco/Worker/Plugin/Discover/Neighbors.pm  view on Meta::CPAN

package App::Netdisco::Worker::Plugin::Discover::Neighbors;

use Dancer ':syntax';
use App::Netdisco::Worker::Plugin;
use aliased 'App::Netdisco::Worker::Status';

use App::Netdisco::Transport::SNMP ();
use App::Netdisco::Util::Device qw/get_device is_discoverable match_to_setting/;
use App::Netdisco::Util::Permission 'acl_matches';
use App::Netdisco::JobQueue 'jq_insert';
use Dancer::Plugin::DBIC 'schema';
use List::Util 'pairs';
use NetAddr::IP::Lite ();
use NetAddr::MAC;
use Encode;
use Try::Tiny;

=head2 discover_new_neighbors( )

Given a Device database object, and a working SNMP connection, discover and
store the device's port neighbors information.

Entries in the Topology database table will override any discovered device
port relationships.

The Device database object can be a fresh L<DBIx::Class::Row> object which is
not yet stored to the database.

Any discovered neighbor unknown to Netdisco will have a C<discover> job
immediately queued (subject to the filtering by the C<discover_*> settings).

=cut

register_worker({ phase => 'main', driver => 'snmp' }, sub {
  my ($job, $workerconf) = @_;

  my $device = $job->device;
  return unless $device->in_storage;

  if (acl_matches($device, 'skip_neighbors') or not setting('discover_neighbors')) {
      return Status->info(
        sprintf ' [%s] neigh - neighbor discovery is disabled on this device',
        $device->ip);
  }

  my $snmp = App::Netdisco::Transport::SNMP->reader_for($device)
    or return Status->defer("discover failed: could not SNMP connect to $device");

  my @to_discover = store_neighbors($device);
  my (%seen_id, %seen_ip) = ((), ());

  # only enqueue if device is not already discovered,
  # discover_* config permits the discovery
  foreach my $neighbor (@to_discover) {
      my ($ip, $remote_id) = @$neighbor;
      if ($seen_ip{ $ip }++) {
          debug sprintf
            ' queue - skip: IP %s is already queued from %s',
            $ip, $device->ip;
          next;
      }

      if ($remote_id and $seen_id{ $remote_id }++) {
          debug sprintf
            ' queue - skip: %s with ID [%s] already queued from %s',
            $ip, $remote_id, $device->ip;
          next;
      }

      my $newdev = get_device($ip);
      next if $newdev->in_storage;

      # risk of things going wrong...?
      # https://quickview.cloudapps.cisco.com/quickview/bug/CSCur12254

      jq_insert({



( run in 0.763 second using v1.01-cache-2.11-cpan-39bf76dae61 )