diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Discover.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Discover.pm index b17633f5..688672a0 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Discover.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Poller/Discover.pm @@ -42,10 +42,11 @@ sub discover { } store_device($device, $snmp); - #store_interfaces($ip, $snmp); - #store_vlans($ip, $snmp); - #store_power($ip, $snmp); - #store_modules($ip, $snmp); + store_interfaces($device, $snmp); + #store_wireless($device, $snmp); + #store_vlans($device, $snmp); + #store_power($device, $snmp); + #store_modules($device, $snmp); return job_done("Ended Discover for $host"); } diff --git a/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm b/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm index de008893..ac6ada3a 100644 --- a/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm +++ b/Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm @@ -1,6 +1,7 @@ package App::Netdisco::Util::DiscoverAndStore; use Dancer qw/:syntax :script/; +use Dancer::Plugin::DBIC 'schema'; use App::Netdisco::Util::DNS 'hostname_from_ip'; use NetAddr::IP::Lite ':lower'; @@ -8,7 +9,7 @@ use NetAddr::IP::Lite ':lower'; use base 'Exporter'; our @EXPORT = (); our @EXPORT_OK = qw/ - store_device + store_device store_interfaces /; our %EXPORT_TAGS = (all => \@EXPORT_OK); @@ -99,4 +100,100 @@ sub store_device { }); } +=head2 store_interfaces( $device, $snmp ) + +Given a Device database object, and a working SNMP connection, discover and +store the device's interface/port information. + +The Device database object can be a fresh L object which is +not yet stored to the database. + +=cut + +sub store_interfaces { + my ($device, $snmp) = @_; + + my $interfaces = $snmp->interfaces; + my $i_type = $snmp->i_type; + my $i_ignore = $snmp->i_ignore; + my $i_descr = $snmp->i_description; + my $i_mtu = $snmp->i_mtu; + my $i_speed = $snmp->i_speed; + my $i_mac = $snmp->i_mac; + my $i_up = $snmp->i_up; + my $i_up_admin = $snmp->i_up_admin; + my $i_name = $snmp->i_name; + my $i_duplex = $snmp->i_duplex; + my $i_duplex_admin = $snmp->i_duplex_admin; + my $i_stp_state = $snmp->i_stp_state; + my $i_vlan = $snmp->i_vlan; + my $i_pvid = $snmp->i_pvid; + my $i_lastchange = $snmp->i_lastchange; + + # clear the cached uptime... + # I think I just threw up a little in my mouth. + delete $snmp->{_uptime}; + my $dev_uptime = $snmp->uptime; + + if (scalar grep {$_ > $dev_uptime} values %$i_lastchange) { + $device->uptime( $dev_uptime + 2**32 ); + } + + # build device interfaces suitable for DBIC + my @interfaces; + foreach my $entry (keys %$interfaces) { + my $port = $interfaces->{$entry}; + + if (not length $port) { + # TODO log message + next; + } + + if (scalar grep {$port =~ m/$_/} @{setting('ignore_interfaces') || []}) { + # TODO log message + next; + } + + my $lc = $i_lastchange->{$entry}; + if ($device->is_column_changed('uptime') and $lc) { + if ($lc < $dev_uptime) { + # ambiguous: lastchange could be sysUptime before or after wrap + if ($dev_uptime > 30000 and $lc < 30000) { + # uptime wrap more than 5min ago but lastchange within 5min + # assume lastchange was directly after boot -> no action + } + else { + # uptime wrap less than 5min ago or lastchange > 5min ago + # to be on safe side, assume lastchange after counter wrap + $lc += 2**32; + # TODO log message + } + } + } + + push @interfaces, { + port => $port, + descr => $i_descr->{$entry}, + up => $i_up->{$entry}, + up_admin => $i_up_admin->{$entry}, + mac => $i_mac->{$entry}, + speed => $i_speed->{$entry}, + mtu => $i_mtu->{$entry}, + name => $i_name->{$entry}, + duplex => $i_duplex->{$entry}, + duplex_admin => $i_duplex_admin->{$entry}, + stp => $i_stp_state->{$entry}, + vlan => $i_vlan->{$entry}, + pvid => $i_pvid->{$entry}, + lastchange => $lc, + }; + } + + schema('netdisco')->txn_do(sub { + $device->ports->delete; + $device->update_or_insert; + $device->ports->populate(\@interfaces); + }); +} + 1;