Ref item 9 on <URL:http://wiki.debian.org/DebianEdu/Meeting/20070813>, here is a update proposal for the stable release.
I propose to update the version of sitesummary in the stable repository from 0.0.30 to 0.0.33. This fixes a bug in the collection of the peername IP address, and add a few featires to list the clients with a given kernel version or that have not submitted information for a while. There is also a draft nagios config generator, but this is not yet complete. The changes are tested on the skolelinux servers, and the resulting output can be seen on <URL:http://maintainer.skolelinux.no/sitesummary/>. Here is the diff -r output between the two versions: Index: debian/changelog =================================================================== --- debian/changelog (revision 38710) +++ debian/changelog (working copy) @@ -1,3 +1,34 @@ +sitesummary (0.0.33) unstable; urgency=low + + * Collect loaded kernel modules, to ease nagios autoconfiguration. + * Add >180 days to the agesinceseen-summary list, for really old entries. + + -- Petter Reinholdtsen <[EMAIL PROTECTED]> Sat, 1 Dec 2007 14:13:16 +0100 + +sitesummary (0.0.32) unstable; urgency=low + + * Collect /proc/mounts and /etc/fstab in system, for use when + generating nagios checks for the file systems. + * Start on experimental code to generate nagios configuration from + the collected sitesummary information. + * Fix peername code in the collector. + * Set the locale to C when collecting data, to make sure the output + format is well known. (Closes: #452899) + * Minor cleanup in output. + + -- Petter Reinholdtsen <[EMAIL PROTECTED]> Mon, 26 Nov 2007 09:52:33 +0100 + +sitesummary (0.0.31) unstable; urgency=low + + * Add -l option to kernelversion-summary and site-summary, to get it + to list the individual hosts with the given kernel version and + site/sitegroup setting. + * New script agesinceseen-summary, listing the hosts that have + failed to submit a report in the last few days. It support -l to + list the individual hosts. + + -- Petter Reinholdtsen <[EMAIL PROTECTED]> Fri, 23 Nov 2007 22:28:14 +0100 + sitesummary (0.0.30) unstable; urgency=low * Change default apache setup to allow everyone read access to Index: agesinceseen-summary =================================================================== --- agesinceseen-summary (revision 0) +++ agesinceseen-summary (revision 39483) @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use SiteSummary; +use Getopt::Std; + +my %agegroup = + ( + 0 => '>0 days', + 3 => '>3 days', + 7 => '>one week', + 14 => '>14 days', + 30 => '>30 days', + 90 => '>90 days', + 180 => '>180 days', +); + +my %agedist; +my %opts; + +sub usage { + my $retval = shift; + print <<EOF; +Usage: $0 [-l] + -l list hosts with the given age +EOF + exit $retval; +} + +getopt("l", \%opts) || usage(1); + +for_all_hosts(\&handle_host); + +print_summary(); + +sub handle_host { + my $hostid = shift; + my $topdir = get_filepath_current($hostid, "/"); + my $age = (time() - (stat($topdir))[9]) / (60 * 60 * 24); + + my $thisgroup; + for my $group (sort { $a <=> $b; } keys %agegroup) { + if ($age > $group) { + $thisgroup = $group; + } + } + if (defined $thisgroup) { + if (exists $agedist{$thisgroup}) { + push @{$agedist{$thisgroup}}, $hostid ; + } else { + $agedist{$thisgroup} = [$hostid]; + } + } +} + +sub print_summary { + printf(" %-20s %5s\n", "hostclass", "count"); + for my $group (sort { $a <=> $b; } keys %agedist) { + printf(" %-20s %5d\n", $agegroup{$group}, scalar @{$agedist{$group}}); + if (exists $opts{l}) { + for my $hostid (sort @{$agedist{$group}}) { + my $hostname = get_hostname($hostid); + my $site = get_site($hostid) || ""; + my $sitegroup = get_sitegroup($hostid) || ""; + printf " %s %s/%s %s\n", $hostname, $site, $sitegroup, $hostid; + } + print "\n"; + } + } +} Index: collect.d/system =================================================================== --- collect.d/system (revision 38710) +++ collect.d/system (working copy) @@ -26,7 +26,15 @@ lsscsi > lsscsi fi +if type lsmod >/dev/null 2>&1; then + lsmod > lsmod +fi + uname -smr > uname-smr uname -n > hostname ifconfig -a > ifconfig-a cat /proc/cpuinfo > cpuinfo + +# Collect mount points, for nagios configuration +cp /etc/fstab fstab +cat /proc/mounts > procmounts Index: kernelversion-summary =================================================================== --- kernelversion-summary (revision 38710) +++ kernelversion-summary (working copy) @@ -4,9 +4,22 @@ use warnings; use SiteSummary; +use Getopt::Std; my %kernelvers; +my %opts; +sub usage { + my $retval = shift; + print <<EOF; +Usage: $0 [-l] + -l list hosts using the given kernel versions +EOF + exit $retval; +} + +getopt("l", \%opts) || usage(1); + for_all_hosts(\&handle_host); print_summary(); @@ -15,14 +28,26 @@ my $hostid = shift; #print "$hostid\n"; for my $kver (get_linux_kernel_ver($hostid)) { - $kver = "" unless defined $kver; - $kernelvers{$kver}++; + $kver = "" unless defined $kver; + if (exists $kernelvers{$kver}) { + push @{$kernelvers{$kver}}, $hostid ; + } else { + $kernelvers{$kver} = [$hostid]; + } } } sub print_summary { printf(" %-20s %5s\n", "kernel", "count"); for my $kver (sort keys %kernelvers) { - printf(" %-20s %5d\n", $kver, $kernelvers{$kver}); + printf(" %-20s %5d\n", $kver, scalar @{$kernelvers{$kver}}); + if (exists $opts{l}) { + for my $hostid (sort @{$kernelvers{$kver}}) { + my $hostname = get_hostname($hostid); + my $site = get_site($hostid) || ""; + my $sitegroup = get_sitegroup($hostid) || ""; + printf " %s %s/%s %s\n", $hostname, $site, $sitegroup, $hostid; + } + } } } Index: sitesummary-makewebreport =================================================================== --- sitesummary-makewebreport (revision 38710) +++ sitesummary-makewebreport (working copy) @@ -15,7 +15,12 @@ <pre> EOF -for f in site-summary hostclass-summary kernelversion-summary debian_edu-summary ; do +for f in site-summary \ + hostclass-summary \ + kernelversion-summary \ + agesinceseen-summary \ + debian_edu-summary ; do + echo "$f:" /usr/lib/sitesummary/$f echo done Index: sitesummary-nodes =================================================================== --- sitesummary-nodes (revision 38710) +++ sitesummary-nodes (working copy) @@ -10,7 +10,7 @@ use Getopt::Std; my %opts; -getopts("m", \%opts); +getopts("mn", \%opts); my %hostnames; @@ -18,6 +18,8 @@ if ($opts{'m'}) { print_munin_list(); +} elsif ($opts{'n'}) { # XXX Nagios config generation do not work yet + generate_nagios_config(); } else { print_list(); } @@ -34,13 +36,13 @@ } } -sub is_munin_client { - my $hostid = shift; - # Check debian/dpkg-l for 'ii *munin-node ' +sub is_pkg_installed { + my ($hostid, $pkgname) = @_; + # Check debian/dpkg-l for 'ii *pkgname ' my $path = get_filepath_current($hostid, "/debian/dpkg-l"); if (open (my $fh, $path)) { while(<$fh>) { - if (m/^ii *munin-node /) { + if (m/^ii *$pkgname /) { close($fh); return 1 } @@ -50,6 +52,17 @@ return undef; } +sub is_munin_client { + my $hostid = shift; + return is_pkg_installed($hostid, "munin-node"); +} + +sub is_nagios_client { + my $hostid = shift; + return is_pkg_installed($hostid, "nagios-nrpe-server") || + is_pkg_installed($hostid, "nagios-text"); +} + sub print_munin_list { for my $hostname (sort keys %hostnames) { next unless (is_munin_client($hostnames{$hostname})); @@ -65,3 +78,100 @@ EOF } } + +sub generate_nagios_config { + for my $hostname (sort keys %hostnames) { + my $hostid = $hostnames{$hostname}; + next unless (is_nagios_client($hostid)); + + my $ifconfigpath = get_filepath_current($hostid, "/system/ifconfig-a"); + my $peerinfopath = get_filepath_current($hostid, "/peerinfo"); + open (F, "<", $peerinfopath)||die "Unable to read from $peerinfopath"; + my ($address) = split(/\s+/, scalar <F>); + close(F); + + # first, check ping to see if the other checks should be performed + print <<EOF; +##################### $hostname ####################### +define host { + host_name $hostname + address $address +} +define service { + use server-service + host_name $hostname + service_description ping + check_command check_ping!100.0,20%!500.0,60% +} +EOF + + print <<EOF if is_pkg_installed($hostid, "openssh-server"); +define service { + use server-service + host_name $hostname + service_description ssh + check_command check_ssh +} +EOF + + my %tcpservices = + ( + 139 => { name => 'samba', package => 'samba' }, + 631 => { name => 'cups', package => 'cupsys' }, + 636 => { name => 'ldaps', package => 'slapd' }, + 3128 => { name => 'squid', package => 'squid' }, +# 10000 => { name => 'webmin', package => 'webmin' }, + ); + + for my $port (sort { $a <=> $b } keys %tcpservices) { + next if (exists $tcpservices{$port}->{package} && ! + is_pkg_installed($hostid, + $tcpservices{$port}->{package})); + my $servicename = $tcpservices{$port}->{name}; + print <<EOF; +define service { + use server-service + host_name $hostname + service_description $servicename + check_command check_tcp!$port +} +EOF + } + # check munin if munin-node is installed + # check hw and sw raid status + # check hardware status + # check free swap + # check X font server + # check LDAP + # check DNS + # check disk free space + my $path = get_filepath_current($hostid, "/system/procmounts"); + if ( -e $path ) { + open (F, "<", $path) || die "unable to read from $path"; + my %checked; + while (<F>) { + chomp; + my ($dev, $partition, $fs, $opts) = split; + next if (exists $checked{$partition}); + next if ($fs eq "devpts" || + $fs eq "proc" || + $fs eq "rootfs" || + $fs eq "rpc_pipefs" || + $fs eq "sysfs" || + $fs eq "tmpfs"); + + $checked{$partition} = 1; + my $warn = 10; + my $crit = 5; + print <<EOF; +define service { + use server-service + host_name $hostname + service_description Disk $partition + check_command check_disk!$warn%!$crit%!$partition +} +EOF + } + } + } +} Index: sitesummary-client =================================================================== --- sitesummary-client (revision 38710) +++ sitesummary-client (working copy) @@ -8,7 +8,12 @@ set -e PATH=/sbin:/usr/sbin:/bin:/usr/bin +export PATH +# Make sure the output from programs is well known. +LC_ALL=C +export LC_ALL + # Make sure to store files in a ramfs backed # storage area on diskless clients, so use /tmp/. tmpdir=/tmp/sitesummary-$$ Index: site-summary =================================================================== --- site-summary (revision 38710) +++ site-summary (working copy) @@ -4,10 +4,25 @@ use warnings; use SiteSummary; +use Getopt::Std; my %sites; my %sitegroups; +my %hostmap; +my %sitegroupmap; +my %opts; +sub usage { + my $retval = shift; + print <<EOF; +Usage: $0 [-l] + -l list hosts with the given site/sitegroup +EOF + exit $retval; +} + +getopt("l", \%opts) || usage(1); + for_all_hosts(\&handle_host); print_summary(); @@ -16,18 +31,48 @@ my $hostid = shift; #print "$hostid\n"; for my $site (get_site($hostid)) { - $site = "" unless defined $site; - $sites{$site}++; - $sitegroups{$site}{get_sitegroup($hostid)}++ if get_sitegroup($hostid); + $site = "" unless defined $site; + $sites{$site}++; + my $sitegroup = get_sitegroup($hostid); + if ($sitegroup) { + $sitegroups{$site}{$sitegroup}++; + if (exists $sitegroupmap{$site} && exists $sitegroupmap{$site}{$sitegroup}) { + push @{$sitegroupmap{$site}{$sitegroup}}, $hostid ; + } else { + $sitegroupmap{$site}{$sitegroup} = [$hostid]; + } + } else { + if (exists $hostmap{$site}) { + push @{$hostmap{$site}}, $hostid ; + } else { + $hostmap{$site} = [$hostid]; + } + } } } sub print_summary { printf(" %-20s %5s\n", "site", "count"); for my $site (sort keys %sites) { - printf(" %-20s %5d\n", $site, $sites{$site}); - for my $sitegroup (sort keys %{$sitegroups{$site}}) { - printf(" %-18s %5d\n", $sitegroup, $sitegroups{$site}{$sitegroup}); - } + printf(" %-20s %5d\n", $site, $sites{$site}); + if (exists $opts{l}) { + for my $hostid (sort @{$hostmap{$site}}) { + my $hostname = get_hostname($hostid); + my $site = get_site($hostid) || ""; + my $sitegroup = get_sitegroup($hostid) || ""; + printf " %s %s/%s %s\n", $hostname, $site, $sitegroup, $hostid; + } + } + for my $sitegroup (sort keys %{$sitegroups{$site}}) { + printf(" %-18s %5d\n", $sitegroup, $sitegroups{$site}{$sitegroup}); + if (exists $opts{l}) { + for my $hostid (sort @{$sitegroupmap{$site}{$sitegroup}}) { + my $hostname = get_hostname($hostid); + my $site = get_site($hostid) || ""; + my $sitegroup = get_sitegroup($hostid) || ""; + printf " %s %s/%s %s\n", $hostname, $site, $sitegroup, $hostid; + } + } + } } } Index: sitesummary-collector.cgi =================================================================== --- sitesummary-collector.cgi (revision 38710) +++ sitesummary-collector.cgi (working copy) @@ -10,6 +10,7 @@ use CGI; use POSIX qw(strftime); use Socket; +use Sys::Syslog; my $basedir = "/var/lib/sitesummary"; my $handlerdir = "/usr/lib/sitesummary/handler.d"; @@ -17,6 +18,9 @@ $ENV{PATH} = "/bin:/usr/bin"; print "Content-Type: text/plain\n\n"; + +my ($peeripaddr, $peername) = get_peerinfo(\*STDIN); + if (exists $ENV{REQUEST_METHOD} && $ENV{REQUEST_METHOD} ne "POST") { print "Sitesummary HTTP-POST submission URL\n"; @@ -62,7 +66,6 @@ EOF } -my ($peeripaddr, $peername) = get_peerinfo(\*STDIN); my $timestamp = strftime("%Y-%m-%dT%H:%M:%S", gmtime()); if ($filename =~ m/.tar.gz$/) { @@ -76,7 +79,7 @@ # XXX Come up with some unique file name. my $savefile = "$basedir/tmpstorage/$peeripaddr-$timestamp-$$-$filename"; -open(SITESUMMARY, ">$savefile") or die "Unable to write to $savefile"; +open(SITESUMMARY, ">", $savefile) or die "Unable to write to $savefile"; print SITESUMMARY @entry; close SITESUMMARY; @@ -95,10 +98,10 @@ my $eth2mac; open(IFCONFIG, "system/ifconfig-a") || die "Unable to read ifconfig-a"; while (<IFCONFIG>) { - chomp; - $eth0mac = $1 if (m/^eth0\s+Link encap:Ethernet HWaddr (\S+)/); - $eth1mac = $1 if (m/^eth1\s+Link encap:Ethernet HWaddr (\S+)/); - $eth2mac = $1 if (m/^eth2\s+Link encap:Ethernet HWaddr (\S+)/); + chomp; + $eth0mac = $1 if (m/^eth0\s+Link encap:Ethernet HWaddr (\S+)/); + $eth1mac = $1 if (m/^eth1\s+Link encap:Ethernet HWaddr (\S+)/); + $eth2mac = $1 if (m/^eth2\s+Link encap:Ethernet HWaddr (\S+)/); } close (IFCONFIG); #print STDERR "MAC: $eth0mac\n"; @@ -110,12 +113,12 @@ my ($peeripaddr, $peername, $filename) = @_; my $dirname; if ($filename =~ m/(.+).tar.gz$/) { - $dirname = $1; - mkdir $dirname; - chdir $dirname; - `tar zxf $filename`; + $dirname = $1; + mkdir $dirname; + chdir $dirname; + `tar zxf $filename`; } else { - die "Unhandled file format '$filename'"; + die "Unhandled file format '$filename'"; } open(PEERINFO, ">peerinfo") || die; @@ -127,37 +130,38 @@ my $status = "new"; if ( -d $newdir ) { - `rm -r $newdir`; - my $status = "update"; + `rm -r $newdir`; + my $status = "update"; } rename $dirname, $newdir || die; for my $handler (<$handlerdir/*>) { - `$handler $newdir $status`; + `$handler $newdir $status`; } } sub get_peerinfo { my $sockethandle = shift; + my ($peeripaddr, $peername) = ("", ""); - # Return something while this function do not work. - return ("127.0.0.1", "localhost"); - - # XXX The call to sockaddr_in trigger "Bad arg length for - # Socket::unpack_sockaddr_in, length is 2, should be 16 at - # /usr/lib/perl/5.8/Socket.pm line 198." No idea why. - my ($peerport, $peeripaddr) = sockaddr_in(getpeername($sockethandle)); - if ($peerport) { - my $peername = gethostbyaddr($peeripaddr, AF_INET); - - if ("" eq $peername) { - syslog('warning', "client without DNS entry connected from \[$peeripaddr\]"); - $peername = "$peeripaddr"; - } + my $sockaddr = getpeername($sockethandle); + if ($sockaddr) { + my $peerport; + ($peerport, $peeripaddr) = sockaddr_in($sockaddr); + $peername = gethostbyaddr($peeripaddr, AF_INET); + } elsif ($ENV{'REMOTE_ADDR'}) { # CGI variable + $peeripaddr = $ENV{'REMOTE_ADDR'}; + $peeripaddr =~ m/(\d+).(\d+).(\d+).(\d+)/; # Untaint + $peeripaddr = "$1.$2.$3.$4"; + $peername = gethostbyaddr($peeripaddr, AF_INET); } else { # Running on the command line, use test host $peeripaddr = "127.0.0.1"; $peername = "localhost"; } + if ("" eq $peername) { + syslog('warning', "%s", "client without DNS entry connected from \[$peeripaddr\]"); + $peername = "$peeripaddr"; + } return ($peeripaddr, $peername); } Index: Makefile =================================================================== --- Makefile (revision 38710) +++ Makefile (working copy) @@ -21,6 +21,7 @@ collect.d/siteinfo SUMMARYSCRIPTS = \ + agesinceseen-summary \ site-summary \ hostclass-summary \ kernelversion-summary \ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

