Code

progress display of jobs in job_queue from foreign si-server too
[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->{'source'}}[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', modified='1' ".
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->{'source'}}[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', modified='1' ".
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->{'source'}}[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', modified='1' ".
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->{'source'}}[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', modified='1' ".
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->{'source'}}[0];
324     my $target = @{$msg_hash->{'target'}}[0];
325     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
327     # test whether content is an empty hash or a string which is required
328         my $content = @{$msg_hash->{$header}}[0];
329     if(ref($content) eq "HASH") { $content = ""; }
331     # clean up header
332     $header =~ s/CLMSG_//g;
334     # TASKBEGIN eq finish or faiend 
335     if (($content eq 'finish') 
336                         || ($content eq 'faiend')
337                         || ($content eq 'savelog')
338                         ) {
339         my $sql_statement = "UPDATE $main::job_queue_tn ".
340             "SET status='done', result='$header "."$content', modified='1' ".
341             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
342         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
343         my $res = $main::job_db->update_dbentry($sql_statement);
344         &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
345         
346         # set fai_state to localboot
347         &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
349         # TASKBEGIN eq chboot
350         } elsif (($content eq 'chboot')
351                 || ($content eq 'test')
352                 || ($content eq 'confdir')
353                 ) {
354                 # just ignor this client message
355                 # do nothing
357         # other TASKBEGIN msgs
358     } else {
359                 # select processing jobs for host
360                 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
361                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
362                 my $res = $main::job_db->select_dbentry($sql_statement);
364                 # there is exactly one job entry in queue for this host
365                 if (keys(%$res) == 1) {
366                         &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
367                         my $sql_statement = "UPDATE $main::job_queue_tn ".
368                 "SET result='$header $content', modified='1' ".
369                 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
370                         my $err = $main::job_db->update_dbentry($sql_statement);
371                         if (not defined  $err) {
372                                 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
373                         }
374                         
375                 # there is no entry or more than one enties
376                 } else {
377                         # in case of more than one running jobs in queue, delete all jobs
378                         if (keys(%$res) > 1) {
379                                 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
380                                                                 "delete entries", 7); 
382                                 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
383                                 my ($err) = $main::job_db->del_dbentry($sql_statement);
384                                 if (not defined $err) {
385                                         &main::daemon_log("$session_id ERROR: can not delete multiple processing queue entries for host '$macaddress': ".Dumper($err), 1); 
386                                 }
387                         }
388                 
389                         # in case of no and more than one running jobs in queue, add one single job
390                         # resolve plain name for host $macaddress
391                         my $plain_name;
392                         my $ldap_handle = &main::get_ldap_handle($session_id);
393                         if( not defined $ldap_handle ) {
394                                 &main::daemon_log("$session_id ERROR: cannot connect to ldap", 1);
395                                 $plain_name = "none";
397                         # try to fetch a 'real name'
398                         } else {
399                                 my $mesg = $ldap_handle->search(
400                                                 base => $main::ldap_base,
401                                                 scope => 'sub',
402                                                 attrs => ['cn'],
403                                                 filter => "(macAddress=$macaddress)");
404                                 if($mesg->code) {
405                                         &main::daemon_log($mesg->error, 1);
406                                         $plain_name = "none";
407                                 } else {
408                                         my $entry= $mesg->entry(0);
409                                         $plain_name = $entry->get_value("cn");
410                                 }
411                         }
414                         &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7); 
415                         my $func_dic = {table=>$main::job_queue_tn,
416                                         primkey=>['macaddress', 'headertag'],
417                                         timestamp=>&get_time,
418                                         status=>'processing',
419                                         result=>"$header $content",
420                                         progress=>'none',
421                                         headertag=>'trigger_action_reinstall',
422                                         targettag=>$target,
423                                         xmlmessage=>'none',
424                                         macaddress=>$macaddress,
425                                         plainname=>$plain_name,
426                     modified=>'1',
427                     siserver=>$source,
428                         };
429                         my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
430                         if ($err != 0)  {
431                                         &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
432                         }
434                 }
436 # -----------------------> Update hier
437 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
438 #  <header>CLMSG_TASKBEGIN</header>
439 # macaddress auslesen, Client im LDAP lokalisieren
440 # FAIstate auf "localboot" setzen, wenn FAIstate "install" oder "softupdate" war
441     }
443     return; 
447 sub TASKEND {
448     my ($msg, $msg_hash, $session_id) = @_;
449     my $header = @{$msg_hash->{'header'}}[0];
450     my $target = @{$msg_hash->{'target'}}[0];
451     my $source = @{$msg_hash->{'source'}}[0];
452     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
454     # test whether content is an empty hash or a string which is required
455     my $content = @{$msg_hash->{$header}}[0];
456     if(ref($content) eq "HASH") { $content = ""; }
458     # clean up header
459     $header =~ s/CLMSG_//g;
461         if ($content eq "savelog 0") {
462                 &main::daemon_log("$session_id DEBUG: got savelog from host '$target' - job done", 7);
463                 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
464                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
465                 my $res = $main::job_db->del_dbentry($sql_statement);
467         } else {
469                         my $sql_statement = "UPDATE $main::job_queue_tn ".
470                                         "SET status='processing', result='$header "."$content', modified='1' ".
471                                         "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
472                         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
473                         my $res = $main::job_db->update_dbentry($sql_statement);
474                         &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
476         }
477 # -----------------------> Update hier
478 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
479 #  <header>CLMSG_TASKBEGIN</header>
480 # macaddress auslesen, Client im LDAP lokalisieren
481 # FAIstate auf "error" setzen
483     return; 
487 sub TASKERROR {
488     my ($msg, $msg_hash, $session_id) = @_;
489     my $header = @{$msg_hash->{'header'}}[0];
490     my $source = @{$msg_hash->{'source'}}[0];
491     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
493     # clean up header
494     $header =~ s/CLMSG_//g;
496     # test whether content is an empty hash or a string which is required
497     my $content = @{$msg_hash->{$header}}[0];
498     if(ref($content) eq "HASH") { $content = ""; } 
500         # set fai_state to localboot
501         &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
502                 
503     my $sql_statement = "UPDATE $main::job_queue_tn ".
504             "SET status='processing', result='$header "."$content', modified='1' ".
505             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
506     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
507     my $res = $main::job_db->update_dbentry($sql_statement);
508     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
510 # -----------------------> Update hier
511 #  <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
512 #  <header>CLMSG_TASKBEGIN</header>
513 # macaddress auslesen, Client im LDAP lokalisieren
514 # FAIstate auf "error" setzen
516     return; 
520 sub HOOK {
521     my ($msg, $msg_hash, $session_id) = @_;
522     my $header = @{$msg_hash->{'header'}}[0];
523     my $source = @{$msg_hash->{'source'}}[0];
524     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
526     # clean up header
527     $header =~ s/CLMSG_//g;
529     # test whether content is an empty hash or a string which is required
530         my $content = @{$msg_hash->{$header}}[0];
531     if(not ref($content) eq "STRING") { $content = ""; }
533     my $sql_statement = "UPDATE $main::job_queue_tn ".
534             "SET status='processing', result='$header "."$content', modified='1' ".
535             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
536     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
537     my $res = $main::job_db->update_dbentry($sql_statement);
538     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
540     return;
544 1;