1 package siTriggered;
3 use strict;
4 use warnings;
6 use Exporter;
7 use Data::Dumper;
8 use GOSA::GosaSupportDaemon;
9 use Socket;
11 our @ISA = qw(Exporter);
13 my @events = (
14 "got_ping",
15 "detected_hardware",
16 "trigger_wake",
17 "reload_ldap_config",
18 "get_terminal_server",
19 );
21 our @EXPORT = @events;
23 BEGIN {}
25 END {}
27 ### Start ######################################################################
29 my $ldap_uri;
30 my $ldap_base;
31 my $ldap_admin_dn;
32 my $ldap_admin_password;
33 my $mesg;
35 my %cfg_defaults = (
36 "server" => {
37 "ldap-uri" => [\$ldap_uri, ""],
38 "ldap-base" => [\$ldap_base, ""],
39 "ldap-admin-dn" => [\$ldap_admin_dn, ""],
40 "ldap-admin-password" => [\$ldap_admin_password, ""],
41 },
42 );
43 &GOSA::GosaSupportDaemon::read_configfile($main::cfg_file, %cfg_defaults);
46 sub get_terminal_server
47 {
48 my ($msg, $msg_hash, $session_id) = @_ ;
49 my $source = @{$msg_hash->{source}}[0];
50 my @out_msg_l;
52 # Send get_load message to all si-clients at terminal server specified in LDAP
53 my $ldap_handle = &main::get_ldap_handle();
54 if (defined $ldap_handle)
55 {
56 my $ldap_mesg = $ldap_handle->search(
57 base => $ldap_base,
58 scope => 'sub',
59 attrs => ['macAddress', 'cn', 'ipHostNumber'],
60 filter => "objectClass=goTerminalServer",
61 );
62 if ($ldap_mesg->count)
63 {
64 # Parse all LDAP results to a sql compliant where statement
65 my @entries = $ldap_mesg->entries;
66 @entries = map ($_->get_value("macAddress"), @entries);
67 @entries = map ("macaddress LIKE '$_'", @entries);
69 my ($hit, $hash, $db_res, $out_msg);
70 # Check known clients if a terminal server is active
71 $db_res = $main::known_clients_db->select_dbentry("SELECT * FROM $main::known_clients_tn WHERE ".join(" AND ", @entries));
72 while (($hit, $hash) = each %$db_res)
73 {
74 $out_msg = &create_xml_string(&create_xml_hash('get_load', $source, $hash->{macaddress}));
75 push(@out_msg_l, $out_msg);
76 }
77 # Check foreign_clients if a terminal server is active
78 $db_res = $main::foreign_clients_db->select_dbentry("SELECT * FROM $main::foreign_clients_tn WHERE ".join(" AND ", @entries));
79 while (($hit, $hash) = each %$db_res)
80 {
81 $out_msg = &create_xml_string(&create_xml_hash('get_load', $source, $hash->{macaddress}));
82 push(@out_msg_l, $out_msg);
83 }
85 ### JUST FOR DEBUGGING # CAN BE DELETED AT ANY TIME ###########################
86 # my $db_res = $main::known_clients_db->select_dbentry("SELECT * FROM $main::known_clients_tn WHERE macaddress LIKE '00:01:6c:9d:b9:fa'");
87 # while (($hit, $hash) = each %$db_res)
88 # {
89 # $out_msg = &create_xml_string(&create_xml_hash('get_load', $source, $hash->{macaddress}));
90 # push(@out_msg_l, $out_msg);
91 # }
92 ### JUST FOR DEBUGGING # CAN BE DELETED AT ANY TIME ###########################
94 # Found terminal server but no running clients on them
95 if (@out_msg_l == 0)
96 {
97 &main::daemon_log("$session_id ERROR: Found no running clients (known_clients_db, foreign_clients_db) on the following determined terminal server", 1);
98 my @entries = $ldap_mesg->entries;
99 foreach my $ts (@entries)
100 {
101 my $ip = (defined $ts->get_value("ipHostNumber")) ? " ip='".$ts->get_value("ipHostNumber")."'" : "" ;
102 my $cn = (defined $ts->get_value("cn")) ? " cn='".$ts->get_value("cn")."'" : "" ;
103 my $mac = (defined $ts->get_value("macAddress")) ? " macAddress='".$ts->get_value("macAddress")."'" : "" ;
104 &main::daemon_log("$session_id ERROR: ".$cn.$mac.$ip , 1);
105 }
106 }
108 }
109 # No terminal server found in LDAP
110 if ($ldap_mesg->count == 0)
111 {
112 &main::daemon_log("$session_id ERROR: No terminal server found in LDAP: \n\tbase='$ldap_base'\n\tscope='sub'\n\tattrs='['macAddress']'\n\tfilter='objectClass=goTerminalServer'", 1);
113 }
115 # Translating errors ?
116 if ($ldap_mesg->code)
117 {
118 &main::daemon_log("$session_id ERROR: Cannot fetch terminal server from LDAP: \n\tbase='$ldap_base'\n\tscope='sub'\n\tattrs='['macAddress']'\n\tfilter='objectClass=goTerminalServer'", 1);
119 }
120 }
121 &main::release_ldap_handle($ldap_handle);
123 return @out_msg_l;
124 }
127 sub get_events {
128 return \@events;
129 }
131 sub reload_ldap_config {
132 my ($msg, $msg_hash, $session_id) = @_;
133 my $header = @{$msg_hash->{header}}[0];
134 my $target = @{$msg_hash->{$header}}[0];
136 my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
137 my @out_msg_l = ( $out_msg );
138 return @out_msg_l;
139 }
142 sub got_ping {
143 my ($msg, $msg_hash, $session_id) = @_;
145 my $source = @{$msg_hash->{source}}[0];
146 my $target = @{$msg_hash->{target}}[0];
147 my $header = @{$msg_hash->{header}}[0];
148 my $act_time = &get_time;
149 my @out_msg_l;
150 my $out_msg;
152 $session_id = @{$msg_hash->{'session_id'}}[0];
154 # check known_clients_db
155 my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source'";
156 my $query_res = $main::known_clients_db->select_dbentry( $sql_statement );
157 if( 1 == keys %{$query_res} ) {
158 my $sql_statement= "UPDATE known_clients ".
159 "SET status='$header', timestamp='$act_time' ".
160 "WHERE hostname='$source'";
161 my $res = $main::known_clients_db->update_dbentry( $sql_statement );
162 }
164 # check known_server_db
165 $sql_statement = "SELECT * FROM known_server WHERE hostname='$source'";
166 $query_res = $main::known_server_db->select_dbentry( $sql_statement );
167 if( 1 == keys %{$query_res} ) {
168 my $sql_statement= "UPDATE known_server ".
169 "SET status='$header', timestamp='$act_time' ".
170 "WHERE hostname='$source'";
171 my $res = $main::known_server_db->update_dbentry( $sql_statement );
172 }
174 # create out_msg
175 my $out_hash = &create_xml_hash($header, $source, "GOSA");
176 &add_content2xml_hash($out_hash, "session_id", $session_id);
177 $out_msg = &create_xml_string($out_hash);
178 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
179 if (defined $forward_to_gosa) {
180 $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
181 }
182 push(@out_msg_l, $out_msg);
184 return @out_msg_l;
185 }
188 sub detected_hardware {
189 my ($msg, $msg_hash, $session_id) = @_;
190 my $address = $msg_hash->{source}[0];
191 my $header = $msg_hash->{header}[0];
192 my $gotoHardwareChecksum= $msg_hash->{detected_hardware}[0]->{gotoHardwareChecksum};
194 my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
195 my $res = $main::known_clients_db->select_dbentry( $sql_statement );
197 # check hit
198 my $hit_counter = keys %{$res};
199 if( not $hit_counter == 1 ) {
200 &main::daemon_log("$session_id ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
201 return;
202 }
204 my $macaddress = $res->{1}->{macaddress};
205 my $hostkey = $res->{1}->{hostkey};
207 if (not defined $macaddress) {
208 &main::daemon_log("$session_id ERROR: no mac address found for client $address", 1);
209 return;
210 }
212 # Perform search
213 my $ldap_handle = &main::get_ldap_handle();
214 $mesg = $ldap_handle->search(
215 base => $ldap_base,
216 scope => 'sub',
217 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
218 );
220 # We need to create a base entry first (if not done from ArpHandler)
221 if($mesg->count == 0) {
222 &main::daemon_log("INFO: Need to create a new LDAP Entry for client $address", 4);
223 my $ipaddress= $1 if $address =~ /^([0-9\.]*?):.*$/;
224 my $dnsname;
225 #FIXME: like in ClientPackages!
226 #if ( defined($heap->{force-hostname}->{$macaddress}) ){
227 # $dnsname= $heap->{force-hostname}->{$macaddress};
228 # &main::daemon_log("INFO: Using forced hostname $dnsname for client $address", 4);
229 if (-e "/var/tmp/$macaddress" ){
230 open(my $TFILE, "<", "/var/tmp/$macaddress");
231 $dnsname= <$TFILE>;
232 close($TFILE);
233 } else {
234 $dnsname= gethostbyaddr(inet_aton($ipaddress), AF_INET) || $ipaddress;
235 }
237 my $cn = (($dnsname =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/) ? $dnsname : sprintf "%s", $dnsname =~ /([^\.]+)\.?/);
238 my $dn = "cn=$cn,ou=incoming,$ldap_base";
239 &main::daemon_log("INFO: Creating entry for $dn",5);
240 my $entry= Net::LDAP::Entry->new( $dn );
241 $entry->dn($dn);
242 $entry->add("objectClass" => "GOhard");
243 $entry->add("cn" => $cn);
244 $entry->add("macAddress" => $macaddress);
245 $entry->add("gotomode" => "locked");
246 $entry->add("gotoSysStatus" => "new-system");
247 $entry->add("ipHostNumber" => $ipaddress);
248 if(defined($main::gosa_unit_tag) && length($main::gosa_unit_tag) > 0) {
249 $entry->add("objectClass" => "gosaAdministrativeUnitTag");
250 $entry->add("gosaUnitTag" => $main::gosa_unit_tag);
251 }
252 my $res=$entry->update($ldap_handle);
253 if(defined($res->{'errorMessage'}) &&
254 length($res->{'errorMessage'}) >0) {
255 &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
256 &main::release_ldap_handle($ldap_handle);
257 return;
258 } else {
259 # Fill $mesg again
260 $mesg = $ldap_handle->search(
261 base => $ldap_base,
262 scope => 'sub',
263 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
264 );
265 }
266 }
268 if($mesg->count == 1) {
269 my $entry= $mesg->entry(0);
270 $entry->changetype("modify");
271 foreach my $attribute (
272 "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel",
273 "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync",
274 "gotoXDriver", "gotoXVsync", "gotoXMonitor", "gotoHardwareChecksum") {
275 if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
276 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
277 if(defined($entry->get_value($attribute))) {
278 $entry->delete($attribute => []);
279 }
280 &main::daemon_log("INFO: Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},5);
281 $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});
282 }
283 }
284 foreach my $attribute (
285 "gotoModules", "ghScsiDev", "ghIdeDev") {
286 if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
287 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
288 if(defined($entry->get_value($attribute))) {
289 $entry->delete($attribute => []);
290 }
291 foreach my $array_entry (keys %{{map { $_ => 1 } sort(@{$msg_hash->{detected_hardware}[0]->{$attribute}}) }}) {
292 $entry->add($attribute => $array_entry);
293 }
294 }
295 }
297 my $res=$entry->update($ldap_handle);
298 if(defined($res->{'errorMessage'}) &&
299 length($res->{'errorMessage'}) >0) {
300 &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
301 } else {
302 &main::daemon_log("INFO: Added Hardware configuration to LDAP", 5);
303 }
304 }
306 # if there is a job in job queue for this host and this macaddress, delete it, cause its no longer used
307 my $del_sql = "DELETE FROM $main::job_queue_tn WHERE (macaddress LIKE '$macaddress' AND headertag='$header')";
308 my $del_res = $main::job_db->exec_statement($del_sql);
309 &main::release_ldap_handle($ldap_handle);
311 return ;
312 }
314 1;