Code

update: opsi functions partly with input sanity check and doxygen headerlines
[gosa.git] / gosa-si / server / events / opsi_com.pm
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) );
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) );
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) );
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   }
375   
376   # return message
377   return ( &create_xml_string($out_hash) );
380     
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);
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);
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) );
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 );
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 );
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 );
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 );
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 );
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;
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);
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);
1085 1;