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