App-Netsync

 view release on metacpan or  search on metacpan

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


=back

=cut

sub identify {
    warn 'too few arguments'  if @_ < 1;
    warn 'too many arguments' if @_ > 3;
    my ($nodes,$data_source,$auto_match) = @_;
    $data_source //= 'DB';
    $auto_match  //= 0;

    unless ($config{'Quiet'}) {
        print 'identifying';
        print ' (using '.$data_source.')...';
        print (($config{'Verbose'}) ? "\n" : (' 'x$config{'DeviceOrder'}).'0');
    }

    my @data;
    { # Retrieve database.

        unless (defined $config{'DeviceField'}    and
                defined $config{'InterfaceField'} and
                defined $config{'InfoFields'}) {
            warn 'Database fields have not been configured.';
            return undef;
        }

        # Initialize output table headers.
        my $fields = $config{'DeviceField'}.','.$config{'InterfaceField'};
        $fields .= ','.join (',',sort @{$config{'InfoFields'}});

        my %inputs = (
            'DB' => sub {
                my %drivers = DBI->installed_drivers;
                say $_ foreach values %drivers; exit; #XXX debug
                unless (defined $config{'DB'}) {
                    warn 'A database has not been configured.';
                    return undef;
                }

                # Connect to the database.
                my $DSN  =       'dbi:'.$config{'DBMS'};
                   $DSN .=     ':host='.$config{'Server'};
                   $DSN .=     ';port='.$config{'Port'};
                   $DSN .= ';database='.$config{'Database'};
                my $db = DBI->connect($DSN,$config{'Username'},$config{'Password'},$config{'DB'});
                my $query = $db->prepare('SELECT '.$fields.' FROM '.$config{'Table'});
                $query->execute;
                @data = @{$query->fetchall_arrayref({})};
                $db->disconnect;
            },
            'default' => sub { # Read a CSV file specified with the database option (-d).
                open (my $db,'<',$data_source);

                my $parser = Text::CSV->new;
                chomp (my @fields = split (',',<$db>));
                $parser->column_names(@fields);

                # Filter out fields that are not needed,
                # and verify the presence of necessary fields.
                my $removed_field_count = 0;
                foreach my $i (keys @fields) {
                    $i -= $removed_field_count;
                    unless ($fields =~ /(^|,)$fields[$i](,|$)/) {
                        ++$removed_field_count;
                        splice (@fields,$i,1);
                    }
                }
                die 'incompatible database' unless @fields == scalar split (',',$fields);

                foreach my $row (@{$parser->getline_hr_all($db)}) {
                    my $entry = {};
                    $entry->{$_} = $row->{$_} foreach @fields;
                    push (@data,$entry);
                }

                close $db;
            },
        );
        ($inputs{$data_source} || $inputs{'default'})->();
    }

    my $conflict_count = 0;
    {
        my %identified; # $identified{$serial} == $node

        ROW : foreach my $row (@data) {
            my $valid = [
                $config{'DeviceField'},
                $config{'InterfaceField'},
            ];
            foreach my $field (@$valid) { # Verify necessary fields aren't empty.
                next ROW unless defined $row->{$field} and $row->{$field} =~ /\S+/; # Otherwise, skip to the next entry.
            }

            # Synchronize the entry with gathered info.
            $conflict_count += synchronize ($nodes,\%identified,$auto_match,[$row]);

            # Show the user how many nodes have been identified if necessary.
            unless ($config{'Quiet'} or $config{'Verbose'}) {
                print  "\b"x$config{'DeviceOrder'};
                printf ('%'.$config{'DeviceOrder'}.'d',scalar keys %identified);
            }
        }

        # Show the user what's been found if necessary.
        unless ($config{'Quiet'}) {
            print scalar keys %identified if $config{'Verbose'};
            print ' synchronized';
            print ' ('.$conflict_count.' conflicts)' if $conflict_count > 0;
            print "\n";
        }
    }

    # Search for network devices and interfaces that were not identified in the database.
    foreach my $ip (sort keys %$nodes) {
        my $node = $nodes->{$ip};
        foreach my $serial (sort keys %{$node->{'devices'}}) {
            my $device = $node->{'devices'}{$serial};
            unless ($device->{'identified'}) {



( run in 2.057 seconds using v1.01-cache-2.11-cpan-13bb782fe5a )