Sunday 16 March 2008

Using nagios to monitor print configuration

Now this isn't a copy a previous post, which was about monitoring print queues. This is about monitoring our quite complex printing configuration system.

Again, a bit of background. We keep as much configuration info as we can in an LDAP directory. And we install printers on our windows desktops ( about 1,200 spread over several sites ) during either the startup scripts (for locally attached printer) or the login script (for network printers). We use the concept of a 'nearest printer', assigned to the workstation dependent on physical location.

So, sticking to network printers, we have:

  • A CUPS queue per printer, served by Samba to windows desktops.
  • A 'nearest printer' attribute in LDAP, attached to the workstation entry. This 'points to'..
  • A printer entry per printer, with an 'installcommand' attribute, which gives an appropriate command line to install that printer on a workstation. This gets run during the login script.
Perhaps it would be clearer to describe how a workstation gets a printer. I'm focusing on network printing, so this happens in the login script.
  • Look up my (the workstation's) LDAP entry.
  • From my LDAP entry, get the nearest printers.
  • For each nearestprinter, get the installcommand from the printer's LDAP entry.
  • And run it.
Now we like this. We can have several printers associated with one workstation, and we could (though we don't) associate nearestprinters with user accounts as well as workstations. It's real easy to change a workstation's printer(s), and users need know nothing about it. When it works, it just works.

But there's no referential integrity going on here. We can have orphans anywhere. A CUPS queue with no install commands. An installcommand referring to a non-existent CUPS queue. A workstation with a nearestprinter that doesn't exist. etc. Basically, config rot, caused by human failure to attend to detail.

And here we get to the point of it all. We have a nagios check called 'check_print_config', which checks all this, and creates a warning state if something's out of whack. It's posted below. As with most code posted here, it's finished to the point where it works. It's not great code. It does, I'd posit, do something interesting.


#!/usr/bin/perl -w
use strict;

my @nagiosCupsQueues;
my @nearestPrinterQueues;
my @installCommandQueues;
my @output = ();

# print "Getting monitored queues from nagios...\n";
@nagiosCupsQueues = (`grep check_cups_queue /etc/nagios2/conf.d/allPrintQueues.cfg | cut -f2 -d'!'`);
chop @nagiosCupsQueues;

# print "Getting installCommand queues from LDAP...\n";
@installCommandQueues = (`ldapsearch -LLL -x -b "ou=hosts,dc=example,dc=com" '(installcommand=*con2prt*)' installcommand | grep '/cd ' | grep -iv idcard | grep -iv tmu220 | grep -iv null | sort | uniq | cut -f4 -d" " | cut -f4
-d"\\\\"`);
chop @installCommandQueues;

# print "Getting nearestprinter queues from LDAP...\n";
@nearestPrinterQueues = (`ldapsearch -LLL -x -b "ou=hosts,dc=example,dc=com" '(&(objectclass=computer)(nearestprinter=*))' nearestprinter | grep nearestprinter | grep -iv lpt | grep -iv archicad | grep -iv tmu220 | grep -iv idcard | grep -iv null | sort | uniq | cut -f1 -d"," | cut -f2 -d"="`);
chop @nearestPrinterQueues;

foreach my $icq ( @installCommandQueues ) {
next if $icq =~ /^$/;
push(@output, "ICQ: $icq ") if ! grep(/^$icq$/i, @nagiosCupsQueues);
}
foreach my $npq ( @nearestPrinterQueues ) {
next if $npq =~ /^$/;
my $npqNotInCups = 0;
my $npqNoInstallCommand = 0;
$npqNotInCups = 1 if ! grep(/^$npq$/i, @nagiosCupsQueues);
$npqNoInstallCommand = 1 if ! grep(/^$npq$/i, @installCommandQueues);
# push(@output, "NPQ:$npq:") if ( $npqNoInstallCommand && $npqNotInCups );
my @duffClients = `ldapsearch -LLL -x -b "ou=hosts,dc=example,dc=com" "nearestprinter=cn=$npq,ou=hosts,dc=example,dc=com" dn | grep dn: | cut -f1 -d"," | cut -f2 -d"="`;
chop @duffClients;
push(@output, "NPQ:$npq: " . join(",", @duffClients) . " ") if ( $npqNoInstallCommand && $npqNotInCups );
}

#print Dumper([ \@output, ]);
if ( @output > 0 ) {
print "WARNING: " . join(" ",@output) . "\n";
exit 1;
} else {
print "OK\n";
exit 0;
}

1 comment:

Anonymous said...

beautyful code! Sometime, I will code like this too.

nice kungfu.

still tring to figure out the grep \xxx\i thing.

bye