Article Figure 1 Listing 1 Listing 2 mar2006.tar

Listing 2 config2db

#!/usr/bin/perl

use strict;
use warnings;
use lib 'scripts';
use IO::File;
use NetAddr::IP;
use Cisco::Reconfig;
use MyConfigCDBI;
$|++;

sub version_file { my $f = shift; $f =~ s/\.config$/\.version/; $f }

sub get_version
{
    my $fh = new IO::File $_[0];
    my $version;        # The output of show version
    my $class;

    unless ($fh)
    {
    warn "Failed to open version file $_[0]: $!\n";
    return (map { 'Could not read version file' } 1 .. 3);
    }

    do { local $/ = undef; $version = <$fh>; };
    close $fh;

    my $sw = ($version =~ m/^(.+Software .+ Version .+)$/m)[0] 
    || 'Cannot find software version';
    my $hw = ($version =~ 
          m/^(cisco .+ (processor .+|bytes of memory\.?))$/mi)[0] 
          || 'Cannot find hardware version';
    my $sn = ($version =~ m/processor board ID (\w+( \([^\)]+\))?)/mi)[0]
    || 'Cannot find serial number';

    if ($version =~ m/cisco\s(Cat6k-|WS-C(29|3[57]|40))/)
    {    $class = 'switch' }
    elsif ($version =~ /cisco\s(2[56]\d\d|18\d\d
|WS-C65\d\d|17\d\d|CISCO76\d\d)\s/ix)
    {    $class = 'router' }
    elsif ($version =~ /cisco\sAIR-AP/)
    {    $class = 'access-point' }

    return ($sw, $hw, $sn, $class);
}

sub get_base_info
{
    my %k = map { $_ => $_[0]->get($_) } 
    ('hostname', 'snmp-server contact', 'snmp-server location');

    return map { $k{$_} =~ s/^$_\s+//; chomp($k{$_}); $k{$_} } sort keys %k;
}

sub get_interfaces
{
    my $config = shift;
    my @ifs = ();
    for my $if ($config->get('interface')->all())
    {
    my @container = (($if->text =~ m/interface (\S+)/)[0]);
    next unless $container[0];
    my $desc = ($if->get('description')->text =~ m/description (.+)$/)[0];
    push @container, $desc;
    for my $addr ($if->get('ip address'))
    {
        next if $addr->text =~ m/no ip address/;
        next unless $addr->text;
        my ($ip, $mask, $class) = 
        $addr->text =~ m/ip address (\S+) (\S+)\s*(secondary)?/;
        $class ||= 'primary';
        my $i = NetAddr::IP->new($ip, $mask);
        next unless $i;
        push @container, [ $i, $class ];
    }
    push @ifs, \@container;
    }
    return @ifs;
}

MyConfig::CDBI->connection('dbi:SQLite:dbname=config.db');

for my $c (@ARGV)
{
    my $config = readconfig($c);
    my ($dev, $loc, $ctc) = get_base_info($config);

    if (not defined $dev)
    {
    warn "$c does not define a device host name\n";
    next;
    }

    my $vc = version_file($c);
    my ($sw, $hw, $sn, $cl) = get_version($vc);

    # Populate our devices table

    my $device = MyConfig::CDBI::Device->find_or_create(
    device => $dev,
    location => $loc,
    contact => $ctc,
    serial => $sn,
    hardware => $hw,
    software => $sw,
    class => $cl
    );

    # Extract the interfaces from the configuration

    for my $if (get_interfaces($config))
    {
    my $ifname = lc shift @$if;
    my $desc = shift @$if;
    print "$c $device $ifname\n";
    my $interface = MyConfig::CDBI::Interface->find_or_create(
        interface => $ifname,
        device => $dev,
        description => $desc
    );
    for my $ip (@$if)
    {
        my $subnet = MyConfig::CDBI::Subnet->find_or_create(
        cidr => $ip->[0]->network->cidr,
        first => scalar $ip->[0]->network->numeric,
        last => scalar $ip->[0]->broadcast->numeric,
        );
        my $address = MyConfig::CDBI::Address->find_or_create(
        ip => scalar $ip->[0]->numeric,
        interface => lc $interface->interface,
        device => $device->device,
        cidr => $subnet->cidr,
        type => $ip->[1],
        );
    }
    }
}