1 package clMessages;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5 "PROGRESS",
6 "FAIREBOOT",
7 "TASKSKIP",
8 "TASKBEGIN",
9 "TASKEND",
10 "TASKERROR",
11 "HOOK",
12 "GOTOACTIVATION",
13 "LOGIN",
14 "LOGOUT",
15 "CURRENTLY_LOGGED_IN",
16 "save_fai_log",
17 );
18 @EXPORT = @events;
20 use strict;
21 use warnings;
22 use Data::Dumper;
23 use GOSA::GosaSupportDaemon;
24 use MIME::Base64;
27 BEGIN {}
29 END {}
31 ### Start ######################################################################
33 my $ldap_uri;
34 my $ldap_base;
35 my $ldap_admin_dn;
36 my $ldap_admin_password;
38 my %cfg_defaults = (
39 "server" => {
40 "ldap-uri" => [\$ldap_uri, ""],
41 "ldap-base" => [\$ldap_base, ""],
42 "ldap-admin-dn" => [\$ldap_admin_dn, ""],
43 "ldap-admin-password" => [\$ldap_admin_password, ""],
44 },
45 );
46 &read_configfile($main::cfg_file, %cfg_defaults);
49 sub get_events {
50 return \@events;
51 }
54 sub read_configfile {
55 my ($cfg_file, %cfg_defaults) = @_;
56 my $cfg;
58 if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
59 if( -r $cfg_file ) {
60 $cfg = Config::IniFiles->new( -file => $cfg_file );
61 } else {
62 &main::daemon_log("ERROR: clMessages.pm couldn't read config file!", 1);
63 }
64 } else {
65 $cfg = Config::IniFiles->new() ;
66 }
67 foreach my $section (keys %cfg_defaults) {
68 foreach my $param (keys %{$cfg_defaults{ $section }}) {
69 my $pinfo = $cfg_defaults{ $section }{ $param };
70 ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
71 }
72 }
73 }
76 sub save_fai_log {
77 my ($msg, $msg_hash, $session_id) = @_;
78 my $header = @{$msg_hash->{'header'}}[0];
79 my $source = @{$msg_hash->{'source'}}[0];
80 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
81 my $all_logs = @{$msg_hash->{$header}}[0];
83 # if there is nothing to log
84 if( ref($all_logs) eq "HASH" ) { return; }
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);
111 }
112 return;
113 }
116 sub LOGIN {
117 my ($msg, $msg_hash, $session_id) = @_;
118 my $header = @{$msg_hash->{'header'}}[0];
119 my $source = @{$msg_hash->{'source'}}[0];
120 my $login = @{$msg_hash->{$header}}[0];
122 my %add_hash = ( table=>$main::login_users_tn,
123 primkey=> ['client', 'user'],
124 client=>$source,
125 user=>$login,
126 timestamp=>&get_time,
127 );
128 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
129 if ($res != 0) {
130 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
131 return;
132 }
134 return;
135 }
138 sub LOGOUT {
139 my ($msg, $msg_hash, $session_id) = @_;
140 my $header = @{$msg_hash->{'header'}}[0];
141 my $source = @{$msg_hash->{'source'}}[0];
142 my $login = @{$msg_hash->{$header}}[0];
144 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE (client='$source' AND user='$login')";
145 my $res = $main::login_users_db->del_dbentry($sql_statement);
146 &main::daemon_log("$session_id INFO: delete user '$login' at client '$source' from login_user_db", 5);
148 return;
149 }
152 sub CURRENTLY_LOGGED_IN {
153 my ($msg, $msg_hash, $session_id) = @_;
154 my ($sql_statement, $db_res);
155 my $header = @{$msg_hash->{'header'}}[0];
156 my $source = @{$msg_hash->{'source'}}[0];
157 my $login = @{$msg_hash->{$header}}[0];
159 if(ref $login eq "HASH") {
160 &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5);
161 return;
162 }
164 # fetch all user currently assigned to the client at login_users_db
165 my %currently_logged_in_user = ();
166 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'";
167 $db_res = $main::login_users_db->select_dbentry($sql_statement);
168 while( my($hit_id, $hit) = each(%{$db_res}) ) {
169 $currently_logged_in_user{$hit->{'user'}} = 1;
170 }
171 &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7);
173 # update all reported users in login_user_db
174 my @logged_in_user = split(/\s+/, $login);
175 &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7);
176 foreach my $user (@logged_in_user) {
177 my %add_hash = ( table=>$main::login_users_tn,
178 primkey=> ['client', 'user'],
179 client=>$source,
180 user=>$user,
181 timestamp=>&get_time,
182 );
183 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
184 if ($res != 0) {
185 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
186 return;
187 }
189 delete $currently_logged_in_user{$user};
190 }
192 # if there is still a user in %currently_logged_in_user
193 # although he is not reported by client
194 # then delete it from $login_user_db
195 foreach my $obsolete_user (keys(%currently_logged_in_user)) {
196 &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
197 "in at client '$source' but still found at login_user_db", 3);
198 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'";
199 my $res = $main::login_users_db->del_dbentry($sql_statement);
200 &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3);
201 }
203 return;
204 }
207 sub GOTOACTIVATION {
208 my ($msg, $msg_hash, $session_id) = @_;
209 my $header = @{$msg_hash->{'header'}}[0];
210 my $source = @{$msg_hash->{'target'}}[0];
211 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
213 # test whether content is an empty hash or a string which is required
214 my $content = @{$msg_hash->{$header}}[0];
215 if(ref($content) eq "HASH") { $content = ""; }
217 # clean up header
218 $header =~ s/CLMSG_//g;
220 my $sql_statement = "UPDATE $main::job_queue_tn ".
221 "SET status='processing', progress='goto-activation' ".
222 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
223 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
224 my $res = $main::job_db->update_dbentry($sql_statement);
225 &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5);
226 return;
227 }
230 sub PROGRESS {
231 my ($msg, $msg_hash, $session_id) = @_;
232 my $header = @{$msg_hash->{'header'}}[0];
233 my $source = @{$msg_hash->{'target'}}[0];
234 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
236 # test whether content is an empty hash or a string which is required
237 my $content = @{$msg_hash->{$header}}[0];
238 if(ref($content) eq "HASH") { $content = ""; }
240 # clean up header
241 $header =~ s/CLMSG_//g;
243 my $sql_statement = "UPDATE $main::job_queue_tn ".
244 "SET progress='$content' ".
245 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
246 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
247 my $res = $main::job_db->update_dbentry($sql_statement);
248 &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5);
250 return;
251 }
254 sub FAIREBOOT {
255 my ($msg, $msg_hash, $session_id) = @_;
256 my $header = @{$msg_hash->{'header'}}[0];
257 my $source = @{$msg_hash->{'target'}}[0];
258 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
260 # test whether content is an empty hash or a string which is required
261 my $content = @{$msg_hash->{$header}}[0];
262 if(ref($content) eq "HASH") { $content = ""; }
264 # clean up header
265 $header =~ s/CLMSG_//g;
267 my $sql_statement = "UPDATE $main::job_queue_tn ".
268 "SET status='processing', result='$header "."$content' ".
269 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
270 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
271 my $res = $main::job_db->update_dbentry($sql_statement);
272 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
274 return;
275 }
278 sub TASKSKIP {
279 my ($msg, $msg_hash, $session_id) = @_;
280 my $header = @{$msg_hash->{'header'}}[0];
281 my $source = @{$msg_hash->{'target'}}[0];
282 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
284 # test whether content is an empty hash or a string which is required
285 my $content = @{$msg_hash->{$header}}[0];
286 if(ref($content) eq "HASH") { $content = ""; }
288 # clean up header
289 $header =~ s/CLMSG_//g;
291 my $sql_statement = "UPDATE $main::job_queue_tn ".
292 "SET status='processing', result='$header "."$content' ".
293 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
294 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
295 my $res = $main::job_db->update_dbentry($sql_statement);
296 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
298 return;
299 }
302 sub TASKBEGIN {
303 my ($msg, $msg_hash, $session_id) = @_;
304 my $header = @{$msg_hash->{'header'}}[0];
305 my $source = @{$msg_hash->{'target'}}[0];
306 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
308 # test whether content is an empty hash or a string which is required
309 my $content = @{$msg_hash->{$header}}[0];
310 if(ref($content) eq "HASH") { $content = ""; }
312 # clean up header
313 $header =~ s/CLMSG_//g;
315 # TASKBEGIN eq finish or faiend
316 if (($content eq 'finish') || ($content eq 'faiend')){
317 my $sql_statement = "UPDATE $main::job_queue_tn ".
318 "SET status='done', result='$header "."$content' ".
319 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
320 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
321 my $res = $main::job_db->update_dbentry($sql_statement);
322 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
324 # set fai_state to localboot
325 &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
327 # other TASKBEGIN msgs
328 } else {
329 # select processing jobs for host
330 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
331 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
332 my $res = $main::job_db->select_dbentry($sql_statement);
334 # there is exactly one job entry in queue for this host
335 if (keys(%$res) == 1) {
336 &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
337 my $sql_statement = "UPDATE $main::job_queue_tn SET result='$header $content' WHERE status='processing' AND macaddress LIKE '$macaddress'";
338 my $err = $main::job_db->update_dbentry($sql_statement);
339 if (not defined $err) {
340 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
341 }
343 # there is no entry or more than one enties
344 } else {
345 # in case of more than one running jobs in queue, delete all jobs
346 if (keys(%$res) > 1) {
347 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
348 "delete entries", 7);
350 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
351 my ($err) = $main::job_db->del_dbentry($sql_statement);
352 if (not defined $err) {
353 &main::daemon_log("$session_id ERROR: can not delete multiple processing queue entries for host '$macaddress': ".Dumper($err), 1);
354 }
355 }
357 # in case of no and more than one running jobs in queue, add one single job
359 # TODO
360 # resolve plain name for host $macaddress
361 &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7);
362 my $func_dic = {table=>$main::job_queue_tn,
363 primkey=>['id'],
364 timestamp=>&get_time,
365 status=>'processing',
366 result=>"$header $content",
367 progress=>'none',
368 headertag=>'trigger_action_reinstall',
369 targettag=>$source,
370 xmlmessage=>'none',
371 macaddress=>$macaddress,
372 plainname=>'none',
373 };
374 my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
375 if ($err != 0) {
376 &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
377 }
379 }
381 # -----------------------> Update hier
382 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
383 # <header>CLMSG_TASKBEGIN</header>
384 # macaddress auslesen, Client im LDAP lokalisieren
385 # FAIstate auf "localboot" setzen, wenn FAIstate "install" oder "softupdate" war
386 }
388 return;
389 }
392 sub TASKEND {
393 my ($msg, $msg_hash, $session_id) = @_;
394 my $header = @{$msg_hash->{'header'}}[0];
395 my $source = @{$msg_hash->{'target'}}[0];
396 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
398 # test whether content is an empty hash or a string which is required
399 my $content = @{$msg_hash->{$header}}[0];
400 if(ref($content) eq "HASH") { $content = ""; }
402 # clean up header
403 $header =~ s/CLMSG_//g;
405 if ($content eq "savelog 0") {
406 &main::daemon_log("$session_id DEBUG: got savelog from host '$source' - jub done", 7);
407 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
408 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
409 my $res = $main::job_db->del_dbentry($sql_statement);
411 } else {
413 my $sql_statement = "UPDATE $main::job_queue_tn ".
414 "SET status='processing', result='$header "."$content' ".
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' - '$content'", 5);
420 }
421 # -----------------------> Update hier
422 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
423 # <header>CLMSG_TASKBEGIN</header>
424 # macaddress auslesen, Client im LDAP lokalisieren
425 # FAIstate auf "error" setzen
427 return;
428 }
431 sub TASKERROR {
432 my ($msg, $msg_hash, $session_id) = @_;
433 my $header = @{$msg_hash->{'header'}}[0];
434 my $source = @{$msg_hash->{'target'}}[0];
435 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
437 # clean up header
438 $header =~ s/CLMSG_//g;
440 # test whether content is an empty hash or a string which is required
441 my $content = @{$msg_hash->{$header}}[0];
442 if(ref($content) eq "HASH") { $content = ""; }
444 # set fai_state to localboot
445 &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
447 my $sql_statement = "UPDATE $main::job_queue_tn ".
448 "SET status='processing', result='$header "."$content' ".
449 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
450 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
451 my $res = $main::job_db->update_dbentry($sql_statement);
452 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
454 # -----------------------> Update hier
455 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
456 # <header>CLMSG_TASKBEGIN</header>
457 # macaddress auslesen, Client im LDAP lokalisieren
458 # FAIstate auf "error" setzen
460 return;
461 }
464 sub HOOK {
465 my ($msg, $msg_hash, $session_id) = @_;
466 my $header = @{$msg_hash->{'header'}}[0];
467 my $source = @{$msg_hash->{'target'}}[0];
468 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
470 # clean up header
471 $header =~ s/CLMSG_//g;
473 # test whether content is an empty hash or a string which is required
474 my $content = @{$msg_hash->{$header}}[0];
475 if(ref($content) eq "HASH") { $content = ""; }
477 my $sql_statement = "UPDATE $main::job_queue_tn ".
478 "SET status='processing', result='$header "."$content' ".
479 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
480 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
481 my $res = $main::job_db->update_dbentry($sql_statement);
482 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
484 return;
485 }
488 1;