1package App::Netdisco::Worker::Plugin::Discover::PortPower; 2 3use Dancer ':syntax'; 4use App::Netdisco::Worker::Plugin; 5use aliased 'App::Netdisco::Worker::Status'; 6 7use App::Netdisco::Transport::SNMP (); 8use Dancer::Plugin::DBIC 'schema'; 9 10register_worker({ phase => 'main', driver => 'snmp' }, sub { 11 my ($job, $workerconf) = @_; 12 13 my $device = $job->device; 14 return unless $device->in_storage; 15 my $snmp = App::Netdisco::Transport::SNMP->reader_for($device) 16 or return Status->defer("discover failed: could not SNMP connect to $device"); 17 18 my $p_watts = $snmp->peth_power_watts; 19 my $p_status = $snmp->peth_power_status; 20 21 if (!defined $p_watts) { 22 return Status->info(sprintf ' [%s] power - 0 power modules', $device->ip); 23 } 24 25 # build device module power info suitable for DBIC 26 my @devicepower; 27 foreach my $entry (keys %$p_watts) { 28 push @devicepower, { 29 module => $entry, 30 power => $p_watts->{$entry}, 31 status => $p_status->{$entry}, 32 }; 33 } 34 35 # cache the device ports to save hitting the database for many single rows 36 my $device_ports = vars->{'device_ports'} 37 || { map {($_->port => $_)} $device->ports->all }; 38 39 my $interfaces = $snmp->interfaces; 40 my $p_ifindex = $snmp->peth_port_ifindex; 41 my $p_admin = $snmp->peth_port_admin; 42 my $p_pstatus = $snmp->peth_port_status; 43 my $p_class = $snmp->peth_port_class; 44 my $p_power = $snmp->peth_port_power; 45 46 # build device port power info suitable for DBIC 47 my @portpower; 48 foreach my $entry (keys %$p_ifindex) { 49 # WRT #475 this is SAFE because we check against known ports below 50 my $port = $interfaces->{ $p_ifindex->{$entry} } or next; 51 52 if (!defined $device_ports->{$port}) { 53 debug sprintf ' [%s] power - local port %s already skipped, ignoring', 54 $device->ip, $port; 55 next; 56 } 57 58 my ($module) = split m/\./, $entry; 59 push @portpower, { 60 port => $port, 61 module => $module, 62 admin => $p_admin->{$entry}, 63 status => $p_pstatus->{$entry}, 64 class => $p_class->{$entry}, 65 power => $p_power->{$entry}, 66 67 }; 68 } 69 70 schema('netdisco')->txn_do(sub { 71 my $gone = $device->power_modules->delete; 72 debug sprintf ' [%s] power - removed %d power modules', 73 $device->ip, $gone; 74 $device->power_modules->populate(\@devicepower); 75 debug sprintf ' [%s] power - added %d new power modules', 76 $device->ip, scalar @devicepower; 77 }); 78 79 schema('netdisco')->txn_do(sub { 80 my $gone = $device->powered_ports->delete; 81 debug sprintf ' [%s] power - removed %d PoE capable ports', 82 $device->ip, $gone; 83 $device->powered_ports->populate(\@portpower); 84 85 return Status->info(sprintf ' [%s] power - added %d new PoE capable ports', 86 $device->ip, scalar @portpower); 87 }); 88}); 89 90true; 91