App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Worker/Plugin/Discover/Properties.pm view on Meta::CPAN
and scalar @{ $i_subs->{$pidx} }
and exists $deviceports{$parent};
$deviceports{$parent}->{has_subinterfaces} = 'true';
foreach my $sidx (@{ $i_subs->{$pidx} }) {
my $sub = $interfaces->{$sidx} or next;
next unless exists $deviceports{$sub};
$deviceports{$sub}->{slave_of} = $parent;
}
}
#Â update num_ports
$device->num_ports( scalar values %deviceports );
# support for updated_device Hook - detect meaningful PORT-LEVEL changes
unless (vars->{'device_changed'}) {
my $ignore = (setting('updated_device_hook_ignored_fields') || {})->{'device_port'} || [];
my %ignore_field = map {($_ => 1)} @$ignore;
# boolean columns: ->hri bypasses DBIC's column handling, so an
# existing row's true/false comes back as the driver's raw "1"/"0"
# while our freshly built %deviceports uses the literal 'true'/'false'
# strings - normalize both before comparing so this isn't a false positive
my $normalize_bool = sub {
my $val = shift;
return (defined $val and grep {$val eq $_} qw/1 t true/) ? 1 : 0;
};
if (join("\0", sort {$a cmp $b} keys %{ vars->{'device_ports'} }) ne join("\0", sort keys %deviceports)) {
vars->{'device_changed'} = 1;
debug sprintf ' [%s] hooks - port set changed: had [%s], now [%s]',
$device->ip, (join ', ', sort {$a cmp $b} keys %{ vars->{'device_ports'} }),
(join ', ', sort {$a cmp $b} keys %deviceports);
}
else {
my $ports_rsrc = schema('netdisco')->resultset('DevicePort')->result_source;
PORTDIFF: foreach my $port (sort {$a cmp $b} keys %deviceports) {
my $old = vars->{'device_ports'}->{$port};
my $new = $deviceports{$port};
foreach my $field (sort {$a cmp $b} keys %$new) {
next if $ignore_field{$field};
my $oldval = (defined $old->$field ? $old->$field : '');
my $newval = (defined $new->{$field} ? $new->{$field} : '');
if ($ports_rsrc->column_info($field)->{'data_type'} =~ m/bool/i) {
$oldval = $normalize_bool->($oldval);
$newval = $normalize_bool->($newval);
}
next if $oldval eq $newval;
vars->{'device_changed'} = 1;
debug sprintf ' [%s] hooks - port %s field %s changed: "%s" -> "%s"',
$device->ip, $port, $field, $oldval, $newval;
last PORTDIFF;
}
}
}
}
# support for Hooks
vars->{'hook_data'}->{'ports'} = [values %deviceports];
schema('netdisco')->resultset('DevicePort')->txn_do_locked(ACCESS_EXCLUSIVE, sub {
my $coder = JSON::PP->new->utf8(0)->allow_nonref(1)->allow_unknown(1);
#Â backup the custom_fields
my %fields = map {($_->port => $coder->decode(Encode::encode('UTF-8',$_->custom_fields || '{}')))}
grep {exists $deviceports{$_->port}}
values %{ vars->{'device_ports'} };
my %ok_fields = map {$_ => 1}
grep {defined}
map {$_->{name}}
@{ setting('custom_fields')->{device_port} || [] };
#Â filter custom_fields for current valid fields
foreach my $port (keys %fields) {
my %new_fields = ();
foreach my $field (keys %ok_fields) {
$new_fields{$field} = exists $fields{$port}->{$field}
? Encode::decode('UTF-8', $fields{$port}->{$field}) : undef;
}
#Â set new custom_fields
$deviceports{$port}->{custom_fields} = $coder->encode(\%new_fields);
}
my $gone = $device->ports->delete({keep_nodes => 1});
debug sprintf ' [%s] interfaces - removed %d interfaces',
$device->ip, $gone;
#Â uptime and num_ports changed
$device->update();
$device->ports->populate([values %deviceports]);
return Status->info(sprintf ' [%s] interfaces - added %d new interfaces',
$device->ip, scalar values %deviceports);
});
});
# return a list of VRF which are OK to connect
sub _get_vrf_list {
my ($device, $snmp) = @_;
return () if ! $snmp->cisco_comm_indexing;
my @ok_vrfs = ();
my $vrf_name = $snmp->vrf_name || {};
while (my ($idx, $vrf) = each(%$vrf_name)) {
if ($vrf =~ /^\S+$/) {
my $ctx_name = pack("C*",split(/\./,$idx));
$ctx_name =~ s/.*[^[:print:]]+//;
debug sprintf(' [%s] Discover VRF %s with SNMP Context %s', $device->ip, $vrf, $ctx_name);
push (@ok_vrfs, $ctx_name);
}
}
return @ok_vrfs;
}
( run in 1.042 second using v1.01-cache-2.11-cpan-800906f7e73 )