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 Data::Dumper;
12 use MIME::Base64;
13 use GOsaSI::GosaSupportDaemon;
15 use Exporter;
17 our @ISA = qw(Exporter);
19 my @events = (
20 "confirm_usr_msg",
21 "PROGRESS",
22 "FAIREBOOT",
23 "TASKSKIP",
24 "TASKBEGIN",
25 "TASKEND",
26 "TASKERROR",
27 "HOOK",
28 "GOTOACTIVATION",
29 "LOGIN",
30 "LOGOUT",
31 "CURRENTLY_LOGGED_IN",
32 "save_fai_log",
33 );
34 our @EXPORT = @events;
36 BEGIN {}
38 END {}
41 ## @method get_events()
42 # @details A brief function returning a list of functions which are exported by importing the module.
43 # @return List of all provided functions
44 sub get_events {
45 return \@events;
46 }
48 ## @method confirm_usr_msg()
49 # @details Confirmed messages are set in the messaging_db from d (deliverd) to s(seen).
50 # @param msg - STRING - xml message with tags 'message', 'subject' and 'usr'
51 # @param msg_hash - HASHREF - message information parsed into a hash
52 # @param session_id - INTEGER - POE session id of the processing of this message
53 sub confirm_usr_msg {
54 my ($msg, $msg_hash, $session_id) = @_;
55 my $message = @{$msg_hash->{'message'}}[0];
56 my $subject = @{$msg_hash->{'subject'}}[0];
57 my $usr = @{$msg_hash->{'usr'}}[0];
59 # set update for this message
60 my $sql = "UPDATE $main::messaging_tn SET flag='s' WHERE (message='$message' AND subject='$subject' AND message_to='$usr')";
61 &main::daemon_log("$session_id DEBUG: $sql", 7);
62 my $res = $main::messaging_db->exec_statement($sql);
65 return;
66 }
69 ## @method save_fai_log()
70 # @details Creates under /var/log/fai/ the directory '$macaddress' and stores within all FAI log files from client.
71 # @param msg - STRING - xml message with tags 'macaddress' and 'save_fai_log'
72 # @param msg_hash - HASHREF - message information parsed into a hash
73 # @param session_id - INTEGER - POE session id of the processing of this message
74 sub save_fai_log {
75 my ($msg, $msg_hash, $session_id) = @_;
76 my $header = @{$msg_hash->{'header'}}[0];
77 my $source = @{$msg_hash->{'source'}}[0];
78 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
79 my $all_logs = @{$msg_hash->{$header}}[0];
81 # if there is nothing to log
82 if( ref($all_logs) eq "HASH" ) {
83 &main::daemon_log("$session_id INFO: There is nothing to log!", 5);
84 return;
85 }
87 my $client_fai_log_dir = $main::client_fai_log_dir;
88 if (not -d $client_fai_log_dir) {
89 mkdir($client_fai_log_dir, 0755)
90 }
92 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $macaddress );
93 if (not -d $client_fai_log_dir) {
94 mkdir($client_fai_log_dir, 0755)
95 }
97 my $time = &get_time;
98 $time = substr($time, 0, 8)."_".substr($time, 8, 6);
99 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, "install_$time" );
100 mkdir($client_fai_log_dir, 0755);
102 my @all_logs = split(/log_file:/, $all_logs);
103 foreach my $log (@all_logs) {
104 if (length $log == 0) { next; };
105 my ($log_file, $log_string) = split(":", $log);
106 my $client_fai_log_file = File::Spec->catfile( $client_fai_log_dir, $log_file);
108 open(my $LOG_FILE, ">", "$client_fai_log_file");
109 print $LOG_FILE &decode_base64($log_string);
110 close($LOG_FILE);
111 chown($main::root_uid, $main::adm_gid, $client_fai_log_file);
112 chmod(0440, $client_fai_log_file);
114 }
115 return;
116 }
118 ## @method LOGIN()
119 # @details Reported user from client is added to login_users_db.
120 # @param msg - STRING - xml message with tag 'LOGIN'
121 # @param msg_hash - HASHREF - message information parsed into a hash
122 # @param session_id - INTEGER - POE session id of the processing of this message
123 sub LOGIN {
124 my ($msg, $msg_hash, $session_id) = @_;
125 my $header = @{$msg_hash->{'header'}}[0];
126 my $source = @{$msg_hash->{'source'}}[0];
127 my $login = @{$msg_hash->{$header}}[0];
128 my $res;
129 my $error_str;
131 # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
132 $res = &set_last_system($msg, $msg_hash, $session_id);
134 # Add user to login_users_db
135 my %add_hash = ( table=>$main::login_users_tn,
136 primkey=> ['client', 'user'],
137 client=>$source,
138 user=>$login,
139 timestamp=>&get_time,
140 regserver=>'localhost',
141 );
142 ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
143 if ($res != 0) {
144 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
145 return;
146 }
148 # Share login information with all other si-server
149 my %data = ( 'new_user' => "$source;$login" );
150 my $info_msg = &build_msg("information_sharing", $main::server_address, "KNOWN_SERVER", \%data);
152 return ($info_msg);
153 }
156 ## @method LOGOUT()
157 # @details Reported user from client is deleted from login_users_db.
158 # @param msg - STRING - xml message with tag 'LOGOUT'
159 # @param msg_hash - HASHREF - message information parsed into a hash
160 # @param session_id - INTEGER - POE session id of the processing of this message
161 sub LOGOUT {
162 my ($msg, $msg_hash, $session_id) = @_;
163 my $header = @{$msg_hash->{'header'}}[0];
164 my $source = @{$msg_hash->{'source'}}[0];
165 my $login = @{$msg_hash->{$header}}[0];
167 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')";
168 my $res = $main::login_users_db->del_dbentry($sql_statement);
169 &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5);
171 return;
172 }
175 ## @method CURRENTLY_LOGGED_IN()
176 # @details Reported users from client are updated in login_users_db. Users which are no longer logged in are deleted from DB.
177 # @param msg - STRING - xml message
178 # @param msg_hash - HASHREF - message information parsed into a hash
179 # @param session_id - INTEGER - POE session id of the processing of this message
180 sub CURRENTLY_LOGGED_IN {
181 my ($msg, $msg_hash, $session_id) = @_;
182 my ($sql_statement, $db_res);
183 my $header = @{$msg_hash->{'header'}}[0];
184 my $source = @{$msg_hash->{'source'}}[0];
185 my $login = @{$msg_hash->{$header}}[0];
187 if(ref $login eq "HASH") {
188 &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5);
189 return;
190 }
192 # Invoke set_last_system; message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
193 my $res = &set_last_system($msg, $msg_hash, $session_id);
195 # fetch all user currently assigned to the client at login_users_db
196 my %currently_logged_in_user = ();
197 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'";
198 $db_res = $main::login_users_db->select_dbentry($sql_statement);
199 while( my($hit_id, $hit) = each(%{$db_res}) ) {
200 $currently_logged_in_user{$hit->{'user'}} = 1;
201 }
202 &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7);
204 # update all reported users in login_user_db
205 my @logged_in_user = split(/\s+/, $login);
206 &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7);
207 foreach my $user (@logged_in_user) {
208 my %add_hash = ( table=>$main::login_users_tn,
209 primkey=> ['client', 'user'],
210 client=>$source,
211 user=>$user,
212 timestamp=>&get_time,
213 regserver=>'localhost',
214 );
215 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
216 if ($res != 0) {
217 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
218 return;
219 }
221 delete $currently_logged_in_user{$user};
222 }
224 # if there is still a user in %currently_logged_in_user
225 # although he is not reported by client
226 # then delete it from $login_user_db
227 foreach my $obsolete_user (keys(%currently_logged_in_user)) {
228 &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
229 "in at client '$source' but still found at login_user_db", 3);
230 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'";
231 my $res = $main::login_users_db->del_dbentry($sql_statement);
232 &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3);
233 }
235 # Delete all users which logged in information is older than their logged_in_user_date_of_expiry
236 my $act_time = &get_time();
237 my $expiry_date = &calc_timestamp($act_time, "minus", $main::logged_in_user_date_of_expiry);
239 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE CAST(timestamp as UNSIGNED)<$expiry_date";
240 $db_res = $main::login_users_db->select_dbentry($sql_statement);
242 while( my($hit_id, $hit) = each(%{$db_res}) ) {
243 &main::daemon_log("$session_id INFO: user '".$hit->{'user'}."' is no longer reported to be logged in at host '".$hit->{'client'}."'", 5);
244 my $sql = "DELETE FROM $main::login_users_tn WHERE (client='".$hit->{'client'}."' AND user='".$hit->{'user'}."')";
245 my $res = $main::login_users_db->del_dbentry($sql);
246 &main::daemon_log("$session_id INFO: delete user '".$hit->{'user'}."' at client '".$hit->{'client'}."' from login_user_db", 5);
247 }
249 # Inform all other server which users are logged in at clients registered at local server
250 my $info_sql = "SELECT * FROM $main::login_users_tn WHERE regserver='localhost'";
251 my $info_res = $main::login_users_db->select_dbentry($info_sql);
252 my $info_msg_hash = &create_xml_hash("information_sharing", $main::server_address, "KNOWN_SERVER");
253 while (my ($hit_id, $hit) = each(%$info_res)) {
254 &add_content2xml_hash($info_msg_hash, 'user_db', $hit->{'client'}.";".$hit->{'user'});
255 }
256 my $info_msg = &create_xml_string($info_msg_hash);
258 return ($info_msg);
259 }
262 ## @method set_last_system()
263 # @details Message sets ldap attributes 'gotoLastSystemLogin' and 'gotoLastSystem'
264 # @param msg - STRING - xml message with tag 'last_system_login' and 'last_system'
265 # @param msg_hash - HASHREF - message information parsed into a hash
266 # @param session_id - INTEGER - POE session id of the processing of this message
267 sub set_last_system {
268 my ($msg, $msg_hash, $session_id) = @_;
269 my $header = @{$msg_hash->{'header'}}[0];
270 my $source = @{$msg_hash->{'source'}}[0];
271 my $login = @{$msg_hash->{$header}}[0];
273 # Sanity check of needed parameter
274 if (not exists $msg_hash->{'timestamp'}){
275 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'timestamp', ".
276 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
277 &main::daemon_log($msg, 1);
278 return;
279 }
280 if (@{$msg_hash->{'timestamp'}} != 1) {
281 &main::daemon_log("$session_id ERROR: xml tag 'timestamp' 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 }
286 if (not exists $msg_hash->{'macaddress'}){
287 &main::daemon_log("$session_id ERROR: message does not contain needed xml tag 'mac_address', ".
288 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
289 &main::daemon_log($msg, 1);
290 return;
291 }
292 if (@{$msg_hash->{'macaddress'}} != 1) {
293 &main::daemon_log("$session_id ERROR: xml tag 'macaddress' has no content or exists more than one time, ".
294 "setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
295 &ymain::daemon_log($msg, 1);
296 return;
297 }
299 # Fetch needed parameter
300 my $mac = @{$msg_hash->{'macaddress'}}[0];
301 my $timestamp = @{$msg_hash->{'timestamp'}}[0];
303 # Prepare login list
304 my @login_list = split(' ', @{$msg_hash->{$header}}[0] );
305 @login_list = &main::del_doubles(@login_list);
307 # Sanity check of login list
308 if (@login_list == 0) {
309 # TODO
310 return;
311 }
313 # Get system info
314 my $ldap_handle=&main::get_ldap_handle($session_id);
315 my $ldap_mesg= $ldap_handle->search(
316 base => $main::ldap_base,
317 scope => 'sub',
318 filter => "macAddress=$mac",
319 );
320 if ($ldap_mesg->count == 0) {
321 &main::daemon_log("$session_id ERROR: no system with mac address='$mac' was found in base '".
322 $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
323 &main::release_ldap_handle($ldap_handle);
324 return;
325 }
327 my $ldap_entry = $ldap_mesg->pop_entry();
328 my $system_dn = $ldap_entry->dn();
330 # For each logged in user set gotoLastSystem and gotoLastSystemLogin
331 foreach my $user (@login_list) {
332 # Search user
333 my $ldap_mesg= $ldap_handle->search(
334 base => $main::ldap_base,
335 scope => 'sub',
336 filter => "(&(objectClass=gosaAccount)(uid=$user))",
337 );
338 # Sanity check of user search
339 if ($ldap_mesg->count == 0) {
340 &main::daemon_log("$session_id WARNING: no user with uid='$user' was found in base '".
341 $main::ldap_base."', setting of 'gotoLastSystem' and 'gotoLastSystemLogin' stopped!", 1);
343 # Set gotoLastSystem and gotoLastSystemLogin
344 } else {
345 my $ldap_entry= $ldap_mesg->pop_entry();
346 my $do_update = 0;
348 # Set gotoLastSystem information
349 my $last_system_dn = $ldap_entry->get_value('gotoLastSystem');
350 if ((defined $last_system_dn) && ($last_system_dn eq $system_dn)) {
351 &main::daemon_log("$session_id INFO: no new 'gotoLastSystem' information for ldap entry 'uid=$user', do nothing!", 5);
352 } elsif ((defined $last_system_dn) && ($last_system_dn ne $system_dn)) {
353 $ldap_entry->replace ( 'gotoLastSystem' => $system_dn );
354 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!",5);
355 $do_update++;
356 } else {
357 $ldap_entry->add( 'gotoLastSystem' => $system_dn );
358 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystem'='$system_dn' at ldap entry 'uid=$user'!", 5);
359 $do_update++;
360 }
362 # Set gotoLastSystemLogin information
363 # Attention: only write information if last_system_dn and system_dn differs
364 my $last_system_login = $ldap_entry->get_value('gotoLastSystemLogin');
365 if ((defined $last_system_login) && ($last_system_dn eq $system_dn)) {
366 &main::daemon_log("$session_id INFO: no new 'gotoLastSystemLogin' information for ldap entry 'uid=$user', do nothing!", 5);
367 } elsif ((defined $last_system_login) && ($last_system_dn ne $system_dn)) {
368 $ldap_entry->replace ( 'gotoLastSystemLogin' => $timestamp );
369 &main::daemon_log("$session_id INFO: update attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!", 5);
370 $do_update++;
371 } else {
372 $ldap_entry->add( 'gotoLastSystemLogin' => $timestamp );
373 &main::daemon_log("$session_id INFO: add attribute 'gotoLastSystemLogin'='$timestamp' at ldap entry 'uid=$user'!",5);
374 $do_update++;
375 }
377 if ($do_update) {
378 my $result = $ldap_entry->update($ldap_handle);
379 if ($result->code() != 0) {
380 &main::daemon_log("$session_id ERROR: setting 'gotoLastSystem' and 'gotoLastSystemLogin' at user '$user' failed: ".
381 $result->{'errorMessage'}."\n".
382 "\tbase: $main::ldap_base\n".
383 "\tscope: 'sub'\n".
384 "\tfilter: 'uid=$user'\n".
385 "\tmessage: $msg", 1);
386 }
387 }
388 }
389 }
390 &main::release_ldap_handle($ldap_handle);
392 return;
393 }
396 ## @method GOTOACTIVATION()
397 # @details Client is set at job_queue_db to status 'processing' and 'modified'.
398 # @param msg - STRING - xml message with tag 'macaddress'
399 # @param msg_hash - HASHREF - message information parsed into a hash
400 # @param session_id - INTEGER - POE session id of the processing of this message
401 sub GOTOACTIVATION {
402 my ($msg, $msg_hash, $session_id) = @_;
403 my $header = @{$msg_hash->{'header'}}[0];
404 my $source = @{$msg_hash->{'source'}}[0];
405 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
407 # test whether content is an empty hash or a string which is required
408 my $content = @{$msg_hash->{$header}}[0];
409 if(ref($content) eq "HASH") { $content = ""; }
411 # clean up header
412 $header =~ s/CLMSG_//g;
414 my $sql_statement = "UPDATE $main::job_queue_tn ".
415 "SET progress='goto-activation', modified='1' ".
416 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
417 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
418 my $res = $main::job_db->update_dbentry($sql_statement);
419 &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5);
420 return;
421 }
424 ## @method PROGRESS()
425 # @details Message reports installation progress of the client. Installation job at job_queue_db is going to be updated.
426 # @param msg - STRING - xml message with tags 'macaddress' and 'PROGRESS'
427 # @param msg_hash - HASHREF - message information parsed into a hash
428 # @param session_id - INTEGER - POE session id of the processing of this message
429 sub PROGRESS {
430 my ($msg, $msg_hash, $session_id) = @_;
431 my $header = @{$msg_hash->{'header'}}[0];
432 my $source = @{$msg_hash->{'source'}}[0];
433 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
435 # test whether content is an empty hash or a string which is required
436 my $content = @{$msg_hash->{$header}}[0];
437 if(ref($content) eq "HASH") { $content = ""; }
439 # clean up header
440 $header =~ s/CLMSG_//g;
442 my $sql_statement = "UPDATE $main::job_queue_tn ".
443 "SET progress='$content', modified='1' ".
444 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
445 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
446 my $res = $main::job_db->update_dbentry($sql_statement);
447 &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5);
449 return;
450 }
453 ## @method FAIREBOOT()
454 # @details Message reports a FAI reboot. Job at job_queue_db is going to be updated.
455 # @param msg - STRING - xml message with tag 'macaddress' and 'FAIREBOOT'
456 # @param msg_hash - HASHREF - message information parsed into a hash
457 # @param session_id - INTEGER - POE session id of the processing of this message
458 sub FAIREBOOT {
459 my ($msg, $msg_hash, $session_id) = @_;
460 my $header = @{$msg_hash->{'header'}}[0];
461 my $source = @{$msg_hash->{'source'}}[0];
462 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
464 # test whether content is an empty hash or a string which is required
465 my $content = @{$msg_hash->{$header}}[0];
466 if(ref($content) eq "HASH") { $content = ""; }
468 # clean up header
469 $header =~ s/CLMSG_//g;
471 my $sql_statement = "UPDATE $main::job_queue_tn ".
472 "SET result='$header "."$content', modified='1' ".
473 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
474 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
475 my $res = $main::job_db->update_dbentry($sql_statement);
476 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
478 return;
479 }
482 ## @method TASKSKIP()
483 # @details Message reports a skipped FAI task. Job at job_queue_db is going to be updated.
484 # @param msg - STRING - xml message with tag 'macaddress'.
485 # @param msg_hash - HASHREF - message information parsed into a hash
486 # @param session_id - INTEGER - POE session id of the processing of this message
487 sub TASKSKIP {
488 my ($msg, $msg_hash, $session_id) = @_;
489 my $header = @{$msg_hash->{'header'}}[0];
490 my $source = @{$msg_hash->{'source'}}[0];
491 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
493 # test whether content is an empty hash or a string which is required
494 my $content = @{$msg_hash->{$header}}[0];
495 if(ref($content) eq "HASH") { $content = ""; }
497 # clean up header
498 $header =~ s/CLMSG_//g;
500 my $sql_statement = "UPDATE $main::job_queue_tn ".
501 "SET result='$header "."$content', modified='1' ".
502 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
503 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
504 my $res = $main::job_db->update_dbentry($sql_statement);
505 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
507 return;
508 }
511 ## @method TASKBEGIN()
512 # @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.
513 # @param msg - STRING - xml message with tag 'macaddress'.
514 # @param msg_hash - HASHREF - message information parsed into a hash
515 # @param session_id - INTEGER - POE session id of the processing of this message
516 sub TASKBEGIN {
517 my ($msg, $msg_hash, $session_id) = @_;
518 my $header = @{$msg_hash->{'header'}}[0];
519 my $source = @{$msg_hash->{'source'}}[0];
520 my $target = @{$msg_hash->{'target'}}[0];
521 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
523 # test whether content is an empty hash or a string which is required
524 my $content = @{$msg_hash->{$header}}[0];
525 if(ref($content) eq "HASH") { $content = ""; }
527 # clean up header
528 $header =~ s/CLMSG_//g;
530 # TASKBEGIN eq finish or faiend
531 if (($content eq 'finish')
532 || ($content eq 'faiend')
533 || ($content eq 'savelog')
534 ) {
535 my $sql_statement = "UPDATE $main::job_queue_tn ".
536 "SET status='done', result='$header "."$content', modified='1' ".
537 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
538 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
539 my $res = $main::job_db->update_dbentry($sql_statement);
540 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
542 # set fai_state to localboot
543 &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
545 # TASKBEGIN eq chboot
546 } elsif (($content eq 'chboot')
547 || ($content eq 'test')
548 || ($content eq 'confdir')
549 ) {
550 # just ignor this client message
551 # do nothing
553 # other TASKBEGIN msgs
554 } else {
555 # TASKBEGIN msgs do only occour during a softupdate or a reinstallation
556 # of a host. Set all waiting update- or reinstall-jobs for host to
557 # processing so they can be handled correctly by the rest of the function.
558 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')";
559 &main::daemon_log("$session_id DEBUB: $waiting_sql", 7);
560 my $waiting_res = $main::job_db->update_dbentry($waiting_sql);
562 # Select processing jobs for host
563 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
564 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
565 my $res = $main::job_db->select_dbentry($sql_statement);
567 # there is exactly one job entry in queue for this host
568 if (keys(%$res) == 1) {
569 &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
570 my $sql_statement = "UPDATE $main::job_queue_tn SET result='$header $content', modified='1', siserver='localhost' WHERE status='processing' AND macaddress LIKE '$macaddress'";
571 my $err = $main::job_db->update_dbentry($sql_statement);
572 if (not defined $err) {
573 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
574 }
576 # There is no entry in queue or more than one entries in queue for this host
577 } else {
578 # In case of more than one running jobs in queue, delete all jobs
579 if (keys(%$res) > 1) {
580 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
581 "delete entries", 7);
583 # set job to status 'done', job will be deleted automatically
584 my $sql_statement = "UPDATE $main::job_queue_tn ".
585 "SET status='done', modified='1'".
586 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
587 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
588 my $res = $main::job_db->update_dbentry( $sql_statement );
590 }
592 # In case of no and more than one running jobs in queue, add one single job
594 # Resolve plain name for host $macaddress
595 my $plain_name;
596 my $ldap_handle=&main::get_ldap_handle($session_id);
597 my $mesg = $ldap_handle->search(
598 base => $main::ldap_base,
599 scope => 'sub',
600 attrs => ['cn'],
601 filter => "(macAddress=$macaddress)");
602 if(not $mesg->code) {
603 my $entry= $mesg->entry(0);
604 $plain_name = $entry->get_value("cn");
605 } else {
606 &main::daemon_log($mesg->error, 1);
607 $plain_name = "none";
608 }
609 &main::release_ldap_handle($ldap_handle);
611 # In any case add a new job to job queue
612 &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7);
613 my $func_dic = {table=>$main::job_queue_tn,
614 primkey=>['macaddress', 'headertag'],
615 timestamp=>&get_time,
616 status=>'processing',
617 result=>"$header $content",
618 progress=>'none',
619 headertag=>'trigger_action_reinstall',
620 targettag=>$target,
621 xmlmessage=>'none',
622 macaddress=>$macaddress,
623 plainname=>$plain_name,
624 modified=>'1',
625 siserver=>'localhost',
626 };
627 my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
628 if ($err != 0) {
629 &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
630 }
631 }
632 }
634 return;
635 }
638 ## @method TASKEND()
639 # @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.
640 # @param msg - STRING - xml message with tag 'macaddress'.
641 # @param msg_hash - HASHREF - message information parsed into a hash
642 # @param session_id - INTEGER - POE session id of the processing of this message
643 sub TASKEND {
644 my ($msg, $msg_hash, $session_id) = @_;
645 my $header = @{$msg_hash->{'header'}}[0];
646 my $target = @{$msg_hash->{'target'}}[0];
647 my $source = @{$msg_hash->{'source'}}[0];
648 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
650 # test whether content is an empty hash or a string which is required
651 my $content = @{$msg_hash->{$header}}[0];
652 if(ref($content) eq "HASH") { $content = ""; }
654 # clean up header
655 $header =~ s/CLMSG_//g;
657 if ($content eq "savelog 0") {
658 &main::daemon_log("$session_id DEBUG: got savelog from host '$target' - job done", 7);
660 # set job to status 'done', job will be deleted automatically
661 my $sql_statement = "UPDATE $main::job_queue_tn ".
662 "SET status='done', modified='1'".
663 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
664 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
665 my $res = $main::job_db->update_dbentry( $sql_statement );
667 } else {
668 my $sql_statement = "UPDATE $main::job_queue_tn ".
669 "SET result='$header "."$content', modified='1' ".
670 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
671 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
672 my $res = $main::job_db->update_dbentry($sql_statement);
673 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
674 }
676 return;
677 }
680 ## @method TASKERROR()
681 # @details Message reports a FAI error. Job at job_queue_db is going to be updated.
682 # @param msg - STRING - xml message with tag 'macaddress' and 'TASKERROR'
683 # @param msg_hash - HASHREF - message information parsed into a hash
684 # @param session_id - INTEGER - POE session id of the processing of this message
685 sub TASKERROR {
686 my ($msg, $msg_hash, $session_id) = @_;
687 my $header = @{$msg_hash->{'header'}}[0];
688 my $source = @{$msg_hash->{'source'}}[0];
689 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
691 # clean up header
692 $header =~ s/CLMSG_//g;
694 # test whether content is an empty hash or a string which is required
695 my $content = @{$msg_hash->{$header}}[0];
696 if(ref($content) eq "HASH") { $content = ""; }
698 # set fai_state to localboot
699 &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
701 my $sql_statement = "UPDATE $main::job_queue_tn ".
702 "SET result='$header "."$content', modified='1' ".
703 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
704 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
705 my $res = $main::job_db->update_dbentry($sql_statement);
706 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
708 return;
709 }
712 ## @method HOOK()
713 # @details Message reports a FAI hook. Job at job_queue_db is going to be updated.
714 # @param msg - STRING - xml message with tag 'macaddress' and 'HOOK'
715 # @param msg_hash - HASHREF - message information parsed into a hash
716 # @param session_id - INTEGER - POE session id of the processing of this message
717 sub HOOK {
718 my ($msg, $msg_hash, $session_id) = @_;
719 my $header = @{$msg_hash->{'header'}}[0];
720 my $source = @{$msg_hash->{'source'}}[0];
721 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
723 # clean up header
724 $header =~ s/CLMSG_//g;
726 # test whether content is an empty hash or a string which is required
727 my $content = @{$msg_hash->{$header}}[0];
728 if(not ref($content) eq "STRING") { $content = ""; }
730 my $sql_statement = "UPDATE $main::job_queue_tn ".
731 "SET result='$header "."$content', modified='1' ".
732 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
733 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
734 my $res = $main::job_db->update_dbentry($sql_statement);
735 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
737 return;
738 }
741 =pod
743 =head1 NAME
745 clMessages - Implementation of a GOsa-SI event module for GOsa-SI-server.
747 =head1 SYNOPSIS
749 use GOSA::GosaSupportDaemon;
750 use MIME::Base64;
752 =head1 DESCRIPTION
754 This GOsa-SI event module containing all functions to handle messages coming from GOsa-SI-clients.
756 This module will be automatically imported by GOsa-SI if it is under F</usr/lib/gosa-si/server/E<lt>PACKAGEMODULEE<gt>/> .
758 =head1 METHODS
760 =over 4
762 =item get_events ( )
764 =item confirm_usr_msg ( )
766 =item PROGRESS ( )
768 =item FAIREBOOT ( )
770 =item TASKSKIP ( )
772 =item TASKBEGIN ( )
774 =item TASKEND ( )
776 =item TASKERROR ( )
778 =item HOOK ( )
780 =item GOTOACTIVATION ( )
782 =item LOGIN ( )
784 =item LOGOUT ( )
786 =item CURRENTLY_LOGGED_IN ( )
788 =item save_fai_log ( )
790 =back
792 =head1 BUGS
794 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>
796 =head1 COPYRIGHT
798 This code is part of GOsa (L<http://www.gosa-project.org>)
800 Copyright (C) 2003-2008 GONICUS GmbH
802 This program is distributed in the hope that it will be useful,
803 but WITHOUT ANY WARRANTY; without even the implied warranty of
804 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
805 GNU General Public License for more details.
807 =cut
810 1;