Changeset b4a01ee848c6689e508db6c683e95fd59cb17f28
- Timestamp:
- 03/20/10 02:37:44
(3 years ago)
- Author:
- Mark Harrison <mark@omniti.com>
- git-committer:
- Mark Harrison <mark@omniti.com> 1269052664 +0000
- git-parent:
[84fa9ac85ea06f95b5b8fb73360ff441d536e056]
- git-author:
- Mark Harrison <mark@omniti.com> 1269052664 +0000
- Message:
Changes to how modules are loaded:
Each module is an object inheriting from Resmon::Module as before, but the
code to support coderefs and raw packages with a handler function is all gone.
In addition, a lot of redundant code was removed, and some small changes made
to the modules themselves:
- The check name is stored in $self->{check_name} (instead of
$self->{object} as in the past)
- The check configuration is stored in $self->{config} and not just as
instance variables.
- All modules must have fully qualified names in the config file. In other
words - Resmon::Module::Resmon instead of just RESMON. In keeping with
other perl module names, I've gone with Title Case instead of ALL CAPS
for the sample module (Resmon). This is simple to change back if desired
however.
git-svn-id: https://labs.omniti.com/resmon/branches/resmon2@268 8c0face9-b7db-6ec6-c4b3-d5f7145c7d55
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| rf51cc7c |
rb4a01ee |
|
| 22 | 22 | if($current) { |
|---|
| 23 | 23 | if(/^\s*([^:\s](?:[^:]*[^:\s])?)\s*:\s*(.+)\s*$/) { |
|---|
| 24 | | my %kvs; |
|---|
| 25 | | $kvs{'type'} = $current; |
|---|
| 26 | | $kvs{'object'} = $1; |
|---|
| | 24 | my $kvs = {}; |
|---|
| | 25 | my $check_name = $1; |
|---|
| 27 | 26 | my @params = split(/,/, $2); |
|---|
| 28 | | grep { $kvs{$1} = $2 if /^\s*(\S+)\s*=>\s*(\S(?:.*\S)?)\s*$/ } |
|---|
| | 27 | grep { $kvs->{$1} = $2 if /^\s*(\S+)\s*=>\s*(\S(?:.*\S)?)\s*$/ } |
|---|
| 29 | 28 | @params; |
|---|
| 30 | | my $object = bless \%kvs, "Resmon::Module::$current"; |
|---|
| | 29 | my $object; |
|---|
| | 30 | eval "use $current; |
|---|
| | 31 | \$object = $current->new(\$check_name, \$kvs);"; |
|---|
| | 32 | if ($@) { |
|---|
| | 33 | print STDERR "Problem loading monitor $current:\n"; |
|---|
| | 34 | print STDERR "$@\n"; |
|---|
| | 35 | print STDERR "This module will not be available\n"; |
|---|
| | 36 | next; |
|---|
| | 37 | } |
|---|
| | 38 | if (!$object->isa("Resmon::Module")) { |
|---|
| | 39 | print STDERR "Module $current isn't of type "; |
|---|
| | 40 | print STDERR "Resmon::Module. This monitor will not be "; |
|---|
| | 41 | print STDERR "available\n"; |
|---|
| | 42 | } |
|---|
| 31 | 43 | push(@{$self->{Module}->{$current}}, $object); |
|---|
| 32 | | |
|---|
| 33 | | # Test to make sure the module actually works |
|---|
| 34 | | my $coderef; |
|---|
| 35 | | eval { $coderef = Resmon::Module::fetch_monitor($current); }; |
|---|
| 36 | | if (!$coderef) { |
|---|
| 37 | | # Try to execute the config_as_hash method. If it fails, |
|---|
| 38 | | # then the module didn't load properly (e.g. syntax |
|---|
| 39 | | # error). |
|---|
| 40 | | eval { $object->config_as_hash; }; |
|---|
| 41 | | if ($@) { |
|---|
| 42 | | # Module failed to load, print error and add to failed |
|---|
| 43 | | # modules list. |
|---|
| 44 | | print STDERR "Problem loading module $current\n"; |
|---|
| 45 | | print STDERR "This module will not be available\n"; |
|---|
| 46 | | $self->{'modstatus'} .= "$current "; |
|---|
| 47 | | } |
|---|
| 48 | | } |
|---|
| 49 | | |
|---|
| 50 | 44 | } elsif (/^\s*\}\s*$/) { |
|---|
| 51 | 45 | $current = undef; |
|---|
- Property mode changed from 100755 to 100644
| r4dec1ca |
rb4a01ee |
|
| 1 | 1 | package Resmon::Module; |
|---|
| | 2 | use strict; |
|---|
| 2 | 3 | |
|---|
| 3 | | use strict; |
|---|
| 4 | | use Data::Dumper; |
|---|
| 5 | | use FileHandle; |
|---|
| 6 | | use UNIVERSAL qw/isa/; |
|---|
| 7 | | my %coderefs; |
|---|
| | 4 | sub new { |
|---|
| | 5 | my ($class, $check_name, $config) = @_; |
|---|
| | 6 | my $self = {}; |
|---|
| | 7 | $self->{config} = $config; |
|---|
| | 8 | $self->{check_name} = $check_name; |
|---|
| | 9 | bless ($self, $class); |
|---|
| | 10 | return $self; |
|---|
| | 11 | } |
|---|
| 8 | 12 | |
|---|
| 9 | | my $rmloading = "Registering"; |
|---|
| | 13 | sub handler { |
|---|
| | 14 | return { |
|---|
| | 15 | 'error_message' => ["Monitor not implemented", "s"] |
|---|
| | 16 | } |
|---|
| | 17 | } |
|---|
| 10 | 18 | |
|---|
| 11 | | sub fetch_monitor { |
|---|
| 12 | | my $type = shift; |
|---|
| 13 | | my $coderef = $coderefs{$type}; |
|---|
| 14 | | return $coderef if ($coderef); |
|---|
| | 19 | sub cache_metrics { |
|---|
| | 20 | # Simple method to cache the results of a check |
|---|
| | 21 | my $self = shift; |
|---|
| | 22 | $self->{lastmetrics} = shift; |
|---|
| | 23 | $self->{lastupdate} = time; |
|---|
| | 24 | } |
|---|
| 15 | 25 | |
|---|
| 16 | | # First if the monitor name is raw and looks right: |
|---|
| 17 | | # is a subclass of Resmon::Module and can 'handler' |
|---|
| 18 | | # then we will promote it into the Resmon::Module namespace |
|---|
| 19 | | # and use this one. |
|---|
| 20 | | eval "use $type;"; |
|---|
| 21 | | if($type->isa(__PACKAGE__) && $type->can('handler')) { |
|---|
| 22 | | eval " |
|---|
| 23 | | package Resmon::Module::$type; |
|---|
| 24 | | use vars qw/\@ISA/; |
|---|
| 25 | | \@ISA = qw($type); |
|---|
| 26 | | 1; |
|---|
| 27 | | "; |
|---|
| 28 | | if($@) { |
|---|
| 29 | | die "Could not repackage $type as Resmon::Module::$type\n"; |
|---|
| 30 | | } |
|---|
| 31 | | return undef; |
|---|
| | 26 | sub get_cached_metrics { |
|---|
| | 27 | my $self = shift; |
|---|
| | 28 | return undef unless $self->{check_interval}; |
|---|
| | 29 | my $now = time; |
|---|
| | 30 | if(($self->{lastupdate} + $self->{check_interval}) >= $now) { |
|---|
| | 31 | return $self->{lastmetrics}; |
|---|
| 32 | 32 | } |
|---|
| 33 | | eval "use Resmon::Module::$type;"; |
|---|
| 34 | 33 | return undef; |
|---|
| 35 | 34 | } |
|---|
| 36 | 35 | |
|---|
| 37 | | sub register_monitor { |
|---|
| 38 | | my ($type, $ref) = @_; |
|---|
| 39 | | if(ref $ref eq 'CODE') { |
|---|
| 40 | | $coderefs{$type} = $ref; |
|---|
| 41 | | } |
|---|
| 42 | | print STDERR "$rmloading $type monitor\n"; |
|---|
| 43 | | } |
|---|
| 44 | | |
|---|
| 45 | | sub fresh_status { |
|---|
| 46 | | my $arg = shift; |
|---|
| 47 | | print STDERR $arg->{type} . |
|---|
| 48 | | ": Warning: fresh_status() is deprecated, and no longer required.\n"; |
|---|
| 49 | | return undef; |
|---|
| 50 | | } |
|---|
| 51 | | |
|---|
| 52 | | sub fresh_status_msg { |
|---|
| 53 | | # Deal with result caching if an 'interval' entry is placed in the config |
|---|
| 54 | | # for that module |
|---|
| 55 | | my $arg = shift; |
|---|
| 56 | | return undef unless $arg->{interval}; |
|---|
| 57 | | my $now = time; |
|---|
| 58 | | if(($arg->{lastupdate} + $arg->{interval}) >= $now) { |
|---|
| 59 | | return $arg->{laststatus}, $arg->{lastmessage}; |
|---|
| 60 | | } |
|---|
| 61 | | return undef; |
|---|
| 62 | | } |
|---|
| 63 | | sub cache_metrics { |
|---|
| 64 | | my $arg = shift; |
|---|
| 65 | | $arg->{lastmetrics} = shift; |
|---|
| 66 | | $arg->{lastupdate} = time; |
|---|
| 67 | | } |
|---|
| 68 | | sub config_as_hash { |
|---|
| 69 | | my $self = shift; |
|---|
| 70 | | my $conf = {}; |
|---|
| 71 | | while(my ($key, $value) = each %$self) { |
|---|
| 72 | | if(! ref $value) { |
|---|
| 73 | | # only stash scalars here. |
|---|
| 74 | | $conf->{$key} = $value; |
|---|
| 75 | | } |
|---|
| 76 | | } |
|---|
| 77 | | return $conf; |
|---|
| 78 | | } |
|---|
| 79 | | |
|---|
| 80 | | sub reload_module { |
|---|
| 81 | | my $self = shift; |
|---|
| 82 | | my $class = ref($self) || $self; |
|---|
| 83 | | $class =~ s/::/\//g; |
|---|
| 84 | | my $file = $INC{"$class.pm"}; |
|---|
| 85 | | # Deal with modules loaded from a LIB directory and not in |
|---|
| 86 | | # lib/Resmon/Module: try MODNAME.pm instead of Resmon/Module/MODNAME.pm |
|---|
| 87 | | unless ($file) { |
|---|
| 88 | | $class =~ s/^.*\/([^\/]+)$/\1/; |
|---|
| 89 | | $file = $INC{"$class.pm"}; |
|---|
| 90 | | } |
|---|
| 91 | | print STDERR "Reloading module: $class\n"; |
|---|
| 92 | | # my $fh = FileHandle->new($file); |
|---|
| 93 | | # local($/); |
|---|
| 94 | | my $redef = 0; |
|---|
| 95 | | local($SIG{__WARN__}) = sub { |
|---|
| 96 | | if($_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) { |
|---|
| 97 | | $redef++; |
|---|
| 98 | | return; |
|---|
| 99 | | } |
|---|
| 100 | | warn @_; |
|---|
| 101 | | }; |
|---|
| 102 | | # eval <$fh>; |
|---|
| 103 | | eval {do($file); die $@ if $@}; |
|---|
| 104 | | return $@ if $@; |
|---|
| 105 | | return $redef; |
|---|
| 106 | | } |
|---|
| 107 | | |
|---|
| 108 | | $rmloading = "Demand loading"; |
|---|
| 109 | 36 | 1; |
|---|
| r84fa9ac |
rb4a01ee |
|
| 493 | 493 | $loaded{$type} = (); |
|---|
| 494 | 494 | foreach (@$mods) { |
|---|
| 495 | | $loaded{$type}{$_->{'object'}} = 1; |
|---|
| | 495 | $loaded{$type}{$_->{'check_name'}} = 1; |
|---|
| 496 | 496 | } |
|---|
| 497 | 497 | } |
|---|
| radc4557 |
rb4a01ee |
|
| 18 | 18 | use Resmon::ExtComm; |
|---|
| 19 | 19 | use Resmon::Status; |
|---|
| 20 | | use Resmon::Module; |
|---|
| 21 | 20 | |
|---|
| 22 | 21 | GetOptions( |
|---|
| … | … | |
| 124 | 123 | while(1) { |
|---|
| 125 | 124 | while(my($module_name, $mod_configs) = each %{$config->{Module}}) { |
|---|
| 126 | | my $coderef = undef; |
|---|
| 127 | | eval { $coderef = Resmon::Module::fetch_monitor($module_name); }; |
|---|
| 128 | | foreach my $monobj (@$mod_configs) { |
|---|
| 129 | | my $check_metric = 'no data'; |
|---|
| | 125 | foreach my $monitor_obj (@$mod_configs) { |
|---|
| | 126 | my $check_metric = {}; |
|---|
| 130 | 127 | my $starttime = [gettimeofday]; |
|---|
| 131 | 128 | # Get old status if it hasn't expired |
|---|
| 132 | | my $check_metric = Resmon::Module::fresh_status_msg($monobj); |
|---|
| | 129 | my $check_metric = $monitor_obj->get_cached_metrics(); |
|---|
| 133 | 130 | # Otherwise, run the check |
|---|
| 134 | 131 | if (!$check_metric) { |
|---|
| 135 | | my $timeout = $monobj->{'check_timeout'} || |
|---|
| | 132 | my $timeout = $monitor_obj->{'check_timeout'} || |
|---|
| 136 | 133 | $config->{'timeout'}; |
|---|
| 137 | 134 | alarm($timeout); |
|---|
| 138 | 135 | eval { |
|---|
| 139 | 136 | local $SIG{ALRM} = sub { die "alarm\n" }; |
|---|
| 140 | | if($coderef) { |
|---|
| 141 | | $check_metric = $coderef->($monobj); |
|---|
| 142 | | } else { |
|---|
| 143 | | $check_metric = $monobj->handler(); |
|---|
| 144 | | } |
|---|
| | 137 | $check_metric = $monitor_obj->handler(); |
|---|
| 145 | 138 | }; |
|---|
| 146 | 139 | alarm 0; |
|---|
| 147 | 140 | # Store the last metrics for use by fresh_status_msg later |
|---|
| 148 | | Resmon::Module::cache_metrics($monobj, $check_metric); |
|---|
| | 141 | $monitor_obj->cache_metrics($check_metric); |
|---|
| 149 | 142 | }; |
|---|
| 150 | 143 | my $checkproblem = $@; |
|---|
| … | … | |
| 162 | 155 | } |
|---|
| 163 | 156 | } |
|---|
| 164 | | $status->store($module_name,$monobj->{'object'}, $results); |
|---|
| 165 | | $status->write($module_name,$monobj->{'object'}, |
|---|
| | 157 | $status->store($module_name,$monitor_obj->{'check_name'}, $results); |
|---|
| | 158 | $status->write($module_name,$monitor_obj->{'check_name'}, |
|---|
| 166 | 159 | $results->{'metric'}, $debug); |
|---|
| 167 | 160 | } |
|---|