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 }
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;
114 }
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);
151 }
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];
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);
169 return;
170 }
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);
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);
257 }
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];
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];
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();
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;
391 }
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;
419 }
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;
448 }
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;
477 }
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;
506 }
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);
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 }
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 }
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;
633 }
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);
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;
675 }
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);
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;
707 }
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;
736 }
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;