1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#!/usr/local/bin/perl -w
##
## cricket-genconf-sensor
##
## Generate Cricket configuration for sensor monitoring
##
## Author: Simon Leinen <simon@limmat.switch.ch>
## Date created: 21-Dec-2006
##
## This script generates Cricket configuration files for
## SNMP-monitorable sensors in a set of routers. It does this on the
## basis of a RANCID configuration file repository. For each router
## in that directory that seems to have monitorable sensors, the
## script calls the `entls' script to generate Cricket configuration.
##
## The script puts newly generated configuration files into a
## temporary directory, and then installs some "safe" configuration
## changes by itself. For other configuration changes, the user is
## presented with "diff" output and has to decide how to apply them.
use strict;
use warnings;
use Cisco::Abbrev;
my $testing = 0;
### Prototypes
sub read_router_configurations ($ );
sub has_sensors_p ($ );
sub postprocess_router_config ($$);
sub maybe_install_new_configuration ($ );
sub install_new_configuration ($ );
my $rancid_directory = '/usr/local/rancid/backbone/configs';
my @routers = read_router_configurations ($rancid_directory);
my $cricket_config_dir = '/home/cricket/cricket-config';
my $old_config_dir = $cricket_config_dir.'/'.'transceiver-monitoring';
-d $old_config_dir or die "cannot find existing configuration $old_config_dir";
my $new_config_dir = '/tmp'.'/foo/';
-d $new_config_dir
or mkdir $new_config_dir
or die "Cannot create $new_config_dir: $!";
my (@unchanged, @installed, @unresolved);
foreach my $router (@routers) {
my $routername = $router->{name};
## For testing, only look at one router
next if $testing and $routername ne 'swiix2';
next unless has_sensors_p ($router);
my $rdir = $new_config_dir.'/'.$routername;
-d $rdir or mkdir $rdir or die "cannot create directory $rdir: $!";
my $retval = system ('perl -Ilib test/entls -t hctiws@'
.$routername.':::::2:v4only > '
.$rdir.'/'.$routername);
if ($retval) {
warn "failed to generate configuration for $routername";
} else {
postprocess_router_config ($rdir.'/'.$routername, $router);
maybe_install_new_configuration ($router);
}
}
print "Unchanged: ",join (", ", map { $_->{name} } @unchanged),"\n";
print "Installed: ",join (", ", map { $_->{name} } @installed),"\n";
print "Unresolved: ",join (", ", map { $_->{name} } @unresolved),"\n";
1;
sub postprocess_router_config ($$) {
my ($file, $router) = @_;
my ($pre, $sd, $post, $long, $desc);
open IN, $file or die "Cannot open configuration file $file: $!";
open OUT, ">$file.post" or die "Cannot open configuration file $file.post: $!";
while (<IN>) {
if (/^(\s*display-name\s*=\s*")(.*)("\s*)$/) {
} elsif (/^(\s*long-desc\s*=\s*")(.*)("\s*)$/) {
} elsif (/^(\s*short-desc\s*=\s*")(.*)("\s*)$/) {
($pre, $sd, $post) = ($1, $2, $3);
$sd =~ s/^transceiver //i;
$long = cisco_long_int ($sd);
$sd = $long if defined $long;
if (defined $long) {
$desc = $long;
$sd = $desc = $router->{ifdesc}->{$long}
if exists $router->{ifdesc}->{$long};
} else {
$long = $desc = $sd;
}
chomp $post;
print OUT "$pre$sd$post\n";
print OUT "\tlong-desc\t = \"<h3>$long - $desc</h3>\"\n";
print OUT "\tdisplay-name\t = \"%router% - $long\"\n";
} else {
print OUT $_;
}
}
close IN or die "Cannot close configuration file $file: $!";
close OUT or die "Cannot close configuration file $file.post: $!";
rename $file, "$file.pre" or unlink $file;
rename "$file.post", $file or rename "$file.pre", $file;
unlink "$file.pre";
return 1;
}
sub read_router_configurations ($ ) {
my ($dir) = @_;
my @routers = ();
opendir CONFIG, $dir
or die "open directory $dir: $!";
foreach my $file (readdir CONFIG) {
next if $testing and $file ne 'swiix2';
next unless -f $dir.'/'.$file;
push @routers, { name => $file };
}
closedir CONFIG
or die "close directory $dir: $!";
@routers;
}
sub has_sensors_p ($ ) {
my ($router) = @_;
my $routername = $router->{name};
my $have_sensor_p = 0;
my ($ifname, %ifdesc);
open (CONFIG, $rancid_directory.'/'.$routername)
or die "open configuration file for $routername: $!";
while (<CONFIG>) {
if (/Receive Power Sensor/) {
$have_sensor_p = 1;
} elsif (/^interface (.*)/) {
$ifname = $1;
} elsif (/^ description (.*)$/
and defined $ifname) {
$ifdesc{$ifname} = $1;
} elsif (/^ /) {
} else {
$ifname = undef;
}
}
close CONFIG or die "close configuration file for $routername: $!";
## foreach my $ifname (sort keys %ifdesc) {
## printf "%-20s %s\n", $ifname, $ifdesc{$ifname};
## }
$router->{ifdesc} = \%ifdesc;
return $have_sensor_p;
}
## maybe_install_new_configuration ROUTER
##
## Check whether the newly generated Cricket configuration file for
## router ROUTER has to/can be installed.
##
## If the file doesn't exist in the current configuration, we can
## safely install the new one.
##
## If the newly generated file is identical to the old one, we don't
## have to do anything.
##
## The the newly generated file differs from the old one, we output
## the diff and don't install anything.
##
## TODO: Apply the diffs. This is not totally trivial, however. As
## long as the diff consists in only added lines, the new file can be
## safely installed over the current one. But when configuration is
## lost (i.e. sensors are removed), we should deactivate the lost
## targets using "collect = 0", rather than removing them entirely, to
## make sure that history is kept.
##
## There is an additional case, namely that a file exists in the
## current configuration that was not generated in the new run. We
## don't handle this situation currently.
##
## TODO: Check the existing configuration for files that were lost in
## the new generation run, and deactivate collection in these files.
##
## Actual installation of configurations is performed by
## install_new_configuration().
##
sub maybe_install_new_configuration ($ ) {
my ($router) = @_;
my $routername = $router->{name};
my $old_file = $old_config_dir.'/'.$routername.'/'.$routername;
my $new_file = $new_config_dir.'/'.$routername.'/'.$routername;
if (! -f $old_file) {
print "NEW: $routername\n";
if (install_new_configuration ($router)) {
push @installed, $router;
} else {
push @unresolved, $router;
}
} else {
my $retval = system ("diff", "-uw", $old_file, $new_file);
if ($retval) {
##warn "TESTING:\n";
##$retval = system "diff -w $old_file $new_file | egrep -v '\^>'";
##warn "TESTING END: $retval\n";
print "DIFFER: $routername\n";
push @unresolved, $router;
} else {
push @unchanged, $router;
unlink $new_file;
}
}
}
## install_new_configuration ROUTER
##
## Install the newly generated configuration file for router ROUTER in
## the active directory tree. The containing directory is created if
## needed.
##
sub install_new_configuration ($ ) {
my ($router) = @_;
my $routername = $router->{name};
my $old_file = $old_config_dir.'/'.$routername.'/'.$routername;
my $new_file = $new_config_dir.'/'.$routername.'/'.$routername;
my $old_dir = $old_config_dir.'/'.$routername;
unless (-d $old_dir || mkdir $old_dir) {
warn "Cannot create $old_dir: $!";
return undef;
}
if (system ("mv", $new_file, $old_file)) {
warn "Failed to move $new_file to $old_file";
return undef;
}
return 1;
}
|