1 ## @file
2 # @details A GOsa-SI-server event module containing all functions for message handling.
3 # @brief Implementation of an event module for GOsa-SI-server.
6 package opsi_com;
7 use Exporter;
8 @ISA = qw(Exporter);
9 my @events = (
10 "get_events",
11 "opsi_install_client",
12 "opsi_get_netboot_products",
13 "opsi_get_local_products",
14 "opsi_get_client_hardware",
15 "opsi_get_client_software",
16 "opsi_get_product_properties",
17 "opsi_set_product_properties",
18 "opsi_list_clients",
19 "opsi_del_client",
20 "opsi_add_client",
21 "opsi_modify_client",
22 "opsi_add_product_to_client",
23 "opsi_del_product_from_client",
24 );
25 @EXPORT = @events;
27 use strict;
28 use warnings;
29 use GOSA::GosaSupportDaemon;
30 use Data::Dumper;
31 use XML::Quote qw(:all);
34 BEGIN {}
36 END {}
38 ## @method get_events()
39 # A brief function returning a list of functions which are exported by importing the module.
40 # @return List of all provided functions
41 sub get_events {
42 return \@events;
43 }
45 ## @method opsi_add_product_to_client
46 # Adds an Opsi product to an Opsi client.
47 # @param msg - STRING - xml message with tags hostId and productId
48 # @param msg_hash - HASHREF - message information parsed into a hash
49 # @param session_id - INTEGER - POE session id of the processing of this message
50 # @return out_msg - STRING - feedback to GOsa in success and error case
51 sub opsi_add_product_to_client {
52 my ($msg, $msg_hash, $session_id) = @_;
53 my $header = @{$msg_hash->{'header'}}[0];
54 my $source = @{$msg_hash->{'source'}}[0];
55 my $target = @{$msg_hash->{'target'}}[0];
56 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
57 my ($hostId, $productId);
58 my $error = 0;
60 # Build return message
61 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
62 if (defined $forward_to_gosa) {
63 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
64 }
66 # Sanity check of needed parameter
67 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
68 $error++;
69 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
70 &add_content2xml_hash($out_hash, "error", "hostId");
71 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
73 }
74 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
75 $error++;
76 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
77 &add_content2xml_hash($out_hash, "error", "productId");
78 &main::daemon_log("$session_id ERROR: no productId specified or procutId tag invalid: $msg", 1);
79 }
81 if (not $error) {
82 # Get hostID
83 $hostId = @{$msg_hash->{'hostId'}}[0];
84 &add_content2xml_hash($out_hash, "hostId", $hostId);
86 # Get productID
87 $productId = @{$msg_hash->{'productId'}}[0];
88 &add_content2xml_hash($out_hash, "productId", $productId);
90 # Do an action request for all these -> "setup".
91 my $callobj = {
92 method => 'setProductActionRequest',
93 params => [ $productId, $hostId, "setup" ],
94 id => 1, };
96 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
97 my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
98 if ($sres_err){
99 &main::daemon_log("$session_id ERROR: cannot add product: ".$sres_err_string, 1);
100 &add_content2xml_hash($out_hash, "error", $sres_err_string);
101 }
102 }
104 # return message
105 return ( &create_xml_string($out_hash) );
106 }
108 ## @method opsi_del_product_from_client
109 # Deletes an Opsi-product from an Opsi-client.
110 # @param msg - STRING - xml message with tags hostId and productId
111 # @param msg_hash - HASHREF - message information parsed into a hash
112 # @param session_id - INTEGER - POE session id of the processing of this message
113 # @return out_msg - STRING - feedback to GOsa in success and error case
114 sub opsi_del_product_from_client {
115 my ($msg, $msg_hash, $session_id) = @_;
116 my $header = @{$msg_hash->{'header'}}[0];
117 my $source = @{$msg_hash->{'source'}}[0];
118 my $target = @{$msg_hash->{'target'}}[0];
119 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
120 my ($hostId, $productId);
121 my $error = 0;
122 my ($sres, $sres_err, $sres_err_string);
124 # Build return message
125 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
126 if (defined $forward_to_gosa) {
127 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
128 }
130 # Sanity check of needed parameter
131 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
132 $error++;
133 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
134 &add_content2xml_hash($out_hash, "error", "hostId");
135 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
137 }
138 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
139 $error++;
140 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
141 &add_content2xml_hash($out_hash, "error", "productId");
142 &main::daemon_log("$session_id ERROR: no productId specified or procutId tag invalid: $msg", 1);
143 }
145 # All parameter available
146 if (not $error) {
147 # Get hostID
148 $hostId = @{$msg_hash->{'hostId'}}[0];
149 &add_content2xml_hash($out_hash, "hostId", $hostId);
151 # Get productID
152 $productId = @{$msg_hash->{'productId'}}[0];
153 &add_content2xml_hash($out_hash, "productId", $productId);
156 #TODO: check the results for more than one entry which is currently installed
157 #$callobj = {
158 # method => 'getProductDependencies_listOfHashes',
159 # params => [ $productId ],
160 # id => 1, };
161 #
162 #my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
163 #my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
164 #if ($sres_err){
165 # &main::daemon_log("ERROR: cannot perform dependency check: ".$sres_err_string, 1);
166 # &add_content2xml_hash($out_hash, "error", $sres_err_string);
167 # return ( &create_xml_string($out_hash) );
168 #}
171 # Check to get product action list
172 my $callobj = {
173 method => 'getPossibleProductActions_list',
174 params => [ $productId ],
175 id => 1, };
176 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
177 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
178 if ($sres_err){
179 &main::daemon_log("$session_id ERROR: cannot get product action list: ".$sres_err_string, 1);
180 &add_content2xml_hash($out_hash, "error", $sres_err_string);
181 $error++;
182 }
183 }
185 # Check action uninstall of product
186 if (not $error) {
187 my $uninst_possible= 0;
188 foreach my $r (@{$sres->result}) {
189 if ($r eq 'uninstall') {
190 $uninst_possible= 1;
191 }
192 }
193 if (!$uninst_possible){
194 &main::daemon_log("$session_id ERROR: cannot uninstall product '$productId', product do not has the action 'uninstall'", 1);
195 &add_content2xml_hash($out_hash, "error", "cannot uninstall product '$productId', product do not has the action 'uninstall'");
196 $error++;
197 }
198 }
200 # Set product state to "none"
201 # Do an action request for all these -> "setup".
202 if (not $error) {
203 my $callobj = {
204 method => 'setProductActionRequest',
205 params => [ $productId, $hostId, "none" ],
206 id => 1,
207 };
208 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
209 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
210 if ($sres_err){
211 &main::daemon_log("$session_id ERROR: cannot delete product: ".$sres_err_string, 1);
212 &add_content2xml_hash($out_hash, "error", $sres_err_string);
213 }
214 }
216 # Return message
217 return ( &create_xml_string($out_hash) );
218 }
220 ## @method opsi_add_client
221 # Adds an Opsi client to Opsi.
222 # @param msg - STRING - xml message with tags hostId and macaddress
223 # @param msg_hash - HASHREF - message information parsed into a hash
224 # @param session_id - INTEGER - POE session id of the processing of this message
225 # @return out_msg - STRING - feedback to GOsa in success and error case
226 sub opsi_add_client {
227 my ($msg, $msg_hash, $session_id) = @_;
228 my $header = @{$msg_hash->{'header'}}[0];
229 my $source = @{$msg_hash->{'source'}}[0];
230 my $target = @{$msg_hash->{'target'}}[0];
231 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
232 my ($hostId, $mac);
233 my $error = 0;
234 my ($sres, $sres_err, $sres_err_string);
236 # build return message with twisted target and source
237 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
238 if (defined $forward_to_gosa) {
239 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
240 }
242 # Sanity check of needed parameter
243 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
244 $error++;
245 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
246 &add_content2xml_hash($out_hash, "error", "hostId");
247 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
248 }
249 if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1)) {
250 $error++;
251 &add_content2xml_hash($out_hash, "macaddress_error", "no macaddress specified or macaddress tag invalid");
252 &add_content2xml_hash($out_hash, "error", "macaddress");
253 &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1);
254 }
256 if (not $error) {
257 # Get hostID
258 $hostId = @{$msg_hash->{'hostId'}}[0];
259 &add_content2xml_hash($out_hash, "hostId", $hostId);
261 # Get macaddress
262 $mac = @{$msg_hash->{'macaddress'}}[0];
263 &add_content2xml_hash($out_hash, "macaddress", $mac);
265 my $name= $hostId;
266 $name=~ s/^([^.]+).*$/$1/;
267 my $domain= $hostId;
268 $domain=~ s/^[^.]+\.(.*)$/$1/;
269 my ($description, $notes, $ip);
271 if (defined @{$msg_hash->{'description'}}[0]){
272 $description = @{$msg_hash->{'description'}}[0];
273 }
274 if (defined @{$msg_hash->{'notes'}}[0]){
275 $notes = @{$msg_hash->{'notes'}}[0];
276 }
277 if (defined @{$msg_hash->{'ip'}}[0]){
278 $ip = @{$msg_hash->{'ip'}}[0];
279 }
281 my $callobj;
282 $callobj = {
283 method => 'createClient',
284 params => [ $name, $domain, $description, $notes, $ip, $mac ],
285 id => 1,
286 };
288 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
289 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
290 if ($sres_err){
291 &main::daemon_log("$session_id ERROR: cannot create client: ".$sres_err_string, 1);
292 &add_content2xml_hash($out_hash, "error", $sres_err_string);
293 }
294 }
296 # Return message
297 return ( &create_xml_string($out_hash) );
298 }
300 ## @method
301 # ???
302 # @param msg - STRING - xml message with tag hostId
303 # @param msg_hash - HASHREF - message information parsed into a hash
304 # @param session_id - INTEGER - POE session id of the processing of this message
305 sub opsi_modify_client {
306 my ($msg, $msg_hash, $session_id) = @_;
307 my $header = @{$msg_hash->{'header'}}[0];
308 my $source = @{$msg_hash->{'source'}}[0];
309 my $target = @{$msg_hash->{'target'}}[0];
310 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
311 my $hostId;
313 # build return message with twisted target and source
314 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
315 if (defined $forward_to_gosa) {
316 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
317 }
319 # Get hostID
320 $hostId = @{$msg_hash->{'hostId'}}[0];
321 &add_content2xml_hash($out_hash, "hostId", $hostId);
322 my $name= $hostId;
323 $name=~ s/^([^.]+).*$/$1/;
324 my $domain= $hostId;
325 $domain=~ s/^[^.]+(.*)$/$1/;
326 my ($description, $notes, $ip, $mac);
328 my $callobj;
330 if (defined @{$msg_hash->{'description'}}[0]){
331 $description = @{$msg_hash->{'description'}}[0];
332 $callobj = {
333 method => 'setHostDescription',
334 params => [ $hostId, $description ],
335 id => 1,
336 };
337 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
338 my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
339 if ($sres_err){
340 &main::daemon_log("ERROR: cannot set description: ".$sres_err_string, 1);
341 &add_content2xml_hash($out_hash, "error", $sres_err_string);
342 return ( &create_xml_string($out_hash) );
343 }
344 }
345 if (defined @{$msg_hash->{'notes'}}[0]){
346 $notes = @{$msg_hash->{'notes'}}[0];
347 $callobj = {
348 method => 'setHostNotes',
349 params => [ $hostId, $notes ],
350 id => 1,
351 };
352 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
353 my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
354 if ($sres_err){
355 &main::daemon_log("ERROR: cannot set notes: ".$sres_err_string, 1);
356 &add_content2xml_hash($out_hash, "error", $sres_err_string);
357 return ( &create_xml_string($out_hash) );
358 }
359 }
360 if (defined @{$msg_hash->{'mac'}}[0]){
361 $mac = @{$msg_hash->{'mac'}}[0];
362 $callobj = {
363 method => 'setMacAddress',
364 params => [ $hostId, $mac ],
365 id => 1,
366 };
367 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
368 my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
369 if ($sres_err){
370 &main::daemon_log("ERROR: cannot set mac address: ".$sres_err_string, 1);
371 &add_content2xml_hash($out_hash, "error", $sres_err_string);
372 return ( &create_xml_string($out_hash) );
373 }
374 }
376 # return message
377 return ( &create_xml_string($out_hash) );
378 }
381 ## @method opsi_get_netboot_products
382 # ???
383 # @param msg - STRING - xml message with tag hostId
384 # @param msg_hash - HASHREF - message information parsed into a hash
385 # @param session_id - INTEGER - POE session id of the processing of this message
386 sub opsi_get_netboot_products {
387 my ($msg, $msg_hash, $session_id) = @_;
388 my $header = @{$msg_hash->{'header'}}[0];
389 my $source = @{$msg_hash->{'source'}}[0];
390 my $target = @{$msg_hash->{'target'}}[0];
391 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
392 my $hostId;
394 # build return message with twisted target and source
395 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
396 if (defined $forward_to_gosa) {
397 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
398 }
400 # Get hostID if defined
401 if (defined @{$msg_hash->{'hostId'}}[0]){
402 $hostId = @{$msg_hash->{'hostId'}}[0];
403 &add_content2xml_hash($out_hash, "hostId", $hostId);
404 }
406 &add_content2xml_hash($out_hash, "xxx", "");
407 my $xml_msg= &create_xml_string($out_hash);
409 # For hosts, only return the products that are or get installed
410 my $callobj;
411 $callobj = {
412 method => 'getNetBootProductIds_list',
413 params => [ ],
414 id => 1,
415 };
417 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
418 my %r = ();
419 for (@{$res->result}) { $r{$_} = 1 }
421 if (&check_opsi_res($res)){
423 if (defined $hostId){
424 $callobj = {
425 method => 'getProductStates_hash',
426 params => [ $hostId ],
427 id => 1,
428 };
430 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
431 if (&check_opsi_res($hres)){
432 my $htmp= $hres->result->{$hostId};
434 # check state != not_installed or action == setup -> load and add
435 foreach my $product (@{$htmp}){
437 if (!defined ($r{$product->{'productId'}})){
438 next;
439 }
441 # Now we've a couple of hashes...
442 if ($product->{'installationStatus'} ne "not_installed" or
443 $product->{'actionRequest'} eq "setup"){
444 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
446 $callobj = {
447 method => 'getProduct_hash',
448 params => [ $product->{'productId'} ],
449 id => 1,
450 };
452 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
453 if (&check_opsi_res($sres)){
454 my $tres= $sres->result;
456 my $name= xml_quote($tres->{'name'});
457 my $r= $product->{'productId'};
458 my $description= xml_quote($tres->{'description'});
459 $name=~ s/\//\\\//;
460 $description=~ s/\//\\\//;
461 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
462 }
464 }
465 }
467 }
469 } else {
470 foreach my $r (@{$res->result}) {
471 $callobj = {
472 method => 'getProduct_hash',
473 params => [ $r ],
474 id => 1,
475 };
477 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
478 if (&check_opsi_res($sres)){
479 my $tres= $sres->result;
481 my $name= xml_quote($tres->{'name'});
482 my $description= xml_quote($tres->{'description'});
483 $name=~ s/\//\\\//;
484 $description=~ s/\//\\\//;
485 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
486 }
488 }
490 }
491 }
493 $xml_msg=~ s/<xxx><\/xxx>//;
495 return ($xml_msg);
496 }
499 ## @method opsi_get_product_properties
500 # ???
501 # @param msg - STRING - xml message with tags ProductId and hostId
502 # @param msg_hash - HASHREF - message information parsed into a hash
503 # @param session_id - INTEGER - POE session id of the processing of this message
504 sub opsi_get_product_properties {
505 my ($msg, $msg_hash, $session_id) = @_;
506 my $header = @{$msg_hash->{'header'}}[0];
507 my $source = @{$msg_hash->{'source'}}[0];
508 my $target = @{$msg_hash->{'target'}}[0];
509 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
510 my $productId = @{$msg_hash->{'productId'}}[0];
511 my $hostId;
513 # build return message with twisted target and source
514 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
516 # Get hostID if defined
517 if (defined @{$msg_hash->{'hostId'}}[0]){
518 $hostId = @{$msg_hash->{'hostId'}}[0];
519 &add_content2xml_hash($out_hash, "hostId", $hostId);
520 }
522 if (defined $forward_to_gosa) {
523 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
524 }
525 &add_content2xml_hash($out_hash, "ProducId", "$productId");
527 # Load actions
528 my $callobj = {
529 method => 'getPossibleProductActions_list',
530 params => [ $productId ],
531 id => 1,
532 };
533 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
534 if (&check_opsi_res($res)){
535 foreach my $action (@{$res->result}){
536 &add_content2xml_hash($out_hash, "action", $action);
537 }
538 }
540 # Add place holder
541 &add_content2xml_hash($out_hash, "xxx", "");
543 # Move to XML string
544 my $xml_msg= &create_xml_string($out_hash);
546 # JSON Query
547 $callobj = {
548 method => 'getProductProperties_hash',
549 params => [ $productId ],
550 id => 1,
551 };
553 $res = $main::opsi_client->call($main::opsi_url, $callobj);
555 if (&check_opsi_res($res)){
556 my $r= $res->result;
557 foreach my $key (keys %{$r}) {
558 my $item= "<item>";
559 my $value= $r->{$key};
560 if (UNIVERSAL::isa( $value, "ARRAY" )){
561 foreach my $subval (@{$value}){
562 $item.= "<$key>".xml_quote($subval)."</$key>";
563 }
564 } else {
565 $item.= "<$key>".xml_quote($value)."</$key>";
566 }
567 $item.= "</item>";
568 $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
569 }
570 }
573 $xml_msg=~ s/<xxx><\/xxx>//;
575 return ($xml_msg);
576 }
579 ## @method opsi_set_product_properties
580 # ???
581 # @param msg - STRING - xml message with tags ProductId, hostId, action and state
582 # @param msg_hash - HASHREF - message information parsed into a hash
583 # @param session_id - INTEGER - POE session id of the processing of this message
584 sub opsi_set_product_properties {
585 my ($msg, $msg_hash, $session_id) = @_;
586 my $header = @{$msg_hash->{'header'}}[0];
587 my $source = @{$msg_hash->{'source'}}[0];
588 my $target = @{$msg_hash->{'target'}}[0];
589 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
590 my $productId = @{$msg_hash->{'productId'}}[0];
591 my $hostId;
593 # build return message with twisted target and source
594 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
595 &add_content2xml_hash($out_hash, "productId", $productId);
597 # Get hostID if defined
598 if (defined @{$msg_hash->{'hostId'}}[0]){
599 $hostId = @{$msg_hash->{'hostId'}}[0];
600 &add_content2xml_hash($out_hash, "hostId", $hostId);
601 }
603 # Set product states if requested
604 if (defined @{$msg_hash->{'action'}}[0]){
605 &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
606 }
607 if (defined @{$msg_hash->{'state'}}[0]){
608 &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
609 }
611 if (defined $forward_to_gosa) {
612 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
613 }
615 # Find properties
616 foreach my $item (@{$msg_hash->{'item'}}){
617 # JSON Query
618 my $callobj;
620 if (defined $hostId){
621 $callobj = {
622 method => 'setProductProperty',
623 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
624 id => 1,
625 };
626 } else {
627 $callobj = {
628 method => 'setProductProperty',
629 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
630 id => 1,
631 };
632 }
634 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
635 my ($res_err, $res_err_string) = &check_opsi_res($res);
636 # TODO : This error message sounds strange
637 if ($res_err){
638 &man::daemon_log("$session_id ERROR: no communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
639 &add_content2xml_hash($out_hash, "error", $res_err_string);
640 }
642 }
644 # return message
645 return ( &create_xml_string($out_hash) );
646 }
649 ## @method opsi_get_client_hardware
650 # ???
651 # @param msg - STRING - xml message with tag hostId
652 # @param msg_hash - HASHREF - message information parsed into a hash
653 # @param session_id - INTEGER - POE session id of the processing of this message
654 sub opsi_get_client_hardware {
655 my ($msg, $msg_hash, $session_id) = @_;
656 my $header = @{$msg_hash->{'header'}}[0];
657 my $source = @{$msg_hash->{'source'}}[0];
658 my $target = @{$msg_hash->{'target'}}[0];
659 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
660 my $hostId = @{$msg_hash->{'hostId'}}[0];
662 # build return message with twisted target and source
663 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
665 if (defined $forward_to_gosa) {
666 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
667 }
668 &add_content2xml_hash($out_hash, "hostId", "$hostId");
669 &add_content2xml_hash($out_hash, "xxx", "");
670 my $xml_msg= &create_xml_string($out_hash);
672 # JSON Query
673 my $callobj = {
674 method => 'getHardwareInformation_hash',
675 params => [ $hostId ],
676 id => 1,
677 };
679 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
680 if (&check_opsi_res($res)){
681 my $result= $res->result;
682 foreach my $r (keys %{$result}){
683 my $item= "<item><id>".xml_quote($r)."</id>";
684 my $value= $result->{$r};
685 foreach my $sres (@{$value}){
687 foreach my $dres (keys %{$sres}){
688 if (defined $sres->{$dres}){
689 $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
690 }
691 }
693 }
694 $item.= "</item>";
695 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
697 }
698 }
700 $xml_msg=~ s/<xxx><\/xxx>//;
702 return ( $xml_msg );
703 }
706 ## @method opsi_list_clients
707 # ???
708 # @param msg - STRING - xml message
709 # @param msg_hash - HASHREF - message information parsed into a hash
710 # @param session_id - INTEGER - POE session id of the processing of this message
711 sub opsi_list_clients {
712 my ($msg, $msg_hash, $session_id) = @_;
713 my $header = @{$msg_hash->{'header'}}[0];
714 my $source = @{$msg_hash->{'source'}}[0];
715 my $target = @{$msg_hash->{'target'}}[0];
716 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
718 # build return message with twisted target and source
719 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
721 if (defined $forward_to_gosa) {
722 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
723 }
725 &add_content2xml_hash($out_hash, "xxx", "");
726 my $xml_msg= &create_xml_string($out_hash);
728 # JSON Query
729 my $callobj = {
730 method => 'getClients_listOfHashes',
731 params => [ ],
732 id => 1,
733 };
735 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
736 if (&check_opsi_res($res)){
738 foreach my $host (@{$res->result}){
739 my $item= "<item><name>".$host->{'hostId'}."</name>";
740 if (defined($host->{'description'})){
741 $item.= "<description>".xml_quote($host->{'description'})."</description>";
742 }
743 $item.= "</item>";
744 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
745 }
747 }
749 $xml_msg=~ s/<xxx><\/xxx>//;
750 return ( $xml_msg );
751 }
754 ## @method opsi_get_client_software
755 # ???
756 # @param msg - STRING - xml message with tag hostId
757 # @param msg_hash - HASHREF - message information parsed into a hash
758 # @param session_id - INTEGER - POE session id of the processing of this message
759 sub opsi_get_client_software {
760 my ($msg, $msg_hash, $session_id) = @_;
761 my $header = @{$msg_hash->{'header'}}[0];
762 my $source = @{$msg_hash->{'source'}}[0];
763 my $target = @{$msg_hash->{'target'}}[0];
764 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
765 my $hostId = @{$msg_hash->{'hostId'}}[0];
767 # build return message with twisted target and source
768 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
770 if (defined $forward_to_gosa) {
771 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
772 }
773 &add_content2xml_hash($out_hash, "hostId", "$hostId");
774 &add_content2xml_hash($out_hash, "xxx", "");
775 my $xml_msg= &create_xml_string($out_hash);
777 # JSON Query
778 my $callobj = {
779 method => 'getSoftwareInformation_hash',
780 params => [ $hostId ],
781 id => 1,
782 };
784 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
785 if (&check_opsi_res($res)){
786 my $result= $res->result;
787 }
789 $xml_msg=~ s/<xxx><\/xxx>//;
791 return ( $xml_msg );
792 }
795 ## @method opsi_get_local_products
796 # ???
797 # @param msg - STRING - xml message with tag hostId
798 # @param msg_hash - HASHREF - message information parsed into a hash
799 # @param session_id - INTEGER - POE session id of the processing of this message
800 sub opsi_get_local_products {
801 my ($msg, $msg_hash, $session_id) = @_;
802 my $header = @{$msg_hash->{'header'}}[0];
803 my $source = @{$msg_hash->{'source'}}[0];
804 my $target = @{$msg_hash->{'target'}}[0];
805 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
806 my $hostId;
808 # build return message with twisted target and source
809 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
811 # Get hostID if defined
812 if (defined @{$msg_hash->{'hostId'}}[0]){
813 $hostId = @{$msg_hash->{'hostId'}}[0];
814 &add_content2xml_hash($out_hash, "hostId", $hostId);
815 }
817 if (defined $forward_to_gosa) {
818 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
819 }
820 &add_content2xml_hash($out_hash, "xxx", "");
821 my $xml_msg= &create_xml_string($out_hash);
823 # For hosts, only return the products that are or get installed
824 my $callobj;
825 $callobj = {
826 method => 'getLocalBootProductIds_list',
827 params => [ ],
828 id => 1,
829 };
831 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
832 my %r = ();
833 for (@{$res->result}) { $r{$_} = 1 }
835 if (&check_opsi_res($res)){
837 if (defined $hostId){
838 $callobj = {
839 method => 'getProductStates_hash',
840 params => [ $hostId ],
841 id => 1,
842 };
844 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
845 if (&check_opsi_res($hres)){
846 my $htmp= $hres->result->{$hostId};
848 # check state != not_installed or action == setup -> load and add
849 foreach my $product (@{$htmp}){
851 if (!defined ($r{$product->{'productId'}})){
852 next;
853 }
855 # Now we've a couple of hashes...
856 if ($product->{'installationStatus'} ne "not_installed" or
857 $product->{'actionRequest'} eq "setup"){
858 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
860 $callobj = {
861 method => 'getProduct_hash',
862 params => [ $product->{'productId'} ],
863 id => 1,
864 };
866 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
867 if (&check_opsi_res($sres)){
868 my $tres= $sres->result;
870 my $name= xml_quote($tres->{'name'});
871 my $r= $product->{'productId'};
872 my $description= xml_quote($tres->{'description'});
873 $name=~ s/\//\\\//;
874 $description=~ s/\//\\\//;
875 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
876 }
878 }
879 }
881 }
883 } else {
884 foreach my $r (@{$res->result}) {
885 $callobj = {
886 method => 'getProduct_hash',
887 params => [ $r ],
888 id => 1,
889 };
891 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
892 if (&check_opsi_res($sres)){
893 my $tres= $sres->result;
895 my $name= xml_quote($tres->{'name'});
896 my $description= xml_quote($tres->{'description'});
897 $name=~ s/\//\\\//;
898 $description=~ s/\//\\\//;
899 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
900 }
902 }
904 }
905 }
907 $xml_msg=~ s/<xxx><\/xxx>//;
909 return ( $xml_msg );
910 }
913 ## @method opsi_del_client
914 # ???
915 # @param msg - STRING - xml message with tag hostId
916 # @param msg_hash - HASHREF - message information parsed into a hash
917 # @param session_id - INTEGER - POE session id of the processing of this message
918 sub opsi_del_client {
919 my ($msg, $msg_hash, $session_id) = @_;
920 my $header = @{$msg_hash->{'header'}}[0];
921 my $source = @{$msg_hash->{'source'}}[0];
922 my $target = @{$msg_hash->{'target'}}[0];
923 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
924 my $hostId = @{$msg_hash->{'hostId'}}[0];
926 # build return message with twisted target and source
927 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
929 if (defined $forward_to_gosa) {
930 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
931 }
932 &add_content2xml_hash($out_hash, "hostId", "$hostId");
934 # JSON Query
935 my $callobj = {
936 method => 'deleteClient',
937 params => [ $hostId ],
938 id => 1,
939 };
941 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
943 my $xml_msg= &create_xml_string($out_hash);
944 return ( $xml_msg );
945 }
948 ## @method opsi_install_client
949 # ???
950 # @param msg - STRING - xml message with tags hostId, macaddress
951 # @param msg_hash - HASHREF - message information parsed into a hash
952 # @param session_id - INTEGER - POE session id of the processing of this message
953 sub opsi_install_client {
954 my ($msg, $msg_hash, $session_id) = @_;
955 my $header = @{$msg_hash->{'header'}}[0];
956 my $source = @{$msg_hash->{'source'}}[0];
957 my $target = @{$msg_hash->{'target'}}[0];
958 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
959 my $hostId = @{$msg_hash->{'hostId'}}[0];
960 my $error = 0;
961 my @out_msg_l;
963 # If no macaddress is specified, raise error
964 my $macaddress;
965 if ((exists $msg_hash->{'macaddress'}) &&
966 ($msg_hash->{'macaddress'}[0] =~ /^([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})$/i)) {
967 $macaddress = $1;
968 } else {
969 $error ++;
970 my $out_msg = "<xml>".
971 "<header>answer</header>".
972 "<source>$main::server_address</source>".
973 "<target>GOSA</target>".
974 "<answer1>1</answer1>".
975 "<error_string>no mac address specified in macaddres-tag</error_string>".
976 "</xml>";
977 push(@out_msg_l, $out_msg);
978 }
980 # Set parameters in opsi
981 if (not $error) {
982 # build return message with twisted target and source
983 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
985 if (defined $forward_to_gosa) {
986 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
987 }
988 &add_content2xml_hash($out_hash, "hostId", "$hostId");
990 # Load all products for this host with status != "not_installed" or actionRequest != "none"
991 if (defined $hostId){
992 my $callobj = {
993 method => 'getProductStates_hash',
994 params => [ $hostId ],
995 id => 1,
996 };
998 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
999 if (&check_opsi_res($hres)){
1000 my $htmp= $hres->result->{$hostId};
1002 # check state != not_installed or action == setup -> load and add
1003 foreach my $product (@{$htmp}){
1004 # Now we've a couple of hashes...
1005 if ($product->{'installationStatus'} ne "not_installed" or
1006 $product->{'actionRequest'} ne "none"){
1008 # Do an action request for all these -> "setup".
1009 $callobj = {
1010 method => 'setProductActionRequest',
1011 params => [ $product->{'productId'}, $hostId, "setup" ],
1012 id => 1,
1013 };
1014 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1015 if (!&check_opsi_res($res)){
1016 &main::daemon_log("ERROR: cannot set product action request for $hostId!", 1);
1017 } else {
1018 &main::daemon_log("INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
1019 }
1021 }
1022 }
1023 }
1024 }
1026 push(@out_msg_l, &create_xml_string($out_hash));
1027 }
1029 # Build wakeup message for client
1030 if (not $error) {
1031 my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
1032 &add_content2xml_hash($wakeup_hash, 'macAddress', $macaddress);
1033 my $wakeup_msg = &create_xml_string($wakeup_hash);
1034 push(@out_msg_l, $wakeup_msg);
1036 # invoke trigger wake for this gosa-si-server
1037 &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
1038 }
1041 return @out_msg_l;
1042 }
1045 ## @method _set_action
1046 # ???
1047 # @param product - STRING - ???
1048 # @param action - STRING - ???
1049 # @param hostId - STRING - ???
1050 sub _set_action {
1051 my $product= shift;
1052 my $action = shift;
1053 my $hostId = shift;
1054 my $callobj;
1056 $callobj = {
1057 method => 'setProductActionRequest',
1058 params => [ $product, $hostId, $action],
1059 id => 1,
1060 };
1062 $main::opsi_client->call($main::opsi_url, $callobj);
1063 }
1065 ## @method _set_state
1066 # ???
1067 # @param product - STRING - ???
1068 # @param action - STRING - ???
1069 # @param hostId - STRING - ???
1070 sub _set_state {
1071 my $product = shift;
1072 my $hostId = shift;
1073 my $action = shift;
1074 my $callobj;
1076 $callobj = {
1077 method => 'setProductState',
1078 params => [ $product, $hostId, $action ],
1079 id => 1,
1080 };
1082 $main::opsi_client->call($main::opsi_url, $callobj);
1083 }
1085 1;