Hi everyone,

I wrote a little Net-SNMP "pass_persist" script to allow polling of
Solaris kstat information, and then display the results in OpenNMS. Here
are some of the details:

snmpd.conf:
---begin---
pass_persist .1.3.6.1.4.1.8072.100.2 /usr/perl5/5.8.4/bin/perl 
/usr/local/share/snmp/snmp-kstat.pl
----end----

Note: The perl used should know about the Kstat.pm perl module. Here's a
sample from a Solaris 10 x86 server:

# locate Kstat.pm
/usr/perl5/5.6.1/lib/Sun/Solaris/Kstat.pm
/usr/perl5/5.8.4/lib/Sun/Solaris/Kstat.pm

snmp.conf:
---begin---
mibs    +NET-SNMP-PASS-PERSIST-MIB
----end----

The NET-SNMP-PASS-PERSIST-MIB.txt MIB file is attached. Only one level
has been defined, allowing you to do stuff like "snmpwalk hostname
kStat".

The Solaris "kstat" tool uses sd/ssd/md device names. To map these to
actual /dev device names and mount points, I've used MapDev.pm.
Unfortunately this CPAN module will only install on Solaris 2.7 or
older. As-is the module works fine on Solaris 10, so I've copied it to a
/usr/local/share/snmp/lib/Solaris/ directory. You may have to edit the
"use lib" directive in the snmp-kstat.pl script depending on where you
locate it. I've attached a copy, just in case.

snmp-kstat.conf (attached):

I've only used this script to poll sd/ssd/md device nread and nwritten
values. Since these are 64bit, I divide them by 10240 before sending
them. This means that whatever analysis you do, you have to multiply the
value by 10240.

The config file is probably self explanitory (I hope). :-)

OpenNMS collectd-configuration.xml:
---begin---
<package name="kstat">
        <filter>(pollerCategory ~ "kStat")</filter>
        <include-range begin="1.1.1.1" end="254.254.254.254"/>
        <include-url>file:/usr/local/opennms/etc/include</include-url>
        <service name="SNMP" interval="60000" user-defined="false" status="on">
                <parameter key="collection" value="kstat-collection"/>
                <parameter key="port" value="161"/>
                <parameter key="retry" value="3"/>
                <parameter key="timeout" value="6000"/>
        </service>
        <outage-calendar>zzz from poll-outages.xml zzz</outage-calendar>
</package>
----end----

I make use of the OpenNMS "Poller Category" asset value. You must
include the word "kStat" for each server you want to be polled.

OpenNMS datacollection-config.xml:
---begin---
    <snmp-collection name="kstat-collection" maxVarsPerPdu="20" 
snmpStorageFlag="select">
        <rrd step="60">
            <rra>RRA:AVERAGE:0.5:1:44640</rra><!-- store 31 days of 1 min 
values -->
            <rra>RRA:AVERAGE:0.5:5:107136</rra><!-- after 31 days, store 5 mins 
values for 1 year -->
            <rra>RRA:MIN:0.5:1:44640</rra>
            <rra>RRA:MIN:0.5:5:107136</rra>
            <rra>RRA:MAX:0.5:1:44640</rra>
            <rra>RRA:MAX:0.5:5:107136</rra>
        </rrd>
        <groups>
            <group name="kstat-group" ifType="ignore">
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.15.1.1" instance="3" 
alias="ksmd0101nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.15.1.1" instance="4" 
alias="ksmd0101nwritten" type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.15.2.1" instance="3" 
alias="ksmd0201nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.15.2.1" instance="4" 
alias="ksmd0201nwritten" type="counter32" />
.
.
.
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.22.1.1" instance="3" 
alias="kssd0101nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.22.1.1" instance="4" 
alias="kssd0101nwritten" type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.22.2.1" instance="3" 
alias="kssd0201nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.22.2.1" instance="4" 
alias="kssd0201nwritten" type="counter32" />
.
.
.
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.24.1.1" instance="3" 
alias="ksssd0101nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.24.1.1" instance="4" 
alias="ksssd0101nwritten" type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.24.2.1" instance="3" 
alias="ksssd0201nread"    type="counter32" />
                <mibObj oid=".1.3.6.1.4.1.8072.100.2.24.2.1" instance="4" 
alias="ksssd0201nwritten" type="counter32" />
.
.
.
            </group>
        </groups>
        <systems>
            <systemDef name="Net-SNMP kStat">
                <sysoidMask>.1.3.6.1.4.1.8072.3.</sysoidMask>
                <collect>
                    <includeGroup>kstat-group</includeGroup>
                </collect>
            </systemDef>
        </systems>
    </snmp-collection>
----end----

In the snmp-kstat.conf file I attached, there are also some
.1.3.6.1.4.1.8072.100.2.22.x.2.x (sd5,a),
.1.3.6.1.4.1.8072.100.2.22.x.3.x (sd5,c), etc. values that you would
probably want to include in the datacollection file.

OpenNMS snmp-graph.properties:
---begin---
report.ksmd0101nrw.name=Bytes per Second on ksmd0101
report.ksmd0101nrw.columns=ksmd0101nread,ksmd0101nwritten
report.ksmd0101nrw.type=node
report.ksmd0101nrw.propertiesValues=ksmd0101name,ksmd0101class
report.ksmd0101nrw.command=--title="Bytes per Second on {ksmd0101class}
{ksmd0101name}" \
 --lower-limit 0 --upper-limit 10000000 \
 DEF:nread={rrd1}:ksmd0101nread:AVERAGE \
 DEF:nwritten={rrd2}:ksmd0101nwritten:AVERAGE \
 CDEF:nreadbytes=nread,10240,* \
 CDEF:nwrittenbytes=nwritten,10240,* \
 LINE1:nreadbytes#0000cc:"Read   " \
 GPRINT:nreadbytes:AVERAGE:"Avg \\: @8.2 @s" \
 GPRINT:nreadbytes:MIN:"Min \\: @8.2 @s" \
 GPRINT:nreadbytes:MAX:"Max \\: @8.2 @s\\n" \
 LINE1:nwrittenbytes#00cc00:"Written" \
 GPRINT:nwrittenbytes:AVERAGE:"Avg \\: @8.2 @s" \
 GPRINT:nwrittenbytes:MIN:"Min \\: @8.2 @s" \
 GPRINT:nwrittenbytes:MAX:"Max \\: @8.2 @s\\n"
----end----

The above is just a sample. You'd have to create many more. The
snmp-kstat.conf file attached needs 5 graph blocks to display all the md
and sd values.

Want to know what it looks like? I've attached a graph.png file to give
you an idea...

LateR!
js.
-- 
Jean-Sebastien Morisset, Sr. UNIX Administrator <[EMAIL PROTECTED]>
Personal Home Page <http://jsmoriss.mvlan.net/>
Underwater and Travel Photographs <http://www.mvpix.com/>
NET-SNMP-PASS-PERSIST-MIB DEFINITIONS ::= BEGIN

--
-- MIB objects for netSnmp pass_persist directive
--

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE,
    NOTIFICATION-TYPE   FROM SNMPv2-SMI
    SnmpAdminString     FROM SNMP-FRAMEWORK-MIB
    netSnmp             FROM NET-SNMP-MIB
;

PassPersist MODULE-IDENTITY
    LAST-UPDATED "200603130000Z"
    ORGANIZATION "www.mvlan.com"
    CONTACT-INFO "Jean-Sebastien Morisset, email: [EMAIL PROTECTED]"
    DESCRIPTION  "MIB objects for netSnmp pass_persist directive"
    REVISION     "200603130000Z"
    DESCRIPTION  "First draft"
    ::= { netSnmp 100 }

--
-- top level structure
--

kStat OBJECT IDENTIFIER ::= { PassPersist 2 }

END
package Solaris::MapDev;
use strict;
use Exporter;
use IO::File;
use Symbol;   # Would like to use IO::Dir, but that isn't available in 5.004_04
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
$VERSION = "0.04";
@ISA = qw(Exporter);
@EXPORT_OK = qw(inst_to_dev dev_to_inst get_inst_names get_dev_names
                mapdev_data_files mapdev_system_files);
%EXPORT_TAGS = ( ALL => [ @EXPORT_OK ] );

# Global flags and data structures
#    $use_system_files - Live system data files used for mapping info
#    $device_to_inst   - /devices entry -> instance name
#    $inst_to_dev      - instance name  -> /dev entry
#    $dev_to_inst      - /dev entry     -> instance name
use vars qw($use_system_files $device_to_inst $inst_to_dev $dev_to_inst);
$use_system_files = 1;   # default - use live system files

################################################################################
# Read /etc/path_to_inst, and build a map from disk and tape /devices entries
# to instance names

sub read_path_to_inst($)
{
my ($path_to_inst) = @_;

my $fh = IO::File->new($path_to_inst, "r")
   || die("Can't open $path_to_inst: $!\n");
while (defined(my $line = $fh->getline()))
   {
   next if ($line =~ /^\s*#/);
   $line =~ s/"//g;
   my ($dev, $inst, $drv) = split(" ", $line);
   if ($drv =~ /^(ss?d|st)$/)
      {
      $device_to_inst->{"/devices$dev"} = "$drv$inst";
      }
   elsif ($drv eq "fd")
      {
      $inst_to_dev->{"$drv$inst"} = "$drv$inst";
      }
   elsif ($drv eq "cmdk")
      {
      $device_to_inst->{"/devices$dev"} = "sd$inst";
      }
   elsif ($drv eq "dad")
      {
      $device_to_inst->{"/devices$dev"} = "dad$inst";
      }
   elsif ($drv eq "atapicd")
      {
      $device_to_inst->{"/devices$dev"} = "atapicd$inst";
      }
   }
$fh->close();
}

################################################################################
# Read in /etc/mnttab and add entries for nfs mount points

sub read_mnttab($)
{
my ($mnttab) = @_;

my $fh = IO::File->new($mnttab, "r") || die("Can't open $mnttab: $!\n");
while (defined(my $line = $fh->getline()))
   {
   next if ($line =~ /^\s*#/);
   my ($special, $fstyp, $opt) = (split(" ", $line))[0,2,3];
   next if ($fstyp ne "nfs");
   $opt =~ s/.*dev=(\w+).*/hex($1) & 0x3ffff/e;
   $inst_to_dev->{"nfs$opt"} = $special;
   }
$fh->close();
}

################################################################################
# Private routine to rebuild the inst_to_dev lookup table.  This is called the
# first time either dev_to_inst or inst_to_dev is called, and also if a device
# cannot be found in the lookup hashes.  It rebuilds $inst_to_dev only, on the
# assumption that we will rarely want to map back from a device to the instance.
# $dev_to_inst is rebuilt when required by dev_to_inst

sub refresh()
{
# Throw away all the current info
$device_to_inst = {};
$inst_to_dev    = {};
$dev_to_inst    = {};

# Read /etc/path_to_inst and /etc/mnttab
read_path_to_inst("/etc/path_to_inst");
read_mnttab("/etc/mnttab");

# Next find all the disk nodes under /dev and /dev/osa if it exists.
# /dev/osa contains extra device nodes not found under /dev for the Symbios
# HW RAID controllers (A1000, A3000).  Note however that if the devices are
# removed, the old info in /dev/osa is not removed, and if any more
# non-Symbios disks are added it will become incorrect.  To get around this, we
# read /dev/osa first if it exists, then /dev.  This will make sure that we get
# the most up-to-date information.
# Also do the same for all the tape devices under /dev/rmt
my ($dir, $dh, $dev, $lnk);
$dh = gensym();
foreach $dir ("/dev/osa/rdsk", "/dev/osa/dev/rdsk", "/dev/rdsk", "/dev/rmt")
   {
   next if (! -d $dir);
   opendir($dh, $dir) || die("Cannot read $dir: $!\n");
   while (defined($dev = readdir($dh)))
      {
      next if ($dev !~ /s0$/ && $dev !~ /^\d+$/);
      $lnk = readlink("$dir/$dev");
      $lnk =~ s!^\.\./\.\.!!;
      $lnk =~ s!:.*$!!;
      if (defined($device_to_inst->{$lnk}))
         {
         if ($dev =~ /s0$/) { $dev =~ s/s0$//; }
         else { $dev = "rmt/$dev" };
         $inst_to_dev->{$device_to_inst->{$lnk}} = $dev;
         }
      }
   closedir($dh);
   }
}

################################################################################
# Use supplied data files as the source of mapping information, instead of the
# current live files.  For details on what's going on, look at refresh

sub mapdev_data_files(%)
{
my %arg = @_;
my $path_to_inst = $arg{path_to_inst}
   || die("No path_to_inst file specified\n");
my $dev_ls = $arg{dev_ls}
   || die("No \"ls -l /dev/...\" files specified\n");
my $mnttab = $arg{mnttab};
$use_system_files = 0;

# Throw away all the current info
$device_to_inst = {};
$inst_to_dev    = {};
$dev_to_inst    = {};

# Scan the path_to_inst and mnttab files
read_path_to_inst($path_to_inst);
read_mnttab($mnttab) if ($mnttab);

my ($dir, $prefix, $dls, $fh, $line, $path, $dev_d, $dev_f, $lnk);
foreach $dir ("/dev/osa/rdsk", "/dev/osa/dev/rdsk", "/dev/rdsk", "/dev/rmt")
   {
   while (($prefix, $dls) = each(%$dev_ls))
      {
      $fh = IO::File->new($dls, "r") || die("Can't open $dls: $!\n");
      $path = $prefix;
      while (defined($line = $fh->getline()))
         {
         # Look for ls -l directory headings
         if ($line =~ /^(?:\.\/)?([\w|\/]+):$/)
            { $path = "$prefix/$1"; }
         # Look for lines that are symlinks to ../../devices
         elsif ($line =~ m!(\S+)\s+->\s+(\.\./\.\./devices\S+)!)
            {
            # Add on the directory prefix if the entry is relative,
            # and remove any "/./" and "dir/../" components
            ($dev_d, $lnk) = ($1, $2);
            $dev_d = "$prefix/$dev_d" if (substr($dev_d, 0, 1) ne "/");
            $dev_d =~ s!/\./!/!g;
            $dev_d =~ s![^/]+/\.\./!!g while ($dev_d =~ /\.\./);

            # Split device path into directory and filename
            ($dev_d, $dev_f) = $dev_d =~ /^(.*)\/(.*)$/;

            # Only process if this is a dir and dev we are interested in
            next if (! ($dev_d eq $dir && $dev_f =~ /^\d+|c\d+t\d+d\d+s0/));

            # Clean up the /device entry
            $lnk =~ s!^\.\./\.\.!!;
            $lnk =~ s!:.*$!!;

            # Record the mapping if it is one we are interested in
            if (defined($device_to_inst->{$lnk}))
               {
               # Tweak the dev name
               if ($dev_f =~ /s0$/) { $dev_f =~ s/s0$//; }
               else { $dev_f = "rmt/$dev_f" };
               $inst_to_dev->{$device_to_inst->{$lnk}} = $dev_f;
               }
            }
         }
      $fh->close();
      }
   }
}

################################################################################
# Switch back to using live system files

sub mapdev_system_files()
{
# Change flag & throw away all the current info
$use_system_files = 1;
$device_to_inst = undef;
$inst_to_dev    = undef;
$dev_to_inst    = undef;
}

################################################################################
# Map an instance name to a device name, rebuilding $inst_to_dev as required

sub inst_to_dev($)
{
my ($inst) = @_;
my ($i, $s);
# Special treatment for disks with slice info
if ($inst =~ /^(ss?d\d+)(?:,(\w))$/ || $inst =~ /^(dad)(?:,(\w))$/)
   {
   $i = $1;
   $s = "s" . (ord($2) - ord("a"));
   }
else
   {
   $i = $inst;
   $s = "";
   }
refresh() if ($use_system_files && ! exists($inst_to_dev->{$i}));
if (exists($inst_to_dev->{$i})) { return("$inst_to_dev->{$i}$s"); }
else { return(undef); }
}

################################################################################
# Map a device name to an instance name, rebuilding $dev_to_inst as required

sub dev_to_inst($)
{
my ($dev) = @_;
my ($d, $s);
# Special treatment for disks with slice info
if ($dev =~ /^(c\d+t\d+d\d+)(?:s(\d))$/)
   {
   $d = $1;
   $s = "," . chr(ord("a") + $2);
   }
else
   {
   $d = $dev;
   $s = "";
   }
if (! defined($inst_to_dev) || ! exists($dev_to_inst->{$d}))
   {
   refresh() if ($use_system_files);
   %$dev_to_inst = reverse(%$inst_to_dev);
   }
if (exists($dev_to_inst->{$d})) { return("$dev_to_inst->{$d}$s"); }
else { return(undef); }
}

################################################################################
# Get a list of all the instance names

sub get_inst_names()
{
refresh() if ($use_system_files && ! defined($inst_to_dev));
return(sort(keys(%$inst_to_dev)));
}

################################################################################
# Get a list of all the device names

sub get_dev_names()
{
refresh() if ($use_system_files && ! defined($inst_to_dev));
return(sort(values(%$inst_to_dev)));
}

################################################################################
1;
__END__

=head1 NAME

Solaris::MapDev - map between instance numbers and device names

=head1 SYNOPSIS

   use Solaris::MapDev qw(inst_to_dev dev_to_inst);
   my $disk = inst_to_dev("sd0");
   my $nfs = inst_to_dev("nfs123");
   my $inst = dev_to_inst("c0t0d0s0");
   mapdev_data_files(path_to_inst => "/copy/of/a/path_to_inst",
                     mnttab => "/copy/of/a/mnttab",
                     dev_ls => { "/dev/rdsk" => "ls-lR/of/dev_dsk",
                                 "/dev/rmt"  => "ls-lR/of/dev_rmt" });
   my $tape = inst_to_dev("st1");

=head1 DESCRIPTION

This module maps both ways between device instance names (e.g. sd0) and /dev
entries (e.g. c0t0d0).  'Vanilla' SCSI disks, SSA disks, A1000, A3000, A3500
and A5000 disks are all catered for, as are tape devices and NFS mounts.

=head1 FUNCTIONS

=head2 inst_to_dev($inst)

Return the device name name given the instance name

=head2 dev_to_inst($dev)

Return the instance name given the device name

=head2 get_inst_names

Return a sorted list of all the instance names

=head2 get_dev_names

Return a sorted list of all the device names

=head2 mapdev_data_files

This tells mapdev to use data held in copies of the real datafiles, rather than
the current "live" files on the system.  This is useful for example when
examining explorer output.  A list of key-value pairs is expected as the
arguments.  Valid keys-value pairs are:

   path_to_inst => "/copy/of/a/path_to_inst",
      A valid path_to_inst file.  This is mandatory.

   mnttab => "/copy/of/a/mnttab",
      A valid /etc/mnttab file.  This is optional - if not
      specified, no information on NFS devices will be displayed.

   dev_ls => { "/dir/path" => "/ls-lR/of/dir/path",
               ... });
      A hash containing path/datafile pairs.  The paths should
      be one of /dev/rdsk, /dev/osa/rdsk, /dev/osa/dev/rdsk or
      /dev/rmt.  The datafiles should be the output of a "ls -l"
      of the specified directory.  A single file containing a
      recursive "ls -Rl" of /dev is also acceptable.

=head2 mapdev_system_files

This tells mapdev to revert to using the current "live" datafiles on the system
- see L<"mapdev_data_files()">

=head1 AUTHOR

Alan Burlison, <[EMAIL PROTECTED]>

=head1 SEE ALSO

L<perl(1)>, F</etc/path_to_inst>, F</dev/osa>, F</dev/rdsk>, F</dev/rmt>,
F</etc/mnttab>

=cut
#!/usr/bin/perl

# Solaris 8 sparc: /usr/perl5/5.00503/bin/perl
# Solaris 10 x86: /usr/perl5/5.8.4/bin/perl

$|=1;

use strict;
use Sun::Solaris::Kstat;
use lib '/usr/local/share/snmp/lib';
use Solaris::MapDev;

use vars qw($base_oid $read_interval @kstat_info);
require "/usr/local/share/snmp/snmp-kstat.conf";
exit 0 unless ($base_oid && $read_interval && @kstat_info);

my $ssk = Sun::Solaris::Kstat->new();
my $readtime;
my $systime;
my $debug;

while (<>) {
        my $oid;
        my $cmd = $_; chop ($cmd);
        my $matched;

        if ($cmd =~ /^DEBUG$/i) {
                $debug = 1;
                print "debug mode on\n";
        } elsif ($cmd =~ /^PING$/i) {
                print "PONG","\n";
        } elsif ($cmd =~ /^GET/i) {
                $oid = <>; chop ($oid);
                $oid =~ s/[^0-9\.]//g;
        } elsif ($cmd =~ /^(QUIT|EXIT)/i) {
                exit 0
        };
        next if (!$oid);
        $oid =~ s/^$base_oid\.?//;

        my @oid_parts = split('\.', $oid);
        my ($oid_mod_num, $oid_dev_num, $oid_sub_num, $oid_stat_num) = 
@oid_parts;

        $oid_mod_num = 1 if (!$oid_mod_num);
        $oid_dev_num = 1 if (!$oid_dev_num);
        $oid_sub_num = 1 if (!$oid_sub_num);
        if (defined $oid_stat_num) { $oid_stat_num++ if ($cmd =~ /^GETNEXT/i); 
} else { $oid_stat_num = 0 }

        while (1) {
                if (! defined $kstat_info[$oid_mod_num 
-1]->{stat}[$oid_stat_num -1]) {
                        print "not defined oid_stat_num\n" if ($debug);
                        if ($cmd =~ /^GETNEXT/i) {
                                $oid_stat_num = 0;
                                $oid_sub_num++;
                                print "oid_sub_num++ = $oid_sub_num\n" if 
($debug);
                        } else { last; };
                };
                if (! defined $kstat_info[$oid_mod_num -1]->{dev}[$oid_dev_num 
-1]->{names}[$oid_sub_num -1]) {
                        print "not defined oid_sub_num\n" if ($debug);
                        if ($cmd =~ /^GETNEXT/i) {
                                $oid_sub_num = 1;
                                $oid_dev_num++;
                                print "oid_dev_num++ = $oid_dev_num\n" if 
($debug);
                        } else { last; };
                };
                if (! defined $kstat_info[$oid_mod_num -1]->{dev}[$oid_dev_num 
-1]->{instance}) {
                        print "not defined oid_dev_num\n" if ($debug);
                        if ($cmd =~ /^GETNEXT/i) {
                                $oid_dev_num = 1;
                                $oid_mod_num++;
                                print "oid_mod_num++ = $oid_mod_num\n" if 
($debug);
                        } else { last; };
                };
                if ($oid_mod_num > scalar(@kstat_info)) {
                        print "oid_mod_num array exceeded\n" if ($debug);
                        last;
                };

                my $mod_name = $kstat_info[$oid_mod_num -1]->{module};
                my $inst_name = $kstat_info[$oid_mod_num 
-1]->{dev}[$oid_dev_num -1]->{instance};
                my $sub_name = $kstat_info[$oid_mod_num -1]->{dev}[$oid_dev_num 
-1]->{names}[$oid_sub_num -1];

                print "mod_name: $mod_name\n" if ($debug);
                print "inst_name: $inst_name\n" if ($debug);
                print "sub_name: $sub_name\n" if ($debug);

                if (defined $mod_name && defined $inst_name && defined 
$sub_name) {
                        print "defined: mod_name, inst_name, sub_name\n" if 
($debug);

                        if ($oid_stat_num == 0) {
                                my $devmnt;
                                my $devname;
                                # volume manager mount points are named d100, 
etc.
                                if ($sub_name =~ /^m(d[0-9]+)$/) {
                                        $devname = $1;
                                # otherwise determine device name (c0t0d0s2, 
etc.)
                                } else {
                                        $devname = 
Solaris::MapDev::inst_to_dev($sub_name);
                                }
                                if ($sub_name =~ /^ssd/ && $devname) {
                                        if (open (EXEIN, "/usr/sbin/vxdisk list 
|")) {
                                                while (my $line = <EXEIN>) {
                                                        if ($line =~ /^$devname 
/) {
                                                                my ($vxdisk, 
$vxgroup) = (split(" ", $line))[2,3];
                                                                $devmnt = 
"$vxdisk:$vxgroup";
                                                        }
                                                }
                                                close(EXEIN);
                                        }
                                }
                                my $devtype = 
$ssk->{$mod_name}{$inst_name}{$sub_name}{"class"}
                                        if (exists 
$ssk->{$mod_name}{$inst_name}{$sub_name} &&
                                                exists 
$ssk->{$mod_name}{$inst_name}{$sub_name}{"class"});

                                print "devname($sub_name): $devname\n" if 
($debug);
                                print "devtype(class): $devtype\n" if ($debug);

                                if ($devname && open (INFILE, "/etc/mnttab")) {
                                        while (my $line = <INFILE>) {
                                                next if ($line =~ /^\s*#/);
                                                my ($dev, $mnt, $fstyp) = 
(split(" ", $line))[0,1,2];
                                                if ($dev =~ /\/dsk\/$devname$/) 
{
                                                        $devmnt = $mnt;
                                                        last;
                                                }
                                        }
                                        close (INFILE);
                                }
                                print 
$base_oid,".",$oid_mod_num,".",$oid_dev_num,".",$oid_sub_num,".",$oid_stat_num,"\n";
                                print "string\n";
                                print "$mod_name:$inst_name:$sub_name";
                                print " ($devname)" if ($devname);
                                print " $devmnt" if ($devmnt);
                                print "\n";
                                $matched = 1;
                                last;
                        } else {
                                my $stat_name = $kstat_info[$oid_mod_num 
-1]->{stat}[$oid_stat_num -1]->{name};
                                my $stat_type = $kstat_info[$oid_mod_num 
-1]->{stat}[$oid_stat_num -1]->{type};
        
                                print 
"\$ssk->{$mod_name}{$inst_name}{$sub_name}{$stat_name}\n" if ($debug);
                                if ($stat_name && $stat_type && exists 
$ssk->{$mod_name}{$inst_name}{$sub_name}{$stat_name}) {
                                        $systime = time();
                                        if ($readtime < $systime - 
$read_interval) {
                                                $readtime = time();
                                                $ssk->update();
                                        }
                                        print 
$base_oid,".",$oid_mod_num,".",$oid_dev_num,".",$oid_sub_num,".",$oid_stat_num,"\n";
                                        print "$stat_type\n";
                                        # shorten 64bit integers 
                                        if ($stat_name =~ /^(nread|nwritten)$/) 
{
                                                print 
$ssk->{$mod_name}{$inst_name}{$sub_name}{$stat_name} / 10240, "\n";
                                        } else {
                                                print 
$ssk->{$mod_name}{$inst_name}{$sub_name}{$stat_name}, "\n";
                                        }
                                        $matched = 1;
                                        last;
                                };
                        };
                };
                # no process matched
                if ($cmd =~ /^GETNEXT/i) {
                        $oid_stat_num++;
                        next;
                }
                last;
        };
        print "NONE","\n" if (!$matched);;
};

# /usr/local/share/snmp/snmp-kstat.conf
#
# ----------------------------------------------------------------------------
# Configuration file for the snmp-kstat.pl script. snmp-kstat.pl provides 
# kernel information that can be polled by OpenNMS. It's started by Net-SNMP
# if the snmpd.conf file contains the following option:
#
# pass_persist .1.3.6.1.4.1.8072.100.2 /usr/bin/perl 
/usr/local/share/snmp/snmp-kstat.pl

# ----------------------------------------------------------------------------
# The base_oid must match the OID entered in the snmpd.conf pass_persist
# option. .1.3.6.1.4.1.8072 is the base Net-SNMP OID. Registering a
# private enterprise OID with IANA should be considered in the future.

$base_oid = '.1.3.6.1.4.1.8072.100.2';

# ----------------------------------------------------------------------------
# Re-read the kernel information every X seconds (checked only when an snmp
# get is received).

$read_interval = '5';

@kstat_info = (
        { 'module' => 'chip', },
        { 'module' => 'conskbd', },
        { 'module' => 'consms', },
        { 'module' => 'cpu', },
        {
                'module' => 'cpu_info',
                'dev' => [ 
                        { 'instance' => '0', 'names' => [ 'cpu_info0', ], },
                        { 'instance' => '1', 'names' => [ 'cpu_info1', ], },
                        { 'instance' => '2', 'names' => [ 'cpu_info2', ], },
                        { 'instance' => '3', 'names' => [ 'cpu_info3', ], },
                ],
                'stat' => [
                        # integer, gauge, counter, timeticks, ipaddress, 
objectid, or string
                        { 'name' => 'brand', 'type' => 'string', },             
# .1
                        { 'name' => 'chip_id', 'type' => 'integer', },          
# .2
                        { 'name' => 'class', 'type' => 'string', },             
# .3
                        { 'name' => 'clock_MHz', 'type' => 'integer', },        
# .4
                        { 'name' => 'cpu_type', 'type' => 'string', },          
# .5
                        { 'name' => 'crtime', 'type' => 'counter', },           
# .6
                        { 'name' => 'fpu_type', 'type' => 'string', },          
# .7
                        { 'name' => 'implementation', 'type' => 'string', },    
# .8
                        { 'name' => 'snaptime', 'type' => 'gauge', },           
# .9
                        { 'name' => 'state', 'type' => 'string', },             
# .10
                        { 'name' => 'state_begin', 'type' => 'counter', },      
# .11
                ],
        },
        { 'module' => 'cpu_stat', },
        { 'module' => 'fssnap', },
        { 'module' => 'icmp', },
        { 'module' => 'ip', },
        { 'module' => 'iscsi', },
        { 'module' => 'kcf', },
        { 'module' => 'kssl', },
        { 'module' => 'lgrp', },
        { 'module' => 'lo', },
        {
                'module' => 'md',       # .15
                'dev' => [
                        { 'instance' => '101', 'names' => [ 'md101', ], },
                ],
                'stat' => [
                        { 'name' => 'class', 'type' => 'string', },             
# .15.x.x.1
                        { 'name' => 'crtime', 'type' => 'counter', },           
# .15.x.x.2
                        { 'name' => 'nread', 'type' => 'counter', },            
# .15.x.x.3 - 64bit value is divided by 10240
                        { 'name' => 'nwritten', 'type' => 'counter', },         
# .15.x.x.4 - 64bit value is divided by 10240
                        { 'name' => 'rcnt', 'type' => 'counter', },             
# .15.x.x.5
                        { 'name' => 'reads', 'type' => 'counter', },            
# .15.x.x.6
                        { 'name' => 'rlastupdate', 'type' => 'counter', },      
# .15.x.x.7
                        { 'name' => 'rlentime', 'type' => 'gauge', },           
# .15.x.x.8
                        { 'name' => 'rtime', 'type' => 'counter', },            
# .15.x.x.9
                        { 'name' => 'snaptime', 'type' => 'gauge', },           
# .15.x.x.10
                        { 'name' => 'wcnt', 'type' => 'counter', },             
# .15.x.x.11
                        { 'name' => 'wlastupdate', 'type' => 'counter', },      
# .15.x.x.12
                        { 'name' => 'wlentime', 'type' => 'gauge', },           
# .15.x.x.13
                        { 'name' => 'writes', 'type' => 'counter', },           
# .15.x.x.14
                        { 'name' => 'wtime', 'type' => 'counter', },            
# .15.x.x.15
                ],
        },
        { 'module' => 'mdi', },
        { 'module' => 'nfs', },
        { 'module' => 'nfs_acl', },
        { 'module' => 'poll', },
        { 'module' => 'portfs', },
        { 'module' => 'sctp', },
        {
                'module' => 'sd',
                'dev' => [ 
                        { 'instance' => '3', 'names' => [ 'sd3,a', ], },
                        { 'instance' => '5', 'names' => [ 'sd5', 'sd5,a', 
'sd5,c', ], },
                ],
                'stat' => [
                        { 'name' => 'class', 'type' => 'string', },
                        { 'name' => 'crtime', 'type' => 'counter', },
                        { 'name' => 'nread', 'type' => 'counter', },
                        { 'name' => 'nwritten', 'type' => 'counter', },
                        { 'name' => 'rcnt', 'type' => 'counter', },
                        { 'name' => 'reads', 'type' => 'counter', },
                        { 'name' => 'rlastupdate', 'type' => 'counter', },
                        { 'name' => 'rlentime', 'type' => 'gauge', },
                        { 'name' => 'rtime', 'type' => 'counter', },
                        { 'name' => 'snaptime', 'type' => 'gauge', },
                        { 'name' => 'wcnt', 'type' => 'counter', },
                        { 'name' => 'wlastupdate', 'type' => 'counter', },
                        { 'name' => 'wlentime', 'type' => 'gauge', },
                        { 'name' => 'writes', 'type' => 'counter', },
                        { 'name' => 'wtime', 'type' => 'counter', },
                ],
        },
        { 'module' => 'sderr', },
        { 'module' => 'ssd', },
        { 'module' => 'ssderr', },
        { 'module' => 'streams', },
        { 'module' => 'tcp', },
        { 'module' => 'udp', },
        { 'module' => 'ufs', },
        { 'module' => 'ufs_log', },
        { 'module' => 'unix', },
        { 'module' => 'usba', },
        { 'module' => 'vmem', },
);

Attachment: graph.png
Description: PNG image

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Net-snmp-users mailing list
Net-snmp-users@lists.sourceforge.net
Please see the following page to unsubscribe or change other options:
https://lists.sourceforge.net/lists/listinfo/net-snmp-users

Reply via email to