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;
6 use Exporter;
7 @ISA = qw(Exporter);
8 my @events = (
9 "confirm_usr_msg",
10 "PROGRESS",
11 "FAIREBOOT",
12 "TASKSKIP",
13 "TASKBEGIN",
14 "TASKEND",
15 "TASKERROR",
16 "HOOK",
17 "GOTOACTIVATION",
18 "LOGIN",
19 "LOGOUT",
20 "CURRENTLY_LOGGED_IN",
21 "save_fai_log",
22 );
23 @EXPORT = @events;
25 use strict;
26 use warnings;
27 use Data::Dumper;
28 use GOSA::GosaSupportDaemon;
29 use MIME::Base64;
32 BEGIN {}
34 END {}
37 ## @method get_events()
38 # @details A brief function returning a list of functions which are exported by importing the module.
39 # @return List of all provided functions
40 sub get_events {
41 return \@events;
42 }
44 ## @method confirm_usr_msg()
45 # @details Confirmed messages are set in the messaging_db from d (deliverd) to s(seen).
46 # @param msg - STRING - xml message with tags 'message', 'subject' and 'usr'
47 # @param msg_hash - HASHREF - message information parsed into a hash
48 # @param session_id - INTEGER - POE session id of the processing of this message
49 sub confirm_usr_msg {
50 my ($msg, $msg_hash, $session_id) = @_;
51 my $message = @{$msg_hash->{'message'}}[0];
52 my $subject = @{$msg_hash->{'subject'}}[0];
53 my $usr = @{$msg_hash->{'usr'}}[0];
55 # set update for this message
56 my $sql = "UPDATE $main::messaging_tn SET flag='s' WHERE (message='$message' AND subject='$subject' AND message_to='$usr')";
57 &main::daemon_log("$session_id DEBUG: $sql", 7);
58 my $res = $main::messaging_db->exec_statement($sql);
61 return;
62 }
65 ## @method save_fai_log()
66 # @details Creates under /var/log/fai/ the directory '$macaddress' and stores within all FAI log files from client.
67 # @param msg - STRING - xml message with tags 'macaddress' and 'save_fai_log'
68 # @param msg_hash - HASHREF - message information parsed into a hash
69 # @param session_id - INTEGER - POE session id of the processing of this message
70 sub save_fai_log {
71 my ($msg, $msg_hash, $session_id) = @_;
72 my $header = @{$msg_hash->{'header'}}[0];
73 my $source = @{$msg_hash->{'source'}}[0];
74 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
75 my $fai_action = @{$msg_hash->{'fai_action'}}[0];
76 my $all_logs = @{$msg_hash->{$header}}[0];
78 # if there is nothing to log
79 if( ref($all_logs) eq "HASH" ) {
80 &main::daemon_log("$session_id INFO: There is nothing to log!", 5);
81 return;
82 }
84 my $client_fai_log_dir = $main::client_fai_log_dir;
85 if (not -d $client_fai_log_dir) {
86 mkdir($client_fai_log_dir, 0755)
87 }
89 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $macaddress );
90 if (not -d $client_fai_log_dir) {
91 mkdir($client_fai_log_dir, 0755)
92 }
94 my $time = &get_time;
95 $time = substr($time, 0, 8)."_".substr($time, 8, 6);
96 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $fai_action ."_".$time );
97 mkdir($client_fai_log_dir, 0755);
99 my @all_logs = split(/log_file:/, $all_logs);
100 foreach my $log (@all_logs) {
101 if (length $log == 0) { next; };
102 my ($log_file, $log_string) = split(":", $log);
103 my $client_fai_log_file = File::Spec->catfile( $client_fai_log_dir, $log_file);
105 open(my $LOG_FILE, ">$client_fai_log_file");
106 print $LOG_FILE &decode_base64($log_string);
107 close($LOG_FILE);
108 chown($main::root_uid, $main::adm_gid, $client_fai_log_file);
109 chmod(0440, $client_fai_log_file);
111 }
112 return;
113 }
115 ## @method LOGIN()
116 # @details Reported user from client is added to login_users_db.
117 # @param msg - STRING - xml message with tag 'LOGIN'
118 # @param msg_hash - HASHREF - message information parsed into a hash
119 # @param session_id - INTEGER - POE session id of the processing of this message
120 sub LOGIN {
121 my ($msg, $msg_hash, $session_id) = @_;
122 my $header = @{$msg_hash->{'header'}}[0];
123 my $source = @{$msg_hash->{'source'}}[0];
124 my $login = @{$msg_hash->{$header}}[0];
125 my $res;
126 my $error_str;
128 # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
129 # &set_last_system($msg, $msg_hash, $session_id);
131 # Add user to login_users_db
132 my %add_hash = ( table=>$main::login_users_tn,
133 primkey=> ['client', 'user'],
134 client=>$source,
135 user=>$login,
136 timestamp=>&get_time,
137 regserver=>'localhost',
138 );
139 ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
140 if ($res != 0) {
141 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
142 return;
143 }
145 # Share login information with all other si-server
146 my %data = ( 'new_user' => "$source;$login" );
147 my $info_msg = &build_msg("information_sharing", $main::server_address, "KNOWN_SERVER", \%data);
149 return ($info_msg);
150 }
153 ## @method LOGOUT()
154 # @details Reported user from client is deleted from login_users_db.
155 # @param msg - STRING - xml message with tag 'LOGOUT'
156 # @param msg_hash - HASHREF - message information parsed into a hash
157 # @param session_id - INTEGER - POE session id of the processing of this message
158 sub LOGOUT {
159 my ($msg, $msg_hash, $session_id) = @_;
160 my $header = @{$msg_hash->{'header'}}[0];
161 my $source = @{$msg_hash->{'source'}}[0];
162 my $login = @{$msg_hash->{$header}}[0];
164 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')";
165 my $res = $main::login_users_db->del_dbentry($sql_statement);
166 &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5);
168 return;
169 }
172 ## @method CURRENTLY_LOGGED_IN()
173 # @details Reported users from client are updated in login_users_db. Users which are no longer logged in are deleted from DB.
174 # @param msg - STRING - xml message
175 # @param msg_hash - HASHREF - message information parsed into a hash
176 # @param session_id - INTEGER - POE session id of the processing of this message
177 sub CURRENTLY_LOGGED_IN {
178 my ($msg, $msg_hash, $session_id) = @_;
179 my ($sql_statement, $db_res);
180 my $header = @{$msg_hash->{'header'}}[0];
181 my $source = @{$msg_hash->{'source'}}[0];
182 my $login = @{$msg_hash->{$header}}[0];
184 if(ref $login eq "HASH") {
185 &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5);
186 return;
187 }
189 # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
190 # &set_last_system($msg, $msg_hash, $session_id);
192 # fetch all user currently assigned to the client at login_users_db
193 my %currently_logged_in_user = ();
194 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'";
195 $db_res = $main::login_users_db->select_dbentry($sql_statement);
196 while( my($hit_id, $hit) = each(%{$db_res}) ) {
197 $currently_logged_in_user{$hit->{'user'}} = 1;
198 }
199 &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7);
201 # update all reported users in login_user_db
202 my @logged_in_user = split(/\s+/, $login);
203 &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7);
204 foreach my $user (@logged_in_user) {
205 my %add_hash = ( table=>$main::login_users_tn,
206 primkey=> ['client', 'user'],
207 client=>$source,
208 user=>$user,
209 timestamp=>&get_time,
210 regserver=>'localhost',
211 );
212 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
213 if ($res != 0) {
214 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
215 return;
216 }
218 delete $currently_logged_in_user{$user};
219 }
221 # if there is still a user in %currently_logged_in_user
222 # although he is not reported by client
223 # then delete it from $login_user_db
224 foreach my $obsolete_user (keys(%currently_logged_in_user)) {
225 &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
226 "in at client '$source' but still found at login_user_db", 3);
227 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'";
228 my $res = $main::login_users_db->del_dbentry($sql_statement);
229 &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3);
230 }
232 # Delete all users which logged in information is older than their logged_in_user_date_of_expiry
233 my $act_time = &get_time();
234 my $expiry_date = &calc_timestamp($act_time, "minus", $main::logged_in_user_date_of_expiry);
236 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE CAST(timestamp as UNSIGNED)<$expiry_date";
237 $db_res = $main::login_users_db->select_dbentry($sql_statement);
239 while( my($hit_id, $hit) = each(%{$db_res}) ) {
240 &main::daemon_log("$session_id INFO: user '".$hit->{'user'}."' is no longer reported to be logged in at host '".$hit->{'client'}."'", 5);
241 my $sql = "DELETE FROM $main::login_users_tn WHERE (client='".$hit->{'client'}."' AND user='".$hit->{'user'}."')";
242 my $res = $main::login_users_db->del_dbentry($sql);
243 &main::daemon_log("$session_id INFO: delete user '".$hit->{'user'}."' at client '".$hit->{'client'}."' from login_user_db", 5);
244 }
246 return;
247 }
250 ## @method set_last_system()
251 # @details Message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
252 # @param msg - STRING - xml message with tag 'last_system_login' and 'last_system'
253 # @param msg_hash - HASHREF - message information parsed into a hash
254 # @param session_id - INTEGER - POE session id of the processing of this message
255 sub set_last_system {
256 my ($msg, $msg_hash, $session_id) = @_;
257 my $header = @{$msg_hash->{'header'}}[0];
258 my $source = @{$msg_hash->{'source'}}[0];
259 my $login = @{$msg_hash->{$header}}[0];
261 # Sanity check of needed parameter
262 if (not exists $msg_hash->{'timestamp'}){
263 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'timestamp', ".
264 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
265 &main::daemon_log($msg, 1);
266 return;
267 }
268 if (@{$msg_hash->{'timestamp'}} != 1) {
269 &main::daemon_log("$session_id ERROR: xml tag 'timestamp' has no content or exists more than one time, ".
270 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
271 &ymain::daemon_log($msg, 1);
272 return;
273 }
274 if (not exists $msg_hash->{'macaddress'}){
275 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'mac_address', ".
276 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
277 &main::daemon_log($msg, 1);
278 return;
279 }
280 if (@{$msg_hash->{'macaddress'}} != 1) {
281 &main::daemon_log("$session_id ERROR: xml tag 'macaddress' has no content or exists more than one time, ".
282 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
283 &ymain::daemon_log($msg, 1);
284 return;
285 }
287 # Fetch needed parameter
288 my $mac = @{$msg_hash->{'macaddress'}}[0];
289 my $timestamp = @{$msg_hash->{'timestamp'}}[0];
291 # Prepare login list
292 my @login_list = split(' ', @{$msg_hash->{$header}}[0] );
293 @login_list = &main::del_doubles(@login_list);
295 # Sanity check of login list
296 if (@login_list == 0) {
297 # TODO
298 return;
299 }
301 # Fetch ldap handle
302 my $ldap_handle = &main::get_ldap_handle();
304 # Get system info
305 my $ldap_mesg= $ldap_handle->search(
306 base => $main::ldap_base,
307 scope => 'sub',
308 filter => "macAddress=$mac",
309 );
310 if ($ldap_mesg->count == 0) {
311 &main::daemon_log("$session_id ERROR: no system with mac address='$mac' was found in base '".
312 $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
313 return;
314 }
316 my $ldap_entry = $ldap_mesg->pop_entry();
317 my $system_dn = $ldap_entry->dn();
319 # For each logged in user set gotoLastSystem and gotoLastSystemLogin
320 foreach my $user (@login_list) {
321 # Search user
322 my $ldap_mesg= $ldap_handle->search(
323 base => $main::ldap_base,
324 scope => 'sub',
325 filter => "uid=$user",
326 );
327 # Sanity check of user search
328 if ($ldap_mesg->count == 0) {
329 &main::daemon_log("$session_id ERROR: no user with uid='$user' was found in base '".
330 $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
332 # Set gotoLastSystem and gotoLastSystemLogin
333 } else {
334 my $ldap_entry= $ldap_mesg->pop_entry();
335 my $do_update = 0;
337 # Set gotoLastSystem information
338 my $last_system_dn = $ldap_entry->get_value('gotoLastSystem');
339 if ((defined $last_system_dn) && ($last_system_dn eq $system_dn)) {
340 &main::daemon_log("$session_id INFO: no new 'gotoLastSystem' inforamtion for ladp entry 'uid=$user', do nothing!", 5);
341 } elsif ((defined $last_system_dn) && ($last_system_dn ne $system_dn)) {
342 $ldap_entry->replace ( 'gotoLastSystem' => $system_dn );
343 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!",5);
344 $do_update++;
345 } else {
346 $ldap_entry->add( 'gotoLastSystem' => $system_dn );
347 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!", 5);
348 $do_update++;
349 }
351 # Set gotoLastSystemLogin information
352 # Attention: only write information if last_system_dn and system_dn differs
353 my $last_system_login = $ldap_entry->get_value('gotoLastSystemLogin');
354 if ((defined $last_system_login) && ($last_system_dn eq $system_dn)) {
355 &main::daemon_log("$session_id INFO: no new 'gotoLastSystemLogin' inforamtion for ladp entry 'uid=$user', do nothing!", 5);
356 } elsif ((defined $last_system_login) && ($last_system_dn ne $system_dn)) {
357 $ldap_entry->replace ( 'gotoLastSystemLogin' => $timestamp );
358 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!", 5);
359 $do_update++;
360 } else {
361 $ldap_entry->add( 'gotoLastSystemLogin' => $timestamp );
362 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!",5);
363 $do_update++;
364 }
366 if ($do_update) {
367 my $result = $ldap_entry->update($ldap_handle);
368 if ($result->code() != 0) {
369 &main::daemon_log("$session_id ERROR: setting 'gotoLastSystem' and 'gotoLastSystemLogin' at user '$user' failed: ".
370 $result->{'errorMessage'}."\n".
371 "\tbase: $main::ldap_base\n".
372 "\tscope: 'sub'\n".
373 "\tfilter: 'uid=$user'\n".
374 "\tmessage: $msg", 1);
375 }
376 }
377 }
378 }
380 return;
381 }
384 ## @method GOTOACTIVATION()
385 # @details Client is set at job_queue_db to status 'processing' and 'modified'.
386 # @param msg - STRING - xml message with tag 'macaddress'
387 # @param msg_hash - HASHREF - message information parsed into a hash
388 # @param session_id - INTEGER - POE session id of the processing of this message
389 sub GOTOACTIVATION {
390 my ($msg, $msg_hash, $session_id) = @_;
391 my $header = @{$msg_hash->{'header'}}[0];
392 my $source = @{$msg_hash->{'source'}}[0];
393 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
395 # test whether content is an empty hash or a string which is required
396 my $content = @{$msg_hash->{$header}}[0];
397 if(ref($content) eq "HASH") { $content = ""; }
399 # clean up header
400 $header =~ s/CLMSG_//g;
402 my $sql_statement = "UPDATE $main::job_queue_tn ".
403 "SET progress='goto-activation', modified='1' ".
404 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
405 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
406 my $res = $main::job_db->update_dbentry($sql_statement);
407 &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5);
408 return;
409 }
412 ## @method PROGRESS()
413 # @details Message reports installation progress of the client. Installation job at job_queue_db is going to be updated.
414 # @param msg - STRING - xml message with tags 'macaddress' and 'PROGRESS'
415 # @param msg_hash - HASHREF - message information parsed into a hash
416 # @param session_id - INTEGER - POE session id of the processing of this message
417 sub PROGRESS {
418 my ($msg, $msg_hash, $session_id) = @_;
419 my $header = @{$msg_hash->{'header'}}[0];
420 my $source = @{$msg_hash->{'source'}}[0];
421 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
423 # test whether content is an empty hash or a string which is required
424 my $content = @{$msg_hash->{$header}}[0];
425 if(ref($content) eq "HASH") { $content = ""; }
427 # clean up header
428 $header =~ s/CLMSG_//g;
430 my $sql_statement = "UPDATE $main::job_queue_tn ".
431 "SET progress='$content', modified='1' ".
432 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
433 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
434 my $res = $main::job_db->update_dbentry($sql_statement);
435 &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5);
437 return;
438 }
441 ## @method FAIREBOOT()
442 # @details Message reports a FAI reboot. Job at job_queue_db is going to be updated.
443 # @param msg - STRING - xml message with tag 'macaddress' and 'FAIREBOOT'
444 # @param msg_hash - HASHREF - message information parsed into a hash
445 # @param session_id - INTEGER - POE session id of the processing of this message
446 sub FAIREBOOT {
447 my ($msg, $msg_hash, $session_id) = @_;
448 my $header = @{$msg_hash->{'header'}}[0];
449 my $source = @{$msg_hash->{'source'}}[0];
450 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
452 # test whether content is an empty hash or a string which is required
453 my $content = @{$msg_hash->{$header}}[0];
454 if(ref($content) eq "HASH") { $content = ""; }
456 # clean up header
457 $header =~ s/CLMSG_//g;
459 my $sql_statement = "UPDATE $main::job_queue_tn ".
460 "SET result='$header "."$content', modified='1' ".
461 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
462 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
463 my $res = $main::job_db->update_dbentry($sql_statement);
464 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
466 return;
467 }
470 ## @method TASKSKIP()
471 # @details Message reports a skipped FAI task. Job at job_queue_db is going to be updated.
472 # @param msg - STRING - xml message with tag 'macaddress'.
473 # @param msg_hash - HASHREF - message information parsed into a hash
474 # @param session_id - INTEGER - POE session id of the processing of this message
475 sub TASKSKIP {
476 my ($msg, $msg_hash, $session_id) = @_;
477 my $header = @{$msg_hash->{'header'}}[0];
478 my $source = @{$msg_hash->{'source'}}[0];
479 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
481 # test whether content is an empty hash or a string which is required
482 my $content = @{$msg_hash->{$header}}[0];
483 if(ref($content) eq "HASH") { $content = ""; }
485 # clean up header
486 $header =~ s/CLMSG_//g;
488 my $sql_statement = "UPDATE $main::job_queue_tn ".
489 "SET result='$header "."$content', modified='1' ".
490 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
491 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
492 my $res = $main::job_db->update_dbentry($sql_statement);
493 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
495 return;
496 }
499 ## @method TASKBEGIN()
500 # @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', 'tests' or 'confdir', just do nothing. In all other cases, job at job_queue_db is going to be updated or created if not exists.
501 # @param msg - STRING - xml message with tag 'macaddress'.
502 # @param msg_hash - HASHREF - message information parsed into a hash
503 # @param session_id - INTEGER - POE session id of the processing of this message
504 sub TASKBEGIN {
505 my ($msg, $msg_hash, $session_id) = @_;
506 my $header = @{$msg_hash->{'header'}}[0];
507 my $source = @{$msg_hash->{'source'}}[0];
508 my $target = @{$msg_hash->{'target'}}[0];
509 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
511 # test whether content is an empty hash or a string which is required
512 my $content = @{$msg_hash->{$header}}[0];
513 if(ref($content) eq "HASH") { $content = ""; }
515 # clean up header
516 $header =~ s/CLMSG_//g;
518 # TASKBEGIN eq finish or faiend
519 if (($content eq 'finish')
520 || ($content eq 'faiend')
521 || ($content eq 'savelog')
522 ) {
523 my $sql_statement = "UPDATE $main::job_queue_tn ".
524 "SET status='done', result='$header "."$content', modified='1' ".
525 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
526 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
527 my $res = $main::job_db->update_dbentry($sql_statement);
528 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
530 # set fai_state to localboot
531 &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
533 # TASKBEGIN eq chboot
534 } elsif (($content eq 'chboot')
535 || ($content eq 'tests')
536 || ($content eq 'confdir')
537 ) {
538 # just ignor this client message
539 # do nothing
541 # other TASKBEGIN msgs
542 } else {
544 # TASKBEGIN msgs do only occour during a softupdate or a reinstallation
545 # of a host. Set all waiting update- or reinstall-jobs for host to
546 # processing so they can be handled correctly by the rest of the function.
547 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
548 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')";
549 &main::daemon_log("$session_id DEBUB: $waiting_sql", 7);
550 my $waiting_res = $main::job_db->update_dbentry($waiting_sql);
552 # select processing jobs for host
553 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
554 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
555 my $res = $main::job_db->select_dbentry($sql_statement);
557 # there is exactly one job entry in queue for this host
558 if (keys(%$res) == 1) {
559 &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
560 my $sql_statement = "UPDATE $main::job_queue_tn ".
561 "SET result='$header $content', modified='1', siserver='localhost' ".
562 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
563 my $err = $main::job_db->update_dbentry($sql_statement);
564 if (not defined $err) {
565 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
566 }
568 # there is no entry or more than one enties
569 } else {
570 # in case of more than one running jobs in queue, delete all jobs
571 if (keys(%$res) > 1) {
572 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
573 "delete entries", 7);
575 # set job to status 'done', job will be deleted automatically
576 my $sql_statement = "UPDATE $main::job_queue_tn ".
577 "SET status='done', modified='1'".
578 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
579 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
580 my $res = $main::job_db->update_dbentry( $sql_statement );
582 }
584 # in case of no and more than one running jobs in queue, add one single job
585 # resolve plain name for host $macaddress
586 my $plain_name;
587 my $ldap_handle = &main::get_ldap_handle($session_id);
588 if( not defined $ldap_handle ) {
589 &main::daemon_log("$session_id ERROR: cannot connect to ldap", 1);
590 $plain_name = "none";
592 # try to fetch a 'real name'
593 } else {
594 my $mesg = $ldap_handle->search(
595 base => $main::ldap_base,
596 scope => 'sub',
597 attrs => ['cn'],
598 filter => "(macAddress=$macaddress)");
599 if($mesg->code) {
600 &main::daemon_log($mesg->error, 1);
601 $plain_name = "none";
602 } else {
603 my $entry= $mesg->entry(0);
604 $plain_name = $entry->get_value("cn");
605 }
606 }
608 # In any case add a new job to job queue
609 &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7);
610 my $func_dic = {table=>$main::job_queue_tn,
611 primkey=>['macaddress', 'headertag'],
612 timestamp=>&get_time,
613 status=>'processing',
614 result=>"$header $content",
615 progress=>'none',
616 headertag=>'trigger_action_reinstall',
617 targettag=>$target,
618 xmlmessage=>'none',
619 macaddress=>$macaddress,
620 plainname=>$plain_name,
621 modified=>'1',
622 siserver=>'localhost',
623 };
624 my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
625 if ($err != 0) {
626 &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
627 }
628 }
629 }
631 return;
632 }
635 ## @method TASKEND()
636 # @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.
637 # @param msg - STRING - xml message with tag 'macaddress'.
638 # @param msg_hash - HASHREF - message information parsed into a hash
639 # @param session_id - INTEGER - POE session id of the processing of this message
640 sub TASKEND {
641 my ($msg, $msg_hash, $session_id) = @_;
642 my $header = @{$msg_hash->{'header'}}[0];
643 my $target = @{$msg_hash->{'target'}}[0];
644 my $source = @{$msg_hash->{'source'}}[0];
645 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
647 # test whether content is an empty hash or a string which is required
648 my $content = @{$msg_hash->{$header}}[0];
649 if(ref($content) eq "HASH") { $content = ""; }
651 # clean up header
652 $header =~ s/CLMSG_//g;
654 if ($content eq "savelog 0") {
655 &main::daemon_log("$session_id DEBUG: got savelog from host '$target' - job done", 7);
657 # set job to status 'done', job will be deleted automatically
658 my $sql_statement = "UPDATE $main::job_queue_tn ".
659 "SET status='done', modified='1'".
660 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
661 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
662 my $res = $main::job_db->update_dbentry( $sql_statement );
664 } else {
665 my $sql_statement = "UPDATE $main::job_queue_tn ".
666 "SET result='$header "."$content', modified='1' ".
667 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
668 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
669 my $res = $main::job_db->update_dbentry($sql_statement);
670 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
671 }
673 return;
674 }
677 ## @method TASKERROR()
678 # @details Message reports a FAI error. Job at job_queue_db is going to be updated.
679 # @param msg - STRING - xml message with tag 'macaddress' and 'TASKERROR'
680 # @param msg_hash - HASHREF - message information parsed into a hash
681 # @param session_id - INTEGER - POE session id of the processing of this message
682 sub TASKERROR {
683 my ($msg, $msg_hash, $session_id) = @_;
684 my $header = @{$msg_hash->{'header'}}[0];
685 my $source = @{$msg_hash->{'source'}}[0];
686 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
688 # clean up header
689 $header =~ s/CLMSG_//g;
691 # test whether content is an empty hash or a string which is required
692 my $content = @{$msg_hash->{$header}}[0];
693 if(ref($content) eq "HASH") { $content = ""; }
695 # set fai_state to localboot
696 &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
698 my $sql_statement = "UPDATE $main::job_queue_tn ".
699 "SET result='$header "."$content', modified='1' ".
700 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
701 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
702 my $res = $main::job_db->update_dbentry($sql_statement);
703 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
705 return;
706 }
709 ## @method HOOK()
710 # @details Message reports a FAI hook. Job at job_queue_db is going to be updated.
711 # @param msg - STRING - xml message with tag 'macaddress' and 'HOOK'
712 # @param msg_hash - HASHREF - message information parsed into a hash
713 # @param session_id - INTEGER - POE session id of the processing of this message
714 sub HOOK {
715 my ($msg, $msg_hash, $session_id) = @_;
716 my $header = @{$msg_hash->{'header'}}[0];
717 my $source = @{$msg_hash->{'source'}}[0];
718 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
720 # clean up header
721 $header =~ s/CLMSG_//g;
723 # test whether content is an empty hash or a string which is required
724 my $content = @{$msg_hash->{$header}}[0];
725 if(not ref($content) eq "STRING") { $content = ""; }
727 my $sql_statement = "UPDATE $main::job_queue_tn ".
728 "SET result='$header "."$content', modified='1' ".
729 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
730 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
731 my $res = $main::job_db->update_dbentry($sql_statement);
732 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
734 return;
735 }
738 =pod
740 =head1 NAME
742 clMessages - Implementation of a GOsa-SI event module for GOsa-SI-server.
744 =head1 SYNOPSIS
746 use GOSA::GosaSupportDaemon;
747 use MIME::Base64;
749 =head1 DESCRIPTION
751 This GOsa-SI event module containing all functions to handle messages coming from GOsa-SI-clients.
753 This module will be automatically imported by GOsa-SI if it is under F</usr/lib/gosa-si/server/E<lt>PACKAGEMODULEE<gt>/> .
755 =head1 METHODS
757 =over 4
759 =item get_events ( )
761 =item confirm_usr_msg ( )
763 =item PROGRESS ( )
765 =item FAIREBOOT ( )
767 =item TASKSKIP ( )
769 =item TASKBEGIN ( )
771 =item TASKEND ( )
773 =item TASKERROR ( )
775 =item HOOK ( )
777 =item GOTOACTIVATION ( )
779 =item LOGIN ( )
781 =item LOGOUT ( )
783 =item CURRENTLY_LOGGED_IN ( )
785 =item save_fai_log ( )
787 =back
789 =head1 BUGS
791 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>
793 =head1 COPYRIGHT
795 This code is part of GOsa (L<http://www.gosa-project.org>)
797 Copyright (C) 2003-2008 GONICUS GmbH
799 This program is distributed in the hope that it will be useful,
800 but WITHOUT ANY WARRANTY; without even the implied warranty of
801 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
802 GNU General Public License for more details.
804 =cut
807 1;