c606822f5b46a50956a35afa732e48557208bd21
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) && ( length($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 }
137 # TODO umstellen wie bei LOGIN
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 = "SELECT * FROM known_clients WHERE hostname='$source'";
145 my $res = $main::known_clients_db->select_dbentry($sql_statement);
146 if( 1 != keys(%$res) ) {
147 &main::daemon_log("DEBUG: clMessages.pm: LOGOUT: no or more hits found in known_clients_db for host '$source'");
148 return;
149 }
151 my $act_login = $res->{'1'}->{'login'};
152 $act_login =~ s/$login,?//gi;
154 if( $act_login eq "" ){ $act_login = "nobody"; }
156 $sql_statement = "UPDATE known_clients SET login='$act_login' WHERE hostname='$source'";
157 $res = $main::known_clients_db->update_dbentry($sql_statement);
159 return;
160 }
163 sub CURRENTLY_LOGGED_IN {
164 my ($msg, $msg_hash, $session_id) = @_;
165 my ($sql_statement, $db_res);
166 my $header = @{$msg_hash->{'header'}}[0];
167 my $source = @{$msg_hash->{'source'}}[0];
168 my $login = @{$msg_hash->{$header}}[0];
170 if(ref $login eq "HASH") {
171 &main::daemon_log("$session_id INFO: no logged in users reported from host '$source'", 5);
172 return;
173 }
175 # fetch all user currently assigned to the client at login_users_db
176 my %currently_logged_in_user = ();
177 $sql_statement = "SELECT * FROM $main::login_users_tn WHERE client='$source'";
178 $db_res = $main::login_users_db->select_dbentry($sql_statement);
179 while( my($hit_id, $hit) = each(%{$db_res}) ) {
180 $currently_logged_in_user{$hit->{'user'}} = 1;
181 }
182 &main::daemon_log("$session_id DEBUG: logged in users from login_user_db: ".join(", ", keys(%currently_logged_in_user)), 7);
184 # update all reported users in login_user_db
185 my @logged_in_user = split(/\s+/, $login);
186 &main::daemon_log("$session_id DEBUG: logged in users reported from client: ".join(", ", @logged_in_user), 7);
187 foreach my $user (@logged_in_user) {
188 my %add_hash = ( table=>$main::login_users_tn,
189 primkey=> ['client', 'user'],
190 client=>$source,
191 user=>$user,
192 timestamp=>&get_time,
193 );
194 my ($res, $error_str) = $main::login_users_db->add_dbentry( \%add_hash );
195 if ($res != 0) {
196 &main::daemon_log("$session_id ERROR: cannot add entry to known_clients: $error_str");
197 return;
198 }
200 delete $currently_logged_in_user{$user};
201 }
203 # if there is still a user in %currently_logged_in_user
204 # although he is not reported by client
205 # then delete it from $login_user_db
206 foreach my $obsolete_user (keys(%currently_logged_in_user)) {
207 &main::daemon_log("$session_id WARNING: user '$obsolete_user' is currently not logged ".
208 "in at client '$source' but still found at login_user_db", 3);
209 my $sql_statement = "DELETE FROM $main::login_users_tn WHERE client='$source' AND user='$obsolete_user'";
210 my $res = $main::login_users_db->del_dbentry($sql_statement);
211 &main::daemon_log("$session_id WARNING: delete user '$obsolete_user' at client '$source' from login_user_db", 3);
212 }
214 return;
215 }
218 sub GOTOACTIVATION {
219 my ($msg, $msg_hash, $session_id) = @_;
220 my $header = @{$msg_hash->{'header'}}[0];
221 my $source = @{$msg_hash->{'target'}}[0];
222 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
224 # test whether content is an empty hash or a string which is required
225 my $content = @{$msg_hash->{$header}}[0];
226 if(ref($content) eq "HASH") { $content = ""; }
228 # clean up header
229 $header =~ s/CLMSG_//g;
231 my $sql_statement = "UPDATE $main::job_queue_tn ".
232 "SET status='processing', progress='goto-activation' ".
233 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
234 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
235 my $res = $main::job_db->update_dbentry($sql_statement);
236 &main::daemon_log("$session_id INFO: $header at '$macaddress'", 5);
237 return;
238 }
241 sub PROGRESS {
242 my ($msg, $msg_hash, $session_id) = @_;
243 my $header = @{$msg_hash->{'header'}}[0];
244 my $source = @{$msg_hash->{'target'}}[0];
245 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
247 # test whether content is an empty hash or a string which is required
248 my $content = @{$msg_hash->{$header}}[0];
249 if(ref($content) eq "HASH") { $content = ""; }
251 # clean up header
252 $header =~ s/CLMSG_//g;
254 my $sql_statement = "UPDATE $main::job_queue_tn ".
255 "SET progress='$content' ".
256 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
257 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
258 my $res = $main::job_db->update_dbentry($sql_statement);
259 &main::daemon_log("$session_id INFO: $header at '$macaddress' - $content%", 5);
261 return;
262 }
265 sub FAIREBOOT {
266 my ($msg, $msg_hash, $session_id) = @_;
267 my $header = @{$msg_hash->{'header'}}[0];
268 my $source = @{$msg_hash->{'target'}}[0];
269 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
271 # test whether content is an empty hash or a string which is required
272 my $content = @{$msg_hash->{$header}}[0];
273 if(ref($content) eq "HASH") { $content = ""; }
275 # clean up header
276 $header =~ s/CLMSG_//g;
278 my $sql_statement = "UPDATE $main::job_queue_tn ".
279 "SET status='processing', result='$header "."$content' ".
280 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
281 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
282 my $res = $main::job_db->update_dbentry($sql_statement);
283 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
285 return;
286 }
289 sub TASKSKIP {
290 my ($msg, $msg_hash, $session_id) = @_;
291 my $header = @{$msg_hash->{'header'}}[0];
292 my $source = @{$msg_hash->{'target'}}[0];
293 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
295 # test whether content is an empty hash or a string which is required
296 my $content = @{$msg_hash->{$header}}[0];
297 if(ref($content) eq "HASH") { $content = ""; }
299 # clean up header
300 $header =~ s/CLMSG_//g;
302 my $sql_statement = "UPDATE $main::job_queue_tn ".
303 "SET status='processing', result='$header "."$content' ".
304 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
305 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
306 my $res = $main::job_db->update_dbentry($sql_statement);
307 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
309 return;
310 }
313 sub TASKBEGIN {
314 my ($msg, $msg_hash, $session_id) = @_;
315 my $header = @{$msg_hash->{'header'}}[0];
316 my $source = @{$msg_hash->{'target'}}[0];
317 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
319 # test whether content is an empty hash or a string which is required
320 my $content = @{$msg_hash->{$header}}[0];
321 if(ref($content) eq "HASH") { $content = ""; }
323 # clean up header
324 $header =~ s/CLMSG_//g;
326 # TASKBEGIN eq finish or faiend
327 if (($content eq 'finish') || ($content eq 'faiend')){
328 my $sql_statement = "UPDATE $main::job_queue_tn ".
329 "SET status='done', result='$header "."$content' ".
330 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
331 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
332 my $res = $main::job_db->update_dbentry($sql_statement);
333 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
335 # set fai_state to localboot
336 &main::change_fai_state('localboot', \@{$msg_hash->{'macaddress'}}, $session_id);
338 # other TASKBEGIN msgs
339 } else {
340 # select processing jobs for host
341 my $sql_statement = "SELECT * FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
342 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
343 my $res = $main::job_db->select_dbentry($sql_statement);
345 # there is exactly one job entry in queue for this host
346 if (keys(%$res) == 1) {
347 &main::daemon_log("$session_id DEBUG: there is already one processing job in queue for host '$macaddress', run an update for this entry", 7);
348 my $sql_statement = "UPDATE $main::job_queue_tn SET result='$header $content' WHERE status='processing' AND macaddress LIKE '$macaddress'";
349 my $err = $main::job_db->update_dbentry($sql_statement);
350 if (not defined $err) {
351 &main::daemon_log("$session_id ERROR: cannot update job_db entry: ".Dumper($err), 1);
352 }
354 # there is no entry or more than one enties
355 } else {
356 # in case of more than one running jobs in queue, delete all jobs
357 if (keys(%$res) > 1) {
358 &main::daemon_log("$session_id DEBUG: there are more than one processing job in queue for host '$macaddress', ".
359 "delete entries", 7);
361 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
362 my ($err) = $main::job_db->del_dbentry($sql_statement);
363 if (not defined $err) {
364 &main::daemon_log("$session_id ERROR: can not delete multiple processing queue entries for host '$macaddress': ".Dumper($err), 1);
365 }
366 }
368 # in case of no and more than one running jobs in queue, add on single job
369 &main::daemon_log("$session_id DEBUG: add job to queue for host '$macaddress'", 7);
370 my $func_dic = {table=>$main::job_queue_tn,
371 primkey=>['id'],
372 timestamp=>&get_time,
373 status=>'processing',
374 result=>"$header $content",
375 progress=>'none',
376 headertag=>'trigger_action_reinstall',
377 targettag=>$source,
378 xmlmessage=>'none',
379 macaddress=>$macaddress,
380 };
381 my ($err, $error_str) = $main::job_db->add_dbentry($func_dic);
382 if ($err != 0) {
383 &main::daemon_log("$session_id ERROR: cannot add entry to job_db: $error_str", 1);
384 }
386 }
388 #my $sql_statement = "UPDATE $main::job_queue_tn ".
389 # "SET status='processing', result='$header "."$content' ".
390 # "WHERE status='processing' AND macaddress LIKE '$macaddress'";
391 #&main::daemon_log("$session_id DEBUG: $sql_statement", 7);
392 #my $res = $main::job_db->update_dbentry($sql_statement);
393 #&main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
396 # -----------------------> Update hier
397 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
398 # <header>CLMSG_TASKBEGIN</header>
399 # macaddress auslesen, Client im LDAP lokalisieren
400 # FAIstate auf "localboot" setzen, wenn FAIstate "install" oder "softupdate" war
401 }
403 return;
404 }
407 sub TASKEND {
408 my ($msg, $msg_hash, $session_id) = @_;
409 my $header = @{$msg_hash->{'header'}}[0];
410 my $source = @{$msg_hash->{'target'}}[0];
411 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
413 # test whether content is an empty hash or a string which is required
414 my $content = @{$msg_hash->{$header}}[0];
415 if(ref($content) eq "HASH") { $content = ""; }
417 # clean up header
418 $header =~ s/CLMSG_//g;
420 if ($header eq "TASKEND softupdate 0") {
421 &main::daemon_log("$session_id DEBUG: softupdate at host '$source' successful", 7);
422 my $sql_statement = "DELETE FROM $main::job_queue_tn WHERE status='processing' AND macaddress LIKE '$macaddress'";
423 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
424 my $res = $main::job_db->del_dbentry($sql_statement);
426 } else {
428 my $sql_statement = "UPDATE $main::job_queue_tn ".
429 "SET status='processing', result='$header "."$content' ".
430 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
431 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
432 my $res = $main::job_db->update_dbentry($sql_statement);
433 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
435 }
436 # -----------------------> Update hier
437 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
438 # <header>CLMSG_TASKBEGIN</header>
439 # macaddress auslesen, Client im LDAP lokalisieren
440 # FAIstate auf "error" setzen
442 return;
443 }
446 sub TASKERROR {
447 my ($msg, $msg_hash, $session_id) = @_;
448 my $header = @{$msg_hash->{'header'}}[0];
449 my $source = @{$msg_hash->{'target'}}[0];
450 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
452 # clean up header
453 $header =~ s/CLMSG_//g;
455 # test whether content is an empty hash or a string which is required
456 my $content = @{$msg_hash->{$header}}[0];
457 if(ref($content) eq "HASH") { $content = ""; }
459 # set fai_state to localboot
460 &main::change_fai_state('error', \@{$msg_hash->{'macaddress'}}, $session_id);
462 my $sql_statement = "UPDATE $main::job_queue_tn ".
463 "SET status='processing', result='$header "."$content' ".
464 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
465 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
466 my $res = $main::job_db->update_dbentry($sql_statement);
467 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
469 # -----------------------> Update hier
470 # <CLMSG_TASKBEGIN>finish</CLMSG_TASKBEGIN>
471 # <header>CLMSG_TASKBEGIN</header>
472 # macaddress auslesen, Client im LDAP lokalisieren
473 # FAIstate auf "error" setzen
475 return;
476 }
479 sub HOOK {
480 my ($msg, $msg_hash, $session_id) = @_;
481 my $header = @{$msg_hash->{'header'}}[0];
482 my $source = @{$msg_hash->{'target'}}[0];
483 my $macaddress = @{$msg_hash->{'macaddress'}}[0];
485 # clean up header
486 $header =~ s/CLMSG_//g;
488 # test whether content is an empty hash or a string which is required
489 my $content = @{$msg_hash->{$header}}[0];
490 if(ref($content) eq "HASH") { $content = ""; }
492 my $sql_statement = "UPDATE $main::job_queue_tn ".
493 "SET status='processing', result='$header "."$content' ".
494 "WHERE status='processing' AND macaddress LIKE '$macaddress'";
495 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
496 my $res = $main::job_db->update_dbentry($sql_statement);
497 &main::daemon_log("$session_id INFO: $header at '$macaddress' - '$content'", 5);
499 return;
500 }
503 1;