Code

new opsi_client to debug ospi problems
[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) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
68         $error++;
69         &add_content2xml_hash($out_hash, "error_string", "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) || (@{$msg_hash->{'productId'}}[0] eq ref 'HASH')) {
75         $error++;
76         &add_content2xml_hash($out_hash, "error_string", "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) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
132         $error++;
133         &add_content2xml_hash($out_hash, "error_string", "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) || (@{$msg_hash->{'productId'}}[0] eq ref 'HASH')) {
139         $error++;
140         &add_content2xml_hash($out_hash, "error_string", "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) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
244         $error++;
245         &add_content2xml_hash($out_hash, "error_string", "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) || (@{$msg_hash->{'macaddress'}}[0] eq ref 'HASH'))  {
250         $error++;
251         &add_content2xml_hash($out_hash, "error_string", "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         } else {
294             &main::daemon_log("$session_id INFO: add opsi client '$hostId' with mac '$mac'", 5); 
295         }
296     }
298     # Return message
299     return ( &create_xml_string($out_hash) );
302 ## @method opsi_modify_client
303 # Modifies the parameters description, mac or notes for an Opsi client if the corresponding message tags are given.
304 # @param msg - STRING - xml message with tag hostId and optional description, mac or notes
305 # @param msg_hash - HASHREF - message information parsed into a hash
306 # @param session_id - INTEGER - POE session id of the processing of this message    
307 # @return out_msg - STRING - feedback to GOsa in success and error case
308 sub opsi_modify_client {
309     my ($msg, $msg_hash, $session_id) = @_;
310     my $header = @{$msg_hash->{'header'}}[0];
311     my $source = @{$msg_hash->{'source'}}[0];
312     my $target = @{$msg_hash->{'target'}}[0];
313     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
314     my $hostId;
315     my $error = 0;
316     my ($sres, $sres_err, $sres_err_string);
318     # Build return message with twisted target and source
319     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
320     if (defined $forward_to_gosa) {
321         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
322     }
324     # Sanity check of needed parameter
325     if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
326         $error++;
327         &add_content2xml_hash($out_hash, "error_string", "no hostId specified or hostId tag invalid");
328         &add_content2xml_hash($out_hash, "error", "hostId");
329         &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1); 
330     }
332     if (not $error) {
333         # Get hostId
334         $hostId = @{$msg_hash->{'hostId'}}[0];
335         &add_content2xml_hash($out_hash, "hostId", $hostId);
336         my $name= $hostId;
337         $name=~ s/^([^.]+).*$/$1/;
338         my $domain= $hostId;
339         $domain=~ s/^[^.]+(.*)$/$1/;
341         # Modify description, notes or mac if defined
342         my ($description, $notes, $mac);
343         my $callobj;
344         if ((exists $msg_hash->{'description'}) && (@{$msg_hash->{'description'}} == 1) ){
345             $description = @{$msg_hash->{'description'}}[0];
346             $callobj = {
347                 method  => 'setHostDescription',
348                 params  => [ $hostId, $description ],
349                 id  => 1,
350             };
351             my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
352             my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
353             if ($sres_err){
354                 &main::daemon_log("ERROR: cannot set description: ".$sres_err_string, 1);
355                 &add_content2xml_hash($out_hash, "error", $sres_err_string);
356             }
357         }
358         if ((exists $msg_hash->{'notes'}) && (@{$msg_hash->{'notes'}} == 1)) {
359             $notes = @{$msg_hash->{'notes'}}[0];
360             $callobj = {
361                 method  => 'setHostNotes',
362                 params  => [ $hostId, $notes ],
363                 id  => 1,
364             };
365             my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
366             my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
367             if ($sres_err){
368                 &main::daemon_log("ERROR: cannot set notes: ".$sres_err_string, 1);
369                 &add_content2xml_hash($out_hash, "error", $sres_err_string);
370             }
371         }
372         if ((exists $msg_hash->{'mac'}) && (@{$msg_hash->{'mac'}} == 1)){
373             $mac = @{$msg_hash->{'mac'}}[0];
374             $callobj = {
375                 method  => 'setMacAddress',
376                 params  => [ $hostId, $mac ],
377                 id  => 1,
378             };
379             my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
380             my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
381             if ($sres_err){
382                 &main::daemon_log("ERROR: cannot set mac address: ".$sres_err_string, 1);
383                 &add_content2xml_hash($out_hash, "error", $sres_err_string);
384             }
385         }
386     }
388     # Return message
389     return ( &create_xml_string($out_hash) );
392     
393 ## @method opsi_get_netboot_products
394 # Get netboot products for specific host.
395 # @param msg - STRING - xml message with tag hostId
396 # @param msg_hash - HASHREF - message information parsed into a hash
397 # @param session_id - INTEGER - POE session id of the processing of this message
398 # @return out_msg - STRING - feedback to GOsa in success and error case
399 sub opsi_get_netboot_products {
400     my ($msg, $msg_hash, $session_id) = @_;
401     my $header = @{$msg_hash->{'header'}}[0];
402     my $source = @{$msg_hash->{'source'}}[0];
403     my $target = @{$msg_hash->{'target'}}[0];
404     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
405     my $hostId;
406     my $xml_msg;
408     # Build return message with twisted target and source
409     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
410     if (defined $forward_to_gosa) {
411         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
412     }
414     # Get hostId if defined
415     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} == 1))  {
416         $hostId = @{$msg_hash->{'hostId'}}[0];
417         &add_content2xml_hash($out_hash, "hostId", $hostId);
418     }
420     &add_content2xml_hash($out_hash, "xxx", "");
421     $xml_msg = &create_xml_string($out_hash);
422     # For hosts, only return the products that are or get installed
423     my $callobj;
424     $callobj = {
425         method  => 'getNetBootProductIds_list',
426         params  => [ ],
427         id  => 1,
428     };
430     &main::daemon_log("$session_id DEBUG: send callobj to opsi_client: ".&opsi_callobj2string($callobj), 7);
431     &main::daemon_log("$session_id DEBUG: waiting for answer from opsi_client!", 7);
432     my $opsi_client =  new JSON::RPC::Client;
433     my $res = $opsi_client->call($main::opsi_url, $callobj);
434     &main::daemon_log("$session_id DEBUG: get answer from opsi_client with number of entries: ".length(@$res), 7);
435     my %r = ();
436     for (@{$res->result}) { $r{$_} = 1 }
438     if (not &check_opsi_res($res)){
440         if (defined $hostId){
442             $callobj = {
443                 method  => 'getProductStates_hash',
444                 params  => [ $hostId ],
445                 id  => 1,
446             };
448             my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
449             if (not &check_opsi_res($hres)){
450                 my $htmp= $hres->result->{$hostId};
452                 # check state != not_installed or action == setup -> load and add
453                 foreach my $product (@{$htmp}){
455                     if (!defined ($r{$product->{'productId'}})){
456                         next;
457                     }
459                     # Now we've a couple of hashes...
460                     if ($product->{'installationStatus'} ne "not_installed" or
461                             $product->{'actionRequest'} eq "setup"){
462                         my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
464                         $callobj = {
465                             method  => 'getProduct_hash',
466                             params  => [ $product->{'productId'} ],
467                             id  => 1,
468                         };
470                         my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
471                         if (not &check_opsi_res($sres)){
472                             my $tres= $sres->result;
474                             my $name= xml_quote($tres->{'name'});
475                             my $r= $product->{'productId'};
476                             my $description= xml_quote($tres->{'description'});
477                             $name=~ s/\//\\\//;
478                             $description=~ s/\//\\\//;
479                             $xml_msg=~ s/<xxx><\/xxx>/\n<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
480                         }
481                     }
482                 }
484             }
486         } else {
487             foreach my $r (@{$res->result}) {
488                 $callobj = {
489                     method  => 'getProduct_hash',
490                     params  => [ $r ],
491                     id  => 1,
492                 };
494                 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
495                 if (not &check_opsi_res($sres)){
496                     my $tres= $sres->result;
498                     my $name= xml_quote($tres->{'name'});
499                     my $description= xml_quote($tres->{'description'});
500                     $name=~ s/\//\\\//;
501                     $description=~ s/\//\\\//;
502                     $xml_msg=~ s/<xxx><\/xxx>/\n<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
503                 }
504             }
506         }
507     }
508     $xml_msg=~ s/<xxx><\/xxx>//;
510     # Return message
511     return ( $xml_msg );
515 ## @method opsi_get_product_properties
516 # Get product properties for a product and a specific host or gobally for a product.
517 # @param msg - STRING - xml message with tags productId and optional hostId
518 # @param msg_hash - HASHREF - message information parsed into a hash
519 # @param session_id - INTEGER - POE session id of the processing of this message
520 # @return out_msg - STRING - feedback to GOsa in success and error case
521 sub opsi_get_product_properties {
522     my ($msg, $msg_hash, $session_id) = @_;
523     my $header = @{$msg_hash->{'header'}}[0];
524     my $source = @{$msg_hash->{'source'}}[0];
525     my $target = @{$msg_hash->{'target'}}[0];
526     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
527     my ($hostId, $productId);
528     my $xml_msg;
530     # Build return message with twisted target and source
531     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
532     if (defined $forward_to_gosa) {
533         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
534     }
536     # Sanity check of needed parameter
537     if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1) || (@{$msg_hash->{'productId'}}[0] eq ref 'HASH'))  {
538         &add_content2xml_hash($out_hash, "error_string", "no productId specified or productId tag invalid");
539         &add_content2xml_hash($out_hash, "error", "productId");
540         &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1); 
542         # Return message
543         return ( &create_xml_string($out_hash) );
544     }
546     # Get productid
547     $productId = @{$msg_hash->{'productId'}}[0];
548     &add_content2xml_hash($out_hash, "producId", "$productId");
550     # Get hostId if defined
551     if (defined @{$msg_hash->{'hostId'}}[0]){
552       $hostId = @{$msg_hash->{'hostId'}}[0];
553       &add_content2xml_hash($out_hash, "hostId", $hostId);
554     }
556     # Load actions
557     my $callobj = {
558       method  => 'getPossibleProductActions_list',
559       params  => [ $productId ],
560       id  => 1,
561     };
562     my $res = $main::opsi_client->call($main::opsi_url, $callobj);
563     if (not &check_opsi_res($res)){
564       foreach my $action (@{$res->result}){
565         &add_content2xml_hash($out_hash, "action", $action);
566       }
567     }
569     # Add place holder
570     &add_content2xml_hash($out_hash, "xxx", "");
572     # Move to XML string
573     $xml_msg= &create_xml_string($out_hash);
575     # JSON Query
576     if (defined $hostId){
577       $callobj = {
578           method  => 'getProductProperties_hash',
579           params  => [ $productId, $hostId ],
580           id  => 1,
581       };
582     } else {
583       $callobj = {
584           method  => 'getProductProperties_hash',
585           params  => [ $productId ],
586           id  => 1,
587       };
588     }
589     $res = $main::opsi_client->call($main::opsi_url, $callobj);
591     # JSON Query 2
592     $callobj = {
593       method  => 'getProductPropertyDefinitions_listOfHashes',
594       params  => [ $productId ],
595       id  => 1,
596     };
598     # Assemble options
599     my $res2 = $main::opsi_client->call($main::opsi_url, $callobj);
600     my $values = {};
601     my $descriptions = {};
602     if (not &check_opsi_res($res2)){
603         my $r= $res2->result;
605           foreach my $entr (@$r){
606             # Unroll values
607             my $cnv;
608             if (UNIVERSAL::isa( $entr->{'values'}, "ARRAY" )){
609               foreach my $v (@{$entr->{'values'}}){
610                 $cnv.= "<value>$v</value>";
611               }
612             } else {
613               $cnv= $entr->{'values'};
614             }
615             $values->{$entr->{'name'}}= $cnv;
616             $descriptions->{$entr->{'name'}}= "<description>".$entr->{'description'}."</description>";
617           }
618     }
620     if (not &check_opsi_res($res)){
621         my $r= $res->result;
622         foreach my $key (keys %{$r}) {
623             my $item= "\n<item>";
624             my $value= $r->{$key};
625             my $dsc= "";
626             my $vals= "";
627             if (defined $descriptions->{$key}){
628               $dsc= $descriptions->{$key};
629             }
630             if (defined $values->{$key}){
631               $vals= $values->{$key};
632             }
633             $item.= "<$key>$dsc<default>".xml_quote($value)."</default>$vals</$key>";
634             $item.= "</item>";
635             $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
636         }
637     }
639     $xml_msg=~ s/<xxx><\/xxx>//;
641     # Return message
642     return ( $xml_msg );
646 ## @method opsi_set_product_properties
647 # Set product properities for a specific host or globaly. Message needs one xml tag 'item' and within one xml tag 'name' and 'value'. The xml tags action and state are optional.
648 # @param msg - STRING - xml message with tags productId, action, state and optional hostId, action and state
649 # @param msg_hash - HASHREF - message information parsed into a hash
650 # @param session_id - INTEGER - POE session id of the processing of this message
651 # @return out_msg - STRING - feedback to GOsa in success and error case
652 sub opsi_set_product_properties {
653     my ($msg, $msg_hash, $session_id) = @_;
654     my $header = @{$msg_hash->{'header'}}[0];
655     my $source = @{$msg_hash->{'source'}}[0];
656     my $target = @{$msg_hash->{'target'}}[0];
657     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
658     my ($productId, $hostId);
660     # Build return message with twisted target and source
661     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
662     if (defined $forward_to_gosa) {
663         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
664     }
666     # Sanity check of needed parameter
667     if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1) || (@{$msg_hash->{'productId'}}[0] eq ref 'HASH'))  {
668         &add_content2xml_hash($out_hash, "error_string", "no productId specified or productId tag invalid");
669         &add_content2xml_hash($out_hash, "error", "productId");
670         &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1); 
671         return ( &create_xml_string($out_hash) );
672     }
673     if (not exists $msg_hash->{'item'}) {
674         &add_content2xml_hash($out_hash, "error_string", "message needs one xml-tag 'item' and within the xml-tags 'name' and 'value'");
675         &add_content2xml_hash($out_hash, "error", "item");
676         &main::daemon_log("$session_id ERROR: message needs one xml-tag 'item' and within the xml-tags 'name' and 'value': $msg", 1); 
677         return ( &create_xml_string($out_hash) );
678     } else {
679         if ((not exists @{$msg_hash->{'item'}}[0]->{'name'}) || (@{@{$msg_hash->{'item'}}[0]->{'name'}} != 1 )) {
680             &add_content2xml_hash($out_hash, "error_string", "message needs within the xml-tag 'item' one xml-tags 'name'");
681             &add_content2xml_hash($out_hash, "error", "name");
682             &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'name': $msg", 1); 
683             return ( &create_xml_string($out_hash) );
684         }
685         if ((not exists @{$msg_hash->{'item'}}[0]->{'value'}) || (@{@{$msg_hash->{'item'}}[0]->{'value'}} != 1 )) {
686             &add_content2xml_hash($out_hash, "error_string", "message needs within the xml-tag 'item' one xml-tags 'value'");
687             &add_content2xml_hash($out_hash, "error", "value");
688             &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'value': $msg", 1); 
689             return ( &create_xml_string($out_hash) );
690         }
691     }
692     # if no hostId is given, set_product_properties will act on globally
693     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} > 1))  {
694         &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
695         &add_content2xml_hash($out_hash, "error", "hostId");
696         &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
697         return ( &create_xml_string($out_hash) );
698     }
700         
701     # Get productId
702     $productId =  @{$msg_hash->{'productId'}}[0];
703     &add_content2xml_hash($out_hash, "productId", $productId);
705     # Get hostId if defined
706     if (exists $msg_hash->{'hostId'}){
707         $hostId = @{$msg_hash->{'hostId'}}[0];
708         &add_content2xml_hash($out_hash, "hostId", $hostId);
709     }
711     # Set product states if requested
712     if (defined @{$msg_hash->{'action'}}[0]){
713         &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
714     }
715     if (defined @{$msg_hash->{'state'}}[0]){
716         &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
717     }
719     # Find properties
720     foreach my $item (@{$msg_hash->{'item'}}){
721         # JSON Query
722         my $callobj;
724         if (defined $hostId){
725             $callobj = {
726                 method  => 'setProductProperty',
727                 params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
728                 id  => 1,
729             };
730         } else {
731             $callobj = {
732                 method  => 'setProductProperty',
733                 params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
734                 id  => 1,
735             };
736         }
738         my $res = $main::opsi_client->call($main::opsi_url, $callobj);
739         my ($res_err, $res_err_string) = &check_opsi_res($res);
741         if ($res_err){
742             &main::daemon_log("$session_id ERROR: communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
743             &add_content2xml_hash($out_hash, "error", $res_err_string);
744         }
745     }
748     # Return message
749     return ( &create_xml_string($out_hash) );
753 ## @method opsi_get_client_hardware
754 # Reports client hardware inventory.
755 # @param msg - STRING - xml message with tag hostId
756 # @param msg_hash - HASHREF - message information parsed into a hash
757 # @param session_id - INTEGER - POE session id of the processing of this message
758 # @return out_msg - STRING - feedback to GOsa in success and error case
759 sub opsi_get_client_hardware {
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;
766     my $error = 0;
767     my $xml_msg;
769     # Build return message with twisted target and source
770     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
771     if (defined $forward_to_gosa) {
772       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
773     }
775     # Sanity check of needed parameter
776     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
777         $error++;
778         &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
779         &add_content2xml_hash($out_hash, "error", "hostId");
780         &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
781     }
783     if (not $error) {
785     # Get hostId
786         $hostId = @{$msg_hash->{'hostId'}}[0];
787         &add_content2xml_hash($out_hash, "hostId", "$hostId");
788         &add_content2xml_hash($out_hash, "xxx", "");
789     }    
791     # Move to XML string
792     $xml_msg= &create_xml_string($out_hash);
793     
794     if (not $error) {
796     # JSON Query
797         my $callobj = {
798             method  => 'getHardwareInformation_hash',
799             params  => [ $hostId ],
800             id  => 1,
801         };
803         my $res = $main::opsi_client->call($main::opsi_url, $callobj);
804         if (not &check_opsi_res($res)){
805             my $result= $res->result;
806             if (ref $result eq "HASH") {
807                 foreach my $r (keys %{$result}){
808                     my $item= "\n<item><id>".xml_quote($r)."</id>";
809                     my $value= $result->{$r};
810                     foreach my $sres (@{$value}){
812                         foreach my $dres (keys %{$sres}){
813                             if (defined $sres->{$dres}){
814                                 $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
815                             }
816                         }
818                     }
819                     $item.= "</item>";
820                     $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
822                 }
823             }
824         }
826         $xml_msg=~ s/<xxx><\/xxx>//;
828     }
830     # Return message
831     return ( $xml_msg );
835 ## @method opsi_list_clients
836 # Reports all Opsi clients. 
837 # @param msg - STRING - xml message 
838 # @param msg_hash - HASHREF - message information parsed into a hash
839 # @param session_id - INTEGER - POE session id of the processing of this message
840 # @return out_msg - STRING - feedback to GOsa in success and error case
841 sub opsi_list_clients {
842     my ($msg, $msg_hash, $session_id) = @_;
843     my $header = @{$msg_hash->{'header'}}[0];
844     my $source = @{$msg_hash->{'source'}}[0];
845     my $target = @{$msg_hash->{'target'}}[0];
846     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
848     # Build return message with twisted target and source
849     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
850     if (defined $forward_to_gosa) {
851       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
852     }
853     &add_content2xml_hash($out_hash, "xxx", "");
855     # Move to XML string
856     my $xml_msg= &create_xml_string($out_hash);
858     # JSON Query
859     my $callobj = {
860         method  => 'getClients_listOfHashes',
861         params  => [ ],
862         id  => 1,
863     };
864     my $res = $main::opsi_client->call($main::opsi_url, $callobj);
865     if (not &check_opsi_res($res)){
866         foreach my $host (@{$res->result}){
867             my $item= "\n<item><name>".$host->{'hostId'}."</name>";
868             if (defined($host->{'description'})){
869                 $item.= "<description>".xml_quote($host->{'description'})."</description>";
870             }
871             if (defined($host->{'notes'})){
872                 $item.= "<notes>".xml_quote($host->{'notes'})."</notes>";
873             }
874             if (defined($host->{'lastSeen'})){
875                 $item.= "<lastSeen>".xml_quote($host->{'lastSeen'})."</lastSeen>";
876             }
878             $callobj = {
879               method  => 'getIpAddress',
880               params  => [ $host->{'hostId'} ],
881               id  => 1,
882             };
883             my $sres= $main::opsi_client->call($main::opsi_url, $callobj);
884             if ( not &check_opsi_res($sres)){
885               $item.= "<ip>".xml_quote($sres->result)."</ip>";
886             }
888             $callobj = {
889               method  => 'getMacAddress',
890               params  => [ $host->{'hostId'} ],
891               id  => 1,
892             };
893             $sres= $main::opsi_client->call($main::opsi_url, $callobj);
894             if ( not &check_opsi_res($sres)){
895                 $item.= "<mac>".xml_quote($sres->result)."</mac>";
896             }
897             $item.= "</item>";
898             $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
899         }
900     }
902     $xml_msg=~ s/<xxx><\/xxx>//;
903     return ( $xml_msg );
908 ## @method opsi_get_client_software
909 # Reports client software inventory.
910 # @param msg - STRING - xml message with tag hostId
911 # @param msg_hash - HASHREF - message information parsed into a hash
912 # @param session_id - INTEGER - POE session id of the processing of this message
913 # @return out_msg - STRING - feedback to GOsa in success and error case
914 sub opsi_get_client_software {
915     my ($msg, $msg_hash, $session_id) = @_;
916     my $header = @{$msg_hash->{'header'}}[0];
917     my $source = @{$msg_hash->{'source'}}[0];
918     my $target = @{$msg_hash->{'target'}}[0];
919     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
920     my $error = 0;
921     my $hostId;
922     my $xml_msg;
924     # Build return message with twisted target and source
925     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
926     if (defined $forward_to_gosa) {
927       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
928     }
930     # Sanity check of needed parameter
931     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
932         $error++;
933         &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
934         &add_content2xml_hash($out_hash, "error", "hostId");
935         &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
936     }
938     if (not $error) {
940     # Get hostId
941         $hostId = @{$msg_hash->{'hostId'}}[0];
942         &add_content2xml_hash($out_hash, "hostId", "$hostId");
943         &add_content2xml_hash($out_hash, "xxx", "");
944     }
946     $xml_msg= &create_xml_string($out_hash);
948     if (not $error) {
950     # JSON Query
951         my $callobj = {
952             method  => 'getSoftwareInformation_hash',
953             params  => [ $hostId ],
954             id  => 1,
955         };
957         my $res = $main::opsi_client->call($main::opsi_url, $callobj);
958         if (not &check_opsi_res($res)){
959             my $result= $res->result;
960 # TODO : Ist das hier schon fertig???   
961         }
963         $xml_msg=~ s/<xxx><\/xxx>//;
965     }
967     # Return message
968     return ( $xml_msg );
972 ## @method opsi_get_local_products
973 # Reports product for given hostId or globally.
974 # @param msg - STRING - xml message with optional tag hostId
975 # @param msg_hash - HASHREF - message information parsed into a hash
976 # @param session_id - INTEGER - POE session id of the processing of this message
977 # @return out_msg - STRING - feedback to GOsa in success and error case
978 sub opsi_get_local_products {
979     my ($msg, $msg_hash, $session_id) = @_;
980     my $header = @{$msg_hash->{'header'}}[0];
981     my $source = @{$msg_hash->{'source'}}[0];
982     my $target = @{$msg_hash->{'target'}}[0];
983     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
984     my $hostId;
986     # Build return message with twisted target and source
987     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
988     if (defined $forward_to_gosa) {
989         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
990     }
991     &add_content2xml_hash($out_hash, "xxx", "");
993     # Get hostId if defined
994     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} == 1))  {
995         $hostId = @{$msg_hash->{'hostId'}}[0];
996         &add_content2xml_hash($out_hash, "hostId", $hostId);
997     }
999     # Move to XML string
1000     my $xml_msg= &create_xml_string($out_hash);
1002     # For hosts, only return the products that are or get installed
1003     my $callobj;
1004     $callobj = {
1005         method  => 'getLocalBootProductIds_list',
1006         params  => [ ],
1007         id  => 1,
1008     };
1010     my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1011     my %r = ();
1012     for (@{$res->result}) { $r{$_} = 1 }
1014     if (not &check_opsi_res($res)){
1016         if (defined $hostId){
1017             $callobj = {
1018                 method  => 'getProductStates_hash',
1019                 params  => [ $hostId ],
1020                 id  => 1,
1021             };
1023             my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
1024             if (not &check_opsi_res($hres)){
1025                 my $htmp= $hres->result->{$hostId};
1027                 # Check state != not_installed or action == setup -> load and add
1028                 foreach my $product (@{$htmp}){
1030                     if (!defined ($r{$product->{'productId'}})){
1031                         next;
1032                     }
1034                     # Now we've a couple of hashes...
1035                     if ($product->{'installationStatus'} ne "not_installed" or
1036                             $product->{'actionRequest'} eq "setup"){
1037                         my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
1039                         $callobj = {
1040                             method  => 'getProduct_hash',
1041                             params  => [ $product->{'productId'} ],
1042                             id  => 1,
1043                         };
1045                         my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1046                         if (not &check_opsi_res($sres)){
1047                             my $tres= $sres->result;
1049                             my $name= xml_quote($tres->{'name'});
1050                             my $r= $product->{'productId'};
1051                             my $description= xml_quote($tres->{'description'});
1052                             $name=~ s/\//\\\//;
1053                             $description=~ s/\//\\\//;
1054                             $xml_msg=~ s/<xxx><\/xxx>/\n<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
1055                         }
1057                     }
1058                 }
1060             }
1062         } else {
1063             foreach my $r (@{$res->result}) {
1064                 $callobj = {
1065                     method  => 'getProduct_hash',
1066                     params  => [ $r ],
1067                     id  => 1,
1068                 };
1070                 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1071                 if (not &check_opsi_res($sres)){
1072                     my $tres= $sres->result;
1074                     my $name= xml_quote($tres->{'name'});
1075                     my $description= xml_quote($tres->{'description'});
1076                     $name=~ s/\//\\\//;
1077                     $description=~ s/\//\\\//;
1078                     $xml_msg=~ s/<xxx><\/xxx>/\n<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
1079                 }
1081             }
1083         }
1084     }
1086     $xml_msg=~ s/<xxx><\/xxx>//;
1088     # Retrun Message
1089     return ( $xml_msg );
1093 ## @method opsi_del_client
1094 # Deletes a client from Opsi.
1095 # @param msg - STRING - xml message with tag hostId
1096 # @param msg_hash - HASHREF - message information parsed into a hash
1097 # @param session_id - INTEGER - POE session id of the processing of this message
1098 # @return out_msg - STRING - feedback to GOsa in success and error case
1099 sub opsi_del_client {
1100     my ($msg, $msg_hash, $session_id) = @_;
1101     my $header = @{$msg_hash->{'header'}}[0];
1102     my $source = @{$msg_hash->{'source'}}[0];
1103     my $target = @{$msg_hash->{'target'}}[0];
1104     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1105     my $hostId;
1106     my $error = 0;
1108     # Build return message with twisted target and source
1109     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1110     if (defined $forward_to_gosa) {
1111       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1112     }
1114     # Sanity check of needed parameter
1115     if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
1116         $error++;
1117         &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
1118         &add_content2xml_hash($out_hash, "error", "hostId");
1119         &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
1120     }
1122     if (not $error) {
1124     # Get hostId
1125         $hostId = @{$msg_hash->{'hostId'}}[0];
1126         &add_content2xml_hash($out_hash, "hostId", "$hostId");
1128     # JSON Query
1129         my $callobj = {
1130             method  => 'deleteClient',
1131             params  => [ $hostId ],
1132             id  => 1,
1133         };
1134         my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1135     }
1137     # Move to XML string
1138     my $xml_msg= &create_xml_string($out_hash);
1140     # Return message
1141     return ( $xml_msg );
1145 ## @method opsi_install_client
1146 # Set a client in Opsi to install and trigger a wake on lan message (WOL).  
1147 # @param msg - STRING - xml message with tags hostId, macaddress
1148 # @param msg_hash - HASHREF - message information parsed into a hash
1149 # @param session_id - INTEGER - POE session id of the processing of this message
1150 # @return out_msg - STRING - feedback to GOsa in success and error case
1151 sub opsi_install_client {
1152     my ($msg, $msg_hash, $session_id) = @_;
1153     my $header = @{$msg_hash->{'header'}}[0];
1154     my $source = @{$msg_hash->{'source'}}[0];
1155     my $target = @{$msg_hash->{'target'}}[0];
1156     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1159     my ($hostId, $macaddress);
1161     my $error = 0;
1162     my @out_msg_l;
1164     # Build return message with twisted target and source
1165     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1166     if (defined $forward_to_gosa) {
1167         &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1168     }
1170     # Sanity check of needed parameter
1171     if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1) || (@{$msg_hash->{'hostId'}}[0] eq ref 'HASH'))  {
1172         $error++;
1173         &add_content2xml_hash($out_hash, "error_string", "no hostId specified or hostId tag invalid");
1174         &add_content2xml_hash($out_hash, "error", "hostId");
1175         &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1); 
1176     }
1177     if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1) || (@{$msg_hash->{'macaddress'}}[0] eq ref 'HASH') )  {
1178         $error++;
1179         &add_content2xml_hash($out_hash, "error_string", "no macaddress specified or macaddress tag invalid");
1180         &add_content2xml_hash($out_hash, "error", "macaddress");
1181         &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1); 
1182     } else {
1183         if ((exists $msg_hash->{'macaddress'}) && 
1184                 ($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)) {  
1185             $macaddress = $1; 
1186         } else { 
1187             $error ++; 
1188             &add_content2xml_hash($out_hash, "error_string", "given mac address is not correct");
1189             &add_content2xml_hash($out_hash, "error", "macaddress");
1190             &main::daemon_log("$session_id ERROR: given mac address is not correct: $msg", 1); 
1191         }
1192     }
1194     if (not $error) {
1196     # Get hostId
1197         $hostId = @{$msg_hash->{'hostId'}}[0];
1198         &add_content2xml_hash($out_hash, "hostId", "$hostId");
1200         # Load all products for this host with status != "not_installed" or actionRequest != "none"
1201         my $callobj = {
1202             method  => 'getProductStates_hash',
1203             params  => [ $hostId ],
1204             id  => 1,
1205         };
1207         my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
1208         if (not &check_opsi_res($hres)){
1209             my $htmp= $hres->result->{$hostId};
1211             # check state != not_installed or action == setup -> load and add
1212             foreach my $product (@{$htmp}){
1213                 # Now we've a couple of hashes...
1214                 if ($product->{'installationStatus'} ne "not_installed" or
1215                         $product->{'actionRequest'} ne "none"){
1217                     # Do an action request for all these -> "setup".
1218                     $callobj = {
1219                         method  => 'setProductActionRequest',
1220                         params  => [ $product->{'productId'}, $hostId, "setup" ],
1221                         id  => 1,
1222                     };
1223                     my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1224                     my ($res_err, $res_err_string) = &check_opsi_res($res);
1225                     if ($res_err){
1226                         &main::daemon_log("$session_id ERROR: cannot set product action request for '$hostId': ".$product->{'productId'}, 1);
1227                     } else {
1228                         &main::daemon_log("$session_id INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
1229                     }
1230                 }
1231             }
1232         }
1233         push(@out_msg_l, &create_xml_string($out_hash));
1234     
1236     # Build wakeup message for client
1237         if (not $error) {
1238             my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
1239             &add_content2xml_hash($wakeup_hash, 'macaddress', $macaddress);
1240             my $wakeup_msg = &create_xml_string($wakeup_hash);
1241             push(@out_msg_l, $wakeup_msg);
1243             # invoke trigger wake for this gosa-si-server
1244             &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
1245         }
1246     }
1247     
1248     # Return messages
1249     return @out_msg_l;
1253 ## @method _set_action
1254 # Set action for an Opsi client
1255 # @param product - STRING - Opsi product
1256 # @param action - STRING - action
1257 # @param hostId - STRING - Opsi hostId
1258 sub _set_action {
1259   my $product= shift;
1260   my $action = shift;
1261   my $hostId = shift;
1262   my $callobj;
1264   $callobj = {
1265     method  => 'setProductActionRequest',
1266     params  => [ $product, $hostId, $action],
1267     id  => 1,
1268   };
1270   $main::opsi_client->call($main::opsi_url, $callobj);
1273 ## @method _set_state
1274 # Set state for an Opsi client
1275 # @param product - STRING - Opsi product
1276 # @param action - STRING - state
1277 # @param hostId - STRING - Opsi hostId
1278 sub _set_state {
1279   my $product = shift;
1280   my $state = shift;
1281   my $hostId = shift;
1282   my $callobj;
1284   $callobj = {
1285     method  => 'setProductState',
1286     params  => [ $product, $hostId, $state ],
1287     id  => 1,
1288   };
1290   $main::opsi_client->call($main::opsi_url, $callobj);
1293 1;