1 ## @file
2 # @details A GOsa-SI event module containing all functions common used by GOsa
3 # @brief Implementation of a GOsa-SI event module.
5 package gosaTriggered;
6 use Exporter;
7 @ISA = qw(Exporter);
8 my @events = (
9 "get_events",
10 "get_login_usr_for_client",
11 "get_client_for_login_usr",
12 "gen_smb_hash",
13 "trigger_reload_ldap_config",
14 "ping",
15 "network_completition",
16 "set_activated_for_installation",
17 "new_key_for_client",
18 "detect_hardware",
19 "get_login_usr",
20 "get_login_client",
21 "trigger_action_localboot",
22 "trigger_action_faireboot",
23 "trigger_action_reboot",
24 "trigger_action_activate",
25 "trigger_action_lock",
26 "trigger_action_halt",
27 "trigger_action_update",
28 "trigger_action_reinstall",
29 "trigger_action_memcheck",
30 "trigger_action_sysinfo",
31 "trigger_action_instant_update",
32 "trigger_action_rescan",
33 "trigger_action_wake",
34 "recreate_fai_server_db",
35 "recreate_fai_release_db",
36 "recreate_packages_list_db",
37 "send_user_msg",
38 "get_available_kernel",
39 "trigger_activate_new",
40 # "get_dak_keyring",
41 # "import_dak_key",
42 # "remove_dak_key",
43 # "get_dak_queue",
44 );
45 @EXPORT = @events;
47 use strict;
48 use warnings;
49 use GOSA::GosaSupportDaemon;
50 use Data::Dumper;
51 use Crypt::SmbHash;
52 use Net::ARP;
53 use Net::Ping;
54 use Socket;
55 use Time::HiRes qw( usleep);
56 use MIME::Base64;
58 BEGIN {}
60 END {}
62 ### Start ######################################################################
64 ## @method get_events()
65 # A brief function returning a list of functions which are exported by importing the module.
66 # @return List of all provided functions
67 sub get_events {
68 return \@events;
69 }
71 ## @method send_usr_msg($msg, $msg_hash, $session_id)
72 # This function accepts usr messages from GOsa, split mulitple target messages to mulitiple single target messages and put all messages into messaging_db
73 # @param msg - STRING - xml message
74 # @param msg_hash - HASHREF - message information parsed into a hash
75 # @param session_id - INTEGER - POE session id of the processing of this message
76 # @return (out_msg) - ARRAY - Array containing the answer message from client
77 sub send_user_msg {
78 my ($msg, $msg_hash, $session_id) = @_ ;
79 my $header = @{$msg_hash->{'header'}}[0];
80 my $source = @{$msg_hash->{'source'}}[0];
81 my $target = @{$msg_hash->{'target'}}[0];
83 #my $subject = &decode_base64(@{$msg_hash->{'subject'}}[0]); # just for debugging
84 my $subject = @{$msg_hash->{'subject'}}[0];
85 my $from = @{$msg_hash->{'from'}}[0];
86 my @users = exists $msg_hash->{'users'} ? @{$msg_hash->{'users'}} : () ;
87 my @groups = exists $msg_hash->{'groups'} ? @{$msg_hash->{'groups'}} : ();
88 my $delivery_time = @{$msg_hash->{'delivery_time'}}[0];
89 #my $message = &decode_base64(@{$msg_hash->{'message'}}[0]); # just for debugging
90 my $message = @{$msg_hash->{'message'}}[0];
92 # keep job queue uptodate if necessary
93 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
94 if( defined $jobdb_id) {
95 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
96 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
97 my $res = $main::job_db->exec_statement($sql_statement);
98 }
100 # error handling
101 if (not $delivery_time =~ /^\d{14}$/) {
102 my $error_string = "delivery_time '$delivery_time' is not a valid timestamp, please use format 'yyyymmddhhmmss'";
103 &main::daemon_log("$session_id ERROR: $error_string", 1);
104 return &create_xml_string(&create_xml_hash($header, $target, $source, $error_string));
105 }
107 # determine new message id
108 my $new_msg_id = 1;
109 my $new_msg_id_sql = "SELECT MAX(CAST(id AS INTEGER)) FROM $main::messaging_tn";
110 my $new_msg_id_res = $main::messaging_db->exec_statement($new_msg_id_sql);
111 if (defined @{@{$new_msg_id_res}[0]}[0] ) {
112 $new_msg_id = int(@{@{$new_msg_id_res}[0]}[0]);
113 $new_msg_id += 1;
114 }
116 # highlight user name and group name
117 my @receiver_l;
118 @users = map(push(@receiver_l, "u_$_"), @users);
119 @groups = map(push(@receiver_l, "g_$_"), @groups);
121 # add incoming message to messaging_db
122 my $func_dic = {table=>$main::messaging_tn,
123 primkey=>[],
124 id=>$new_msg_id,
125 subject=>$subject,
126 message_from=>$from,
127 message_to=>join(",", @receiver_l),
128 flag=>"n",
129 direction=>"in",
130 delivery_time=>$delivery_time,
131 message=>$message,
132 timestamp=>&get_time(),
133 };
134 my $res = $main::messaging_db->add_dbentry($func_dic);
135 if (not $res == 0) {
136 &main::daemon_log("$session_id ERROR: gosaTriggered.pm: cannot add message to message_db: $res", 1);
137 } else {
138 &main::daemon_log("$session_id INFO: gosaTriggered.pm: message with subject '$subject' successfully added to message_db", 5);
139 }
141 return;
142 }
145 sub recreate_fai_server_db {
146 my ($msg, $msg_hash, $session_id) = @_ ;
147 my $out_msg;
149 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
150 if( defined $jobdb_id) {
151 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
152 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
153 my $res = $main::job_db->exec_statement($sql_statement);
154 }
156 $main::fai_server_db->create_table("new_fai_server", \@main::fai_server_col_names);
157 &main::create_fai_server_db("new_fai_server",undef,"dont", $session_id);
158 $main::fai_server_db->move_table("new_fai_server", $main::fai_server_tn);
160 my @out_msg_l = ( $out_msg );
161 return @out_msg_l;
162 }
165 sub recreate_fai_release_db {
166 my ($msg, $msg_hash, $session_id) = @_ ;
167 my $out_msg;
169 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
170 if( defined $jobdb_id) {
171 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
172 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
173 my $res = $main::job_db->exec_statement($sql_statement);
174 }
176 $main::fai_release_db->create_table("new_fai_release", \@main::fai_release_col_names);
177 &main::create_fai_release_db("new_fai_release", $session_id);
178 $main::fai_release_db->move_table("new_fai_release", $main::fai_release_tn);
180 my @out_msg_l = ( $out_msg );
181 return @out_msg_l;
182 }
185 sub recreate_packages_list_db {
186 my ($msg, $msg_hash, $session_id) = @_ ;
187 my $out_msg;
189 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
190 if( defined $jobdb_id) {
191 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
192 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
193 my $res = $main::job_db->exec_statement($sql_statement);
194 }
196 &main::create_packages_list_db;
198 my @out_msg_l = ( $out_msg );
199 return @out_msg_l;
200 }
203 sub get_login_usr_for_client {
204 my ($msg, $msg_hash, $session_id) = @_ ;
205 my $header = @{$msg_hash->{'header'}}[0];
206 my $source = @{$msg_hash->{'source'}}[0];
207 my $target = @{$msg_hash->{'target'}}[0];
208 my $client = @{$msg_hash->{'client'}}[0];
210 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
211 if( defined $jobdb_id) {
212 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
213 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
214 my $res = $main::job_db->exec_statement($sql_statement);
215 }
217 $header =~ s/^gosa_//;
219 my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$client' OR macaddress LIKE '$client'";
220 my $res = $main::known_clients_db->select_dbentry($sql_statement);
222 my $out_msg = "<xml><header>$header</header><source>$target</source><target>$source</target>";
223 $out_msg .= &db_res2xml($res);
224 $out_msg .= "</xml>";
226 my @out_msg_l = ( $out_msg );
227 return @out_msg_l;
228 }
231 sub get_client_for_login_usr {
232 my ($msg, $msg_hash, $session_id) = @_ ;
233 my $header = @{$msg_hash->{'header'}}[0];
234 my $source = @{$msg_hash->{'source'}}[0];
235 my $target = @{$msg_hash->{'target'}}[0];
237 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
238 if( defined $jobdb_id) {
239 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
240 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
241 my $res = $main::job_db->exec_statement($sql_statement);
242 }
244 my $usr = @{$msg_hash->{'usr'}}[0];
245 $header =~ s/^gosa_//;
247 my $sql_statement = "SELECT * FROM known_clients WHERE login LIKE '%$usr%'";
248 my $res = $main::known_clients_db->select_dbentry($sql_statement);
250 my $out_msg = "<xml><header>$header</header><source>$target</source><target>$source</target>";
251 $out_msg .= &db_res2xml($res);
252 $out_msg .= "</xml>";
253 my @out_msg_l = ( $out_msg );
254 return @out_msg_l;
256 }
259 sub ping {
260 my ($msg, $msg_hash, $session_id) = @_ ;
261 my $header = @{$msg_hash->{header}}[0];
262 my $target = @{$msg_hash->{target}}[0];
263 my $source = @{$msg_hash->{source}}[0];
264 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
265 my $error = 0;
266 my $answer_msg;
267 my ($sql, $res);
269 if( defined $jobdb_id) {
270 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
271 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
272 my $res = $main::job_db->exec_statement($sql_statement);
273 }
275 # send message
276 $sql = "SELECT * FROM $main::known_clients_tn WHERE ((hostname='$target') || (macaddress LIKE '$target'))";
277 $res = $main::known_clients_db->exec_statement($sql);
279 # sanity check of db result
280 my ($host_name, $host_key);
281 if ((defined $res) && (@$res > 0) && @{@$res[0]} > 0) {
282 $host_name = @{@$res[0]}[0];
283 $host_key = @{@$res[0]}[2];
284 } else {
285 &main::daemon_log("$session_id ERROR: cannot determine host_name and host_key from known_clients_db at function ping\n$msg", 1);
286 my %data = ( 'answer_xml' => 'host not found in known_clients_db',
287 'macaddress' => $target,
288 );
289 $answer_msg = &build_msg("got_ping_error", $main::server_address, $source, \%data);
290 $error = 1;
291 }
293 if (not $error) {
294 my $client_hash = &create_xml_hash("ping", $main::server_address, $host_name);
295 &add_content2xml_hash($client_hash, 'session_id', $session_id);
296 my $client_msg = &create_xml_string($client_hash);
297 &main::send_msg_to_target($client_msg, $host_name, $host_key, $header, $session_id);
299 my $message_id;
300 my $i = 0;
301 while (1) {
302 $i++;
303 $sql = "SELECT * FROM $main::incoming_tn WHERE headertag='answer_$session_id'";
304 $res = $main::incoming_db->exec_statement($sql);
305 if (ref @$res[0] eq "ARRAY") {
306 $message_id = @{@$res[0]}[0];
307 last;
308 }
310 # do not run into a endless loop
311 if ($i > 100) { last; }
312 usleep(100000);
313 }
315 # if an answer to the question exists
316 if (defined $message_id) {
317 my $answer_xml = @{@$res[0]}[3];
318 my %data = ( 'answer_xml' => 'bin noch da' );
319 $answer_msg = &build_msg("got_ping", $target, $source, \%data);
320 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
321 if (defined $forward_to_gosa){
322 $answer_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
323 }
324 $sql = "DELETE FROM $main::incoming_tn WHERE id=$message_id";
325 $res = $main::incoming_db->exec_statement($sql);
326 }
328 }
330 return ( $answer_msg );
331 }
335 sub gen_smb_hash {
336 my ($msg, $msg_hash, $session_id) = @_ ;
337 my $source = @{$msg_hash->{source}}[0];
338 my $target = @{$msg_hash->{target}}[0];
339 my $password = @{$msg_hash->{password}}[0];
341 my %data= ('hash' => join(q[:], ntlmgen $password));
342 my $out_msg = &build_msg("gen_smb_hash", $target, $source, \%data );
343 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
344 if (defined $forward_to_gosa) {
345 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
346 }
348 return ( $out_msg );
349 }
352 sub network_completition {
353 my ($msg, $msg_hash, $session_id) = @_ ;
354 my $source = @{$msg_hash->{source}}[0];
355 my $target = @{$msg_hash->{target}}[0];
356 my $name = @{$msg_hash->{hostname}}[0];
358 # Can we resolv the name?
359 my %data;
360 if (inet_aton($name)){
361 my $address = inet_ntoa(inet_aton($name));
362 my $p = Net::Ping->new('tcp');
363 my $mac= "";
364 if ($p->ping($address, 1)){
365 $mac = Net::ARP::arp_lookup("", $address);
366 }
368 %data= ('ip' => $address, 'mac' => $mac);
369 } else {
370 %data= ('ip' => '', 'mac' => '');
371 }
373 my $out_msg = &build_msg("network_completition", $target, $source, \%data );
374 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
375 if (defined $forward_to_gosa) {
376 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
377 }
379 return ( $out_msg );
380 }
383 sub detect_hardware {
384 my ($msg, $msg_hash, $session_id) = @_ ;
385 # just forward msg to client, but dont forget to split off 'gosa_' in header
386 my $source = @{$msg_hash->{source}}[0];
387 my $target = @{$msg_hash->{target}}[0];
388 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
389 if( defined $jobdb_id) {
390 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
391 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
392 my $res = $main::job_db->exec_statement($sql_statement);
393 }
395 my $out_hash = &create_xml_hash("detect_hardware", $source, $target);
396 if( defined $jobdb_id ) {
397 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
398 }
399 my $out_msg = &create_xml_string($out_hash);
401 my @out_msg_l = ( $out_msg );
402 return @out_msg_l;
404 }
407 sub trigger_reload_ldap_config {
408 my ($msg, $msg_hash, $session_id) = @_ ;
409 my $target = @{$msg_hash->{target}}[0];
411 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
412 if( defined $jobdb_id) {
413 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
414 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
415 my $res = $main::job_db->exec_statement($sql_statement);
416 }
418 my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
419 my @out_msg_l = ( $out_msg );
421 return @out_msg_l;
422 }
425 sub set_activated_for_installation {
426 my ($msg, $msg_hash, $session_id) = @_;
427 my $header = @{$msg_hash->{header}}[0];
428 my $source = @{$msg_hash->{source}}[0];
429 my $target = @{$msg_hash->{target}}[0];
430 my @out_msg_l;
432 # update status of job
433 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
434 if( defined $jobdb_id) {
435 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
436 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
437 my $res = $main::job_db->exec_statement($sql_statement);
438 }
440 # create set_activated_for_installation message for delivery
441 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
442 if( defined $jobdb_id ) {
443 &add_content2xml_hash($out_hash, 'jobdb_id', $jobdb_id);
444 }
445 my $out_msg = &create_xml_string($out_hash);
446 push(@out_msg_l, $out_msg);
448 return @out_msg_l;
449 }
452 sub trigger_action_faireboot {
453 my ($msg, $msg_hash, $session_id) = @_;
454 my $macaddress = @{$msg_hash->{macaddress}}[0];
455 my $source = @{$msg_hash->{source}}[0];
457 my @out_msg_l;
458 $msg =~ s/<header>gosa_trigger_action_faireboot<\/header>/<header>trigger_action_faireboot<\/header>/;
459 push(@out_msg_l, $msg);
461 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
462 &main::change_fai_state('install', \@{$msg_hash->{macaddress}}, $session_id);
464 # set job to status 'done', job will be deleted automatically
465 my $sql_statement = "UPDATE $main::job_queue_tn ".
466 "SET status='done', modified='1'".
467 "WHERE (macaddress='$macaddress' AND status='processing')";
468 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
469 my $res = $main::job_db->update_dbentry( $sql_statement );
471 return @out_msg_l;
472 }
475 sub trigger_action_lock {
476 my ($msg, $msg_hash, $session_id) = @_;
477 my $macaddress = @{$msg_hash->{macaddress}}[0];
478 my $source = @{$msg_hash->{source}}[0];
480 &main::change_goto_state('locked', \@{$msg_hash->{macaddress}}, $session_id);
481 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
482 if( defined $jobdb_id) {
483 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
484 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
485 my $res = $main::job_db->exec_statement($sql_statement);
486 }
488 my @out_msg_l;
489 return @out_msg_l;
490 }
493 sub trigger_action_activate {
494 my ($msg, $msg_hash, $session_id) = @_;
495 my $macaddress = @{$msg_hash->{macaddress}}[0];
496 my $source = @{$msg_hash->{source}}[0];
498 &main::change_goto_state('active', \@{$msg_hash->{macaddress}}, $session_id);
499 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
500 if( defined $jobdb_id) {
501 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
502 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
503 my $res = $main::job_db->exec_statement($sql_statement);
504 }
506 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $macaddress);
507 if( exists $msg_hash->{'jobdb_id'} ) {
508 &add_content2xml_hash($out_hash, 'jobdb_id', @{$msg_hash->{'jobdb_id'}}[0]);
509 }
510 my $out_msg = &create_xml_string($out_hash);
512 return ( $out_msg );
513 }
516 sub trigger_action_localboot {
517 my ($msg, $msg_hash, $session_id) = @_;
518 $msg =~ s/<header>gosa_trigger_action_localboot<\/header>/<header>trigger_action_localboot<\/header>/;
519 &main::change_fai_state('localboot', \@{$msg_hash->{macaddress}}, $session_id);
520 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
521 if( defined $jobdb_id) {
522 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
523 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
524 my $res = $main::job_db->exec_statement($sql_statement);
525 }
527 my @out_msg_l = ($msg);
528 return @out_msg_l;
529 }
532 sub trigger_action_halt {
533 my ($msg, $msg_hash, $session_id) = @_;
534 $msg =~ s/<header>gosa_trigger_action_halt<\/header>/<header>trigger_action_halt<\/header>/;
536 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
537 if( defined $jobdb_id) {
538 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
539 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
540 my $res = $main::job_db->exec_statement($sql_statement);
541 }
543 my @out_msg_l = ($msg);
544 return @out_msg_l;
545 }
548 sub trigger_action_reboot {
549 my ($msg, $msg_hash, $session_id) = @_;
550 $msg =~ s/<header>gosa_trigger_action_reboot<\/header>/<header>trigger_action_reboot<\/header>/;
552 &main::change_fai_state('reboot', \@{$msg_hash->{macaddress}}, $session_id);
553 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
554 if( defined $jobdb_id) {
555 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
556 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
557 my $res = $main::job_db->exec_statement($sql_statement);
558 }
560 my @out_msg_l = ($msg);
561 return @out_msg_l;
562 }
565 sub trigger_action_memcheck {
566 my ($msg, $msg_hash, $session_id) = @_ ;
567 $msg =~ s/<header>gosa_trigger_action_memcheck<\/header>/<header>trigger_action_memcheck<\/header>/;
569 &main::change_fai_state('memcheck', \@{$msg_hash->{macaddress}}, $session_id);
570 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
571 if( defined $jobdb_id) {
572 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
573 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
574 my $res = $main::job_db->exec_statement($sql_statement);
575 }
577 my @out_msg_l = ($msg);
578 return @out_msg_l;
579 }
582 sub trigger_action_reinstall {
583 my ($msg, $msg_hash, $session_id) = @_;
584 $msg =~ s/<header>gosa_trigger_action_reinstall<\/header>/<header>trigger_action_reinstall<\/header>/;
586 &main::change_fai_state('reinstall', \@{$msg_hash->{macaddress}}, $session_id);
588 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
589 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
590 my @out_msg_l = ($wake_msg, $msg);
591 return @out_msg_l;
592 }
595 sub trigger_action_update {
596 my ($msg, $msg_hash, $session_id) = @_;
597 $msg =~ s/<header>gosa_trigger_action_update<\/header>/<header>trigger_action_update<\/header>/;
599 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
601 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
602 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
603 my @out_msg_l = ($wake_msg, $msg);
604 return @out_msg_l;
605 }
608 sub trigger_action_instant_update {
609 my ($msg, $msg_hash, $session_id) = @_;
610 $msg =~ s/<header>gosa_trigger_action_instant_update<\/header>/<header>trigger_action_instant_update<\/header>/;
612 &main::change_fai_state('update', \@{$msg_hash->{macaddress}}, $session_id);
614 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
615 if( defined $jobdb_id) {
616 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
617 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
618 my $res = $main::job_db->exec_statement($sql_statement);
619 }
621 my %data = ( 'macAddress' => \@{$msg_hash->{macaddress}} );
622 my $wake_msg = &build_msg("trigger_wake", "GOSA", "KNOWN_SERVER", \%data);
623 my @out_msg_l = ($wake_msg, $msg);
624 return @out_msg_l;
625 }
628 sub trigger_action_sysinfo {
629 my ($msg, $msg_hash, $session_id) = @_;
630 $msg =~ s/<header>gosa_trigger_action_sysinfo<\/header>/<header>trigger_action_sysinfo<\/header>/;
632 &main::change_fai_state('sysinfo', \@{$msg_hash->{macaddress}}, $session_id);
633 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
634 if( defined $jobdb_id) {
635 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
636 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
637 my $res = $main::job_db->exec_statement($sql_statement);
638 }
640 my @out_msg_l = ($msg);
641 return @out_msg_l;
642 }
645 sub new_key_for_client {
646 my ($msg, $msg_hash, $session_id) = @_;
648 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
649 if( defined $jobdb_id) {
650 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
651 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
652 my $res = $main::job_db->exec_statement($sql_statement);
653 }
655 $msg =~ s/<header>gosa_new_key_for_client<\/header>/<header>new_key<\/header>/;
656 my @out_msg_l = ($msg);
657 return @out_msg_l;
658 }
661 sub trigger_action_rescan {
662 my ($msg, $msg_hash, $session_id) = @_;
664 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
665 if( defined $jobdb_id) {
666 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
667 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
668 my $res = $main::job_db->exec_statement($sql_statement);
669 }
672 $msg =~ s/<header>gosa_trigger_action_rescan<\/header>/<header>detect_hardware<header>/;
673 my @out_msg_l = ($msg);
674 return @out_msg_l;
675 }
678 sub trigger_action_wake {
679 my ($msg, $msg_hash, $session_id) = @_;
681 my $jobdb_id = @{$msg_hash->{'jobdb_id'}}[0];
682 if( defined $jobdb_id) {
683 my $sql_statement = "UPDATE $main::job_queue_tn SET status='processed' WHERE id=jobdb_id";
684 &main::daemon_log("$session_id DEBUG: $sql_statement", 7);
685 my $res = $main::job_db->exec_statement($sql_statement);
686 }
688 # build out message
689 my $out_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
690 foreach (@{$msg_hash->{target}}) {
691 &add_content2xml_hash($out_hash, 'macAddress', $_);
692 }
693 my $out_msg = &create_xml_string($out_hash);
695 # invoke trigger wake for this gosa-si-server
696 &main::server_server_com::trigger_wake($out_msg, $out_hash, $session_id);
698 # send trigger wake to all other gosa-si-server
699 my @out_msg_l = ($out_msg);
700 return @out_msg_l;
701 }
704 sub get_available_kernel {
705 my ($msg, $msg_hash, $session_id) = @_;
707 my $source = @{$msg_hash->{'source'}}[0];
708 my $target = @{$msg_hash->{'target'}}[0];
709 my $release= @{$msg_hash->{'release'}}[0];
711 my @kernel;
712 # Get Kernel packages for release
713 my $sql_statement = "SELECT * FROM $main::packages_list_tn WHERE distribution='$release' AND package LIKE 'linux\-image\-%'";
714 my $res_hash = $main::packages_list_db->select_dbentry($sql_statement);
715 my %data;
716 my $i=1;
718 foreach my $package (keys %{$res_hash}) {
719 $data{"answer".$i++}= $data{"answer".$i++}= ${$res_hash}{$package}->{'package'};
720 }
721 $data{"answer".$i++}= "default";
723 my $out_msg = &build_msg("get_available_kernel", $target, $source, \%data);
724 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
725 if (defined $forward_to_gosa) {
726 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
727 }
729 return ( $out_msg );
730 }
733 sub trigger_activate_new {
734 my ($msg, $msg_hash, $session_id) = @_;
736 my $source = @{$msg_hash->{'source'}}[0];
737 my $target = @{$msg_hash->{'target'}}[0];
738 my $header= @{$msg_hash->{'header'}}[0];
739 my $mac= (defined($msg_hash->{'mac'}))?@{$msg_hash->{'mac'}}[0]:undef;
740 my $ogroup= (defined($msg_hash->{'ogroup'}))?@{$msg_hash->{'ogroup'}}[0]:undef;
741 my $timestamp= (defined($msg_hash->{'timestamp'}))?@{$msg_hash->{'timestamp'}}[0]:undef;
742 my $base= (defined($msg_hash->{'base'}))?@{$msg_hash->{'base'}}[0]:undef;
743 my $hostname= (defined($msg_hash->{'fqdn'}))?@{$msg_hash->{'fqdn'}}[0]:undef;
744 my $ip_address= (defined($msg_hash->{'ip'}))?@{$msg_hash->{'ip'}}[0]:undef;
745 my $dhcp_statement= (defined($msg_hash->{'dhcp'}))?@{$msg_hash->{'dhcp'}}[0]:undef;
746 my $jobdb_id= (defined($msg_hash->{'jobdb_id'}))?@{$msg_hash->{'jobdb_id'}}[0]:undef;
748 my $ldap_handle = &main::get_ldap_handle();
749 my $ldap_entry;
750 my $ogroup_entry;
751 my $changed_attributes_counter = 0;
753 eval {
755 my $ldap_mesg= $ldap_handle->search(
756 base => $main::ldap_base,
757 scope => 'sub',
758 filter => "(&(objectClass=gosaGroupOfnames)(cn=$ogroup))",
759 );
760 if($ldap_mesg->count == 1) {
761 $ogroup_entry= $ldap_mesg->pop_entry();
762 } elsif ($ldap_mesg->count == 0) {
763 &main::daemon_log("ERROR: A GosaGroupOfNames with cn '$ogroup' was not found in base '".$main::ldap_base."'!", 1);
764 } else {
765 &main::daemon_log("ERROR: More than one ObjectGroups with cn '$ogroup' was found in base '".$main::ldap_base."'!", 1);
766 }
768 # build the base, use optional base parameter or take it from ogroup
769 if(!(defined($base) && (length($base) > 0))) {
770 # Subtract the ObjectGroup cn
771 $base = $1 if $ogroup_entry->dn =~ /cn=$ogroup,ou=groups,(.*)$/;
772 }
774 # prepend ou=systems (configurable through config)
775 $base = $main::new_systems_ou.",".$base;
777 # Search for an existing entry (should be in ou=incoming)
778 $ldap_mesg= $ldap_handle->search(
779 base => $main::ldap_base,
780 scope => 'sub',
781 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
782 );
784 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
786 if($ldap_mesg->count == 1) {
787 &main::daemon_log("DEBUG: One system with mac address '$mac' was found in base '".$main::ldap_base."'!", 6);
788 # Get the entry from LDAP
789 $ldap_entry= $ldap_mesg->pop_entry();
791 if(!($ldap_entry->dn() eq "cn=".$ldap_entry->get_value('cn').",$base")) {
792 # Move the entry to the new ou
793 $ldap_entry->changetype('moddn');
794 $ldap_entry->add(
795 newrdn => "cn=".$ldap_entry->get_value('cn'),
796 deleteoldrdn => 1,
797 newsuperior => $base,
798 );
799 }
801 }
803 $ldap_mesg= $ldap_handle->search(
804 base => $main::ldap_base,
805 scope => 'sub',
806 filter => "(&(objectClass=GOhard)(|(macAddress=$mac)(dhcpHWaddress=$mac)))",
807 );
809 # TODO: Find a way to guess an ip address for hosts with no ldap entry (MAC->ARP->IP)
811 if($ldap_mesg->count == 1) {
812 $ldap_entry= $ldap_mesg->pop_entry();
813 # Check for needed objectClasses
814 my $oclasses = $ldap_entry->get_value('objectClass', asref => 1);
815 foreach my $oclass ("FAIobject", "GOhard") {
816 if(!(scalar grep $_ eq $oclass, map {$_ => 1} @$oclasses)) {
817 &main::daemon_log("Adding objectClass $oclass", 1);
818 $ldap_entry->add(
819 objectClass => $oclass,
820 );
821 my $oclass_result = $ldap_entry->update($ldap_handle);
822 }
823 }
825 # Set FAIstate
826 if(defined($ldap_entry->get_value('FAIstate'))) {
827 if(!($ldap_entry->get_value('FAIstate') eq 'install')) {
828 $ldap_entry->replace(
829 'FAIstate' => 'install'
830 );
831 my $replace_result = $ldap_entry->update($ldap_handle);
832 }
833 } else {
834 $ldap_entry->add(
835 'FAIstate' => 'install'
836 );
837 my $add_result = $ldap_entry->update($ldap_handle);
838 }
841 } elsif ($ldap_mesg->count == 0) {
842 # TODO: Create a new entry
843 # $ldap_entry = Net::LDAP::Entry->new();
844 # $ldap_entry->dn("cn=$mac,$base");
845 &main::daemon_log("WARNING: No System with mac address '$mac' was found in base '".$main::ldap_base."'! Re-queuing job.", 4);
846 $main::job_db->exec_statement("UPDATE jobs SET status = 'waiting', timestamp = '".&get_time()."' WHERE id = $jobdb_id");
847 } else {
848 &main::daemon_log("ERROR: More than one system with mac address '$mac' was found in base '".$main::ldap_base."'!", 1);
849 }
851 # Add to ObjectGroup
852 if(!(scalar grep $_, map {$_ => 1} $ogroup_entry->get_value('member', asref => 1))) {
853 $ogroup_entry->add (
854 'member' => $ldap_entry->dn(),
855 );
856 my $ogroup_result = $ogroup_entry->update($ldap_handle);
857 if ($ogroup_result->code() != 0) {
858 &main::daemon_log("ERROR: Updating the ObjectGroup '$ogroup' failed (code '".$ogroup_result->code()."') with '".$ogroup_result->{'errorMessage'}."'!", 1);
859 }
860 }
862 # Finally set gotoMode to active
863 if(defined($ldap_entry->get_value('gotoMode'))) {
864 if(!($ldap_entry->get_value('gotoMode') eq 'active')) {
865 $ldap_entry->replace(
866 'gotoMode' => 'active'
867 );
868 my $activate_result = $ldap_entry->update($ldap_handle);
869 if ($activate_result->code() != 0) {
870 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
871 }
872 }
873 } else {
874 $ldap_entry->add(
875 'gotoMode' => 'active'
876 );
877 my $activate_result = $ldap_entry->update($ldap_handle);
878 if ($activate_result->code() != 0) {
879 &main::daemon_log("ERROR: Activating system '".$ldap_entry->dn()."' failed (code '".$activate_result->code()."') with '".$activate_result->{'errorMessage'}."'!", 1);
880 }
881 }
882 };
883 if($@) {
884 &main::daemon_log("ERROR: activate_new failed with '$@'!", 1);
885 }
887 # Delete job
888 $main::job_db->exec_statement("DELETE FROM jobs WHERE id = $jobdb_id");
890 # create set_activated_for_installation message for delivery
891 my $out_hash = &create_xml_hash("set_activated_for_installation", $source, $target);
892 my $out_msg = &create_xml_string($out_hash);
893 my @out_msg_l = ($out_msg);
895 return @out_msg_l;
896 }
899 #sub get_dak_keyring {
900 # my ($msg, $msg_hash) = @_;
901 # my $source = @{$msg_hash->{'source'}}[0];
902 # my $target = @{$msg_hash->{'target'}}[0];
903 # my $header= @{$msg_hash->{'header'}}[0];
904 # my $session_id = @{$msg_hash->{'session_id'}}[0];
905 #
906 # # build return message with twisted target and source
907 # my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
908 # &add_content2xml_hash($out_hash, "session_id", $session_id);
909 #
910 # my @keys;
911 # my %data;
912 #
913 # my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
914 #
915 # my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
916 # my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
917 #
918 # # Check if the keyrings are in place and readable
919 # if(
920 # &run_as($main::dak_user, "test -r $keyring")->{'resultCode'} != 0
921 # ) {
922 # &add_content2xml_hash($out_hash, "error", "DAK Keyring is not readable");
923 # } else {
924 # my $command = "$gpg --list-keys";
925 # my $output = &run_as($main::dak_user, $command);
926 # &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
927 #
928 # my $i=0;
929 # foreach (@{$output->{'output'}}) {
930 # if ($_ =~ m/^pub\s.*$/) {
931 # ($keys[$i]->{'pub'}->{'length'}, $keys[$i]->{'pub'}->{'uid'}, $keys[$i]->{'pub'}->{'created'}) = ($1, $2, $3)
932 # if $_ =~ m/^pub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
933 # $keys[$i]->{'pub'}->{'expires'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expires:\s(\d{4}-\d{2}-\d{2})\]/;
934 # $keys[$i]->{'pub'}->{'expired'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expired:\s(\d{4}-\d{2}-\d{2})\]/;
935 # } elsif ($_ =~ m/^sub\s.*$/) {
936 # ($keys[$i]->{'sub'}->{'length'}, $keys[$i]->{'sub'}->{'uid'}, $keys[$i]->{'sub'}->{'created'}) = ($1, $2, $3)
937 # if $_ =~ m/^sub\s*?(\w*?)\/(\w*?)\s(\d{4}-\d{2}-\d{2})/;
938 # $keys[$i]->{'sub'}->{'expires'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expires:\s(\d{4}-\d{2}-\d{2})\]/;
939 # $keys[$i]->{'sub'}->{'expired'} = $1 if $_ =~ m/^pub\s*?\w*?\/\w*?\s\d{4}-\d{2}-\d{2}\s\[expired:\s(\d{4}-\d{2}-\d{2})\]/;
940 # } elsif ($_ =~ m/^uid\s.*$/) {
941 # push @{$keys[$i]->{'uid'}}, $1 if $_ =~ m/^uid\s*?([^\s].*?)$/;
942 # } elsif ($_ =~ m/^$/) {
943 # $i++;
944 # }
945 # }
946 # }
947 #
948 # my $i=0;
949 # foreach my $key (@keys) {
950 # # &main::daemon_log(Dumper($key));
951 # &add_content2xml_hash($out_hash, "answer".$i++, $key);
952 # }
953 # my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
954 # if (defined $forward_to_gosa) {
955 # &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
956 # }
957 # return &create_xml_string($out_hash);
958 #}
959 #
960 #
961 #sub import_dak_key {
962 # my ($msg, $msg_hash) = @_;
963 # my $source = @{$msg_hash->{'source'}}[0];
964 # my $target = @{$msg_hash->{'target'}}[0];
965 # my $header= @{$msg_hash->{'header'}}[0];
966 # my $session_id = @{$msg_hash->{'session_id'}}[0];
967 # my $key = &decode_base64(@{$msg_hash->{'key'}}[0]);
968 #
969 # # build return message with twisted target and source
970 # my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
971 # &add_content2xml_hash($out_hash, "session_id", $session_id);
972 #
973 # my %data;
974 #
975 # my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
976 #
977 # my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
978 # my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --keyring $keyring";
979 #
980 # # Check if the keyrings are in place and writable
981 # if(
982 # &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
983 # ) {
984 # &add_content2xml_hash($out_hash, "error", "DAK Keyring is not writable");
985 # } else {
986 # my $keyfile;
987 # open($keyfile, ">/tmp/gosa_si_tmp_dak_key");
988 # print $keyfile $key;
989 # close($keyfile);
990 # my $command = "$gpg --import /tmp/gosa_si_tmp_dak_key";
991 # my $output = &run_as($main::dak_user, $command);
992 # &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
993 # unlink("/tmp/gosa_si_tmp_dak_key");
994 #
995 # if($output->{'resultCode'} != 0) {
996 # &add_content2xml_hash($out_hash, "error", "Import of DAK key failed! Output was '".$output->{'output'}."'");
997 # } else {
998 # &add_content2xml_hash($out_hash, "answer", "Import of DAK key successfull! Output was '".$output->{'output'}."'");
999 # }
1000 # }
1001 #
1002 # my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1003 # if (defined $forward_to_gosa) {
1004 # &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1005 # }
1006 # return &create_xml_string($out_hash);
1007 #}
1008 #
1009 #
1010 #sub remove_dak_key {
1011 # my ($msg, $msg_hash) = @_;
1012 # my $source = @{$msg_hash->{'source'}}[0];
1013 # my $target = @{$msg_hash->{'target'}}[0];
1014 # my $header= @{$msg_hash->{'header'}}[0];
1015 # my $session_id = @{$msg_hash->{'session_id'}}[0];
1016 # my $key = @{$msg_hash->{'keyid'}}[0];
1017 # # build return message with twisted target and source
1018 # my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
1019 # &add_content2xml_hash($out_hash, "session_id", $session_id);
1020 #
1021 # my %data;
1022 #
1023 # my $keyring = $main::dak_signing_keys_directory."/keyring.gpg";
1024 #
1025 # my $gpg_cmd = `which gpg`; chomp $gpg_cmd;
1026 # my $gpg = "$gpg_cmd --no-default-keyring --no-random-seed --homedir ".$main::dak_signing_keys_directory." --keyring $keyring";
1027 #
1028 # # Check if the keyrings are in place and writable
1029 # if(
1030 # &run_as($main::dak_user, "test -w $keyring")->{'resultCode'} != 0
1031 # ) {
1032 # &add_content2xml_hash($out_hash, "error", "DAK keyring is not writable");
1033 # } else {
1034 # # Check if the key is present in the keyring
1035 # if(&run_as($main::dak_user, "$gpg --list-keys $key")->{'resultCode'} == 0) {
1036 # my $command = "$gpg --batch --yes --delete-key $key";
1037 # my $output = &run_as($main::dak_user, $command);
1038 # &main::daemon_log("$session_id DEBUG: ".$output->{'command'}, 7);
1039 # } else {
1040 # &add_content2xml_hash($out_hash, "error", "DAK key with id '$key' was not found in keyring");
1041 # }
1042 # }
1043 #
1044 # my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1045 # if (defined $forward_to_gosa) {
1046 # &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1047 # }
1048 # return &create_xml_string($out_hash);
1049 #}
1052 #sub get_dak_queue {
1053 # my ($msg, $msg_hash, $session_id) = @_;
1054 # my %data;
1055 # my $source = @{$msg_hash->{'source'}}[0];
1056 # my $target = @{$msg_hash->{'target'}}[0];
1057 # my $header= @{$msg_hash->{'header'}}[0];
1058 #
1059 # my %data;
1060 #
1061 # foreach my $dir ("unchecked", "new", "accepted") {
1062 # foreach my $file(<"$main::dak_queue_directory/$dir/*.changes">) {
1063 # }
1064 # }
1065 #
1066 # my $out_msg = &build_msg("get_dak_queue", $target, $source, \%data);
1067 # my @out_msg_l = ($out_msg);
1068 # return @out_msg_l;
1069 #}
1072 # vim:ts=4:shiftwidth:expandtab
1073 1;