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', }, );
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