Code

- Corrected open perl function, corrected variable passing to open and close
[gosa.git] / gosa-si / server / events / clMessages.pm
1 ## @file
2 # @brief Implementation of a GOsa-SI event module. 
3 # @details A GOsa-SI event module containing all functions to handle incoming messages from clients.
5 package clMessages;
8 use strict;
9 use warnings;
11 use Exporter;
12 use Data::Dumper;
13 use GOSA::GosaSupportDaemon;
14 use MIME::Base64;
16 @ISA = qw(Exporter);
17 my @events = (
18     "confirm_usr_msg",
19     "PROGRESS",
20     "FAIREBOOT",
21     "TASKSKIP",
22     "TASKBEGIN",
23     "TASKEND",
24     "TASKERROR",
25     "HOOK",
26     "GOTOACTIVATION",
27     "LOGIN",
28     "LOGOUT",
29     "CURRENTLY_LOGGED_IN",
30     "save_fai_log",
31     );
32 @EXPORT = @events;
34 BEGIN {}
36 END {}
39 ## @method get_events()
40 # @details A brief function returning a list of functions which are exported by importing the module.
41 # @return List of all provided functions
42 sub get_events {
43     return \@events;
44 }
46 ## @method confirm_usr_msg()
47 # @details Confirmed messages are set in the messaging_db from d (deliverd) to s(seen). 
48 # @param msg - STRING - xml message with tags 'message', 'subject' and 'usr'
49 # @param msg_hash - HASHREF - message information parsed into a hash
50 # @param session_id - INTEGER - POE session id of the processing of this message
51 sub confirm_usr_msg {
52     my ($msg, $msg_hash, $session_id) = @_;
53     my $message = @{$msg_hash->{'message'}}[0];
54     my $subject = @{$msg_hash->{'subject'}}[0];
55     my $usr = @{$msg_hash->{'usr'}}[0];
57     # set update for this message
58     my $sql = "UPDATE $main::messaging_tn SET flag='s' WHERE (message='$message' AND subject='$subject' AND message_to='$usr')"; 
59     &main::daemon_log("$session_id DEBUG: $sql", 7);
60     my $res = $main::messaging_db->exec_statement($sql); 
63     return;
64 }
67 ## @method save_fai_log()
68 # @details Creates under /var/log/fai/ the directory '$macaddress' and stores within all FAI log files from client.
69 # @param msg - STRING - xml message with tags 'macaddress' and 'save_fai_log'
70 # @param msg_hash - HASHREF - message information parsed into a hash
71 # @param session_id - INTEGER - POE session id of the processing of this message
72 sub save_fai_log {
73     my ($msg, $msg_hash, $session_id) = @_;
74     my $header = @{$msg_hash->{'header'}}[0];
75     my $source = @{$msg_hash->{'source'}}[0];
76     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
77     my $all_logs = @{$msg_hash->{$header}}[0];
79     # if there is nothing to log
80     if( ref($all_logs) eq "HASH" ) { 
81         &main::daemon_log("$session_id INFO: There is nothing to log!", 5);
82         return; 
83     }
84         
85     my $client_fai_log_dir = $main::client_fai_log_dir;
86     if (not -d $client_fai_log_dir) {
87         mkdir($client_fai_log_dir, 0755)
88     }
90     $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $macaddress );
91     if (not -d $client_fai_log_dir) {
92         mkdir($client_fai_log_dir, 0755)
93     }
95     my $time = &get_time;
96     $time = substr($time, 0, 8)."_".substr($time, 8, 6);
97     $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, "install_$time" );
98     mkdir($client_fai_log_dir, 0755);
100     my @all_logs = split(/log_file:/, $all_logs); 
101     foreach my $log (@all_logs) {
102         if (length $log == 0) { next; };
103         my ($log_file, $log_string) = split(":", $log);
104         my $client_fai_log_file = File::Spec->catfile( $client_fai_log_dir, $log_file);
106                 open(my $LOG_FILE, ">", "$client_fai_log_file"); 
107                 print $LOG_FILE &decode_base64($log_string);
108                 close($LOG_FILE);
109                 chown($main::root_uid, $main::adm_gid, $client_fai_log_file);
110                 chmod(0440, $client_fai_log_file);
112     }
113     return;
116 ## @method LOGIN()
117 # @details Reported user from client is added to login_users_db.
118 # @param msg - STRING - xml message with tag 'LOGIN'
119 # @param msg_hash - HASHREF - message information parsed into a hash
120 # @param session_id - INTEGER - POE session id of the processing of this message
121 sub LOGIN {
122     my ($msg, $msg_hash, $session_id) = @_;
123     my $header = @{$msg_hash->{'header'}}[0];
124     my $source = @{$msg_hash->{'source'}}[0];
125     my $login = @{$msg_hash->{$header}}[0];
126     my $res;
127     my $error_str;
129     # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
130         $res = &set_last_system($msg, $msg_hash, $session_id);
132     # Add user to login_users_db
133     my %add_hash = ( table=>$main::login_users_tn, 
134         primkey=> ['client', 'user'],
135         client=>$source,
136         user=>$login,
137         timestamp=>&get_time,
138         regserver=>'localhost',
139         ); 
140     ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
141     if ($res != 0)  {
142         &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
143         return;
144     }
146     # Share login information with all other si-server
147     my %data = ( 'new_user'  => "$source;$login" );
148     my $info_msg = &build_msg("information_sharing", $main::server_address, "KNOWN_SERVER", \%data);
150     return ($info_msg);  
154 ## @method LOGOUT()
155 # @details Reported user from client is deleted from login_users_db.
156 # @param msg - STRING - xml message with tag 'LOGOUT'
157 # @param msg_hash - HASHREF - message information parsed into a hash
158 # @param session_id - INTEGER - POE session id of the processing of this message
159 sub LOGOUT {
160     my ($msg, $msg_hash, $session_id) = @_;
161     my $header = @{$msg_hash->{'header'}}[0];
162     my $source = @{$msg_hash->{'source'}}[0];
163     my $login = @{$msg_hash->{$header}}[0];
164     
165     my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')"; 
166     my $res =  $main::login_users_db->del_dbentry($sql_statement);
167     &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5); 
168     
169     return;
173 ## @method CURRENTLY_LOGGED_IN()
174 # @details Reported users from client are updated in login_users_db. Users which are no longer logged in are deleted from DB. 
175 # @param msg - STRING - xml message
176 # @param msg_hash - HASHREF - message information parsed into a hash
177 # @param session_id - INTEGER - POE session id of the processing of this message
178 sub CURRENTLY_LOGGED_IN {
179     my ($msg, $msg_hash, $session_id) = @_;
180     my ($sql_statement, $db_res);
181     my $header = @{$msg_hash->{'header'}}[0];
182     my $source = @{$msg_hash->{'source'}}[0];
183     my $login = @{$msg_hash->{$header}}[0];
185     if(ref $login eq "HASH") { 
186         &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5); 
187         return;     
188     }
190     # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
191         my $res = &set_last_system($msg, $msg_hash, $session_id);
192     
193     # fetch all user currently assigned to the client at login_users_db
194     my %currently_logged_in_user = (); 
195     $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'"; 
196     $db_res = $main::login_users_db->select_dbentry($sql_statement);
197     while( my($hit_id, $hit) = each(%{$db_res}) ) {
198         $currently_logged_in_user{$hit->{'user'}} = 1;
199     }
200     &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7); 
202     # update all reported users in login_user_db
203     my @logged_in_user = split(/\s+/, $login);
204     &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7); 
205     foreach my $user (@logged_in_user) {
206         my %add_hash = ( table=>$main::login_users_tn, 
207                 primkey=> ['client', 'user'],
208                 client=>$source,
209                 user=>$user,
210                 timestamp=>&get_time,
211                 regserver=>'localhost',
212                 ); 
213         my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
214         if ($res != 0)  {
215             &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
216             return;
217         }
219         delete $currently_logged_in_user{$user};
220     }
222     # if there is still a user in %currently_logged_in_user 
223     # although he is not reported by client 
224     # then delete it from $login_user_db
225     foreach my $obsolete_user (keys(%currently_logged_in_user)) {
226         &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
227                 "in at client '$source' but still found at login_user_db", 3); 
228         my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'"; 
229         my $res =  $main::login_users_db->del_dbentry($sql_statement);
230         &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3); 
231     }
233     # Delete all users which logged in information is older than their logged_in_user_date_of_expiry
234     my $act_time = &get_time();
235     my $expiry_date = &calc_timestamp($act_time, "minus", $main::logged_in_user_date_of_expiry); 
237     $sql_statement = "SELECT * FROM $main::login_users_tn WHERE CAST(timestamp as UNSIGNED)<$expiry_date"; 
238     $db_res = $main::login_users_db->select_dbentry($sql_statement);
240     while( my($hit_id, $hit) = each(%{$db_res}) ) {
241         &main::daemon_log("$session_id INFO: user '".$hit->{'user'}."' is no longer reported to be logged in at host '".$hit->{'client'}."'", 5);
242         my $sql = "DELETE FROM $main::login_users_tn WHERE (client='".$hit->{'client'}."' AND user='".$hit->{'user'}."')"; 
243         my $res =  $main::login_users_db->del_dbentry($sql);
244         &main::daemon_log("$session_id INFO: delete user '".$hit->{'user'}."' at client '".$hit->{'client'}."' from login_user_db", 5); 
245     }
247     # Inform all other server which users are logged in at clients registered at local server
248     my $info_sql = "SELECT * FROM $main::login_users_tn WHERE regserver='localhost'";
249     my $info_res = $main::login_users_db->select_dbentry($info_sql);
250     my $info_msg_hash = &create_xml_hash("information_sharing", $main::server_address, "KNOWN_SERVER");
251     while (my ($hit_id, $hit) = each(%$info_res)) {
252         &add_content2xml_hash($info_msg_hash, 'user_db', $hit->{'client'}.";".$hit->{'user'});
253     }
254     my $info_msg = &create_xml_string($info_msg_hash);
256     return ($info_msg);  
260 ## @method set_last_system()
261 # @details Message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
262 # @param msg - STRING - xml message with tag 'last_system_login' and 'last_system'
263 # @param msg_hash - HASHREF - message information parsed into a hash
264 # @param session_id - INTEGER - POE session id of the processing of this message
265 sub set_last_system {
266         my ($msg, $msg_hash, $session_id) = @_;
267         my $header = @{$msg_hash->{'header'}}[0];
268         my $source = @{$msg_hash->{'source'}}[0];
269     my $login = @{$msg_hash->{$header}}[0];
270     
271         # Sanity check of needed parameter
272         if (not exists $msg_hash->{'timestamp'}){
273                 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'timestamp', ".
274                                                 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
275                 &main::daemon_log($msg, 1);
276                 return;
277         }
278         if (@{$msg_hash->{'timestamp'}} != 1)  {
279                 &main::daemon_log("$session_id ERROR: xml tag 'timestamp' has no content or exists more than one time, ".
280                                                 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
281                 &ymain::daemon_log($msg, 1);
282                 return;
283         }
284         if (not exists $msg_hash->{'macaddress'}){
285                 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'mac_address', ".
286                                                 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
287                 &main::daemon_log($msg, 1);
288                 return;
289         }
290         if (@{$msg_hash->{'macaddress'}} != 1)  {
291                 &main::daemon_log("$session_id ERROR: xml tag 'macaddress' has no content or exists more than one time, ".
292                                                 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
293                 &ymain::daemon_log($msg, 1);
294                 return;
295         }
297         # Fetch needed parameter
298         my $mac =  @{$msg_hash->{'macaddress'}}[0];
299         my $timestamp = @{$msg_hash->{'timestamp'}}[0];
300         
301         # Prepare login list
302         my @login_list = split(' ', @{$msg_hash->{$header}}[0] );
303     @login_list = &main::del_doubles(@login_list);
305         # Sanity check of login list
306         if (@login_list == 0) {
307                 # TODO
308                 return;
309         }
311         # Get system info
312         my $ldap_handle=&main::get_ldap_handle($session_id);
313         my $ldap_mesg= $ldap_handle->search(
314                                         base => $main::ldap_base,
315                                         scope => 'sub',
316                                         filter => "macAddress=$mac",
317                                         );
318         if ($ldap_mesg->count == 0) {
319                 &main::daemon_log("$session_id ERROR: no system with mac address='$mac' was found in base '".
320                                                 $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
321                 &main::release_ldap_handle($ldap_handle);
322                 return;
323         }
325         my $ldap_entry = $ldap_mesg->pop_entry();
326         my $system_dn = $ldap_entry->dn();
327         
328         # For each logged in user set gotoLastSystem and gotoLastSystemLogin
329         foreach my $user (@login_list) {
330                 # Search user
331                 my $ldap_mesg= $ldap_handle->search(
332                                                 base => $main::ldap_base,
333                                                 scope => 'sub',
334                                                 filter => "(&(objectClass=gosaAccount)(uid=$user))",
335                                                 );
336                 # Sanity check of user search
337                 if ($ldap_mesg->count == 0) {
338                         &main::daemon_log("$session_id ERROR: no user with uid='$user' was found in base '".
339                                                         $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
341                 # Set gotoLastSystem and gotoLastSystemLogin
342                 } else {
343                         my $ldap_entry= $ldap_mesg->pop_entry();
344             my $do_update = 0;
346             # Set gotoLastSystem information
347             my $last_system_dn = $ldap_entry->get_value('gotoLastSystem');
348             if ((defined $last_system_dn) && ($last_system_dn eq $system_dn)) {
349                 &main::daemon_log("$session_id INFO: no new 'gotoLastSystem' information for ldap entry 'uid=$user', do nothing!", 5);
350             } elsif ((defined $last_system_dn) && ($last_system_dn ne $system_dn)) {
351                 $ldap_entry->replace ( 'gotoLastSystem' => $system_dn );
352                 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!",5);
353                 $do_update++;
354             } else {
355                 $ldap_entry->add( 'gotoLastSystem' => $system_dn );
356                 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!", 5);
357                 $do_update++;
358             }
360             # Set gotoLastSystemLogin information
361             # Attention: only write information if last_system_dn and system_dn differs
362             my $last_system_login = $ldap_entry->get_value('gotoLastSystemLogin');
363             if ((defined $last_system_login) && ($last_system_dn eq $system_dn)) {
364                 &main::daemon_log("$session_id INFO: no new 'gotoLastSystemLogin' information for ldap entry 'uid=$user', do nothing!", 5);
365             } elsif ((defined $last_system_login) && ($last_system_dn ne $system_dn)) {
366                 $ldap_entry->replace ( 'gotoLastSystemLogin' => $timestamp );
367                 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!", 5);
368                 $do_update++;
369             } else {
370                 $ldap_entry->add( 'gotoLastSystemLogin' => $timestamp );
371                 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!",5);
372                 $do_update++;
373             }
375             if ($do_update) {
376                 my $result = $ldap_entry->update($ldap_handle);
377                 if ($result->code() != 0) {
378                     &main::daemon_log("$session_id ERROR: setting 'gotoLastSystem' and 'gotoLastSystemLogin' at user '$user' failed: ".
379                             $result->{'errorMessage'}."\n".
380                             "\tbase: $main::ldap_base\n".
381                             "\tscope: 'sub'\n".
382                             "\tfilter: 'uid=$user'\n".
383                             "\tmessage: $msg", 1); 
384                 }
385             }
386                 }
387         }
388         &main::release_ldap_handle($ldap_handle);
390         return;
394 ## @method GOTOACTIVATION()
395 # @details Client is set at job_queue_db to status 'processing' and 'modified'.
396 # @param msg - STRING - xml message with tag 'macaddress'
397 # @param msg_hash - HASHREF - message information parsed into a hash
398 # @param session_id - INTEGER - POE session id of the processing of this message
399 sub GOTOACTIVATION {
400     my ($msg, $msg_hash, $session_id) = @_;
401     my $header = @{$msg_hash->{'header'}}[0];
402     my $source = @{$msg_hash->{'source'}}[0];
403     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
405     # test whether content is an empty hash or a string which is required
406     my $content = @{$msg_hash->{$header}}[0];
407     if(ref($content) eq "HASH") { $content = ""; }
409     # clean up header
410     $header =~ s/CLMSG_//g;
412     my $sql_statement = "UPDATE $main::job_queue_tn ".
413             "SET progress='goto-activation', modified='1' ".
414             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
415     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
416     my $res = $main::job_db->update_dbentry($sql_statement);
417     &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5); 
418     return; 
422 ## @method PROGRESS()
423 # @details Message reports installation progress of the client. Installation job at job_queue_db is going to be updated.
424 # @param msg - STRING - xml message with tags 'macaddress' and 'PROGRESS'
425 # @param msg_hash - HASHREF - message information parsed into a hash
426 # @param session_id - INTEGER - POE session id of the processing of this message
427 sub PROGRESS {
428     my ($msg, $msg_hash, $session_id) = @_;
429     my $header = @{$msg_hash->{'header'}}[0];
430     my $source = @{$msg_hash->{'source'}}[0];
431     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
433     # test whether content is an empty hash or a string which is required
434     my $content = @{$msg_hash->{$header}}[0];
435     if(ref($content) eq "HASH") { $content = ""; }
437     # clean up header
438     $header =~ s/CLMSG_//g;
440     my $sql_statement = "UPDATE $main::job_queue_tn ".
441         "SET progress='$content', modified='1' ".
442         "WHERE status='processing' AND macaddress LIKE '$macaddress'";
443     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
444     my $res = $main::job_db->update_dbentry($sql_statement);
445     &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5); 
447     return;
451 ## @method FAIREBOOT()
452 # @details Message reports a FAI reboot. Job at job_queue_db is going to be updated.
453 # @param msg - STRING - xml message with tag 'macaddress' and 'FAIREBOOT'
454 # @param msg_hash - HASHREF - message information parsed into a hash
455 # @param session_id - INTEGER - POE session id of the processing of this message
456 sub FAIREBOOT {
457     my ($msg, $msg_hash, $session_id) = @_;
458     my $header = @{$msg_hash->{'header'}}[0];
459     my $source = @{$msg_hash->{'source'}}[0];
460     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
462     # test whether content is an empty hash or a string which is required
463         my $content = @{$msg_hash->{$header}}[0];
464     if(ref($content) eq "HASH") { $content = ""; }
466     # clean up header
467     $header =~ s/CLMSG_//g;
469     my $sql_statement = "UPDATE $main::job_queue_tn ".
470             "SET 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     return; 
480 ## @method TASKSKIP()
481 # @details Message reports a skipped FAI task. Job at job_queue_db is going to be updated. 
482 # @param msg - STRING - xml message with tag 'macaddress'.
483 # @param msg_hash - HASHREF - message information parsed into a hash
484 # @param session_id - INTEGER - POE session id of the processing of this message
485 sub TASKSKIP {
486     my ($msg, $msg_hash, $session_id) = @_;
487     my $header = @{$msg_hash->{'header'}}[0];
488     my $source = @{$msg_hash->{'source'}}[0];
489     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
491     # test whether content is an empty hash or a string which is required
492         my $content = @{$msg_hash->{$header}}[0];
493     if(ref($content) eq "HASH") { $content = ""; }
495     # clean up header
496     $header =~ s/CLMSG_//g;
498     my $sql_statement = "UPDATE $main::job_queue_tn ".
499             "SET result='$header "."$content', modified='1' ".
500             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
501     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
502     my $res = $main::job_db->update_dbentry($sql_statement);
503     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
505     return; 
509 ## @method TASKBEGIN()
510 # @details Message reports a starting FAI task. If the task is equal to 'finish', 'faiend' or 'savelog', job at job_queue_db is being set to status 'done' and FAI state is being set to 'localboot'. If task is equal to 'chboot', 'test' or 'confdir', just do nothing. In all other cases, job at job_queue_db is going to be updated or created if not exists. 
511 # @param msg - STRING - xml message with tag 'macaddress'.
512 # @param msg_hash - HASHREF - message information parsed into a hash
513 # @param session_id - INTEGER - POE session id of the processing of this message
514 sub TASKBEGIN {
515     my ($msg, $msg_hash, $session_id) = @_;
516     my $header = @{$msg_hash->{'header'}}[0];
517     my $source = @{$msg_hash->{'source'}}[0];
518     my $target = @{$msg_hash->{'target'}}[0];
519     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
521     # test whether content is an empty hash or a string which is required
522         my $content = @{$msg_hash->{$header}}[0];
523     if(ref($content) eq "HASH") { $content = ""; }
525     # clean up header
526     $header =~ s/CLMSG_//g;
528     # TASKBEGIN eq finish or faiend 
529     if (($content eq 'finish') 
530                         || ($content eq 'faiend')
531                         || ($content eq 'savelog')
532                         ) {
533         my $sql_statement = "UPDATE $main::job_queue_tn ".
534             "SET status='done', 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); 
539         
540         # set fai_state to localboot
541         &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
543         # TASKBEGIN eq chboot
544         } elsif (($content eq 'chboot')
545                 || ($content eq 'test')
546                 || ($content eq 'confdir')
547                 ) {
548                 # just ignor this client message
549                 # do nothing
551         # other TASKBEGIN msgs
552     } else {
553                 # TASKBEGIN msgs do only occour during a softupdate or a reinstallation
554                 # of a host. Set all waiting update- or reinstall-jobs for host to
555                 # processing so they can be handled correctly by the rest of the function.
556                 my $waiting_sql = "UPDATE $main::job_queue_tn SET status='processing' WHERE status='waiting' AND macaddress LIKE '$macaddress' AND (headertag='trigger_action_update' OR headertag='trigger_action_reinstall')"; 
557                 &main::daemon_log("$session_id DEBUB: $waiting_sql", 7);
558                 my $waiting_res = $main::job_db->update_dbentry($waiting_sql);
560                 # Select processing jobs for host
561                 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
562                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
563                 my $res = $main::job_db->select_dbentry($sql_statement);
565                 # there is exactly one job entry in queue for this host
566                 if (keys(%$res) == 1) {
567                         &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
568                         my $sql_statement = "UPDATE $main::job_queue_tn SET result='$header $content', modified='1', siserver='localhost' WHERE status='processing' AND macaddress LIKE '$macaddress'";
569                         my $err = $main::job_db->update_dbentry($sql_statement);
570                         if (not defined  $err) {
571                                 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
572                         }
573                         
574                 # There is no entry in queue or more than one entries in queue for this host
575                 } else {
576                         # In case of more than one running jobs in queue, delete all jobs
577                         if (keys(%$res) > 1) {
578                                 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
579                                                                 "delete entries", 7); 
581                 # set job to status 'done', job will be deleted automatically
582                 my $sql_statement = "UPDATE $main::job_queue_tn ".
583                     "SET status='done', modified='1'".
584                     "WHERE status='processing' AND macaddress LIKE '$macaddress'";
585                 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
586                 my $res = $main::job_db->update_dbentry( $sql_statement );
588                         }
589                 
590                         # In case of no and more than one running jobs in queue, add one single job
592                         # Resolve plain name for host $macaddress
593                         my $plain_name;
594                         my $ldap_handle=&main::get_ldap_handle($session_id);
595                         my $mesg = $ldap_handle->search(
596                                         base => $main::ldap_base,
597                                         scope => 'sub',
598                                         attrs => ['cn'],
599                                         filter => "(macAddress=$macaddress)");
600                         if(not $mesg->code) {
601                                 my $entry= $mesg->entry(0);
602                                 $plain_name = $entry->get_value("cn");
603                         } else {
604                                 &main::daemon_log($mesg->error, 1);
605                                 $plain_name = "none";
606                         }
607                         &main::release_ldap_handle($ldap_handle);
609             # In any case add a new job to job queue
610                         &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7); 
611                         my $func_dic = {table=>$main::job_queue_tn,
612                                         primkey=>['macaddress', 'headertag'],
613                                         timestamp=>&get_time,
614                                         status=>'processing',
615                                         result=>"$header $content",
616                                         progress=>'none',
617                                         headertag=>'trigger_action_reinstall',
618                                         targettag=>$target,
619                                         xmlmessage=>'none',
620                                         macaddress=>$macaddress,
621                                         plainname=>$plain_name,
622                     modified=>'1',
623                     siserver=>'localhost',
624                         };
625                         my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
626                         if ($err != 0)  {
627                                         &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
628                         }
629                 }
630     }
632     return; 
636 ## @method TASKEND()
637 # @details Message reports a finished FAI task. If task is equal to 'savelog', job at job_queue_db is going to be set to status 'done'. Otherwise, job is going to be updated. 
638 # @param msg - STRING - xml message with tag 'macaddress'.
639 # @param msg_hash - HASHREF - message information parsed into a hash
640 # @param session_id - INTEGER - POE session id of the processing of this message
641 sub TASKEND {
642     my ($msg, $msg_hash, $session_id) = @_;
643     my $header = @{$msg_hash->{'header'}}[0];
644     my $target = @{$msg_hash->{'target'}}[0];
645     my $source = @{$msg_hash->{'source'}}[0];
646     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
648     # test whether content is an empty hash or a string which is required
649     my $content = @{$msg_hash->{$header}}[0];
650     if(ref($content) eq "HASH") { $content = ""; }
652     # clean up header
653     $header =~ s/CLMSG_//g;
655         if ($content eq "savelog 0") {
656                 &main::daemon_log("$session_id DEBUG: got savelog from host '$target' - job done", 7);
657         
658         # set job to status 'done', job will be deleted automatically
659         my $sql_statement = "UPDATE $main::job_queue_tn ".
660                                         "SET status='done', modified='1'".
661                     "WHERE status='processing' AND macaddress LIKE '$macaddress'";
662         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
663         my $res = $main::job_db->update_dbentry( $sql_statement );
665         } else {
666         my $sql_statement = "UPDATE $main::job_queue_tn ".
667             "SET result='$header "."$content', modified='1' ".
668             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
669         &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
670         my $res = $main::job_db->update_dbentry($sql_statement);
671         &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
672         }
674     return; 
678 ## @method TASKERROR()
679 # @details Message reports a FAI error. Job at job_queue_db is going to be updated. 
680 # @param msg - STRING - xml message with tag 'macaddress' and 'TASKERROR'
681 # @param msg_hash - HASHREF - message information parsed into a hash
682 # @param session_id - INTEGER - POE session id of the processing of this message
683 sub TASKERROR {
684     my ($msg, $msg_hash, $session_id) = @_;
685     my $header = @{$msg_hash->{'header'}}[0];
686     my $source = @{$msg_hash->{'source'}}[0];
687     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
689     # clean up header
690     $header =~ s/CLMSG_//g;
692     # test whether content is an empty hash or a string which is required
693     my $content = @{$msg_hash->{$header}}[0];
694     if(ref($content) eq "HASH") { $content = ""; } 
696         # set fai_state to localboot
697         &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
698                 
699     my $sql_statement = "UPDATE $main::job_queue_tn ".
700             "SET result='$header "."$content', modified='1' ".
701             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
702     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
703     my $res = $main::job_db->update_dbentry($sql_statement);
704     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
706     return; 
710 ## @method HOOK()
711 # @details Message reports a FAI hook. Job at job_queue_db is going to be updated. 
712 # @param msg - STRING - xml message with tag 'macaddress' and 'HOOK'
713 # @param msg_hash - HASHREF - message information parsed into a hash
714 # @param session_id - INTEGER - POE session id of the processing of this message
715 sub HOOK {
716     my ($msg, $msg_hash, $session_id) = @_;
717     my $header = @{$msg_hash->{'header'}}[0];
718     my $source = @{$msg_hash->{'source'}}[0];
719     my $macaddress = @{$msg_hash->{'macaddress'}}[0];
721     # clean up header
722     $header =~ s/CLMSG_//g;
724     # test whether content is an empty hash or a string which is required
725         my $content = @{$msg_hash->{$header}}[0];
726     if(not ref($content) eq "STRING") { $content = ""; }
728     my $sql_statement = "UPDATE $main::job_queue_tn ".
729             "SET result='$header "."$content', modified='1' ".
730             "WHERE status='processing' AND macaddress LIKE '$macaddress'"; 
731     &main::daemon_log("$session_id DEBUG: $sql_statement", 7);         
732     my $res = $main::job_db->update_dbentry($sql_statement);
733     &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5); 
735     return;
739 =pod
741 =head1 NAME
743 clMessages - Implementation of a GOsa-SI event module for GOsa-SI-server.
745 =head1 SYNOPSIS
747  use GOSA::GosaSupportDaemon;
748  use MIME::Base64;
750 =head1 DESCRIPTION
752 This GOsa-SI event module containing all functions to handle messages coming from GOsa-SI-clients. 
754 This module will be automatically imported by GOsa-SI if it is under F</usr/lib/gosa-si/server/E<lt>PACKAGEMODULEE<gt>/> .
756 =head1 METHODS
758 =over 4
760 =item get_events ( )
762 =item confirm_usr_msg ( )
764 =item PROGRESS ( )
766 =item FAIREBOOT ( )
768 =item TASKSKIP ( )
770 =item TASKBEGIN ( )
772 =item TASKEND ( )
774 =item TASKERROR ( )
776 =item HOOK ( )
778 =item GOTOACTIVATION ( )
780 =item LOGIN ( )
782 =item LOGOUT ( )
784 =item CURRENTLY_LOGGED_IN ( )
786 =item save_fai_log ( )
788 =back
790 =head1 BUGS
792 Please report any bugs, or post any suggestions, to the GOsa mailing list E<lt>gosa-devel@oss.gonicus.deE<gt> or to L<https://oss.gonicus.de/labs/gosa>
794 =head1 COPYRIGHT
796 This code is part of GOsa (L<http://www.gosa-project.org>)
798 Copyright (C) 2003-2008 GONICUS GmbH
800 This program is distributed in the hope that it will be useful,
801 but WITHOUT ANY WARRANTY; without even the implied warranty of
802 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
803 GNU General Public License for more details.
805 =cut
808 1;