Stable update proposal: sitesummary 0.0.33
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 <pere@debian.org> 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 <pere@debian.org> 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 <pere@debian.org> 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 \
Reply to: