App-Netsync

 view release on metacpan or  search on metacpan

lib/App/Netsync/Network.pm  view on Meta::CPAN

package App::Netsync::Network; #XXX This package should be object-oriented.

=head1 NAME

App::Netsync::Network - methods for manipulating network structures

=head1 DESCRIPTION

This module is responsible for for manipulating an internal view of a network.

=head1 SYNOPSIS

 use App::Netsync 'devices_interfaces';
 use App::Netsync::Network;
 use feature 'say';

 my %node;
 $node{'ip'}       = '10.0.0.1';
 $node{'hostname'} = 'host1';
 $node{'session'}  = App::Netsync::SNMP::Session $node{'ip'};
 $node{'info'}     = App::Netsync::SNMP::Info $session;

 my $serial2if2ifName = device_interfaces ($node{'info'}->vendor,$node{'session'});

 node_initialize (\%node,$serial2if2ifName);
 say node_string \%node;
 node_dump \%node;

 # or

 device_initialize (\%node,$_,$serial2if2ifName->{$_}) foreach keys $serial2if2ifName;
 foreach my $serial (keys %{$node{'devices'}}) {
    my $device = $node{'devices'}{$serial};
    say device_string $device;
    device_dump $device;
 }

 # or

 foreach my $serial (keys %serial2if2ifName) {
    $node->{'devices'}{$serial} = \%device;
    my $device = $node{'devices'}{$serial};
    $device->{'node'} = $node;

    my $if2ifName = $serial2if2ifName{$serial};
    interface_initialize ($device,$if2ifName->{$_},$_) foreach keys %$if2ifName;
 }

 foreach my $serial (keys %{$node{'devices'}}) {
    my $device = $node{'devices'}{$serial};
    foreach my $ifName (keys %{$device->{'interfaces'}}) {
       my interface = device->{'interfaces'}{$ifName};
       say interface_string $interface;
       interface_dump $interface;
    }
 }


 my %nodes;
 $nodes{'10.0.0.1'} = \%node;
 $nodes{'10.0.0.2'}{'ip'} = '10.0.0.2';
 $nodes{'10.0.0.3'}{'ip'} = '10.0.0.3';
 $nodes{'10.0.0.4'}{'ip'} = '10.0.0.4';
 $nodes{'10.0.0.5'}{'ip'} = '10.0.0.5';

 my $n = node_find (\%nodes,'10.0.0.5');
 $n->{'ip'} == '10.0.0.5';

 $n->{'devices'}{'1A2B3C4D5E6F'}{'serial'} = '1A2B3C4D5E6F';

 my $d = device_find (\%nodes,'1A2B3C4D5E6F');
 $d->{'serial'} == '1A2B3C4D5E6F';

 $d->{'interfaces'}{'ethernet1/1/1'}{'ifName'} = ethernet1/1/1;

 my $i = interface_find ($n->{'devices'},'ethernet1/1/1');
 $i->{'ifName'} = 'ethernet1/1/1';

=cut


use 5.006;
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie; #XXX Is autodie adequate?

use File::Basename;
use version;

our ($SCRIPT,$VERSION);
our %config;

BEGIN {
    ($SCRIPT)  = fileparse ($0,"\.[^.]*");
    ($VERSION) = version->declare('v4.0.0');

    require Exporter;
    our @ISA = ('Exporter');
    our @EXPORT = (
        'node_initialize','device_initialize','interface_initialize',
        'node_string'    ,'device_string'    ,'interface_string',
        'node_dump'      ,'device_dump'      ,'interface_dump',
        'node_find'      ,'device_find'      ,'interface_find',
    );

    $config{'Indent'}  = 4;
    $config{'Quiet'}   = 0;
    $config{'Verbose'} = 0;
}


=head1 METHODS

lib/App/Netsync/Network.pm  view on Meta::CPAN

I<( @interfaces )>

=over 3

=item interfaces

an array of devices to stringify

=back

=cut

sub interface_string {
    warn 'too few arguments' if @_ < 1;
    my (@interfaces) = @_;

    my @interface_strings;
    foreach my $interface (@interfaces) {
        my $interface_string;
        if ($interface->{'ifName'} // $interface->{'IID'} // $interface->{'device'} // 0) {
            $interface_string  = $interface->{'ifName'}.' ('.$interface->{'IID'}.')';
            $interface_string .= ' on '.device_string $interface->{'device'};
        }
        push (@interface_strings,$interface_string);
    }
    return $interface_strings[0] if @interfaces == 1;
    return @interface_strings;
}




################################################################################




=head2 node_dump

prints a node structure

B<Arguments>

I<( @nodes )>

=over 3

=item nodes

an array of nodes to print

=back

=cut

sub node_dump {
    warn 'too few arguments' if @_ < 1;
    my (@nodes) = @_;

    foreach my $node (@nodes) {
        say node_string $node;

        my $device_count = 0;
        if (defined $node->{'devices'}) {
            $device_count = scalar keys %{$node->{'devices'}};

            my ($identified_device_count,$interface_count,$identified_interface_count) = (0,0,0);
            foreach my $serial (keys %{$node->{'devices'}}) {
                my $device = $node->{'devices'}{$serial};
                ++$identified_device_count if $device->{'identified'};
                next unless defined $device->{'interfaces'};
                $interface_count += scalar keys %{$device->{'interfaces'}};
                foreach my $ifName (keys %{$device->{'interfaces'}}) {
                    my $interface = $device->{'interfaces'}{$ifName};
                    ++$identified_interface_count if $interface->{'identified'};
                }
            }
            print ((' 'x$config{'Indent'}).$device_count.' device');
            print 's' if $device_count > 1;
            print ' ('.$identified_device_count.' identified)' if $identified_device_count > 0;
            print "\n";
            print ((' 'x$config{'Indent'}).$interface_count.' interface');
            print 's' if $interface_count > 1;
            print ' ('.$identified_interface_count.' identified)' if $identified_interface_count > 0;
            print "\n";
        }

        if (defined $node->{'info'}) {
            my $info = $node->{'info'};
            if ($device_count == 1) {
                #say ((' 'x$config{'Indent'}).$info->class);
                say ((' 'x$config{'Indent'}).$info->vendor.' '.$info->model);
                say ((' 'x$config{'Indent'}).$info->serial);
            }
        }
    }
    say scalar (@nodes).' nodes' if @nodes > 1;
}


=head2 device_dump

prints a device structure

B<Arguments>

I<( @devices )>

=over 3

=item devices

an array of devices to print

=back

=cut

sub device_dump {
    warn 'too few arguments' if @_ < 1;
    my (@devices) = @_;

    foreach my $device (@devices) {
        say device_string $device;

        if (defined $device->{'identified'}) {
            say ((' 'x$config{'Indent'}).(($device->{'identified'}) ? 'identified' : 'unidentified'));
        }

        if (defined $device->{'interfaces'}) {
            my $interface_count = scalar keys %{$device->{'interfaces'}};
            my $identified_interface_count = 0;
            foreach my $ifName (keys %{$device->{'interfaces'}}) {
                my $interface = $device->{'interfaces'}{$ifName};
                ++$identified_interface_count if $interface->{'identified'};
            }
            print ((' 'x$config{'Indent'}).$interface_count.' interface');
            print 's' if $interface_count > 1;
            say ' ('.$identified_interface_count.' identified)';
        }
    }
    say scalar (@devices).' devices' if @devices > 1;
}


=head2 interface_dump

prints an interface structure

B<Arguments>

I<( @interfaces )>

=over 3

=item interfaces

an array of interfaces to print

=back

=cut

sub interface_dump {
    warn 'too few arguments' if @_ < 1;
    my (@interfaces) = @_;

    foreach my $interface (@interfaces) {
        say interface_string $interface;

        if (defined $interface->{'identified'}) {
            say ((' 'x$config{'Indent'}).(($interface->{'identified'}) ? 'identified' : 'unidentified'));
        }

        if (defined $interface->{'info'}) {
            foreach my $field (sort keys %{$interface->{'info'}}) {
                print ((' 'x$config{'Indent'}).$field.': ');
                say (($interface->{'info'}{$field} =~ /[\S]+/) ? $interface->{'info'}{$field} : '(empty)');
            }
        }
    }
    say scalar (@interfaces).' interfaces' if @interfaces > 1;
}




################################################################################




=head2 node_find

check for a node in a set of nodes

B<Arguments>

I<( \%nodes , $ip )>

=over 3

=item nodes

an array of nodes to search

=item ip

the IP address of the node

=back

=cut

sub node_find {
    warn 'too few arguments'  if @_ < 2;
    warn 'too many arguments' if @_ > 2;
    my ($nodes,$ip) = @_;

    return $nodes->{$ip};
}


=head2 device_find

check for a device in a set of nodes

B<Arguments>

I<( \%nodes , $serial )>

=over 3

=item nodes

an array of nodes to search

=item serial

a unique device identifier

=back



( run in 0.465 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )