#!/usr/bin/perl
#
# Generate list of nodes to load from /etc/munin/munin.conf to check
# all the machines reporting to sitesummary.

use strict;
use warnings;

use SiteSummary;
use Getopt::Std;

my %opts;
getopts("mn", \%opts);

my %hostnames;

for_all_hosts(\&handle_host);

if ($opts{'m'}) {
    print_munin_list();
} elsif ($opts{'n'}) { # XXX Nagios config generation do not work yet
    generate_nagios_config();
} else {
    print_list();
}

sub handle_host {
    my $hostid = shift;
    my $hostname = get_hostname($hostid);
    $hostnames{$hostname} = $hostid;
}

sub print_list {
    for my $hostname (sort keys %hostnames) {
        print "$hostname\n";
    }
}

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 *$pkgname /) {
                close($fh);
                return 1
            }
        }
        close($fh);
    }
    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") ||
        is_pkg_installed($hostid, "nagios2");
}

sub print_munin_list {
    for my $hostname (sort keys %hostnames) {
        next unless (is_munin_client($hostnames{$hostname}));

    # Using hostname as address, to avoid hardcoding IP addresses in
    # the file.  Might be an idea to fetch the IP address from
    # system/ifconfig-a
        print <<EOF;
[$hostname]
    address $hostname
    use_node_name yes

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
            }
        }
    }
}
