implementation of refresh, discover, and store_device
This commit is contained in:
		| @@ -33,7 +33,7 @@ sub capacity_for { | ||||
|   debug "checking local capacity for action $action"; | ||||
|  | ||||
|   my $action_map = { | ||||
|     Poller => [qw//], | ||||
|     Poller => [qw/refresh discover/], | ||||
|     Interactive => [qw/location contact portcontrol portname vlan power/], | ||||
|   }; | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ my $fqdn = hostfqdn || 'localhost'; | ||||
|  | ||||
| my $role_map = { | ||||
|   (map {$_ => 'Poller'} | ||||
|       qw//), | ||||
|       qw/refresh discover/), | ||||
|   (map {$_ => 'Interactive'} | ||||
|       qw/location contact portcontrol portname vlan power/) | ||||
| }; | ||||
|   | ||||
| @@ -26,6 +26,7 @@ sub worker_body { | ||||
|           my $job = schema('daemon')->resultset('Admin') | ||||
|                       ->new_result($candidate); | ||||
|           my $jid = $job->job; | ||||
|           my $target = $job->action; | ||||
|  | ||||
|           next unless $self->can($target); | ||||
|           debug "poll ($wid): can ${target}() for job $jid"; | ||||
|   | ||||
| @@ -3,9 +3,13 @@ package App::Netdisco::Daemon::Worker::Poller::Discover; | ||||
| use Dancer qw/:moose :syntax :script/; | ||||
| use Dancer::Plugin::DBIC 'schema'; | ||||
|  | ||||
| use App::Netdisco::Util::SNMP ':all'; | ||||
| use App::Netdisco::Util::SNMP 'snmp_connect'; | ||||
| use App::Netdisco::Util::Device 'get_device'; | ||||
| use App::Netdisco::Util::DiscoverAndStore ':all'; | ||||
| use App::Netdisco::Daemon::Worker::Interactive::Util ':all'; | ||||
|  | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use Role::Tiny; | ||||
| use namespace::clean; | ||||
|  | ||||
| @@ -29,6 +33,21 @@ sub refresh { | ||||
| sub discover { | ||||
|   my ($self, $job) = @_; | ||||
|  | ||||
|   my $host = NetAddr::IP::Lite->new($job->device); | ||||
|   my $device = get_device($host->addr); | ||||
|   my $snmp = snmp_connect($device); | ||||
|  | ||||
|   if (!defined $snmp) { | ||||
|       return error("Discover failed: could not SNMP connect to $host"); | ||||
|   } | ||||
|  | ||||
|   store_device($device, $snmp); | ||||
|   #store_interfaces($ip, $snmp); | ||||
|   #store_vlans($ip, $snmp); | ||||
|   #store_power($ip, $snmp); | ||||
|   #store_modules($ip, $snmp); | ||||
|  | ||||
|   return done("Ended Discover for $host"); | ||||
| } | ||||
|  | ||||
| 1; | ||||
|   | ||||
							
								
								
									
										53
									
								
								Netdisco/lib/App/Netdisco/Util/DNS.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Netdisco/lib/App/Netdisco/Util/DNS.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| package App::Netdisco::Util::DNS; | ||||
|  | ||||
| use strict; | ||||
| use warnings FATAL => 'all'; | ||||
|  | ||||
| use Net::DNS; | ||||
|  | ||||
| use base 'Exporter'; | ||||
| our @EXPORT = (); | ||||
| our @EXPORT_OK = qw/ | ||||
|   hostname_from_ip | ||||
| /; | ||||
| our %EXPORT_TAGS = (all => \@EXPORT_OK); | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| App::Netdisco::Util::DNS | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| A set of helper subroutines to support parts of the Netdisco application. | ||||
|  | ||||
| There are no default exports, however the C<:all> tag will export all | ||||
| subroutines. | ||||
|  | ||||
| =head1 EXPORT_OK | ||||
|  | ||||
| =head2 hostname_from_ip( $ip ) | ||||
|  | ||||
| Given an IP address (either IPv4 or IPv6), return the canonical hostname. | ||||
|  | ||||
| Returns C<undef> if no PTR record exists for the IP. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub hostname_from_ip { | ||||
|   my $ip = shift; | ||||
|  | ||||
|   my $res   = Net::DNS::Resolver->new; | ||||
|   my $query = $res->search($ip); | ||||
|  | ||||
|   if ($query) { | ||||
|       foreach my $rr ($query->answer) { | ||||
|           next unless $rr->type eq "PTR"; | ||||
|           return $rr->ptrdname; | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   return undef; | ||||
| } | ||||
|  | ||||
| 1; | ||||
|  | ||||
							
								
								
									
										102
									
								
								Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								Netdisco/lib/App/Netdisco/Util/DiscoverAndStore.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| package App::Netdisco::Util::DiscoverAndStore; | ||||
|  | ||||
| use Dancer qw/:syntax :script/; | ||||
|  | ||||
| use App::Netdisco::Util::DNS 'hostname_from_ip'; | ||||
| use NetAddr::IP::Lite ':lower'; | ||||
|  | ||||
| use base 'Exporter'; | ||||
| our @EXPORT = (); | ||||
| our @EXPORT_OK = qw/ | ||||
|   store_device | ||||
| /; | ||||
| our %EXPORT_TAGS = (all => \@EXPORT_OK); | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| App::Netdisco::Util::DiscoverAndStore | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| A set of helper subroutines to support parts of the Netdisco application. | ||||
|  | ||||
| There are no default exports, however the C<:all> tag will export all | ||||
| subroutines. | ||||
|  | ||||
| =head1 EXPORT_OK | ||||
|  | ||||
| =head2 store_device( $device, $snmp ) | ||||
|  | ||||
| Given a Device database object, and a working SNMP connection, discover and | ||||
| store basic device information. | ||||
|  | ||||
| The Device database object can be a fresh L<DBIx::Class::Row> object which is | ||||
| not yet stored to the database. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub store_device { | ||||
|   my ($device, $snmp) = @_; | ||||
|  | ||||
|   my $ip_index   = $snmp->ip_index; | ||||
|   my $interfaces = $snmp->interfaces; | ||||
|   my $ip_netmask = $snmp->ip_netmask; | ||||
|  | ||||
|   # build device interfaces suitable for DBIC | ||||
|   my @interfaces; | ||||
|   foreach my $entry (keys %$ip_index) { | ||||
|       my $ip = NetAddr::IP::Lite->new($entry); | ||||
|       my $addr = $ip->addr; | ||||
|  | ||||
|       next if $addr eq '0.0.0.0'; | ||||
|       next if $ip->within(NetAddr::IP::Lite->new('127.0.0.0/8')); | ||||
|       next if setting('ignore_private_nets') and $ip->is_rfc1918; | ||||
|  | ||||
|       my $iid = $ip_index->{$addr}; | ||||
|       my $port = $interfaces->{$iid}; | ||||
|       my $subnet = $ip_netmask->{$addr} | ||||
|         ? NetAddr::IP::Lite->new($addr, $ip_netmask->{$addr})->network->cidr | ||||
|         : undef; | ||||
|  | ||||
|       push @interfaces, { | ||||
|           alias => $addr, | ||||
|           port => $port, | ||||
|           subnet => $subnet, | ||||
|           dns => hostname_from_ip($addr), | ||||
|       }; | ||||
|   } | ||||
|  | ||||
|   # VTP Management Domain -- assume only one. | ||||
|   my $vtpdomains = $snmp->vtp_d_name; | ||||
|   my $vtpdomain; | ||||
|   if (defined $vtpdomains and scalar values %$vtpdomains) { | ||||
|       $device->vtp_domain( (values %$vtpdomains)[-1] ); | ||||
|   } | ||||
|  | ||||
|   my $hostname = hostname_from_ip($device->ip); | ||||
|   $device->dns($hostname) if length $hostname; | ||||
|  | ||||
|   my @properties = qw/ | ||||
|     snmp_ver snmp_comm | ||||
|     description uptime contact name location | ||||
|     layers ports mac serial model | ||||
|     ps1_type ps2_type ps1_status ps2_status | ||||
|     fan slots | ||||
|     vendor os os_ver | ||||
|   /; | ||||
|  | ||||
|   foreach my $property (@properties) { | ||||
|       $device->$property( $snmp->$property ); | ||||
|   } | ||||
|  | ||||
|   $device->snmp_class( $snmp->class ); | ||||
|   $device->last_discover(scalar localtime); | ||||
|  | ||||
|   schema('netdisco')->txn_do(sub { | ||||
|     $device->device_ips->delete; | ||||
|     $device->update_or_insert; | ||||
|     $device->device_ips->populate(\@interfaces); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| 1; | ||||
		Reference in New Issue
	
	Block a user