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) );
106 }
108 ## @method opsi_del_product_from_client
109 # Deletes an Opsi-product from an Opsi-client.
110 # @param msg - STRING - xml message with tags hostId and productId
111 # @param msg_hash - HASHREF - message information parsed into a hash
112 # @param session_id - INTEGER - POE session id of the processing of this message
113 # @return out_msg - STRING - feedback to GOsa in success and error case
114 sub opsi_del_product_from_client {
115 my ($msg, $msg_hash, $session_id) = @_;
116 my $header = @{$msg_hash->{'header'}}[0];
117 my $source = @{$msg_hash->{'source'}}[0];
118 my $target = @{$msg_hash->{'target'}}[0];
119 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
120 my ($hostId, $productId);
121 my $error = 0;
122 my ($sres, $sres_err, $sres_err_string);
124 # Build return message
125 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
126 if (defined $forward_to_gosa) {
127 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
128 }
130 # Sanity check of needed parameter
131 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1) || (@{$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) );
218 }
220 ## @method opsi_add_client
221 # Adds an Opsi client to Opsi.
222 # @param msg - STRING - xml message with tags hostId and macaddress
223 # @param msg_hash - HASHREF - message information parsed into a hash
224 # @param session_id - INTEGER - POE session id of the processing of this message
225 # @return out_msg - STRING - feedback to GOsa in success and error case
226 sub opsi_add_client {
227 my ($msg, $msg_hash, $session_id) = @_;
228 my $header = @{$msg_hash->{'header'}}[0];
229 my $source = @{$msg_hash->{'source'}}[0];
230 my $target = @{$msg_hash->{'target'}}[0];
231 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
232 my ($hostId, $mac);
233 my $error = 0;
234 my ($sres, $sres_err, $sres_err_string);
236 # Build return message with twisted target and source
237 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
238 if (defined $forward_to_gosa) {
239 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
240 }
242 # Sanity check of needed parameter
243 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1) || (@{$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) );
300 }
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) );
390 }
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: opsi_url $main::opsi_url", 7);
432 &main::daemon_log("$session_id DEBUG: waiting for answer from opsi_client!", 7);
433 my $res = $main::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 );
512 }
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 );
643 }
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 }
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) );
750 }
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);
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 );
832 }
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 );
904 }
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 );
969 }
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 );
1090 }
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 );
1142 }
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));
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 }
1248 # Return messages
1249 return @out_msg_l;
1250 }
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);
1271 }
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);
1291 }
1293 1;