App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Util/Snapshot.pm view on Meta::CPAN
Helper functions for L<SNMP::Info> instances.
There are no default exports, however the C<:all> tag will export all
subroutines.
=head1 EXPORT_OK
=head2 load_cache_for_device( $device )
Tries to find a device cache in database or on disk, or build one from
a net-snmp snmpwalk on disk. Returns a cache.
=cut
sub load_cache_for_device {
my $device = shift;
return {} unless ($device->is_pseudo or not $device->in_storage);
my $pseudo_cache = catfile( catdir(($ENV{NETDISCO_HOME} || $ENV{HOME}), 'logs', 'snapshots'), $device->ip );
my $loadmibs = schema('netdisco')->resultset('SNMPObject')->count;
if (-f $pseudo_cache and not $loadmibs) {
warning "device snapshot exists ($pseudo_cache) but no MIB data available.";
warning 'skipping offline cache load - run a "loadmibs" job if you want this!';
return {};
}
my %oids = ();
#Â ideally we have a cache in the db
if ($device->is_pseudo
and not $device->oids->search({ -or => [
-bool => \q{ array_length(oid_parts, 1) IS NULL },
-bool => \q{ jsonb_typeof(value) != 'array' }, ] })->count) {
my @rows = $device->oids->search({},{
join => 'oid_fields',
columns => [qw/oid value/],
select => [qw/oid_fields.mib oid_fields.leaf/], as => [qw/mib leaf/],
})->hri->all;
$oids{$_->{oid}} = {
%{ $_ },
value => (@{ from_json($_->{value}) })[0],
} for @rows;
}
#Â or we have an snmpwalk file on disk
elsif (-f $pseudo_cache and not $device->in_storage) {
debug sprintf "importing snmpwalk from disk ($pseudo_cache)";
my @lines = read_lines($pseudo_cache);
my %store = ();
#Â sometimes we're given a snapshot with iso. instead of .1.
if ($lines[0] !~ m/^.\d/) {
warning 'snapshot file rejected - has translated names/values instead of numeric';
return {};
}
#Â parse the snmpwalk output which looks like
# .1.0.8802.1.1.2.1.1.1.0 = INTEGER: 30
foreach my $line (@lines) {
my ($oid, $type, $value) = $line =~ m/^(\S+)\s+=\s+(?:([^:]+):\s+)?(.+)$/;
next unless $oid and $value;
#Â empty string makes the capture go wonky
$value = '' if $value =~ m/^[^:]+: ?$/;
#Â remove quotes from strings
$value =~ s/^"//;
$value =~ s/"$//;
$store{$oid} = {
oid => $oid,
oid_parts => [], #Â not needed temporarily
value => to_json([ ((defined $type and $type eq 'BASE64') ? $value
: encode_base64(trim($value), '')) ]),
};
}
#Â put into the database (temporarily)
#Â this MUST happen here and not be refactored into make_snmpwalk_browsable
#Â because make_snmpwalk_browsable is also called from snapshot job.
#Â it will all be cleaned up after
schema('netdisco')->txn_do(sub {
$device->oids->delete;
$device->oids->populate([values %store]);
});
#Â get back out of the database as tables with related snmp_object (for the enum)
%oids = make_snmpwalk_browsable($device);
$oids{$_}->{value} = (@{ from_json( $oids{$_}->{value} ) })[0]
for keys %oids;
}
# inflate the cache to an SNMP::Info cache instance
return snmpwalk_to_snmpinfo_cache(%oids);
}
=head2 make_snmpwalk_browsable( $device )
Takes the device_browser rows for a device and rewrites them to convert
table rows to hashref, enum values translated, and oid_parts filled.
=cut
sub make_snmpwalk_browsable {
my $device = shift;
my %oids = ();
#Â to get relation from device_browser to snmp_object working for tables
#Â we need to temporarily populate device_browser with potential table oids.
#Â it will all be cleaned up after
my %value_oids = map {($_ => 1)} $device->oids->get_column('oid')->all;
my %table_oids = ();
foreach my $orig_oid (keys %value_oids) {
(my $oid = $orig_oid) =~ s/\.\d+$//;
my $new_oid = '';
( run in 0.613 second using v1.01-cache-2.11-cpan-39bf76dae61 )