Code

bugfix: clMessages.pm: handle an empty content of HOOK msgs
[gosa.git] / gosa-si / server / events / clMessages.pm
1 package clMessages;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5     "confirm_usr_msg",
6     "PROGRESS",
7     "FAIREBOOT",
8     "TASKSKIP",
9     "TASKBEGIN",
10     "TASKEND",
11     "TASKERROR",
12     "HOOK",
13     "GOTOACTIVATION",
14     "LOGIN",
15     "LOGOUT",
16     "CURRENTLY_LOGGED_IN",
17     "save_fai_log",
18     );
19 @EXPORT = @events;
21 use strict;
22 use warnings;
23 use Data::Dumper;
24 use GOSA::GosaSupportDaemon;
25 use MIME::Base64;
28 BEGIN {}
30 END {}
32 ### Start ######################################################################
34 my $ldap_uri;
35 my $ldap_base;
36 my $ldap_admin_dn;
37 my $ldap_admin_password;
39 my %cfg_defaults = (
40 "server" => {
41    "ldap-uri" => [\$ldap_uri, ""],
42    "ldap-base" => [\$ldap_base, ""],
43    "ldap-admin-dn" => [\$ldap_admin_dn, ""],
44    "ldap-admin-password" => [\$ldap_admin_password, ""],
45    },
46 );
47 &read_configfile($main::cfg_file, %cfg_defaults);
50 sub get_events {
51     return \@events;
52 }
55 sub confirm_usr_msg {
56     my ($msg, $msg_hash, $session_id) = @_;
57     my $message = @{$msg_hash->{'message'}}[0];
58     my $subject = @{$msg_hash->{'subject'}}[0];
59     my $usr = @{$msg_hash->{'usr'}}[0];
61     # set update for this message
62     my $sql = "UPDATE $main::messaging_tn SET flag='s' WHERE (message='$message' AND subject='$subject' AND message_to='$usr')"; 
63     &main::daemon_log("$session_id DEBUG: $sql", 7);
64     my $res = $main::messaging_db->exec_statement($sql); 
67     return;
68 }
72 sub read_configfile {
73     my ($cfg_file, %cfg_defaults) = @_;
74     my $cfg;
76     if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
77         if( -r $cfg_file ) {
78             $cfg = Config::IniFiles->new( -file => $cfg_file );
79         } else {
80             &main::daemon_log("ERROR: clMessages.pm couldn't read config file!", 1);
81         }
82     } else {
83         $cfg = Config::IniFiles->new() ;
84     }
85     foreach my $section (keys %cfg_defaults) {
86         foreach my $param (keys %{$cfg_defaults{ $section }}) {
87             my $pinfo = $cfg_defaults{ $section }{ $param };
88             ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
89         }
90     }
91 }
94 sub save_fai_log {
95     my ($msg, $msg_hash, $session_id) = @_;
96     my $header = @{$msg_hash->{'header'}}[0];
97     my $source = @{$msg_hash->{'source'}}[0];
98     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
99     my $all_logs = @{$msg_hash->{$header}}[0];
101     # if there is nothing to log
102     if( ref($all_logs) eq "HASH" ) { return; }
103         
104     my $client_fai_log_dir = $main::client_fai_log_dir;
105     if (not -d $client_fai_log_dir) {
106         mkdir($client_fai_log_dir, 0755)
107     }
109     $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $macaddress );
110     if (not -d $client_fai_log_dir) {
111         mkdir($client_fai_log_dir, 0755)
112     }
114     my $time = &get_time;
115     $time = substr($time, 0, 8)."_".substr($time, 8, 6);
116     $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, "install_$time" );
117     mkdir($client_fai_log_dir, 0755);
119     my @all_logs = split(/log_file:/, $all_logs); 
120     foreach my $log (@all_logs) {
121         if (length $log == 0) { next; };
122         my ($log_file, $log_string) = split(":", $log);
123         my $client_fai_log_file = File::Spec->catfile( $client_fai_log_dir, $log_file);
125         open(my $LOG_FILE, ">$client_fai_log_file"); 
126         print $LOG_FILE &decode_base64($log_string);
127         close($LOG_FILE);
129     }
130     return;
134 sub LOGIN {
135     my ($msg, $msg_hash, $session_id) = @_;
136     my $header = @{$msg_hash->{'header'}}[0];
137     my $source = @{$msg_hash->{'source'}}[0];
138     my $login = @{$msg_hash->{$header}}[0];
140     my %add_hash = ( table=>$main::login_users_tn, 
141         primkey=> ['client', 'user'],
142         client=>$source,
143         user=>$login,
144         timestamp=>&get_time,
145         ); 
146     my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
147     if ($res != 0)  {
148         &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
149         return;
150     }
152     return;   
156 sub LOGOUT {
157     my ($msg, $msg_hash, $session_id) = @_;
158     my $header = @{$msg_hash->{'header'}}[0];
159     my $source = @{$msg_hash->{'source'}}[0];
160     my $login = @{$msg_hash->{$header}}[0];
161     
162     my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')"; 
163     my $res =  $main::login_users_db->del_dbentry($sql_statement);
164     &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5); 
165     
166     return;
170 sub CURRENTLY_LOGGED_IN {
171     my ($msg, $msg_hash, $session_id) = @_;
172     my ($sql_statement, $db_res);
173     my $header = @{$msg_hash->{'header'}}[0];
174     my $source = @{$msg_hash->{'source'}}[0];
175     my $login = @{$msg_hash->{$header}}[0];
177     if(ref $login eq "HASH") { 
178         &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5); 
179         return;     
180     }
181     
182     # fetch all user currently assigned to the client at login_users_db
183     my %currently_logged_in_user = (); 
184     $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'"; 
185     $db_res = $main::login_users_db->select_dbentry($sql_statement);
186     while( my($hit_id, $hit) = each(%{$db_res}) ) {
187         $currently_logged_in_user{$hit->{'user'}} = 1;
188     }
189     &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7); 
191     # update all reported users in login_user_db
192     my @logged_in_user = split(/\s+/, $login);
193     &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7); 
194     foreach my $user (@logged_in_user) {
195         my %add_hash = ( table=>$main::login_users_tn, 
196                 primkey=> ['client', 'user'],
197                 client=>$source,
198                 user=>$user,
199                 timestamp=>&get_time,
200                 ); 
201         my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
202         if ($res != 0)  {
203             &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
204             return;
205         }
207         delete $currently_logged_in_user{$user};
208     }
210     # if there is still a user in %currently_logged_in_user 
211     # although he is not reported by client 
212     # then delete it from $login_user_db
213     foreach my $obsolete_user (keys(%currently_logged_in_user)) {
214         &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
215                 "in at client '$source' but still found at login_user_db", 3); 
216         my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'"; 
217         my $res =  $main::login_users_db->del_dbentry($sql_statement);
218         &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3); 
219     }
221     return;
225 sub GOTOACTIVATION {
226     my ($msg, $msg_hash, $session_id) = @_;
227     my $header = @{$msg_hash->{'header'}}[0];
228     my $source = @{$msg_hash->{'target'}}[0];
229     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
231     # test whether content is an empty hash or a string which is required
232     my $content = @{$msg_hash->{$header}}[0];
233     if(ref($content) eq "HASH") { $content = ""; }
235     # clean up header
236     $header =~ s/CLMSG_//g;
238     my $sql_statement = "UPDATE $main::job_queue_tn ".
239             "SET status='processing', progress='goto-activation' ".
240             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
241     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
242     my $res = $main::job_db->update_dbentry($sql_statement);
243     &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5); 
244     return; 
248 sub PROGRESS {
249     my ($msg, $msg_hash, $session_id) = @_;
250     my $header = @{$msg_hash->{'header'}}[0];
251     my $source = @{$msg_hash->{'target'}}[0];
252     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
254     # test whether content is an empty hash or a string which is required
255     my $content = @{$msg_hash->{$header}}[0];
256     if(ref($content) eq "HASH") { $content = ""; }
258     # clean up header
259     $header =~ s/CLMSG_//g;
261     my $sql_statement = "UPDATE $main::job_queue_tn ".
262         "SET progress='$content' ".
263         "WHERE status='processing' AND macaddress LIKE '$macaddress'";
264     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
265     my $res = $main::job_db->update_dbentry($sql_statement);
266     &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5); 
268     return;
272 sub FAIREBOOT {
273     my ($msg, $msg_hash, $session_id) = @_;
274     my $header = @{$msg_hash->{'header'}}[0];
275     my $source = @{$msg_hash->{'target'}}[0];
276     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
278     # test whether content is an empty hash or a string which is required
279         my $content = @{$msg_hash->{$header}}[0];
280     if(ref($content) eq "HASH") { $content = ""; }
282     # clean up header
283     $header =~ s/CLMSG_//g;
285     my $sql_statement = "UPDATE $main::job_queue_tn ".
286             "SET status='processing', result='$header "."$content' ".
287             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
288     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
289     my $res = $main::job_db->update_dbentry($sql_statement);
290     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
292     return; 
296 sub TASKSKIP {
297     my ($msg, $msg_hash, $session_id) = @_;
298     my $header = @{$msg_hash->{'header'}}[0];
299     my $source = @{$msg_hash->{'target'}}[0];
300     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
302     # test whether content is an empty hash or a string which is required
303         my $content = @{$msg_hash->{$header}}[0];
304     if(ref($content) eq "HASH") { $content = ""; }
306     # clean up header
307     $header =~ s/CLMSG_//g;
309     my $sql_statement = "UPDATE $main::job_queue_tn ".
310             "SET status='processing', result='$header "."$content' ".
311             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
312     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
313     my $res = $main::job_db->update_dbentry($sql_statement);
314     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
316     return; 
320 sub TASKBEGIN {
321     my ($msg, $msg_hash, $session_id) = @_;
322     my $header = @{$msg_hash->{'header'}}[0];
323     my $source = @{$msg_hash->{'target'}}[0];
324     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
326     # test whether content is an empty hash or a string which is required
327         my $content = @{$msg_hash->{$header}}[0];
328     if(ref($content) eq "HASH") { $content = ""; }
330     # clean up header
331     $header =~ s/CLMSG_//g;
333     # TASKBEGIN eq finish or faiend 
334     if (($content eq 'finish') || ($content eq 'faiend')){
335         my $sql_statement = "UPDATE $main::job_queue_tn ".
336             "SET status='done', result='$header "."$content' ".
337             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
338         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
339         my $res = $main::job_db->update_dbentry($sql_statement);
340         &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
341         
342         # set fai_state to localboot
343         &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
345         # TASKBEGIN eq chboot
346         } elsif ($content eq 'chboot') {
347                 # just ignor this client message
348                 # do nothing
350         # other TASKBEGIN msgs
351     } else {
352                 # select processing jobs for host
353                 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
354                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
355                 my $res = $main::job_db->select_dbentry($sql_statement);
357                 # there is exactly one job entry in queue for this host
358                 if (keys(%$res) == 1) {
359                         &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
360                         my $sql_statement = "UPDATE $main::job_queue_tn SET result='$header $content' WHERE status='processing' AND macaddress LIKE '$macaddress'";
361                         my $err = $main::job_db->update_dbentry($sql_statement);
362                         if (not defined  $err) {
363                                 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
364                         }
365                         
366                 # there is no entry or more than one enties
367                 } else {
368                         # in case of more than one running jobs in queue, delete all jobs
369                         if (keys(%$res) > 1) {
370                                 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
371                                                                 "delete entries", 7); 
373                                 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
374                                 my ($err) = $main::job_db->del_dbentry($sql_statement);
375                                 if (not defined $err) {
376                                         &main::daemon_log("$session_id ERROR: can not delete multiple processing queue entries for host '$macaddress': ".Dumper($err), 1); 
377                                 }
378                         }
379                 
380                         # in case of no and more than one running jobs in queue, add one single job
381                         # resolve plain name for host $macaddress
382                         my $plain_name;
383                         my $ldap_handle = &main::get_ldap_handle($session_id);
384                         if( not defined $ldap_handle ) {
385                                 &main::daemon_log("$session_id ERROR: cannot connect to ldap", 1);
386                                 $plain_name = "none";
388                         # try to fetch a 'real name'
389                         } else {
390                                 my $mesg = $ldap_handle->search(
391                                                 base => $main::ldap_base,
392                                                 scope => 'sub',
393                                                 attrs => ['cn'],
394                                                 filter => "(macAddress=$macaddress)");
395                                 if($mesg->code) {
396                                         &main::daemon_log($mesg->error, 1);
397                                         $plain_name = "none";
398                                 } else {
399                                         my $entry= $mesg->entry(0);
400                                         $plain_name = $entry->get_value("cn");
401                                 }
402                         }
405                         &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7); 
406                         my $func_dic = {table=>$main::job_queue_tn,
407                                         primkey=>[],
408                                         timestamp=>&get_time,
409                                         status=>'processing',
410                                         result=>"$header $content",
411                                         progress=>'none',
412                                         headertag=>'trigger_action_reinstall',
413                                         targettag=>$source,
414                                         xmlmessage=>'none',
415                                         macaddress=>$macaddress,
416                                         plainname=>$plain_name,
417                         };
418                         my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
419                         if ($err != 0)  {
420                                         &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
421                         }
423                 }
425 # -----------------------> Update hier
426 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
427 #  <header>CLMSG_TASKBEGIN</header>
428 # macaddress auslesen, Client im LDAP lokalisieren
429 # FAIstate auf "localboot" setzen, wenn FAIstate "install" oder "softupdate" war
430     }
432     return; 
436 sub TASKEND {
437     my ($msg, $msg_hash, $session_id) = @_;
438     my $header = @{$msg_hash->{'header'}}[0];
439     my $source = @{$msg_hash->{'target'}}[0];
440     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
442     # test whether content is an empty hash or a string which is required
443     my $content = @{$msg_hash->{$header}}[0];
444     if(ref($content) eq "HASH") { $content = ""; }
446     # clean up header
447     $header =~ s/CLMSG_//g;
449         if ($content eq "savelog 0") {
450                 &main::daemon_log("$session_id DEBUG: got savelog from host '$source' - jub done", 7);
451                 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
452                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
453                 my $res = $main::job_db->del_dbentry($sql_statement);
455         } else {
457                         my $sql_statement = "UPDATE $main::job_queue_tn ".
458                                         "SET status='processing', result='$header "."$content' ".
459                                         "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
460                         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
461                         my $res = $main::job_db->update_dbentry($sql_statement);
462                         &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
464         }
465 # -----------------------> Update hier
466 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
467 #  <header>CLMSG_TASKBEGIN</header>
468 # macaddress auslesen, Client im LDAP lokalisieren
469 # FAIstate auf "error" setzen
471     return; 
475 sub TASKERROR {
476     my ($msg, $msg_hash, $session_id) = @_;
477     my $header = @{$msg_hash->{'header'}}[0];
478     my $source = @{$msg_hash->{'target'}}[0];
479     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
481     # clean up header
482     $header =~ s/CLMSG_//g;
484     # test whether content is an empty hash or a string which is required
485     my $content = @{$msg_hash->{$header}}[0];
486     if(ref($content) eq "HASH") { $content = ""; } 
488         # set fai_state to localboot
489         &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
490                 
491     my $sql_statement = "UPDATE $main::job_queue_tn ".
492             "SET status='processing', result='$header "."$content' ".
493             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
494     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
495     my $res = $main::job_db->update_dbentry($sql_statement);
496     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
498 # -----------------------> Update hier
499 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
500 #  <header>CLMSG_TASKBEGIN</header>
501 # macaddress auslesen, Client im LDAP lokalisieren
502 # FAIstate auf "error" setzen
504     return; 
508 sub HOOK {
509     my ($msg, $msg_hash, $session_id) = @_;
510     my $header = @{$msg_hash->{'header'}}[0];
511     my $source = @{$msg_hash->{'target'}}[0];
512     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
514     # clean up header
515     $header =~ s/CLMSG_//g;
517     # test whether content is an empty hash or a string which is required
518         my $content = @{$msg_hash->{$header}}[0];
519     if(not ref($content) eq "STRING") { $content = ""; }
521     my $sql_statement = "UPDATE $main::job_queue_tn ".
522             "SET status='processing', result='$header "."$content' ".
523             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
524     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
525     my $res = $main::job_db->update_dbentry($sql_statement);
526     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
528     return;
532 1;