1 package clMessages;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5 "confirm_usr_msg",
6 "PROGRESS",
7 "FAIREBOOT",
8 "TASKSKIP",
9 "TASKBEGIN",
10 "TASKEND",
11 "TASKERROR",
12 "HOOK",
13 "GOTOACTIVATION",
14 "LOGIN",
15 "LOGOUT",
16 "CURRENTLY_LOGGED_IN",
17 "save_fai_log",
18 );
19 @EXPORT = @events;
21 use strict;
22 use warnings;
23 use Data::Dumper;
24 use GOSA::GosaSupportDaemon;
25 use MIME::Base64;
28 BEGIN {}
30 END {}
32 ### Start ######################################################################
34 my $ldap_uri;
35 my $ldap_base;
36 my $ldap_admin_dn;
37 my $ldap_admin_password;
39 my %cfg_defaults = (
40 "server" => {
41 "ldap-uri" => [\$ldap_uri, ""],
42 "ldap-base" => [\$ldap_base, ""],
43 "ldap-admin-dn" => [\$ldap_admin_dn, ""],
44 "ldap-admin-password" => [\$ldap_admin_password, ""],
45 },
46 );
47 &read_configfile($main::cfg_file, %cfg_defaults);
50 sub get_events {
51 return \@events;
52 }
55 sub confirm_usr_msg {
56 my ($msg, $msg_hash, $session_id) = @_;
57 my $message = @{$msg_hash->{'message'}}[0];
58 my $subject = @{$msg_hash->{'subject'}}[0];
59 my $usr = @{$msg_hash->{'usr'}}[0];
61 # set update for this message
62 my $sql = "UPDATE $main::messaging_tn SET flag='s' WHERE (message='$message' AND subject='$subject' AND message_to='$usr')";
63 &main::daemon_log("$session_id DEBUG: $sql", 7);
64 my $res = $main::messaging_db->exec_statement($sql);
67 return;
68 }
72 sub read_configfile {
73 my ($cfg_file, %cfg_defaults) = @_;
74 my $cfg;
76 if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
77 if( -r $cfg_file ) {
78 $cfg = Config::IniFiles->new( -file => $cfg_file );
79 } else {
80 &main::daemon_log("ERROR: clMessages.pm couldn't read config file!", 1);
81 }
82 } else {
83 $cfg = Config::IniFiles->new() ;
84 }
85 foreach my $section (keys %cfg_defaults) {
86 foreach my $param (keys %{$cfg_defaults{ $section }}) {
87 my $pinfo = $cfg_defaults{ $section }{ $param };
88 ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
89 }
90 }
91 }
94 sub save_fai_log {
95 my ($msg, $msg_hash, $session_id) = @_;
96 my $header = @{$msg_hash->{'header'}}[0];
97 my $source = @{$msg_hash->{'source'}}[0];
98 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
99 my $all_logs = @{$msg_hash->{$header}}[0];
101 # if there is nothing to log
102 if( ref($all_logs) eq "HASH" ) { return; }
104 my $client_fai_log_dir = $main::client_fai_log_dir;
105 if (not -d $client_fai_log_dir) {
106 mkdir($client_fai_log_dir, 0755)
107 }
109 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, $macaddress );
110 if (not -d $client_fai_log_dir) {
111 mkdir($client_fai_log_dir, 0755)
112 }
114 my $time = &get_time;
115 $time = substr($time, 0, 8)."_".substr($time, 8, 6);
116 $client_fai_log_dir = File::Spec->catfile( $client_fai_log_dir, "install_$time" );
117 mkdir($client_fai_log_dir, 0755);
119 my @all_logs = split(/log_file:/, $all_logs);
120 foreach my $log (@all_logs) {
121 if (length $log == 0) { next; };
122 my ($log_file, $log_string) = split(":", $log);
123 my $client_fai_log_file = File::Spec->catfile( $client_fai_log_dir, $log_file);
125 open(my $LOG_FILE, ">$client_fai_log_file");
126 print $LOG_FILE &decode_base64($log_string);
127 close($LOG_FILE);
129 }
130 return;
131 }
134 sub LOGIN {
135 my ($msg, $msg_hash, $session_id) = @_;
136 my $header = @{$msg_hash->{'header'}}[0];
137 my $source = @{$msg_hash->{'source'}}[0];
138 my $login = @{$msg_hash->{$header}}[0];
140 my %add_hash = ( table=>$main::login_users_tn,
141 primkey=> ['client', 'user'],
142 client=>$source,
143 user=>$login,
144 timestamp=>&get_time,
145 );
146 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
147 if ($res != 0) {
148 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
149 return;
150 }
152 return;
153 }
156 sub LOGOUT {
157 my ($msg, $msg_hash, $session_id) = @_;
158 my $header = @{$msg_hash->{'header'}}[0];
159 my $source = @{$msg_hash->{'source'}}[0];
160 my $login = @{$msg_hash->{$header}}[0];
162 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')";
163 my $res = $main::login_users_db->del_dbentry($sql_statement);
164 &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5);
166 return;
167 }
170 sub CURRENTLY_LOGGED_IN {
171 my ($msg, $msg_hash, $session_id) = @_;
172 my ($sql_statement, $db_res);
173 my $header = @{$msg_hash->{'header'}}[0];
174 my $source = @{$msg_hash->{'source'}}[0];
175 my $login = @{$msg_hash->{$header}}[0];
177 if(ref $login eq "HASH") {
178 &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5);
179 return;
180 }
182 # fetch all user currently assigned to the client at login_users_db
183 my %currently_logged_in_user = ();
184 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'";
185 $db_res = $main::login_users_db->select_dbentry($sql_statement);
186 while( my($hit_id, $hit) = each(%{$db_res}) ) {
187 $currently_logged_in_user{$hit->{'user'}} = 1;
188 }
189 &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7);
191 # update all reported users in login_user_db
192 my @logged_in_user = split(/\s+/, $login);
193 &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7);
194 foreach my $user (@logged_in_user) {
195 my %add_hash = ( table=>$main::login_users_tn,
196 primkey=> ['client', 'user'],
197 client=>$source,
198 user=>$user,
199 timestamp=>&get_time,
200 );
201 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
202 if ($res != 0) {
203 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
204 return;
205 }
207 delete $currently_logged_in_user{$user};
208 }
210 # if there is still a user in %currently_logged_in_user
211 # although he is not reported by client
212 # then delete it from $login_user_db
213 foreach my $obsolete_user (keys(%currently_logged_in_user)) {
214 &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
215 "in at client '$source' but still found at login_user_db", 3);
216 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'";
217 my $res = $main::login_users_db->del_dbentry($sql_statement);
218 &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3);
219 }
221 return;
222 }
225 sub GOTOACTIVATION {
226 my ($msg, $msg_hash, $session_id) = @_;
227 my $header = @{$msg_hash->{'header'}}[0];
228 my $source = @{$msg_hash->{'source'}}[0];
229 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
231 # test whether content is an empty hash or a string which is required
232 my $content = @{$msg_hash->{$header}}[0];
233 if(ref($content) eq "HASH") { $content = ""; }
235 # clean up header
236 $header =~ s/CLMSG_//g;
238 my $sql_statement = "UPDATE $main::job_queue_tn ".
239 "SET status='processing', progress='goto-activation', modified='1' ".
240 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
241 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
242 my $res = $main::job_db->update_dbentry($sql_statement);
243 &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5);
244 return;
245 }
248 sub PROGRESS {
249 my ($msg, $msg_hash, $session_id) = @_;
250 my $header = @{$msg_hash->{'header'}}[0];
251 my $source = @{$msg_hash->{'source'}}[0];
252 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
254 # test whether content is an empty hash or a string which is required
255 my $content = @{$msg_hash->{$header}}[0];
256 if(ref($content) eq "HASH") { $content = ""; }
258 # clean up header
259 $header =~ s/CLMSG_//g;
261 my $sql_statement = "UPDATE $main::job_queue_tn ".
262 "SET progress='$content', modified='1' ".
263 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
264 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
265 my $res = $main::job_db->update_dbentry($sql_statement);
266 &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5);
268 return;
269 }
272 sub FAIREBOOT {
273 my ($msg, $msg_hash, $session_id) = @_;
274 my $header = @{$msg_hash->{'header'}}[0];
275 my $source = @{$msg_hash->{'source'}}[0];
276 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
278 # test whether content is an empty hash or a string which is required
279 my $content = @{$msg_hash->{$header}}[0];
280 if(ref($content) eq "HASH") { $content = ""; }
282 # clean up header
283 $header =~ s/CLMSG_//g;
285 my $sql_statement = "UPDATE $main::job_queue_tn ".
286 "SET status='processing', result='$header "."$content', modified='1' ".
287 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
288 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
289 my $res = $main::job_db->update_dbentry($sql_statement);
290 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
292 return;
293 }
296 sub TASKSKIP {
297 my ($msg, $msg_hash, $session_id) = @_;
298 my $header = @{$msg_hash->{'header'}}[0];
299 my $source = @{$msg_hash->{'source'}}[0];
300 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
302 # test whether content is an empty hash or a string which is required
303 my $content = @{$msg_hash->{$header}}[0];
304 if(ref($content) eq "HASH") { $content = ""; }
306 # clean up header
307 $header =~ s/CLMSG_//g;
309 my $sql_statement = "UPDATE $main::job_queue_tn ".
310 "SET status='processing', result='$header "."$content', modified='1' ".
311 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
312 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
313 my $res = $main::job_db->update_dbentry($sql_statement);
314 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
316 return;
317 }
320 sub TASKBEGIN {
321 my ($msg, $msg_hash, $session_id) = @_;
322 my $header = @{$msg_hash->{'header'}}[0];
323 my $source = @{$msg_hash->{'source'}}[0];
324 my $target = @{$msg_hash->{'target'}}[0];
325 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
327 # test whether content is an empty hash or a string which is required
328 my $content = @{$msg_hash->{$header}}[0];
329 if(ref($content) eq "HASH") { $content = ""; }
331 # clean up header
332 $header =~ s/CLMSG_//g;
334 # TASKBEGIN eq finish or faiend
335 if (($content eq 'finish')
336 || ($content eq 'faiend')
337 || ($content eq 'savelog')
338 ) {
339 my $sql_statement = "UPDATE $main::job_queue_tn ".
340 "SET status='done', result='$header "."$content', modified='1' ".
341 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
342 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
343 my $res = $main::job_db->update_dbentry($sql_statement);
344 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
346 # set fai_state to localboot
347 &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
349 # TASKBEGIN eq chboot
350 } elsif (($content eq 'chboot')
351 || ($content eq 'test')
352 || ($content eq 'confdir')
353 ) {
354 # just ignor this client message
355 # do nothing
357 # other TASKBEGIN msgs
358 } else {
359 # select processing jobs for host
360 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
361 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
362 my $res = $main::job_db->select_dbentry($sql_statement);
364 # there is exactly one job entry in queue for this host
365 if (keys(%$res) == 1) {
366 &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
367 my $sql_statement = "UPDATE $main::job_queue_tn ".
368 "SET result='$header $content', modified='1' ".
369 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
370 my $err = $main::job_db->update_dbentry($sql_statement);
371 if (not defined $err) {
372 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
373 }
375 # there is no entry or more than one enties
376 } else {
377 # in case of more than one running jobs in queue, delete all jobs
378 if (keys(%$res) > 1) {
379 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
380 "delete entries", 7);
382 # set job to status 'done', job will be deleted automatically
383 my $sql_statement = "UPDATE $main::job_queue_tn ".
384 "SET status='done', modified='1'".
385 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
386 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
387 my $res = $main::job_db->update_dbentry( $sql_statement );
389 }
391 # in case of no and more than one running jobs in queue, add one single job
392 # resolve plain name for host $macaddress
393 my $plain_name;
394 my $ldap_handle = &main::get_ldap_handle($session_id);
395 if( not defined $ldap_handle ) {
396 &main::daemon_log("$session_id ERROR: cannot connect to ldap", 1);
397 $plain_name = "none";
399 # try to fetch a 'real name'
400 } else {
401 my $mesg = $ldap_handle->search(
402 base => $main::ldap_base,
403 scope => 'sub',
404 attrs => ['cn'],
405 filter => "(macAddress=$macaddress)");
406 if($mesg->code) {
407 &main::daemon_log($mesg->error, 1);
408 $plain_name = "none";
409 } else {
410 my $entry= $mesg->entry(0);
411 $plain_name = $entry->get_value("cn");
412 }
413 }
416 &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7);
417 my $func_dic = {table=>$main::job_queue_tn,
418 primkey=>['macaddress', 'headertag'],
419 timestamp=>&get_time,
420 status=>'processing',
421 result=>"$header $content",
422 progress=>'none',
423 headertag=>'trigger_action_reinstall',
424 targettag=>$target,
425 xmlmessage=>'none',
426 macaddress=>$macaddress,
427 plainname=>$plain_name,
428 modified=>'1',
429 siserver=>$source,
430 };
431 my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
432 if ($err != 0) {
433 &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
434 }
436 }
438 # -----------------------> Update hier
439 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
440 # <header>CLMSG_TASKBEGIN</header>
441 # macaddress auslesen, Client im LDAP lokalisieren
442 # FAIstate auf "localboot" setzen, wenn FAIstate "install" oder "softupdate" war
443 }
445 return;
446 }
449 sub TASKEND {
450 my ($msg, $msg_hash, $session_id) = @_;
451 my $header = @{$msg_hash->{'header'}}[0];
452 my $target = @{$msg_hash->{'target'}}[0];
453 my $source = @{$msg_hash->{'source'}}[0];
454 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
456 # test whether content is an empty hash or a string which is required
457 my $content = @{$msg_hash->{$header}}[0];
458 if(ref($content) eq "HASH") { $content = ""; }
460 # clean up header
461 $header =~ s/CLMSG_//g;
463 if ($content eq "savelog 0") {
464 &main::daemon_log("$session_id DEBUG: got savelog from host '$target' - job done", 7);
466 # set job to status 'done', job will be deleted automatically
467 my $sql_statement = "UPDATE $main::job_queue_tn ".
468 "SET status='done', modified='1'".
469 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
470 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
471 my $res = $main::job_db->update_dbentry( $sql_statement );
473 } else {
474 my $sql_statement = "UPDATE $main::job_queue_tn ".
475 "SET status='processing', result='$header "."$content', modified='1' ".
476 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
477 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
478 my $res = $main::job_db->update_dbentry($sql_statement);
479 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
480 }
482 return;
483 }
486 sub TASKERROR {
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 # clean up header
493 $header =~ s/CLMSG_//g;
495 # test whether content is an empty hash or a string which is required
496 my $content = @{$msg_hash->{$header}}[0];
497 if(ref($content) eq "HASH") { $content = ""; }
499 # set fai_state to localboot
500 &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
502 my $sql_statement = "UPDATE $main::job_queue_tn ".
503 "SET status='processing', result='$header "."$content', modified='1' ".
504 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
505 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
506 my $res = $main::job_db->update_dbentry($sql_statement);
507 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
509 # -----------------------> Update hier
510 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
511 # <header>CLMSG_TASKBEGIN</header>
512 # macaddress auslesen, Client im LDAP lokalisieren
513 # FAIstate auf "error" setzen
515 return;
516 }
519 sub HOOK {
520 my ($msg, $msg_hash, $session_id) = @_;
521 my $header = @{$msg_hash->{'header'}}[0];
522 my $source = @{$msg_hash->{'source'}}[0];
523 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
525 # clean up header
526 $header =~ s/CLMSG_//g;
528 # test whether content is an empty hash or a string which is required
529 my $content = @{$msg_hash->{$header}}[0];
530 if(not ref($content) eq "STRING") { $content = ""; }
532 my $sql_statement = "UPDATE $main::job_queue_tn ".
533 "SET status='processing', result='$header "."$content', modified='1' ".
534 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
535 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
536 my $res = $main::job_db->update_dbentry($sql_statement);
537 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
539 return;
540 }
543 1;