File Coverage

blib/lib/Luka.pm
Criterion Covered Total %
statement 57 201 28.3
branch 0 60 0.0
condition 0 35 0.0
subroutine 19 24 79.1
pod 1 3 33.3
total 77 323 23.8


line stmt bran cond sub pod time code
1             # $Id: Luka.pm,v 1.12 2006/07/17 22:02:44 toni Exp $
2             package Luka;
3 2     2   56006 use strict;
  2         4  
  2         66  
4 2     2   11 use warnings;
  2         4  
  2         48  
5 2     2   2011 use Socket;
  2         16093  
  2         1158  
6 2     2   2329 use Sys::Syslog;
  2         41342  
  2         154  
7 2     2   1861 use Sys::Hostname;
  2         2659  
  2         108  
8 2     2   2083 use Sys::Hostname::Long;
  2         2630  
  2         101  
9 2     2   934 use Luka::Mailer;
  2         6  
  2         74  
10 2     2   1145 use Luka::Exceptions;
  2         8  
  2         68  
11 2     2   938 use Luka::Error;
  2         5  
  2         47  
12 2     2   997 use Luka::Conf;
  2         7  
  2         70  
13 2     2   14 use Error qw(:try);
  2         6  
  2         19  
14 2     2   379 use Data::Dumper;
  2         5  
  2         138  
15              
16             push @Exception::Class::Base::ISA, 'Error'
17             unless Exception::Class::Base->isa('Error');
18              
19 2     2   11 use Carp;
  2         4  
  2         110  
20 2     2   11 use Exporter;
  2         5  
  2         325  
21             our (@ISA, @EXPORT_OK, @EXPORT, @modes, %error_str );
22              
23             @ISA = qw(Exporter);
24             @EXPORT_OK = qw(report_error);
25              
26             our $VERSION = "1.07";
27             our $LukaDebug = "LukaDebug";
28              
29 2     2   2695 use Class::Std;
  2         27219  
  2         14  
30              
31             {
32             # config definition of the script handled
33             my %script_about : ATTR( :get :set );
34              
35             #-----------------------------------
36             # captured error/report properties
37             #-----------------------------------
38             my %error : ATTR( :get :set ); # error object
39             my %id : ATTR( :get :set );
40             my %line : ATTR( :get :set );
41             my %stacktrace : ATTR( :get :set );
42             my %text : ATTR( :get :set ); # error string
43             my %severity : ATTR( :get :set );
44             my %args : ATTR( :get :set );
45             my %context : ATTR( :get :set );
46              
47             # config file location (for tests)
48             my %conf : ATTR( :get :set );
49              
50             # captured script properties
51             my %path : ATTR( :get :set );
52             my %filename : ATTR( :get :set );
53              
54             # captured device state
55             my %ipaddr : ATTR( :get :set );
56             my %hostname : ATTR( :get :set );
57             my %hostname_long : ATTR( :get :set );
58             my %local_date_time : ATTR( :get :set );
59             my %syslogd : ATTR( :get :set );
60              
61             # captured process state
62             my %pid : ATTR( :get :set );
63             my %uid : ATTR( :get :set );
64             my %euid : ATTR( :get :set );
65             my %gid : ATTR( :get :set );
66             my %egid : ATTR( :get :set );
67              
68             # global config options
69             my %doc_base : ATTR( :get :set );
70             my %debug : ATTR( :get :set );
71             my %nomail : ATTR( :get :set );
72             my %state_code_error : ATTR( :get :set );
73             my %state_code_success : ATTR( :get :set );
74             my %default_state_code_error : ATTR( :get :set );
75             my %default_state_code_success : ATTR( :get :set );
76              
77             # reporting [delivery:email]
78             my %send_to : ATTR( :get :set );
79             my %send_cc : ATTR( :get :set );
80             my %send_from : ATTR( :get :set );
81             my %send_subj_success : ATTR( :get :set );
82             my %report_body_error : ATTR( :get :set );
83             my %report_body_success : ATTR( :get :set );
84              
85             # syslog logging options
86             my %syslogopt : ATTR( :get :set );
87             my %syslogfacility : ATTR( :get :set );
88              
89             @modes = qw( error success );
90             $error_str{"modes"} = "Unknown mode 'ARG'. Available modes: " . join(",",@modes);
91             $error_str{"unknown_method"} = "Unknown method 'ARG' can not be called on " .
92             __PACKAGE__ . " objects.";
93              
94             sub validate_modes : PRIVATE {
95 0         0 my ($self, $mode) = @_;
96 0 0       0 if (!grep {/^$mode$/} @modes ) {
  0         0  
97 0         0 throw Luka::Exception::Program
98             ( error => $self->get_error_str("modes",$mode), show_trace =>1 );
99             }
100 2     2   1312 }
  2         3  
  2         11  
101              
102             sub get_error_str : PRIVATE {
103 0         0 my ($self, $type, $arg) = @_;
104 0 0       0 if (exists $error_str{$type}) {
105 0         0 my $str = $error_str{$type};
106 0         0 $str =~ s/ARG/$arg/;
107 0         0 return $str;
108             } else {
109 0         0 throw Luka::Exception::Program
110             ( error => "Error type '$type', isn't defined", show_trace =>1 );
111             }
112 2     2   764 }
  2         4  
  2         9  
113              
114             sub get : PRIVATE {
115 0         0 my ($self, $val, $mode) = @_;
116             #print "val=$val,mode=$mode\n";
117 0         0 $self->validate_modes($mode);
118 0         0 my $method = "get_" . $val . "_" . $mode;
119 0 0       0 if ( $self->can($method) ) {
120             #print "method=$method\n";
121 0         0 return $self->$method;
122             } else {
123 0         0 throw Luka::Exception::Program
124             ( error => $self->get_error_str("unknown_method",$method), show_trace =>1 );
125             }
126 2     2   598 }
  2         17  
  2         11  
127              
128             sub BUILD {
129 0     0 0   my ($self, $ident, $arg_ref) = @_;
130              
131 0           my $luka_conf;
132             # capture device and process state
133 0           my $unknown = "unknown";
134 0           $hostname{$ident} = hostname();
135 0           $hostname_long{$ident} = hostname_long();
136 0           $pid{$ident} = $$;
137 0           $uid{$ident} = $<;
138 0           $euid{$ident} = $>;
139 0           $gid{$ident} = $(;
140 0           $egid{$ident} = $);
141 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(CORE::time());
142 0           $local_date_time{$ident} =
143             sprintf("%s-%s-%sT%s:%s:%s",$year + 1900,$mon + 1,$mday,$hour,$min,$sec);
144 0   0       $hostname{$ident} = hostname() || $unknown;
145 0   0       $hostname_long{$ident} = hostname_long() || $unknown;
146              
147             # error/report properties
148 0 0         if (defined $arg_ref->{'error'}) {
149              
150 0           my $E = $arg_ref->{'error'};
151              
152 0           $filename{$ident} = $arg_ref->{'filename'};
153             #$filename{$ident} = $E->file;
154 0   0       $id{$ident} = $E->id || "generic";
155 0 0         $severity{$ident} = $E->can("severity") ? $E->severity : $unknown;
156 0 0         $args{$ident} = $E->can("args") ?
    0          
157             (defined($E->args) ? $E->args : $unknown) : $unknown;
158 0 0         $context{$ident} = $E->can("context") ? $E->context : $unknown;
159 0           $line{$ident} = $E->line;
160 0           $path{$ident} = $E->path;
161 0 0         $conf{$ident} = $E->conf ? $E->conf : undef;
162              
163 0 0 0       if ( ref($E) eq "Error::Simple" or ref($E) eq "Luka::Error" ) {
164              
165 0   0       $text{$ident} = $E->text || $unknown;
166 0   0       $stacktrace{$ident} = $E->stacktrace || $unknown;
167              
168             } else {
169              
170 0   0       $text{$ident} = $E->error || $unknown;
171 0   0       $stacktrace{$ident} = $E->trace || $unknown;
172            
173             }
174              
175             # do we have syslogd running or not?
176             try {
177             #eval {
178             #local $SIG{'__DIE__'}; # see "perldoc -f eval"
179 0 0   0     openlog($filename{$ident}, "pid,noname", "daemon")
180             || die;
181 0 0         syslog('info', "Luka initiating...") || die;
182 0           $syslogd{$ident} = 1;
183 0           open(BLA, '>> /tmp/log');
184 0           print BLA "test try \n";
185 0           close BLA;
186             #};
187             } catch Error with {
188             #if ($@ or $!) {
189 0     0     my $e = shift;
190 0           my $bla = Dumper $e;
191 0           open(BLA2, '>> /tmp/log');
192 0           print BLA2 "test catch\n";
193 0           close BLA2;
194 0           die "oops";
195 0           $syslogd{$ident} = undef;
196             }
197              
198             #===========================================================
199             # we had to delay seting of IP address, because of config
200             # object dependecy on possible optional 'conf' value passed
201             # to thrown Luka execptions.
202             #==========================================================
203 0           $luka_conf = Luka::Conf->new( conf => $conf{$ident}, syslogd => $syslogd{$ident} );
204 0           $ipaddr{$ident} = $unknown;
205 0           my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($hostname{$ident});
206             # of all interfaces, use closest match to IP from the config
207 0           my $expected_ip = $luka_conf->get_conf('global','expected_ip');
208 0           for(0..$#addrs) {
209 0           $addrs[$_] = inet_ntoa($addrs[$_]);
210             # print $addrs[$_] . "\n";
211 0 0         $ipaddr{$ident} = $addrs[$_] if $addrs[$_] =~ $expected_ip;
212             }
213              
214             } else { # success
215              
216 0           my $caller = (caller(1))[1];
217 0           my ($vol,$dir,$file) = File::Spec->splitpath($caller);
218 0           $arg_ref->{'filename'} = $file;
219 0           $filename{$ident} = $arg_ref->{'filename'};
220              
221             # do we have syslogd running or not?
222 0           eval {
223 0           openlog($filename{$ident}, "pid,noname", "daemon");
224 0           syslog('info', "Luka initiating...");
225             };
226 0 0         if ($@) {
227 0           $syslogd{$ident} = undef;
228             } else {
229 0           $syslogd{$ident} = 1;
230             }
231              
232             #===========================================================
233             # we had to delay seting of IP address, because of config
234             # object dependecy on possible optional 'conf' value passed
235             # to thrown Luka execptions.
236             #==========================================================
237 0           $luka_conf = Luka::Conf->new( syslogd => $syslogd{$ident} );
238 0           $ipaddr{$ident} = $unknown;
239 0           my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($hostname{$ident});
240              
241             # of all interfaces, use closest match to IP from the config
242 0           my $expected_ip = $luka_conf->get_conf('global','expected_ip');
243 0           for(0..$#addrs) {
244 0           $addrs[$_] = inet_ntoa($addrs[$_]);
245             # print $addrs[$_] . "\n";
246 0 0         $ipaddr{$ident} = $addrs[$_] if $addrs[$_] =~ $expected_ip;
247             }
248            
249 0           $text{$ident} = $luka_conf->get_conf( $arg_ref->{'filename'},'about' );
250             }
251              
252             # reporting [delivery:email]
253 0           $send_subj_success{$ident} = $luka_conf->get_conf( $arg_ref->{'filename'}, 'on_success');
254              
255 0           $send_to{$ident} = $arg_ref->{'filename'} .
256             "@" . $luka_conf->get_conf('global','email_domain');
257              
258 0           $send_cc{$ident} = $luka_conf->get_conf( $arg_ref->{'filename'}, 'cc');
259              
260 0   0       $send_from{$ident} = $luka_conf->get_conf( $arg_ref->{'filename'}, 'from') ||
261             "root@" . $hostname_long{$ident};
262              
263 0           $doc_base{$ident} = $luka_conf->get_conf('global','doc_base') . "/" .
264             $luka_conf->get_conf($arg_ref->{'filename'},'doc');
265              
266 0 0         if (defined $arg_ref->{'error'}) {
267 0           $doc_base{$ident} .= "#" . $self->get_id;
268 0 0         $report_body_error{$ident} .= sprintf("%s=%s\n","host",$self->get_hostname_long eq "localhost" ?
269             $self->get_hostname : $self->get_hostname_long);
270 0 0         $report_body_error{$ident} .= sprintf("%s=%s\n","hosterr",$self->get_syslogd ? "" : "syslogd");
271 0           $report_body_error{$ident} .= sprintf("%s=%s\n","ipaddr",$self->get_ipaddr);
272 0           $report_body_error{$ident} .= sprintf("%s=%s\n","time",$self->get_local_date_time);
273 0           $report_body_error{$ident} .= sprintf("%s=%s\n","script",$arg_ref->{'filename'});
274 0           $report_body_error{$ident} .= sprintf("%s=%s\n","path", $self->get_path);
275 0           $report_body_error{$ident} .= sprintf("%s=%s\n","line",$self->get_line);
276 0           $report_body_error{$ident} .= sprintf("%s=%s\n","pid",$self->get_pid);
277 0           $report_body_error{$ident} .= sprintf("%s=%s\n","severity",$self->get_severity);
278 0           $report_body_error{$ident} .= sprintf("%s=%s\n","context",$self->get_context);
279 0           $report_body_error{$ident} .= sprintf("%s=%s\n","args",$self->get_args);
280 0           $report_body_error{$ident} .= sprintf("%s=%s\n","id",$self->get_id);
281 0           $report_body_error{$ident} .= sprintf("%s=%s\n\n","error",$self->get_text);
282 0           $report_body_error{$ident} .= sprintf("%s\n",$self->get_stacktrace);
283             } else {
284 0 0         $report_body_success{$ident} .= sprintf("%s=%s\n","host",$self->get_hostname_long eq "localhost" ?
    0          
285             $self->get_hostname : $self->get_hostname_long)
286             . sprintf("%s=%s\n","hosterr",$self->get_syslogd ? "" : "syslogd")
287             . sprintf("%s=%s\n","ipaddr",$self->get_ipaddr)
288             . sprintf("%s=%s\n","time",$self->get_local_date_time)
289             . sprintf("%s=%s\n","script",$arg_ref->{'filename'})
290             . sprintf("%s=%s\n","pid",$self->get_pid);
291             }
292              
293 0           $default_state_code_error{$ident} = "E";
294 0           $default_state_code_success{$ident} = "I";
295 0           $state_code_error{$ident} =
296             $luka_conf->get_conf('global','single_char_error_code');
297 0           $state_code_success{$ident} =
298             $luka_conf->get_conf('global','single_char_success_code');
299              
300 0           $debug{$ident} = $luka_conf->get_conf('global','debug');
301 0           $nomail{$ident} = $luka_conf->get_conf($arg_ref->{'filename'},'nomail');
302 0           $script_about{$ident} = $luka_conf->get_conf($arg_ref->{'filename'},'about');
303 0           $syslogopt{$ident} = $luka_conf->get_conf('global','syslogopt');
304 0           $syslogfacility{$ident} = $luka_conf->get_conf('global','syslogfacility');
305              
306             # what are the underlining Error class and text
307 0 0 0       if ($debug{$ident} eq 1 && defined $arg_ref->{'error'} and defined($syslogd{$ident})) {
      0        
308 0           openlog( $filename{$ident}, $syslogopt{$ident}, $syslogfacility{$ident});
309 0           syslog('warning', "[$LukaDebug][class] %s", ref($arg_ref->{'error'}));
310 0           syslog('warning', "[$LukaDebug][text] %s", $self->get_text);
311 0           syslog('warning', "[$LukaDebug][context] %s", $self->get_context);
312 0           syslog('warning', "[$LukaDebug][args] %s", $self->get_args);
313 0           syslog('warning', "[$LukaDebug][id] %s", $self->get_id);
314 0           syslog('warning', "[$LukaDebug][hostname] %s", $self->get_hostname);
315 0           syslog('warning', "[$LukaDebug][ipaddres] %s", $self->get_ipaddr);
316 0           syslog('warning', "[$LukaDebug][hostname_long] %s", $self->get_hostname_long);
317             }
318            
319             } # BUILD
320              
321             #======================
322             # PUBLIC interface
323             #======================
324             sub report_error {
325 0     0 0   my ($self,$message) = @_;
326 0           $self->report("error",$message);
327             }
328              
329             sub report_success {
330 0     0 1   my ($self,$message) = @_;
331 0           $self->report("success",$message);
332             }
333             #========================
334             # PUBLIC interface ENDS
335             #========================
336              
337             sub report : PRIVATE {
338 0           my ($self,$mode,$message) = @_;
339              
340 0 0         openlog( $self->get_filename, $self->get_syslogopt, $self->get_syslogfacility )
341             if $self->get_syslogd;
342              
343 0 0         if ($mode eq "error" ) { # error mode
344              
345 0 0         syslog('warning', "Error at line %s: %s", $self->get_line, $self->get_text)
346             if $self->get_syslogd;
347              
348             } else { # success mode
349              
350 0 0         if ($message) {
351 0           $self->set_text($message);
352             } else {
353 0           $self->set_text($self->get_send_subj_success);
354             }
355              
356             }
357              
358 0 0         if (not $self->get_nomail) {
359              
360 0   0       my $mess = Luka::Mailer->new
361             ( to => $self->get_send_to,
362             cc => $self->get_send_cc,
363             subject => sprintf("[%s][%s][%s] %s",
364             $self->get_hostname,
365             $self->get_local_date_time,
366             $self->get("state_code",$mode) ||
367             $self->get("default_state_code",$mode),
368             $self->get_text),
369             from => $self->get_send_from,
370             body => $self->get_script_about . "\n\n" .
371             $self->get_doc_base . "\n\n" .
372             $self->get("report_body",$mode) . "\n\n",
373             );
374            
375 0 0         if (not $mess->send("Report emailed to recepients.\n")) {
376              
377 0 0         if ($self->get_syslogd) {
378              
379 0           syslog('warning', "Couldn't report by email: to: %s, cc: %s, from: %s",
380             $self->get_send_to, $self->get_send_cc, $self->get_send_from);
381 0           syslog('warning', "Mail system reported: %s", $mess->error);
382              
383             }
384              
385 0           warn( "Couldn't report by email to:" . $self->get_send_to . ";cc:" .
386             $self->get_send_cc . ";from:" . $self->get_send_from . "\n");
387             } else {
388              
389 0 0         syslog( 'info', ucfirst($mode) . " report sent to " .
390             $self->get_send_to . "," . $self->get_send_cc )
391             if $self->get_syslogd;
392              
393             }
394              
395             } # if nomail
396            
397 0 0         closelog() if $self->get_syslogd;
398            
399 2     2   6840 } # sub _report
  2         5  
  2         17  
400              
401             }
402              
403             1;
404              
405             __END__