Code

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