root/lib/Resmon/Module.pm

Revision a7d2d7beb82bb785cdd2982a653f279494d3530a, 5.3 kB (checked in by Eric Sproul <esproul@omniti.com>, 7 years ago)

Fix a regex bug with remoteport match, update regexes to work on Linux as well as Solaris

git-svn-id: https://labs.omniti.com/resmon/trunk@43 8c0face9-b7db-6ec6-c4b3-d5f7145c7d55

  • Property mode set to 100755
Line 
1 package Resmon::Module;
2
3 use strict;
4 use Data::Dumper;
5 use UNIVERSAL qw/isa/;
6 my %coderefs;
7
8 my $rmloading = "Registering";
9
10 sub fetch_monitor {
11   my $type = shift;
12   my $coderef = $coderefs{$type};
13   return $coderef if ($coderef);
14
15   # First if the monitor name is raw and looks right:
16   #   is a subclass of Resmon::Module and can 'handler'
17   # then we will promote it into the Resmon::Module namespace
18   # and use this one.
19   eval "use $type;";
20   if($type->isa(__PACKAGE__) && $type->can('handler')) {
21     eval "
22       package Resmon::Module::$type;
23       use vars qw/\@ISA/;
24       \@ISA = qw($type);
25       1;
26     ";
27     if($@) {
28       die "Could not repackage $type as Resmon::Module::$type\n";
29     }
30     return undef;
31   }
32   eval "use Resmon::Module::$type;";
33   return undef;
34 }
35
36 sub register_monitor {
37   my ($type, $ref) = @_;
38   if(ref $ref eq 'CODE') {
39     $coderefs{$type} = $ref;
40   }
41   print STDERR "$rmloading $type monitor\n";
42 }
43 sub fresh_status {
44   my $arg = shift;
45   return undef unless $arg->{interval};
46   my $now = time;
47   if(($arg->{lastupdate} + $arg->{interval}) >= $now) {
48     return $arg->{laststatus};
49   }
50   return undef;
51 }
52 sub set_status {
53   my $arg = shift;
54   $arg->{laststatus} = shift;
55   $arg->{lastmessage} = shift;
56   $arg->{lastupdate} = time;
57   if($arg->{laststatus} =~ /^([A-Z]+)\((.*)\)$/s) {
58     # This handles old-style modules that return just set status as
59     #     STATE(message)
60     $arg->{laststatus} = $1;
61     $arg->{lastmessage} = $2;
62   }
63   return ($arg->{laststatus}, $arg->{lastmessage});
64 }
65 sub config_as_hash {
66   my $self = shift;
67   my $conf = {};
68   while(my ($key, $value) = each %$self) {
69     if(! ref $value) {
70       # only stash scalars here.
71       $conf->{$key} = $value;
72     }
73   }
74   return $conf;
75 }
76 #### Begin actual monitor functions ####
77
78 package Resmon::Module::DATE;
79 use vars qw/@ISA/;
80 @ISA = qw/Resmon::Module/;
81
82 sub handler {
83   my $arg = shift;
84   my $os = $arg->fresh_status();
85   return $arg->set_status("OK(".time().")");
86 }
87
88 package Resmon::Module::DISK;
89 use Resmon::ExtComm qw/cache_command/;
90 use vars qw/@ISA/;
91 @ISA = qw/Resmon::Module/;
92
93 sub handler {
94   my $arg = shift;
95   my $os = $arg->fresh_status();
96   return $os if $os;
97   my $devorpart = $arg->{'object'};
98   my $output = cache_command("df -k", 120);
99   my ($line) = grep(/$devorpart\s*/, split(/\n/, $output));
100   if($line =~ /(\d+)%/) {
101     if($1 <= $arg->{'limit'}) {
102       return $arg->set_status("OK($1% full)");
103     }
104     return $arg->set_status("BAD($1% full)");
105   }
106   return $arg->set_status("BAD(no data)");
107 }
108
109 package Resmon::Module::LOGFILE;
110 use vars qw/@ISA/;
111 @ISA = qw/Resmon::Module/;
112
113 my %logfile_stats;
114 sub handler {
115   my $arg = shift;
116   my $os = $arg->fresh_status();
117   return $os if $os;
118   my $file = $arg->{'object'};
119   my $match = $arg->{'match'};
120   my $max = $arg->{'max'} || 8;
121   my @statinfo = stat($file);
122   if(exists($arg->{file_dev})) {
123     if(($arg->{file_dev} == $statinfo[0]) &&
124        ($arg->{file_ino} == $statinfo[1])) {
125       if($arg->{lastsize} == $statinfo[7]) {
126         if($arg->{errors}) {
127           return $arg->set_status("BAD($arg->{nerrs}: $arg->{errors})");
128         }
129         return $arg->set_status("OK(0)");
130       }
131     } else {
132       # File is a different file now
133       $arg->{lastsize} = 0;
134       $arg->{nerrs} = 0;
135       $arg->{errors} = '';
136     }
137   }
138   if(!open(LOG, "<$file")) {
139     return $arg->set_status("BAD(ENOFILE)");
140   }
141   seek(LOG, $arg->{lastsize}, 0);
142
143   while(<LOG>) {
144     chomp;
145     if(/$match/) {
146       if($arg->{nerrs} < $max) {
147         $arg->{errors} .= " " if(length($arg->{errors}));
148         $arg->{errors} .= $_;
149       }
150       $arg->{nerrs}++;
151     }
152   }
153
154   # Remember where we were
155   $arg->{file_dev} = $statinfo[0];
156   $arg->{file_ino} = $statinfo[1];
157   $arg->{lastsize} = $statinfo[7];
158
159   if($arg->{nerrs}) {
160     return $arg->set_status("BAD($arg->{nerrs}: $arg->{errors})");
161   }
162   return $arg->set_status("OK(0)");
163 }
164
165 package Resmon::Module::FILEAGE;
166 use vars qw/@ISA/;
167 @ISA = qw/Resmon::Module/;
168
169 sub handler {
170   my $arg = shift;
171   my $os = $arg->fresh_status();
172   return $os if $os;
173   my $file = $arg->{'object'};
174   my @statinfo = stat($file);
175   my $age = time() - $statinfo[9];
176   return $arg->set_status("BAD(to old $age seconds)")
177         if($arg->{maximum} && ($age > $arg->{maximum}));
178   return $arg->set_status("BAD(to new $age seconds)")
179         if($arg->{minimum} && ($age > $arg->{minimum}));
180   return $arg->set_status("OK($age)");
181 }
182
183 package Resmon::Module::NETSTAT;
184 use Resmon::ExtComm qw/cache_command/;
185 use vars qw/@ISA/;
186 @ISA = qw/Resmon::Module/;
187
188 sub handler {
189   my $arg = shift;
190   my $os = $arg->fresh_status();
191   return $os if $os;
192   my $output = cache_command("netstat -an", 30);
193   my @lines = split(/\n/, $output);
194   @lines = grep(/\s$arg->{state}\s*$/, @lines) if($arg->{state});
195   @lines = grep(/^$arg->{localip}/, @lines) if($arg->{localip});
196   @lines = grep(/^[\w\d\*\.]+.*[\.\:]+$arg->{localport}/, @lines) if($arg->{localport});
197   @lines = grep(/[\d\*\.]+\d+\s+$arg->{remoteip}/, @lines)
198         if($arg->{remoteip});
199   @lines = grep(/[\d\*\.]+\s+[\d\*\.]+[\.\:]+$arg->{remoteport}\s+/, @lines)
200         if($arg->{remoteport});
201   my $count = scalar(@lines);
202   return $arg->set_status("BAD($count)")
203         if($arg->{limit} && ($count > $arg->{limit}));
204   return $arg->set_status("BAD($count)")
205         if($arg->{atleast} && ($count < $arg->{atleast}));
206   return $arg->set_status("OK($count)");
207 }
208
209 $rmloading = "Demand loading";
210 1;
Note: See TracBrowser for help on using the browser.