root/resmon

Revision f51cc7c864024ce120ec1eeaba4ba1bed38241e1, 6.2 kB (checked in by Mark Harrison <mark@omniti.com>, 8 years ago)

Indentation/formatting fixes (4 spaces per OmniTI coding style)

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

  • Property mode set to 100755
Line 
1 #!/usr/bin/perl
2
3 BEGIN {
4     (my $dir = $0) =~ s/\/?[^\/]+$//;
5     eval "use lib '$dir/lib';";
6     die $@ if($@);
7 };
8
9 use strict;
10 use Time::HiRes qw( gettimeofday tv_interval sleep );
11 use POSIX qw( :sys_wait_h setsid );
12 use Getopt::Long;
13 use Data::Dumper;
14 use vars qw($config_file $debug $status_file $interface $port $config
15 $status $update);
16
17 use Resmon::Config;
18 use Resmon::ExtComm;
19 use Resmon::Status;
20 use Resmon::Module;
21
22 GetOptions(
23     "i=s" => \$interface,
24     "p=i" => \$port,
25     "c=s" => \$config_file,
26     "d"   => \$debug,
27     "f=s" => \$status_file,
28     "u"   => \$update,
29 );
30
31 if ($update) {
32     use Resmon::Updater;
33     (my $resmondir = $0) =~ s/\/?[^\/]+$//;
34     exit(Resmon::Updater::update($debug, $resmondir));
35 }
36
37 $config_file ||= "$0.conf";
38 die "Cannot open configuration file: $config_file" unless (-r $config_file);
39
40 sub configure {
41     $config = Resmon::Config->new($config_file);
42     $config->{statusfile} = $status_file if($status_file);
43     $config->{port} = $port if($port);
44     $config->{interface} = $interface if($interface);
45 }
46
47 sub reconfigure {
48     my $modstatus = "";
49     print STDERR "Reloading modules...\n";
50     my $modules = $config->{Module};
51     while ( my ($key, $value) = each(%$modules) ) {
52         my $mod = $value->[0]; # Only need the first of each module
53         # Called this way rather than $mod->reload_module() in order to deal
54         # with modules that failed to load on startup and won't have a
55         # reload_module method.
56         my $errs = Resmon::Module::reload_module($mod);
57         if ($errs) {
58             my $modname = ref($mod) || $mod;
59             $modname =~ s/Resmon::Module:://;
60             $modstatus .= "$modname ";
61             print STDERR " Failed to reload module $modname\n";
62             print STDERR $errs;
63             print STDERR " This module is no longer available.\n";
64         }
65     }
66     print STDERR "Reloading configuration...\n";
67     eval { configure(); };
68     if ($@) {
69         # The config object is recreated every time we reload, so we shouldn't
70         # need to reset this BAD value to empty on a successful load.
71         $config->{'configstatus'} = "BAD";
72         print STDERR " Failed to reload: ";
73         print STDERR $@;
74         print STDERR " Continuing with old configuration\n";
75     }
76
77     $config->{'modstatus'} = $modstatus;
78     $status->purge($config);
79 }
80
81 my $sighup = 0;
82 sub sighup_handler { $sighup = 1; }
83 $SIG{'HUP'} = \&sighup_handler;
84
85 configure();
86
87 my $sigint = 0;
88 sub sigint_handler { $sigint = 1; }
89 $SIG{'INT'} = \&sigint_handler;
90
91 my $rmlast = undef;
92 sub wait_interval {
93     $rmlast = [gettimeofday] unless defined($rmlast);
94     my $elapsed = $config->{interval} - tv_interval($rmlast);
95     if($elapsed > 0) {
96         sleep($elapsed);
97     }
98     $rmlast = [gettimeofday];
99 }
100
101 sub reap_zombies {
102     my $kid;
103     do {
104         $kid = waitpid(-1, WNOHANG);
105     } while $kid > 0;
106 }
107
108 unless($debug) {
109     fork && exit;
110     setsid;
111     open(STDIN, "</dev/null");
112     open(STDOUT, ">/dev/null");
113     open(STDERR, ">/dev/null");
114     fork && exit;
115 }
116
117 my $list = [];
118 $status = Resmon::Status->new($config->{statusfile});
119 $status->open();
120 $status->serve_http_on($config->{interface}, $config->{port},
121     $config->{authuser}, $config->{authpass})
122 if($config->{port});
123
124 while(1) {
125     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_rv = 'BAD',
130             my $check_metric = 'no data';
131             my $starttime = [gettimeofday];
132             # Get old status if it hasn't expired
133             my ($check_rv, $check_metric) = Resmon::Module::fresh_status_msg(
134                 $monobj);
135             # Otherwise, run the check
136             if (!$check_rv) {
137                 my $timeout = $monobj->{'check_timeout'} ||
138                     $config->{'timeout'};
139                 alarm($timeout);
140                 eval {
141                     local $SIG{ALRM} = sub { die "alarm\n" };
142                     if($coderef) {
143                         ($check_rv, $check_metric) = $coderef->($monobj);
144                     } else {
145                         ($check_rv, $check_metric) = $monobj->handler();
146                     }
147                 };
148                 alarm 0;
149                 # Store the last status for use by fresh_status_msg later
150                 # Also converts old style status messages
151                 ($check_rv, $check_metric) =
152                 Resmon::Module::set_status($monobj, $check_rv, $check_metric);
153             }
154             my $checkstat = $@;
155             my $confighash = {};
156             eval { $confighash = $monobj->config_as_hash(); };
157             my $results = {
158                 #configuration => $confighash,
159                 last_runtime_seconds => sprintf("%.6f", tv_interval($starttime))
160             };
161             if($checkstat) {
162                 $results->{state} = 'BAD';
163                 $results->{metric} = { "message" =>
164                     "Bad module or problem running handler code."};
165                 if ($checkstat eq "alarm\n") {
166                     $results->{metric} = { "message" =>
167                         "Check timeout"};
168                     Resmon::ExtComm::clean_up;
169                 }
170             } else {
171                 $results->{state} = $check_rv;
172                 if (ref($check_metric) eq "HASH") {
173                     my $metric = {};
174                     while(my ($k, $v) = each %$check_metric) {
175                         $metric->{$k} = $v;
176                     }
177                     $results->{metric} = $metric;
178                 } else {
179                     $results->{metric} = { "message" => $check_metric };
180                 }
181             }
182             $status->store($module_name,$monobj->{'object'}, $results);
183             printf("%s: %s\n%s\n", $module_name, $monobj->{'object'},
184                 Dumper($results)) if $debug;
185         }
186     }
187     $status->close();
188     die "Exiting.\n" if($sigint);
189     if ($sighup) {
190         $sighup = 0;
191         reconfigure();
192     } else {
193         reap_zombies();
194         wait_interval();
195         reap_zombies();
196     }
197     die "Exiting.\n" if($sigint);
198     print "\n---- ".localtime(time)."----------\n"
199     unless $status->open();
200 }
Note: See TracBrowser for help on using the browser.