#!/usr/bin/perl -w

# cfgstoragemaker: MRTG config generator for storage monitoring via SNMP
# Copyright (C) 2001, 2002 LibertySurf Telecom, Cyril Bouthors

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.

# Cyril Bouthors <cyril@bouthors.org> Sun Apr 29 13:35:12 CEST 2001

use integer;
use diagnostics;
use sigtrap qw(SEGV BUS);
use strict  qw(subs vars refs);
use subs    qw(afunc blurfl);

my $snmp_root = 'host.hrStorage.hrStorageTable.hrStorageEntry';
my $debug=0; #1 for additional info

my $tpl_dir = '/etc/cfgstoragemaker';
my $tpl_header = 'header.tpl';
my $tpl_body   = 'body.tpl';

my $body = '';

my $type_root='OID: host.hrStorage.hrStorageTypes.hrStorage';

open(HEADER, "$tpl_dir/$tpl_header") or die "Can't open $tpl_header: $!";
print <HEADER>;
close HEADER;

open(BODY, "$tpl_dir/$tpl_body") or die "Can't open $tpl_body: $!";
while (<BODY>) {
    $body .= $_;
}
close BODY;

foreach (@ARGV) {
    my ($community, $host) = split /@/;
    defined $community and defined $host or die "Invalid argument.";
    
    print STDERR "$0: Requesting $host (community=$community).\n";
    
    # ugly
    open(WALK, "snmpwalk -c $community -v1 $host $snmp_root |")
	or die "Can't start snmpwalk: $!";
    
    my %data;
    my @indexes;
    
    while (<WALK>) {
	chop;
	my ($var, $val) = split (' = ');
	
	$var =~ s/^HOST-RESOURCES-MIB::hrStorage//;

	if ( $var =~ /^Index\./ ) {
	    my $index = $var;
	    $index =~ s/^.*\.//;

	    push(@indexes, $index);
	}

	if ( $var =~ /^Type\./ ) { #clean type
	    $val =~ s/^.*hrStorage//;
	}

	if ($val =~ /(INTEGER|STRING): / ) {
	    $val =~ s/(INTEGER|STRING): //;
	}

	if ( $var =~ /^AllocationUnits\./ ) { #clean AllocationUnits
	    $val =~ s/ Bytes//;

	    $val=4096 if $val eq 0; # avoid stupid SNMP agents
	}

	print $var . ' = ' . $val . "\n" if $debug;
	$data{$var}=$val;
    }

    close(WALK);

    print STDERR "$0: Computing results for $host.\n";

    print STDERR "$0: WARNING: $host know nothing about storage !
$0: Please check if 'Host Resources MIB' is available.\n"
    if ! @indexes;

    foreach my $index (@indexes) {
	next if ! defined $data{"Size.$index"}; #avoid Memory Buffers
	next if $data{"Size.$index"} <= 0; #avoid /dev/pts and /proc/bus/usb

	my $part = $data{"Descr.$index"};

	my $target = $data{"Descr.$index"};
	$target =~ s/^\///; #remove heading slash
	$target =~ s/(\/| )/-/g; #remove slashes and spaces
	$target = $host . '-' . $target;

	my $size =
	    $data{"Size.$index"} / 1000 * $data{"AllocationUnits.$index"}
	/ 1024 * 1000;

	my $human_readable_size = human_readable($size);

	my $blocksize = $data{"AllocationUnits.$index"};

	my $type = $data{"Type\.$index"};

	eval $body;

    }
}

################################################################
# convert storage sizes into human readable values
# contrib from David Schmitt <david@schmitt.edv-bus.at>
sub human_readable {
    my $size = shift;

    no integer;
    my $mb =       1024;
    my $gb = $mb * 1024;
    my $tb = $gb * 1024;

    if ($size >= $tb) {
	$size /= $tb;
	$size =~ s/^(\d*\.\d).*$/$1 TB/;
    }
    elsif ($size >= $gb) {
	$size /= $gb;
	$size =~ s/^(\d*\.\d).*$/$1 GB/;
    }
    elsif ($size >= $mb) {
	$size /= $mb;
	$size =~ s/^(\d*\.\d).*$/$1 MB/;
    }

    return $size;
}
