OSSP CVS Repository

ossp - ossp-pkg/snmpdx/snmpdx.d/sysVM.pm
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/snmpdx/snmpdx.d/sysVM.pm
##
##  OSSP snmpdx - SNMP Daemon Extension
##  Copyright (c) 2003-2007 The OSSP Project <http://www.ossp.org/>
##  Copyright (c) 2003-2007 Ralf S. Engelschall <rse@engelschall.com>
##  Copyright (c) 2003-2005 Cable & Wireless <http://www.cw.com/>
##
##  This file is part of OSSP snmpdx, a SNMP daemon extension which
##  can be found at http://www.ossp.org/pkg/tool/snmpdx/.
##
##  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.0 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 file; if not, write to the Free Software
##  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
##  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
##
##  sysVM.pm: probe for System Virtual Memory
##

package My::Probe::sysVM;
our @ISA = qw(My::Probe);

sub oids ($) {
    my ($self) = @_;
    return $self->{-ctx}->{-mib}->oids("*.snmpdx.host.system.sysVM.*");
}

sub probe ($$) {
    my ($self, $obj) = @_;

    if ($self->{-ctx}->{-platform}->id() =~ m/FreeBSD/i) {
        ##
        ##  FreeBSD 4/5
        ##
        ##  sysVMRamMax   "/sbin/sysctl -a", "hw.physmem", convert bytes to MB
        ##  sysVMRamUsed  sysVMRamMax - sysVMRamFree
        ##  sysVMRamFree  "/sbin/sysctl -a", "vm.stats.vm.*", convert pages to MB
        ##  sysVMSwapMax  "/usr/sbin/swapinfo -k", 1K-blocks, last line, convert KB to MB
        ##  sysVMSwapUsed "/usr/sbin/swapinfo -k", Used, last line, convert KB to MB
        ##  sysVMSwapFree sysVMSwapMax - sysVMSwapUsed
        ##  sysVMActivity "/usr/bin/vmstat", add pi and po column
        ##
        if ($obj->{-name} =~ m/\.sysVMRam(Max|Used|Free)$/) {
            my $sysVMRamMax;
            my $sysVMRamUsed;
            my $sysVMRamFree;

            #   query system for sysctl(8) variables
            my $out = $self->{-ctx}->{-sys}->run("/sbin/sysctl -a", "1m");
            my $sysctl = {};
            foreach my $line (split(/\n/, $out->{-stdout})) {
                $sysctl->{$1} = $2 if ($line =~ m/^([^:]+):\s+(.+)\s*$/s);
            }

            #   determine sysVMRamMax
            $sysVMRamMax = int(&mem_rounded($sysctl->{"hw.physmem"}) / (1024*1024));

            #   determine sysVMRamFree
            $sysVMRamFree =
                int((  $sysctl->{"hw.pagesize"}
                     * (  $sysctl->{"vm.stats.vm.v_inactive_count"} 
                        + $sysctl->{"vm.stats.vm.v_cache_count"}
                        + $sysctl->{"vm.stats.vm.v_free_count"}    )) / (1024*1024));

            #   determine sysVMRamUsed
            if (defined($sysVMRamMax) and defined($sysVMRamFree)) {
                $sysVMRamUsed = ($sysVMRamMax - $sysVMRamFree);
            }

            #   provide result
            $obj->{-value} = $sysVMRamMax  if ($obj->{-name} =~ m/\.sysVMRamMax$/);
            $obj->{-value} = $sysVMRamUsed if ($obj->{-name} =~ m/\.sysVMRamUsed$/);
            $obj->{-value} = $sysVMRamFree if ($obj->{-name} =~ m/\.sysVMRamFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMSwap(Max|Used|Free)$/) {
            my $sysVMSwapMax;
            my $sysVMSwapUsed;
            my $sysVMSwapFree;

            #   determine sysVMSwapMax and sysVMSwapUsed
            my $out = $self->{-ctx}->{-sys}->run("/usr/sbin/swapinfo -k", "1m");
            my $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^\s*([^\n]*\b1K-blocks[^\n]*\bUsed[^\n]*).*\n([^\n]+)$/s) {
                $n2i = &mkn2i(split(/\s+/, $1));
            }
            my @dat = split(/\s+/, $2);
            if (defined($n2i->{_1K_blocks})) {
                $sysVMSwapMax = int(@dat[$n2i->{_1K_blocks}] / 1024)
            }
            if (defined($n2i->{Used})) {
                $sysVMSwapUsed = int(@dat[$n2i->{Used}] / 1024)
            }

            #   determine sysVMSwapFree
            if (defined($sysVMSwapMax) and defined($sysVMSwapUsed)) {
                $sysVMSwapFree = $sysVMSwapMax - $sysVMSwapUsed;
            }

            #   provide result
            $obj->{-value} = $sysVMSwapMax  if ($obj->{-name} =~ m/\.sysVMSwapMax$/);
            $obj->{-value} = $sysVMSwapUsed if ($obj->{-name} =~ m/\.sysVMSwapUsed$/);
            $obj->{-value} = $sysVMSwapFree if ($obj->{-name} =~ m/\.sysVMSwapFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMActivity$/) {
            my $sysVMActivity;

            my $out = $self->{-ctx}->{-sys}->run("/usr/bin/vmstat", "1m");
            my $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^[^\n]*\n *([^\n]*(\bp[io]\b[^\n]*){2})\n *([^\n]*)\n$/s) {
                $n2i = &mkn2i(split / +/, $1);
            }
            if (defined($n2i->{pi}) and defined($n2i->{po})) {
                my @dat = split(/ +/, $3);
                $sysVMActivity = @dat[$n2i->{pi}] + @dat[$n2i->{po}];
            }
            $obj->{-value} = $sysVMActivity;
        }
    }
    elsif ($self->{-ctx}->{-platform}->id() =~ m/Linux/i) {
        ##
        ##  Linux 2.2/2.4
        ##
        ##  sysVMRamMax   "/bin/cat /proc/meminfo", MemTotal, convert KB to MB
        ##  sysVMRamUsed  "/bin/cat /proc/meminfo", MemTotal-Buffers-Cached-MemFree, convert KB to MB
        ##  sysVMRamFree  sysVMRamMax - sysVMRamUsed
        ##  sysVMSwapMax  "/bin/cat /proc/meminfo", SwapTotal, convert KB to MB
        ##  sysVMSwapUsed sysVMSwapMax - sysVMSwapFree
        ##  sysVMSwapFree "/bin/cat /proc/meminfo", SwapFree, convert KB to MB
        ##  sysVMActivity "/usr/bin/vmstat", add si and so column
        ##
        ##  FIXME: sysVMRamMax does not include the kernel and some of
        ##  its structures so it is not pyhsical RAM, see dmesg | egrep
        ##  '^Memory:'. Additionally, /bin/cat is used here but could be
        ##  replaced by native Perl code to improve performance...
        ##
        if ($obj->{-name} =~ m/\.sysVMRam(Max|Used|Free)$/) {
            my $sysVMRamMax;
            my $sysVMRamUsed;
            my $sysVMRamFree;

            #   determine sysVMRamMax and sysVMRamUsed
            my $out = $self->{-ctx}->{-sys}->run("/bin/cat /proc/meminfo", "1m");
            my $raw = $out->{-stdout};
            my $tmp = {};
            $tmp->{MemTotal} = $1 if ($raw =~ m/\nMemTotal:[^\n]*\b(\d+)\b[^\n]*kB\n/s);
            $tmp->{Buffers}  = $1 if ($raw =~ m/\nBuffers:[^\n]*\b(\d+)\b[^\n]*kB\n/s);
            $tmp->{Cached}   = $1 if ($raw =~ m/\nCached:[^\n]*\b(\d+)\b[^\n]*kB\n/s);
            $tmp->{MemFree}  = $1 if ($raw =~ m/\nMemFree:[^\n]*\b(\d+)\b[^\n]*kB\n/s);
            if (defined($tmp->{MemTotal})) {
                $sysVMRamMax = int($tmp->{MemTotal} / 1024);
            }
            if (    defined($tmp->{MemTotal})
                and defined($tmp->{Buffers})
                and defined($tmp->{Cached})
                and defined($tmp->{MemFree}) ) {
                $sysVMRamUsed = int ((  $tmp->{MemTotal} 
                                      - $tmp->{Buffers} 
                                      - $tmp->{Cached} 
                                      - $tmp->{MemFree} ) / 1024 );
            }

            #   determine sysVMRamFree
            if (defined $sysVMRamMax and defined $sysVMRamUsed) {
                $sysVMRamFree = $sysVMRamMax - $sysVMRamUsed;
            }

            #   provide result
            $obj->{-value} = $sysVMRamMax  if ($obj->{-name} =~ m/\.sysVMRamMax$/);
            $obj->{-value} = $sysVMRamUsed if ($obj->{-name} =~ m/\.sysVMRamUsed$/);
            $obj->{-value} = $sysVMRamFree if ($obj->{-name} =~ m/\.sysVMRamFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMSwap(Max|Used|Free)$/) {
            my $sysVMSwapMax;
            my $sysVMSwapUsed;
            my $sysVMSwapFree;

            #   determine sysVMSwapMax and sysVMSwapFree
            my $out = $self->{-ctx}->{-sys}->run("/bin/cat /proc/meminfo", "1m");
            my $raw = $out->{-stdout};
            if ($raw =~ m/\nSwapTotal:[^\n]*\b(\d+)\b[^\n]*kB\n/s) {
                $sysVMSwapMax = int($1 / 1024);
            }
            if ($raw =~ m/\nSwapFree:[^\n]*\b(\d+)\b[^\n]*kB\n/s) {
                $sysVMSwapFree = int($1 / 1024);
            }

            #   determine sysVMSwapUsed
            if (defined($sysVMSwapMax) and defined($sysVMSwapFree)) {
                $sysVMSwapUsed = $sysVMSwapMax - $sysVMSwapFree;
            }

            #   provide result
            $obj->{-value} = $sysVMSwapMax  if ($obj->{-name} =~ m/\.sysVMSwapMax$/);
            $obj->{-value} = $sysVMSwapUsed if ($obj->{-name} =~ m/\.sysVMSwapUsed$/);
            $obj->{-value} = $sysVMSwapFree if ($obj->{-name} =~ m/\.sysVMSwapFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMActivity$/) {
            my $sysVMActivity;

            my $out = $self->{-ctx}->{-sys}->run("/usr/bin/vmstat", "1m");
            my $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^[^\n]*\n *([^\n]*(\bs[io]\b[^\n]*){2})\n *([^\n]*)\n$/s) {
                $n2i = &mkn2i(split(/\s+/, $1)) if (not defined($n2i->{sr}));
            }
            if (defined($n2i->{si}) and defined($n2i->{so})) {
                my @dat = split(/\s+/, $3);
                $sysVMActivity = @dat[$n2i->{si}] + @dat[$n2i->{so}];
            }
            $obj->{-value} = $sysVMActivity;
        }
    }
    elsif ($self->{-ctx}->{-platform}->id() =~ m/SunOS/i) {
        ##
        ##  Sun Solaris 2.x (SunOS 5.x)
        ##
        ##  sysVMRamMax   "/usr/platform/$arch/sbin/prtdiag", Memory size
        ##  sysVMRamUsed  sysVMRamMax - sysVMRamFree
        ##  sysVMRamFree  "/bin/pagesize" * "/bin/sar -r 1 1", freemem, convert bytes to MB
        ##  sysVMSwapMax  "swap -l", egrep ^/ and accumulate, convert 512byte blocks to MB
        ##  sysVMSwapUsed sysVMSwapMax - sysVMSwapFree
        ##  sysVMSwapFree "swap -l", egrep ^/ and accumulate, convert 512byte blocks to MB
        ##  sysVMActivity "/bin/vmstat", sr column
        ##
        if ($obj->{-name} =~ m/\.sysVMRam(Max|Used|Free)$/) {
            my $sysVMRamMax;
            my $sysVMRamUsed;
            my $sysVMRamFree;

            #   determine architecture
            my $arch = $self->{-ctx}->{-platform}->arch();

            #   determine page size
            my $out = $self->{-ctx}->{-sys}->run("/bin/pagesize", "forever");
            my $raw = $out->{-stdout};
            my $pagesize = 4096;
            if ($raw =~ m/^(\d+)$/) {
                $pagesize = $1;
            }

            #   determine sysVMRamMax
            $out = $self->{-ctx}->{-sys}->run("/usr/platform/$arch/sbin/prtdiag -v", "1m");
            $raw = $out->{-stdout};
            if ($raw =~ m/\nMemory size: (\d+) Megabytes/s) {
                $sysVMRamMax = $1;
            }

            #   determine sysVMRamFree
            $out = $self->{-ctx}->{-sys}->run("/bin/sar -r 1 1", "1m");
            $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^.*\n([^\n]*\bfreemem[^\n]*)\n(.*)$/s) {
                $n2i = &mkn2i(split(/\s+/, $1));
            }
            my @dat = split(/\s+/, $2);
            if (defined($n2i->{freemem})) {
                $tmp = @dat[$n2i->{freemem}];
            }
            $sysVMRamFree = int($tmp * $pagesize / (1024*1024)) if (defined($tmp));

            #   determine sysVMRamUsed
            if (defined($sysVMRamMax) and defined($sysVMRamFree)) {
                $sysVMRamUsed = $sysVMRamMax - $sysVMRamFree;
            }

            #   provide result
            $obj->{-value} = $sysVMRamMax  if ($obj->{-name} =~ m/\.sysVMRamMax$/);
            $obj->{-value} = $sysVMRamUsed if ($obj->{-name} =~ m/\.sysVMRamUsed$/);
            $obj->{-value} = $sysVMRamFree if ($obj->{-name} =~ m/\.sysVMRamFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMSwap(Max|Used|Free)$/) {
            my $sysVMSwapMax;
            my $sysVMSwapUsed;
            my $sysVMSwapFree;

            #   determine sysVMSwapMax, sysVMSwapFree
            my $out = $self->{-ctx}->{-sys}->run("/usr/sbin/swap -l", "1m");
            my $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^\s*([^\n]*\bblocks[^\n]*\bfree[^\n]*)\n(.*)$/s) {
                $n2i = &mkn2i(split(/\s+/, $1)) if (scalar(keys(%{$n2i})) == 0);
            }
            my $tmpMax;
            my $tmpFree;
            foreach my $r (split(/\n/, $2)) {
                if ($r =~ m/^\//) {
                    my @dat = split(/\s+/, $r);
                    if (defined($n2i->{blocks})) {
                        $tmpMax  = 0 if (not defined($tmpMax));
                        $tmpMax  += @dat[$n2i->{blocks}];
                    }
                    if (defined($n2i->{free})) {
                        $tmpFree = 0 if (not defined($tmpFree));
                        $tmpFree += @dat[$n2i->{free}];
                    }
                }
            }
            $sysVMSwapMax  = int($tmpMax  * 512 / 1024 / 1024) if (defined($tmpMax));
            $sysVMSwapFree = int($tmpFree * 512 / 1024 / 1024) if (defined($tmpFree));

            #   determine sysVMSwapUsed
            if (defined($sysVMSwapMax) and defined($sysVMSwapFree)) {
                $sysVMSwapUsed = $sysVMSwapMax - $sysVMSwapFree;
            }

            #   provide result
            $obj->{-value} = $sysVMSwapMax  if ($obj->{-name} =~ m/\.sysVMSwapMax$/);
            $obj->{-value} = $sysVMSwapUsed if ($obj->{-name} =~ m/\.sysVMSwapUsed$/);
            $obj->{-value} = $sysVMSwapFree if ($obj->{-name} =~ m/\.sysVMSwapFree$/);
        }
        elsif ($obj->{-name} =~ m/\.sysVMActivity$/) {
            my $sysVMActivity;

            my $out = $self->{-ctx}->{-sys}->run("/bin/vmstat", "1m");
            my $raw = $out->{-stdout};
            my $n2i = {};
            if ($raw =~ m/^[^\n]*\n *([^\n]*\bsr\b[^\n]*)\n *([^\n]*)\n$/s) {
                $n2i = &mkn2i(split(/\s+/, $1)) if (not defined($n2i->{sr}));
            }
            if (defined $n2i->{sr}) {
                my @dat = split(/\s+/, $2);
                $sysVMActivity = @dat[$n2i->{sr}];
            }
            $obj->{-value} = $sysVMActivity;
        }
    }
    return;
}

#   table row name to index mapping
sub mkn2i ($) {
    my (@name) = @_;
    my $rc = {};
    my $i = 0;
    foreach my $f (@name) {
        $f =~ s/[^\w]/_/;
        $f =~ s/^([^a-zA-Z_])/_$1/;
        $rc->{$f} = $i++;
    };
    return $rc;
}

#   round the physical memory size to the next power of two which is
#   reasonable for memory cards. We do this by first determining the
#   guessed memory card size under the assumption that usual computer
#   hardware has an average of a maximally eight memory cards installed
#   and those are usually of equal size.
sub mem_rounded {
    my ($mem_size) = @_;
    my $chip_size  = 1;
    my $chip_guess = ($mem_size / 8) - 1;
    while ($chip_guess != 0) {
        $chip_guess >>= 1;
        $chip_size  <<= 1;
    }
    my $mem_round = (int($mem_size / $chip_size) + 1) * $chip_size;
    return $mem_round;
}

1;


CVSTrac 2.0.1