refactor snmp_connect to handle versions and device classes
This commit is contained in:
		| @@ -95,7 +95,7 @@ sub store_device { | ||||
|       $device->$property( $snmp->$property ); | ||||
|   } | ||||
|  | ||||
|   $device->snmp_class( $snmp->class ); | ||||
|   $device->snmp_class( $snmp->device_type ); | ||||
|   $device->last_discover(\'now()'); | ||||
|  | ||||
|   schema('netdisco')->txn_do(sub { | ||||
|   | ||||
| @@ -60,6 +60,30 @@ sub _snmp_connect_generic { | ||||
|   # get device details from db | ||||
|   my $device = get_device($ip); | ||||
|  | ||||
|   # TODO: only supporing v2c at the moment | ||||
|   my %snmp_args = ( | ||||
|     DestHost => $device->ip, | ||||
|     Retries => (setting('snmpretries') || 2), | ||||
|     Timeout => (setting('snmptimeout') || 1000000), | ||||
|     MibDirs => [ _build_mibdirs() ], | ||||
|     IgnoreNetSNMPConf => 1, | ||||
|     Debug => ($ENV{INFO_TRACE} || 0), | ||||
|   ); | ||||
|  | ||||
|   # TODO: add version force support | ||||
|   # use existing SNMP version or try 2, 1 | ||||
|   my @versions = (($device->snmp_ver || setting('snmpver') || 2)); | ||||
|   push @versions, 1; | ||||
|  | ||||
|   # use existing or new device class | ||||
|   my @classes = ('SNMP::Info'); | ||||
|   if ($device->snmp_class) { | ||||
|     unshift @classes, $device->snmp_class; | ||||
|   } | ||||
|   else { | ||||
|     $snmp_args{AutoSpecity} = 1; | ||||
|   } | ||||
|  | ||||
|   # get the community string(s) | ||||
|   my $comm_type = pop; | ||||
|   my @communities = @{ setting($comm_type) || []}; | ||||
| @@ -67,36 +91,61 @@ sub _snmp_connect_generic { | ||||
|     if length $device->snmp_comm | ||||
|        and length $comm_type and $comm_type eq 'community'; | ||||
|  | ||||
|   # TODO: only supporing v2c at the moment | ||||
|   my %snmp_args = ( | ||||
|     DestHost => $device->ip, | ||||
|     Version => ($device->snmp_ver || setting('snmpver') || 2), | ||||
|     Retries => (setting('snmpretries') || 2), | ||||
|     Timeout => (setting('snmptimeout') || 1000000), | ||||
|     MibDirs => [ _build_mibdirs() ], | ||||
|     AutoSpecify => 1, | ||||
|     IgnoreNetSNMPConf => 1, | ||||
|     Debug => ($ENV{INFO_TRACE} || 0), | ||||
|   ); | ||||
|  | ||||
|   my $info = undef; | ||||
|   my $last_comm = 0; | ||||
|   COMMUNITY: foreach my $c (@communities) { | ||||
|       next unless defined $c and length $c; | ||||
|       try { | ||||
|           $info = SNMP::Info->new(%snmp_args, Community => $c); | ||||
|           ++$last_comm if ( | ||||
|             $info | ||||
|             and (not defined $info->error) | ||||
|             and length $info->uptime | ||||
|           ); | ||||
|       }; | ||||
|       last COMMUNITY if $last_comm; | ||||
|   VERSION: foreach my $ver (@versions) { | ||||
|       next unless length $ver; | ||||
|  | ||||
|       CLASS: foreach my $class (@classes) { | ||||
|           next unless length $class; | ||||
|  | ||||
|           COMMUNITY: foreach my $comm (@communities) { | ||||
|               next unless length $comm; | ||||
|  | ||||
|               $info = _try_connect($ver, $class, $comm, \%snmp_args) | ||||
|                 and last VERSION; | ||||
|           } | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   return $info; | ||||
| } | ||||
|  | ||||
| sub _try_connect { | ||||
|   my ($ver, $class, $comm, $snmp_args) = @_; | ||||
|   my $info = undef; | ||||
|  | ||||
|   try { | ||||
|       debug | ||||
|         sprintf '[%s] try_connect with ver: %s, class: %s, comm: %s', | ||||
|         $snmp_args->{DestHost}, $ver, $class, $comm; | ||||
|       eval "require $class"; | ||||
|  | ||||
|       $info = $class->new(%$snmp_args, Version => $ver, Community => $comm); | ||||
|       undef $info unless ( | ||||
|         (not defined $info->error) | ||||
|         and length $info->uptime | ||||
|         and ($info->layers or $info->description) | ||||
|         and $info->class | ||||
|       ); | ||||
|  | ||||
|       # first time a device is discovered, re-instantiate into specific class | ||||
|       if ($info and $info->device_type ne $class) { | ||||
|           $class = $info->device_type; | ||||
|           debug | ||||
|             sprintf '[%s] try_connect with ver: %s, new class: %s, comm: %s', | ||||
|             $snmp_args->{DestHost}, $ver, $class, $comm; | ||||
|  | ||||
|           eval "require $class"; | ||||
|           $info = $class->new(%$snmp_args, Version => $ver, Community => $comm); | ||||
|       } | ||||
|   } | ||||
|   catch { | ||||
|       debug $_; | ||||
|   }; | ||||
|  | ||||
|   return $info; | ||||
| } | ||||
|  | ||||
| sub _build_mibdirs { | ||||
|   return map { dir(setting('mibhome'), $_) } | ||||
|              @{ setting('mibdirs') || [] }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user