1 package logHandling;
4 use strict;
5 use warnings;
7 use Exporter;
8 use GOSA::GosaSupportDaemon;
9 use Data::Dumper;
10 use File::Spec;
11 use MIME::Base64;
13 our @ISA = qw(Exporter);
15 my @events = (
16 "get_events",
17 "show_log_by_mac",
18 "show_log_by_date",
19 "show_log_by_date_and_mac",
20 "show_log_files_by_date_and_mac",
21 "get_log_file_by_date_and_mac",
22 "get_recent_log_by_mac",
23 "delete_log_by_date_and_mac",
24 );
26 our @EXPORT = @events;
28 BEGIN {}
30 END {}
32 ### Start ######################################################################
35 #=== FUNCTION ================================================================
36 # NAME: get_events
37 # PARAMETERS: none
38 # RETURNS: reference of exported events
39 # DESCRIPTION: tells the caller which functions are available
40 #===============================================================================
41 sub get_events {
42 return \@events
43 }
46 #=== FUNCTION ================================================================
47 # NAME: show_log_by_date
48 # DESCRIPTION: reporting installed hosts matching to regex of date
49 # PARAMETERS: [$msg] original incoming message
50 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
51 # [$session_id] POE session id
52 # RETURNS: gosa-si valid answer string
53 #===============================================================================
54 sub show_log_by_date {
55 my ($msg, $msg_hash, $session_id) = @_;
56 my $header = @{$msg_hash->{header}}[0];
57 my $target = @{$msg_hash->{target}}[0];
58 my $source = @{$msg_hash->{source}}[0];
59 my $date_l = $msg_hash->{date};
60 my $out_msg;
61 $header =~ s/gosa_//;
63 if (not -d $main::client_fai_log_dir) {
64 my $error_string = "client fai log directory '$main::client_fai_log_dir' do not exist";
65 &main::daemon_log("$session_id ERROR: $error_string", 1);
66 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
67 }
69 # build out_msg
70 my $out_hash = &create_xml_hash($header, $target, $source);
72 # read mac directory
73 opendir(DIR, $main::client_fai_log_dir);
74 my @avail_macs = readdir(DIR);
75 closedir(DIR);
76 foreach my $avail_mac (@avail_macs) {
77 # check mac address
78 if ($avail_mac eq ".." || $avail_mac eq ".") { next; }
80 # read install dates directory
81 my $mac_dir = File::Spec->catdir($main::client_fai_log_dir, $avail_mac);
82 opendir(DIR, $mac_dir);
83 my @avail_dates = readdir(DIR);
84 closedir(DIR);
85 foreach my $date ( @{$date_l} ) { # multiple date selection is allowed
86 foreach my $avail_date (@avail_dates) {
87 # check install date
88 if ($avail_date eq ".." || $avail_date eq ".") { next; }
89 if (not $avail_date =~ /$date/i) { next; }
91 # add content to out_msg
92 &add_content2xml_hash($out_hash, $avail_date, $avail_mac);
93 }
94 }
95 }
97 $out_msg = &create_xml_string($out_hash);
98 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
99 if (defined $forward_to_gosa) {
100 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
101 }
103 return ($out_msg);
104 }
107 #=== FUNCTION ================================================================
108 # NAME: show_log_by_mac
109 # DESCRIPTION: reporting installation dates matching to regex of mac address
110 # PARAMETERS: [$msg] original incoming message
111 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
112 # [$session_id] POE session id
113 # RETURNS: gosa-si valid answer string
114 #===============================================================================
115 sub show_log_by_mac {
116 my ($msg, $msg_hash, $session_id) = @_;
117 my $header = @{$msg_hash->{header}}[0];
118 my $target = @{$msg_hash->{target}}[0];
119 my $source = @{$msg_hash->{source}}[0];
120 my $mac_l = $msg_hash->{mac};
122 $header =~ s/gosa_//;
124 if (not -d $main::client_fai_log_dir) {
125 my $error_string = "client fai log directory '$main::client_fai_log_dir' do not exist";
126 &main::daemon_log("$session_id ERROR: $error_string", 1);
127 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
128 }
130 # build out_msg
131 my $out_hash = &create_xml_hash($header, $target, $source);
133 # read mac directory
134 opendir(DIR, $main::client_fai_log_dir);
135 my @avail_macs = readdir(DIR);
136 closedir(DIR);
137 foreach my $mac (@{$mac_l}) { # multiple mac selection is allowed
138 foreach my $avail_mac ( @avail_macs ) {
139 # check mac address
140 if ($avail_mac eq ".." || $avail_mac eq ".") { next; }
141 if (not $avail_mac =~ /$mac/i) { next; }
143 # read install dates directory
144 my $act_log_dir = File::Spec->catdir($main::client_fai_log_dir, $avail_mac);
145 if (not -d $act_log_dir) { next; }
146 opendir(DIR, $act_log_dir);
147 my @avail_dates = readdir(DIR);
148 closedir(DIR);
149 $avail_mac =~ s/:/_/g; # make mac address XML::Simple valid
150 foreach my $avail_date (@avail_dates) {
151 # check install date
152 if ($avail_date eq ".." || $avail_date eq ".") { next; }
154 # add content to out_msg
155 &add_content2xml_hash($out_hash, "mac_$avail_mac", $avail_date);
156 }
157 }
158 }
160 my $out_msg = &create_xml_string($out_hash);
161 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
162 if (defined $forward_to_gosa) {
163 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
164 }
166 return ($out_msg);
167 }
170 #=== FUNCTION ================================================================
171 # NAME: show_log_by_date_and_mac
172 # DESCRIPTION: reporting host and installation dates matching to regex of date and regex of mac address
173 # PARAMETERS: [$msg] original incoming message
174 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
175 # [$session_id] POE session id
176 # RETURNS: gosa-si valid answer string
177 #===============================================================================
178 sub show_log_by_date_and_mac {
179 my ($msg, $msg_hash, $session_id) = @_ ;
180 my $header = @{$msg_hash->{header}}[0];
181 my $target = @{$msg_hash->{target}}[0];
182 my $source = @{$msg_hash->{source}}[0];
183 my $date = @{$msg_hash->{date}}[0];
184 my $mac = @{$msg_hash->{mac}}[0];
185 $header =~ s/gosa_//;
187 if (not -d $main::client_fai_log_dir) {
188 my $error_string = "client fai log directory '$main::client_fai_log_dir' do not exist";
189 &main::daemon_log("$session_id ERROR: $error_string", 1);
190 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
191 }
193 # build out_msg
194 my $out_hash = &create_xml_hash($header, $target, $source);
196 # read mac directory
197 opendir(DIR, $main::client_fai_log_dir);
198 my @avail_macs = readdir(DIR);
199 closedir(DIR);
200 foreach my $avail_mac ( @avail_macs ) {
201 # check mac address
202 if ($avail_mac eq ".." || $avail_mac eq ".") { next; }
203 if (not $avail_mac =~ /$mac/i) { next; }
204 my $act_log_dir = File::Spec->catdir($main::client_fai_log_dir, $avail_mac);
206 # read install date directory
207 opendir(DIR, $act_log_dir);
208 my @install_dates = readdir(DIR);
209 closedir(DIR);
210 foreach my $avail_date (@install_dates) {
211 # check install date
212 if ($avail_date eq ".." || $avail_date eq ".") { next; }
213 if (not $avail_date =~ /$date/i) { next; }
215 # add content to out_msg
216 &add_content2xml_hash($out_hash, $avail_date, $avail_mac);
217 }
218 }
220 my $out_msg = &create_xml_string($out_hash);
221 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
222 if (defined $forward_to_gosa) {
223 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
224 }
226 return $out_msg;
227 }
230 #=== FUNCTION ================================================================
231 # NAME: show_log_files_by_date_and_mac
232 # DESCRIPTION: reporting installation log files matching exatly to date and mac address
233 # PARAMETERS: [$msg] original incoming message
234 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
235 # [$session_id] POE session id
236 # RETURNS: gosa-si valid answer string
237 #===============================================================================
238 sub show_log_files_by_date_and_mac {
239 my ($msg, $msg_hash, $session_id) = @_ ;
240 my $header = @{$msg_hash->{header}}[0];
241 my $target = @{$msg_hash->{target}}[0];
242 my $source = @{$msg_hash->{source}}[0];
243 my $date = @{$msg_hash->{date}}[0];
244 my $mac = @{$msg_hash->{mac}}[0];
245 $header =~ s/gosa_//;
247 my $act_log_dir = File::Spec->catdir($main::client_fai_log_dir, $mac, $date);
248 if (not -d $act_log_dir) {
249 my $error_string = "client fai log directory '$act_log_dir' do not exist";
250 &main::daemon_log("$session_id ERROR: $error_string", 1);
251 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
252 }
254 # build out_msg
255 my $out_hash = &create_xml_hash($header, $target, $source);
257 # read mac / install date directory
258 opendir(DIR, $act_log_dir);
259 my @log_files = readdir(DIR);
260 closedir(DIR);
262 foreach my $log_file (@log_files) {
263 if ($log_file eq ".." || $log_file eq ".") { next; }
265 # add content to out_msg
266 &add_content2xml_hash($out_hash, $header, $log_file);
267 }
269 my $out_msg = &create_xml_string($out_hash);
270 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
271 if (defined $forward_to_gosa) {
272 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
273 }
275 return $out_msg;
276 }
279 #=== FUNCTION ================================================================
280 # NAME: get_log_file_by_date_and_mac
281 # DESCRIPTION: returning the given log file, base64 coded, matching exactly to date and mac address
282 # PARAMETERS: [$msg] original incoming message
283 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
284 # [$session_id] POE session id
285 # RETURNS: gosa-si valid answer string
286 #===============================================================================
287 sub get_log_file_by_date_and_mac {
288 my ($msg, $msg_hash, $session_id) = @_ ;
289 my $header = @{$msg_hash->{header}}[0];
290 my $target = @{$msg_hash->{target}}[0];
291 my $source = @{$msg_hash->{source}}[0];
292 my $date = @{$msg_hash->{date}}[0];
293 my $mac = @{$msg_hash->{mac}}[0];
294 my $log_file = @{$msg_hash->{log_file}}[0];
295 $header =~ s/gosa_//;
297 # sanity check
298 my $act_log_file = File::Spec->catfile($main::client_fai_log_dir, $mac, $date, $log_file);
299 if (not -f $act_log_file) {
300 my $error_string = "client fai log file '$act_log_file' do not exist or could not be read";
301 &main::daemon_log("$session_id ERROR: $error_string", 1);
302 &main::daemon_log("$session_id ERROR: mac='$mac', date='$date', log_file='$log_file'", 1);
303 &main::daemon_log("$session_id ERROR: could not process message: $msg", 1);
304 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
305 }
307 # read log file
308 my $log_content;
309 open(my $FILE, "<", "$act_log_file");
310 my @log_lines = <$FILE>;
311 close($FILE);
313 # prepare content for xml sending
314 $log_content = join("", @log_lines);
315 $log_content = &encode_base64($log_content);
317 # build out_msg and send
318 my $out_hash = &create_xml_hash($header, $target, $source);
319 &add_content2xml_hash($out_hash, $log_file, $log_content);
320 my $out_msg = &create_xml_string($out_hash);
321 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
322 if (defined $forward_to_gosa) {
323 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
324 }
326 return $out_msg;
327 }
330 # sorting function for fai log directory names
331 # used by get_recent_log_by_mac
332 sub transform {
333 my $a = shift;
334 $a =~ /_(\d{8}?)_(\d{6}?)$/ || return 0;
335 return int("$1$2");
336 }
337 sub by_log_date {
338 &transform($a) <=> &transform($b);
339 }
340 #=== FUNCTION ================================================================
341 # NAME: get_recent_log_by_mac
342 # DESCRIPTION: reporting the latest installation date matching to regex of mac address
343 # PARAMETERS: [$msg] original incoming message
344 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
345 # [$session_id] POE session id
346 # RETURNS: gosa-si valid answer string
347 #===============================================================================
348 sub get_recent_log_by_mac {
349 my ($msg, $msg_hash, $session_id) = @_ ;
350 my $header = @{$msg_hash->{header}}[0];
351 my $target = @{$msg_hash->{target}}[0];
352 my $source = @{$msg_hash->{source}}[0];
353 my $mac = @{$msg_hash->{mac}}[0];
354 $header =~ s/gosa_//;
356 # sanity check
357 if (not -d $main::client_fai_log_dir) {
358 my $error_string = "client fai log directory '$main::client_fai_log_dir' do not exist";
359 &main::daemon_log("$session_id ERROR: $error_string", 1);
360 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
361 }
363 opendir (DIR, $main::client_fai_log_dir);
364 my @avail_macs = readdir(DIR);
365 closedir(DIR);
366 my $act_log_dir;
367 my $act_mac;
368 foreach my $avail_mac (@avail_macs) {
369 if ($avail_mac eq ".." || $avail_mac eq ".") { next; }
370 if (not $avail_mac =~ /$mac/i) { next; }
371 $act_log_dir = File::Spec->catdir($main::client_fai_log_dir, $avail_mac);
372 $act_mac = $avail_mac;
373 }
374 if (not defined $act_log_dir) {
375 my $error_string = "do not find mac '$mac' in directory '$main::client_fai_log_dir'";
376 &main::daemon_log("$session_id ERROR: $error_string", 1);
377 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
378 }
380 # read mac directory
381 opendir(DIR, $act_log_dir);
382 my @avail_dates = readdir(DIR);
383 closedir(DIR);
385 # search for the latest log
386 my @sorted_dates = sort by_log_date @avail_dates;
387 my $latest_log = pop(@sorted_dates);
389 # build out_msg
390 my $out_hash = &create_xml_hash($header, $target, $source);
392 # read latest log directory
393 my $latest_log_dir = File::Spec->catdir($main::client_fai_log_dir, $act_mac, $latest_log);
394 opendir(DIR, $latest_log_dir);
395 my @log_files = readdir(DIR);
396 closedir(DIR);
398 # add all log_files to out_msg
399 foreach my $log_file (@log_files) {
400 if ($log_file eq ".." || $log_file eq ".") { next; }
401 &add_content2xml_hash($out_hash, $latest_log, $log_file);
402 }
404 my $out_msg = &create_xml_string($out_hash);
405 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
406 if (defined $forward_to_gosa) {
407 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
408 }
410 return $out_msg;
411 }
414 #=== FUNCTION ================================================================
415 # NAME: delete_log_by_date_and_mac
416 # DESCRIPTION: delete installation date directory matching to regex of date and regex of mac address
417 # missing date or mac is substitutet with regex '.'; if both is missing, deleting is rejected
418 # PARAMETERS: [$msg] original incoming message
419 # [$msg_hash] incoming message transformed to hash concerning XML::Simple
420 # [$session_id] POE session id
421 # RETURNS: gosa-si valid answer string
422 #===============================================================================
423 sub delete_log_by_date_and_mac {
424 my ($msg, $msg_hash, $session_id) = @_ ;
425 my $header = @{$msg_hash->{header}}[0];
426 my $target = @{$msg_hash->{target}}[0];
427 my $source = @{$msg_hash->{source}}[0];
428 my $date = @{$msg_hash->{date}}[0];
429 my $mac = @{$msg_hash->{mac}}[0];
430 $header =~ s/gosa_//;
432 # sanity check
433 if (not -d $main::client_fai_log_dir) {
434 my $error_string = "client fai log directory '$main::client_fai_log_dir' do not exist";
435 &main::daemon_log("$session_id ERROR: $session_id", 1);
436 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
437 }
438 if ((not defined $date) && (not defined $mac)) {
439 my $error_string = "deleting all log files from gosa-si-server by an empty delete message is not permitted";
440 &main::daemon_log("$session_id INFO: $error_string", 5);
441 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
442 }
443 if (not defined $date) { $date = "."; } # set date to a regular expression matching to everything
444 if (not defined $mac) { $mac = "."; } # set mac to a regular expression matching to everything
446 # build out_msg
447 my $out_hash = &create_xml_hash($header, $target, $source);
449 # read mac directory
450 opendir(DIR, $main::client_fai_log_dir);
451 my @avail_macs = readdir(DIR);
452 closedir(DIR);
453 foreach my $avail_mac ( @avail_macs ) {
454 # check mac address
455 if ($avail_mac eq ".." || $avail_mac eq ".") { next; }
456 if (not $avail_mac =~ /$mac/i) { next; }
457 my $act_log_dir = File::Spec->catdir($main::client_fai_log_dir, $avail_mac);
459 # read install date directory
460 opendir(DIR, $act_log_dir);
461 my @install_dates = readdir(DIR);
462 closedir(DIR);
463 foreach my $avail_date (@install_dates) {
464 # check install date
465 if ($avail_date eq ".." || $avail_date eq ".") { next; }
466 if (not $avail_date =~ /$date/i) { next; }
468 # delete directory and reptorting
469 my $dir_to_delete = File::Spec->catdir($main::client_fai_log_dir, $avail_mac, $avail_date);
470 #my $error = rmdir($dir_to_delete);
471 my $error = 0;
472 if ($error == 1) {
473 &main::daemon_log("$session_id ERROR: log directory '$dir_to_delete' cannot be deleted: $!", 1);
474 } else {
475 &main::daemon_log("$session_id INFO: log directory '$dir_to_delete' deleted", 5);
476 &add_content2xml_hash($out_hash, $avail_date, $avail_mac);
477 }
478 }
479 }
481 my $out_msg = &create_xml_string($out_hash);
482 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
483 if (defined $forward_to_gosa) {
484 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
485 }
487 return $out_msg;
488 }
490 1;