Chinaunix首页 | 论坛 | 博客
  • 博客访问: 22257
  • 博文数量: 2
  • 博客积分: 291
  • 博客等级: 二等列兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-15 21:13
文章分类
文章存档

2013年(1)

2011年(1)

分类: 网络与安全

2013-09-23 18:51:12

Monitoring remote Linux Storage Partitions via SNMP
================================

Task:
    Adminstration, System Monitoring

Requirment:
    Remote Linux-Host snmpd enabaled, SNMP Version 2c used, SNMP Community as 'public'
    (see more in details: /etc/snmp/snmpd.conf)

Monitoring-Host:
    OpsView (Nagios implemented). Perl module: Net::SNMP installed.

Perl code snippet:

1
#!/usr/bin/perl -w
2
3 # Nagios plugin to check remote disk partitions via SNMP
4 # Author: Ulmer
5 # Created on: 2013-09-18
6
7 use strict;
8 use Getopt::Std;
9 #use Net::SNMP qw(:snmp);
10 use Net::SNMP qw(oid_lex_sort oid_base_match snmp_type_ntop);
11
12 # Set snmp
13 use constant SNMP_VERSION => 2;
14 use constant SNMP_COMMUNITY => 'public';
15 use constant OID_HR_STORAGE_TABLE => '1.3.6.1.2.1.25.2.3';
16
17 # Nagios Exit Code
18 use constant EXIT_OK => 0;
19 use constant EXIT_WARNING => 1;
20 use constant EXIT_CRITICAL => 2;
21 use constant EXIT_UNKNOWN => 3;
22
23 # Nagios default critical and warning values
24 use constant DISK_CRITICAL => 95;
25 use constant DISK_WARNING => 85;
26
27 # Set key name
28 use constant KEY_TYPE => 'type';
29 use constant KEY_DATA => 'data';
30 use constant KEY_MOUNT => 'mount';
31 use constant KEY_SIZE => 'size';
32 use constant KEY_USED => 'used';
33 use constant KEY_AVAIL => 'avail';
34 use constant KEY_USESPACE => 'usespace';
35
36 # Set command line input options
37 # -H Sets $opt_H as a side effect.
38 # -c [Critical used space in percetage] Sets $opt_c as a side effect.
39 # -w [Warning used space in percetage] Sets $opt_w as a side effect.
40 # -d [Debugging mode] Sets $opt_d as a side effect.
41 getopt('Hwcd');
42 our($opt_H, $opt_w, $opt_c, $opt_d);
43
44
45 ######################################################################
46 # Subroutines #
47 ######################################################################
48
49 sub snmp_walk {
50 my ($session, $walk_oid) = @_;
51 my @args = (-maxrepetitions => 25, -varbindlist => [$walk_oid]);
52 # HoH data structure { => {'type'=>, 'data'=>}}
53 my $records = {};
54
55 LINE: while (defined($session->get_bulk_request(@args))) {
56     my @oids = oid_lex_sort( keys %{$session->var_bind_list()} );
57     foreach my $oid (@oids) {
58        if (!oid_base_match($walk_oid, $oid)) {
59           last LINE;
60        }
61     my $type = snmp_type_ntop($session->var_bind_types()->{$oid});
62     my $data = $session->var_bind_list()->{$oid};
63
64     # Store walk records
65     $records->{$oid}->{KEY_TYPE} = $type;
66     $records->{$oid}->{KEY_DATA} = $data;
67
68     # Make sure we have not hit the end of the MIB
69     if ($session->var_bind_list()->{$oid} eq 'endOfMibView') {
70         last LINE; 
71     }
72 }
73 # Get the last OBJECT IDENTIFIER in the returned list
74 @args = (-maxrepetitions => 25, -varbindlist => [pop(@oids)]);
75 }
76 return $records;
77 }
78
79 sub get_storage_partitions {
80 my ($snmp_walk_records) = @_;
81 my $partitions = {};
82 foreach my $oid (sort keys %$snmp_walk_records) {
83 my $type = $snmp_walk_records->{$oid}->{KEY_TYPE};
84 my $data = $snmp_walk_records->{$oid}->{KEY_DATA};
85 if ($type eq 'OCTET STRING' and $data =~ /^\//) {
86 # We'v got partition path
87 my @oid_items = split /\./, $oid;
88 # Fetching partition's block (1024 or 4096, ...)
89 # the OID for disk block is oid_items[-2] = 4;
90 $oid_items[-2] = 4;
91 my $oid_disk_block = join '.', @oid_items;
92 my $block_multiple_factor = 1;
93 if (exists($snmp_walk_records->{$oid_disk_block})) {
94 my $block_data = $snmp_walk_records->{$oid_disk_block}->{KEY_DATA};
95 if ($block_data >= 1024) {
96 $block_multiple_factor = $block_data / 1024;
97 }
98 }
99 # Fechting total size : oid_items[-2] = 5
100 $oid_items[-2] = 5;
101 my $oid_disk_size = join '.', @oid_items;
102 my $size = -1;
103 if (exists($snmp_walk_records->{$oid_disk_size})) {
104 my $size_data = $snmp_walk_records->{$oid_disk_size}->{KEY_DATA};
105 $size = $size_data * $block_multiple_factor;
106 }
107 # Fechting disk used : oid_items[-2] = 6
108 $oid_items[-2] = 6;
109 my $oid_disk_used = join '.', @oid_items;
110 my $used = -1;
111 if (exists($snmp_walk_records->{$oid_disk_used})) {
112 my $used_data = $snmp_walk_records->{$oid_disk_used}->{KEY_DATA};
113 $used = $used_data * $block_multiple_factor;
114 }
115 my $avail = $size - $used;
116 my $use_space = -1;
117 if ($size > 0 && $used > 0) {
118 $use_space = sprintf("%d", ($used / $size) * 100);
119 }
120 # Generate partitions records
121 if ($size > 0 ) {
122 $partitions->{$oid}->{KEY_MOUNT} = $data;
123 $partitions->{$oid}->{KEY_SIZE} = $size;
124 $partitions->{$oid}->{KEY_USED} = $used;
125 $partitions->{$oid}->{KEY_AVAIL} = $avail;
126 $partitions->{$oid}->{KEY_USESPACE} = $use_space;
127 }
128 }
129 }
130 return $partitions;
131 }
132
133 sub display_disk_partition {
134 my ($partitions) = @_;
135
136 foreach my $oid (sort keys %$partitions) {
137 my $mnt = $partitions->{$oid}->{KEY_MOUNT};
138 my $size = $partitions->{$oid}->{KEY_SIZE};
139 my $used = $partitions->{$oid}->{KEY_USED};
140 my $avail = $partitions->{$oid}->{KEY_AVAIL};
141 my $usespace = $partitions->{$oid}->{KEY_USESPACE};
142
143 my $format = "%.2f";
144 my $out = '['. $mnt. ']: size=';
145 if ($size > (1024*1024)) {
146 $out .= sprintf($format, $size/(1024*1024)).'G';
147 } elsif ($size > 1024) {
148 $out .= sprintf($format, $size/1024).'M';
149 } else {
150 $out .= $size.'K';
151 }
152 $out .= ', used=';
153 if ($used > (1024*1024)) {
154 $out .= sprintf($format, $used/(1024*1024)).'G';
155 } elsif ($used > 1024) {
156 $out .= sprintf($format, $used/1024). 'M';
157 } else {
158 $out .= $used.'K';
159 }
160 $out .= ', avail=';
161 if ($avail > (1024*1024)) {
162 $out .= sprintf($format, $avail/(1024*1024)).'G';
163 } elsif ($avail > 1024) {
164 $out .= sprintf($format, $avail/1024).'M';
165 } else {
166 $out .= $avail.'K';
167 }
168 $out .= ', use%='.$usespace.'%';
169 print "$out\n";
170 }
171 }
172
173 sub check_used_space {
174 my ($storage_partitions, $max_allowed_space) = @_;
175
176 my @failures = ();
177 foreach my $oid (sort keys %$storage_partitions) {
178 my $mnt = $storage_partitions->{$oid}->{KEY_MOUNT};
179 my $usespace = $storage_partitions->{$oid}->{KEY_USESPACE};
180 if ($usespace >= $max_allowed_space) {
181 push @failures, '['. $mnt. ']: use%='. $usespace. ' >= max. allowed!';
182 }
183 }
184 return @failures;
185 }
186
187 sub dump_snmpwalk {
188 my ($snmpwalk_records) = @_;
189 foreach my $oid (sort keys %$snmpwalk_records) {
190 print $oid. ' = '. $snmpwalk_records->{$oid}->{KEY_TYPE} . ': '.
191 $snmpwalk_records->{$oid}->{KEY_DATA} . "\n";
192 }
193 }
194
195 sub usage {
196 print "Usage: $0 ARGUMENTS\n";
197 print " Nagios Plugin for check remote disk via SNMP\n";
198 print " Support SNMP Version: '2c', Community: 'public'\n";
199 print " Required Arguments:\n";
200 print " -H : fqdns or ip\n";
201 print " Optional:\n";
202 print " -w [maximum used space] : ".
203 "Warning for used space, default is ". DISK_WARNING. "%\n";
204 print " -c [maximum used space] : ".
205 "Crtitical for used space, default is ". DISK_CRITICAL. "%\n";
206 print " -d [y|yes]: Debugging mode\n";
207 }
208
209
210 ######################################################################
211 # Main Program #
212 ######################################################################
213 my $exit_code = EXIT_UNKNOWN;
214 my @stdout = ("Check Hard Disk Partitions...");
215
216 if ($opt_H) {
217 my $host = $opt_H;
218 my ($session, $error) = Net::SNMP->session(
219 -hostname => $host,
220 -community => SNMP_COMMUNITY,
221 -port => 161,
222 -version => SNMP_VERSION,
223 );
224 if (!defined($session)) {
225 printf("Session error: %s.\n", $error);
226 $session->close;
227 exit EXIT_UNKNOWN;
228 }
229 # check remote system response firstly
230 my $oidSysDescr = '1.3.6.1.2.1.1.1.0';
231 my $result = $session->get_request(-varbindlist=>[$oidSysDescr]);
232 if (!defined($result)) {
233 printf("Result error: %s.\n", $session->error);
234 $session->close;
235 exit EXIT_UNKNOWN;
236 }
237
238 # Start snmpwalk to collect oids responses
239 my $snmpwalk_records = snmp_walk($session, OID_HR_STORAGE_TABLE);
240 my $disk_partitions = get_storage_partitions($snmpwalk_records);
241 $session->close;
242
243 # Check used space
244 my $warning_space = DISK_WARNING;
245 my $critical_space = DISK_CRITICAL;
246 if ($opt_w and $opt_w =~ /^\d{1,2}$/) {
247 $warning_space = $opt_w;
248 }
249 if ($opt_c and $opt_c =~ /^\d{1,2}$/) {
250 $critical_space = $opt_c;
251 }
252 my @warning = check_used_space($disk_partitions, $warning_space);
253 my @critical = check_used_space($disk_partitions, $critical_space);
254 if (@warning > 0 ) {
255 foreach my $msg (@warning) {
256 push @stdout, 'WARNING: '. $msg;
257 }
258 $exit_code = EXIT_WARNING;
259 } elsif (@critical > 0 ) {
260 foreach my $msg (@critical) {
261 push @stdout, 'CRITICAL: '. $msg;
262 }
263 $exit_code = EXIT_CRITICAL;
264 } else {
265 $exit_code = EXIT_OK;
266 push @stdout, 'RESULT: OK';
267 foreach my $oid (sort keys %$disk_partitions) {
268 my $mnt = $disk_partitions->{$oid}->{KEY_MOUNT};
269 my $usespace = $disk_partitions->{$oid}->{KEY_USESPACE};
270 push @stdout, "[$mnt]: use%=$usespace;";
271 }
272 }
273 if ($opt_d && $opt_d =~ /^y|yes$/i) {
274 # dump
275 display_disk_partition($disk_partitions);
276 print "Dump snmpwalk: hrStorageTable: ". OID_HR_STORAGE_TABLE. " ...\n";
277 dump_snmpwalk($snmpwalk_records);
278 } else {
279 print join("\n", @stdout);
280 }
281 print "\n";
282 exit $exit_code;
283 } else {
284 usage();
285 exit EXIT_UNKNOWN;
286 }
287
288 __END__






阅读(1936) | 评论(0) | 转发(0) |
0

上一篇:博客已升级,请注意变更地址

下一篇:没有了

给主人留下些什么吧!~~