#!/usr/bin/perl

#/*
# * snmpdf.pl - Greg Schenzel <inittab@unixdev.net>
# * 
# * Produces parseable, human-readable, df-style disk filesystem
# * usage information from a remote system running snmpd.
# * 
# * Configuration:
# *
# *   $disk_dev_max:
# *     Set to the maximum length of the filesystem device column for
# *     padding and cropping.
# *
# *   $disk_div:
# *     Set to 1 for output in KB
# *     Set to 1024 for output in MB
# *     Set to 1048576 for output in GB
# *
# *     After any changes to this variable, you should also change the
# *     3 "MB" references in the "printf" line at the end of the main
# *     loop.
# *
# * TODOs:
# *   CSV output
# *   Print "KB/MB/GB" depending on the value of disk_div
# *   Command line arguments for disk_dev_max and disk_div
# *   Command line argument to limit output to one filesystem
# *   Should we be limiting precision to 12?
# */

use strict;
use warnings;

my $host = $ARGV[0];
my $diskref = {};
my $disk_dev_max = 25;
my $disk_div = 1024;

if (!$host) {
    print "Usage: snmpdf <hostname>\n";
    exit 1
}

open(SNMPWALK, "snmpwalk -c public -v 1 $host -OQ 1.3.6.1.4.1.2021.9.1 |");
while (<SNMPWALK>) {
    if (m/^UCD-SNMP-MIB::(dsk\S+)\.(\d+) = (.*)$/) {
        $diskref->{$2}->{$1} = $3;
    }
}
close(SNMPWALK) or die "ERROR: Could not snmpwalk host: $host";

print "Filesystem                          Size           Used          Avail    Use% Mounted\n";
for my $diskidx ( sort keys %$diskref ) {
    my $disk = $diskref->{$diskidx};
    my $disk_dev = $disk->{"dskDevice"};
    my $disk_mount = $disk->{"dskPath"};
    my $disk_avail = $disk->{"dskAvail"} / $disk_div;
    my $disk_total = $disk->{"dskTotal"} / $disk_div;
    my $disk_used = $disk->{"dskUsed"} / $disk_div;
    my $disk_utilization = $disk_total == 0 ? 0 : ($disk_used / $disk_total) * 100;
    my $disk_dev_len = length($disk_dev);

    if ($disk_dev_len > $disk_dev_max) {
       $disk_dev = substr($disk_dev, 0, $disk_dev_max);
    }
    elsif ($disk_dev_len < $disk_dev_max) {
        my $diff = $disk_dev_max - $disk_dev_len;
        for (my $i = 0; $i < $diff; $i++) {
            $disk_dev = $disk_dev . " ";
        }
    }

    printf "%s %12.2fMB %12.2fMB %12.2fMB %6.2f%% %s\n", $disk_dev, $disk_total, $disk_used, $disk_avail, $disk_utilization, $disk_mount;
}


