1 ## @file
2 # @details A GOsa-SI-server event module containing all functions for message handling.
3 # @brief Implementation of an event module for GOsa-SI-server.
6 package opsi_com;
7 use Exporter;
8 @ISA = qw(Exporter);
9 my @events = (
10 "get_events",
11 "opsi_install_client",
12 "opsi_get_netboot_products",
13 "opsi_get_local_products",
14 "opsi_get_client_hardware",
15 "opsi_get_client_software",
16 "opsi_get_product_properties",
17 "opsi_set_product_properties",
18 "opsi_list_clients",
19 "opsi_del_client",
20 "opsi_add_client",
21 "opsi_modify_client",
22 "opsi_add_product_to_client",
23 "opsi_del_product_from_client",
24 );
25 @EXPORT = @events;
27 use strict;
28 use warnings;
29 use GOSA::GosaSupportDaemon;
30 use Data::Dumper;
31 use XML::Quote qw(:all);
34 BEGIN {}
36 END {}
38 ## @method get_events()
39 # A brief function returning a list of functions which are exported by importing the module.
40 # @return List of all provided functions
41 sub get_events {
42 return \@events;
43 }
45 ## @method opsi_add_product_to_client
46 # Adds an Opsi product to an Opsi client.
47 # @param msg - STRING - xml message with tags hostId and productId
48 # @param msg_hash - HASHREF - message information parsed into a hash
49 # @param session_id - INTEGER - POE session id of the processing of this message
50 # @return out_msg - STRING - feedback to GOsa in success and error case
51 sub opsi_add_product_to_client {
52 my ($msg, $msg_hash, $session_id) = @_;
53 my $header = @{$msg_hash->{'header'}}[0];
54 my $source = @{$msg_hash->{'source'}}[0];
55 my $target = @{$msg_hash->{'target'}}[0];
56 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
57 my ($hostId, $productId);
58 my $error = 0;
60 # Build return message
61 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
62 if (defined $forward_to_gosa) {
63 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
64 }
66 # Sanity check of needed parameter
67 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
68 $error++;
69 &add_content2xml_hash($out_hash, "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)) {
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)) {
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)) {
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)) {
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)) {
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)) {
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 # Sanity check of needed parameter
415 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
416 &add_content2xml_hash($out_hash, "error_string", "no hostId specified or hostId tag invalid");
417 &add_content2xml_hash($out_hash, "error", "hostId");
418 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
419 return &create_xml_string($out_hash);
420 }
422 # Get hostID if defined
423 $hostId = @{$msg_hash->{'hostId'}}[0];
424 &add_content2xml_hash($out_hash, "hostId", $hostId);
426 &add_content2xml_hash($out_hash, "xxx", "");
427 $xml_msg= &create_xml_string($out_hash);
429 # For hosts, only return the products that are or get installed
430 my $callobj;
431 $callobj = {
432 method => 'getNetBootProductIds_list',
433 params => [ ],
434 id => 1,
435 };
437 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
438 my %r = ();
439 for (@{$res->result}) { $r{$_} = 1 }
441 if (not &check_opsi_res($res)){
443 if (defined $hostId){
444 $callobj = {
445 method => 'getProductStates_hash',
446 params => [ $hostId ],
447 id => 1,
448 };
450 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
451 if (not &check_opsi_res($hres)){
452 my $htmp= $hres->result->{$hostId};
454 # check state != not_installed or action == setup -> load and add
455 foreach my $product (@{$htmp}){
457 if (!defined ($r{$product->{'productId'}})){
458 next;
459 }
461 # Now we've a couple of hashes...
462 if ($product->{'installationStatus'} ne "not_installed" or
463 $product->{'actionRequest'} eq "setup"){
464 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
466 $callobj = {
467 method => 'getProduct_hash',
468 params => [ $product->{'productId'} ],
469 id => 1,
470 };
472 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
473 if (not &check_opsi_res($sres)){
474 my $tres= $sres->result;
476 my $name= xml_quote($tres->{'name'});
477 my $r= $product->{'productId'};
478 my $description= xml_quote($tres->{'description'});
479 $name=~ s/\//\\\//;
480 $description=~ s/\//\\\//;
481 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
482 }
483 }
484 }
486 }
488 } else {
489 foreach my $r (@{$res->result}) {
490 $callobj = {
491 method => 'getProduct_hash',
492 params => [ $r ],
493 id => 1,
494 };
496 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
497 if (not &check_opsi_res($sres)){
498 my $tres= $sres->result;
500 my $name= xml_quote($tres->{'name'});
501 my $description= xml_quote($tres->{'description'});
502 $name=~ s/\//\\\//;
503 $description=~ s/\//\\\//;
504 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
505 }
506 }
508 }
509 }
510 $xml_msg=~ s/<xxx><\/xxx>//;
512 # Return message
513 return ( $xml_msg );
514 }
517 ## @method opsi_get_product_properties
518 # Get product properties for a product and a specific host or gobally for a product.
519 # @param msg - STRING - xml message with tags productId and optional hostId
520 # @param msg_hash - HASHREF - message information parsed into a hash
521 # @param session_id - INTEGER - POE session id of the processing of this message
522 # @return out_msg - STRING - feedback to GOsa in success and error case
523 sub opsi_get_product_properties {
524 my ($msg, $msg_hash, $session_id) = @_;
525 my $header = @{$msg_hash->{'header'}}[0];
526 my $source = @{$msg_hash->{'source'}}[0];
527 my $target = @{$msg_hash->{'target'}}[0];
528 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
529 my ($hostId, $productId);
530 my $xml_msg;
532 # Build return message with twisted target and source
533 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
534 if (defined $forward_to_gosa) {
535 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
536 }
538 # Sanity check of needed parameter
539 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
540 &add_content2xml_hash($out_hash, "error_string", "no productId specified or productId tag invalid");
541 &add_content2xml_hash($out_hash, "error", "productId");
542 &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1);
544 # Return message
545 return ( &create_xml_string($out_hash) );
546 }
548 # Get productid
549 $productId = @{$msg_hash->{'productId'}}[0];
550 &add_content2xml_hash($out_hash, "producId", "$productId");
552 # Get hostID if defined
553 if (defined @{$msg_hash->{'hostId'}}[0]){
554 $hostId = @{$msg_hash->{'hostId'}}[0];
555 &add_content2xml_hash($out_hash, "hostId", $hostId);
556 }
558 # Load actions
559 my $callobj = {
560 method => 'getPossibleProductActions_list',
561 params => [ $productId ],
562 id => 1,
563 };
564 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
565 if (not &check_opsi_res($res)){
566 foreach my $action (@{$res->result}){
567 &add_content2xml_hash($out_hash, "action", $action);
568 }
569 }
571 # Add place holder
572 &add_content2xml_hash($out_hash, "xxx", "");
574 # Move to XML string
575 $xml_msg= &create_xml_string($out_hash);
577 # JSON Query
578 if (defined $hostId){
579 $callobj = {
580 method => 'getProductProperties_hash',
581 params => [ $productId, $hostId ],
582 id => 1,
583 };
584 } else {
585 $callobj = {
586 method => 'getProductProperties_hash',
587 params => [ $productId ],
588 id => 1,
589 };
590 }
592 $res = $main::opsi_client->call($main::opsi_url, $callobj);
593 if (not &check_opsi_res($res)){
594 my $r= $res->result;
595 foreach my $key (keys %{$r}) {
596 my $item= "<item>";
597 my $value= $r->{$key};
598 if (UNIVERSAL::isa( $value, "ARRAY" )){
599 foreach my $subval (@{$value}){
600 $item.= "<$key>".xml_quote($subval)."</$key>";
601 }
602 } else {
603 $item.= "<$key>".xml_quote($value)."</$key>";
604 }
605 $item.= "</item>";
606 $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
607 }
608 }
610 $xml_msg=~ s/<xxx><\/xxx>//;
612 # Return message
613 return ( $xml_msg );
614 }
617 ## @method opsi_set_product_properties
618 # 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.
619 # @param msg - STRING - xml message with tags productId, action, state and optional hostId, action and state
620 # @param msg_hash - HASHREF - message information parsed into a hash
621 # @param session_id - INTEGER - POE session id of the processing of this message
622 # @return out_msg - STRING - feedback to GOsa in success and error case
623 sub opsi_set_product_properties {
624 my ($msg, $msg_hash, $session_id) = @_;
625 my $header = @{$msg_hash->{'header'}}[0];
626 my $source = @{$msg_hash->{'source'}}[0];
627 my $target = @{$msg_hash->{'target'}}[0];
628 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
629 my ($productId, $hostId);
631 # Build return message with twisted target and source
632 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
633 if (defined $forward_to_gosa) {
634 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
635 }
637 # Sanity check of needed parameter
638 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
639 &add_content2xml_hash($out_hash, "error_string", "no productId specified or productId tag invalid");
640 &add_content2xml_hash($out_hash, "error", "productId");
641 &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1);
642 return ( &create_xml_string($out_hash) );
643 }
644 if (not exists $msg_hash->{'item'}) {
645 &add_content2xml_hash($out_hash, "error_string", "message needs one xml-tag 'item' and within the xml-tags 'name' and 'value'");
646 &add_content2xml_hash($out_hash, "error", "item");
647 &main::daemon_log("$session_id ERROR: message needs one xml-tag 'item' and within the xml-tags 'name' and 'value': $msg", 1);
648 return ( &create_xml_string($out_hash) );
649 } else {
650 if ((not exists @{$msg_hash->{'item'}}[0]->{'name'}) || (@{@{$msg_hash->{'item'}}[0]->{'name'}} != 1 )) {
651 &add_content2xml_hash($out_hash, "error_string", "message needs within the xml-tag 'item' one xml-tags 'name'");
652 &add_content2xml_hash($out_hash, "error", "name");
653 &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'name': $msg", 1);
654 return ( &create_xml_string($out_hash) );
655 }
656 if ((not exists @{$msg_hash->{'item'}}[0]->{'value'}) || (@{@{$msg_hash->{'item'}}[0]->{'value'}} != 1 )) {
657 &add_content2xml_hash($out_hash, "error_string", "message needs within the xml-tag 'item' one xml-tags 'value'");
658 &add_content2xml_hash($out_hash, "error", "value");
659 &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'value': $msg", 1);
660 return ( &create_xml_string($out_hash) );
661 }
662 }
663 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
664 &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
665 &add_content2xml_hash($out_hash, "error", "hostId");
666 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
667 return ( &create_xml_string($out_hash) );
668 }
671 # Get productId
672 $productId = @{$msg_hash->{'productId'}}[0];
673 &add_content2xml_hash($out_hash, "productId", $productId);
675 # Get hostID if defined
676 if (exists $msg_hash->{'hostId'}){
677 $hostId = @{$msg_hash->{'hostId'}}[0];
678 &add_content2xml_hash($out_hash, "hostId", $hostId);
679 }
681 # Set product states if requested
682 if (defined @{$msg_hash->{'action'}}[0]){
683 &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
684 }
685 if (defined @{$msg_hash->{'state'}}[0]){
686 &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
687 }
689 # Find properties
690 foreach my $item (@{$msg_hash->{'item'}}){
691 # JSON Query
692 my $callobj;
694 if (defined $hostId){
695 $callobj = {
696 method => 'setProductProperty',
697 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
698 id => 1,
699 };
700 } else {
701 $callobj = {
702 method => 'setProductProperty',
703 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
704 id => 1,
705 };
706 }
708 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
709 my ($res_err, $res_err_string) = &check_opsi_res($res);
711 if ($res_err){
712 &man::daemon_log("$session_id ERROR: communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
713 &add_content2xml_hash($out_hash, "error", $res_err_string);
714 }
715 }
718 # Return message
719 return ( &create_xml_string($out_hash) );
720 }
723 ## @method opsi_get_client_hardware
724 # Reports client hardware inventory.
725 # @param msg - STRING - xml message with tag hostId
726 # @param msg_hash - HASHREF - message information parsed into a hash
727 # @param session_id - INTEGER - POE session id of the processing of this message
728 # @return out_msg - STRING - feedback to GOsa in success and error case
729 sub opsi_get_client_hardware {
730 my ($msg, $msg_hash, $session_id) = @_;
731 my $header = @{$msg_hash->{'header'}}[0];
732 my $source = @{$msg_hash->{'source'}}[0];
733 my $target = @{$msg_hash->{'target'}}[0];
734 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
735 my $hostId;
736 my $error = 0;
737 my $xml_msg;
739 # Build return message with twisted target and source
740 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
741 if (defined $forward_to_gosa) {
742 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
743 }
745 # Sanity check of needed parameter
746 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
747 $error++;
748 &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
749 &add_content2xml_hash($out_hash, "error", "hostId");
750 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
751 }
753 if (not $error) {
755 # Get hostID
756 $hostId = @{$msg_hash->{'hostId'}}[0];
757 &add_content2xml_hash($out_hash, "hostId", "$hostId");
758 &add_content2xml_hash($out_hash, "xxx", "");
759 }
761 # Move to XML string
762 $xml_msg= &create_xml_string($out_hash);
764 if (not $error) {
766 # JSON Query
767 my $callobj = {
768 method => 'getHardwareInformation_hash',
769 params => [ $hostId ],
770 id => 1,
771 };
773 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
774 if (not &check_opsi_res($res)){
775 my $result= $res->result;
776 foreach my $r (keys %{$result}){
777 my $item= "<item><id>".xml_quote($r)."</id>";
778 my $value= $result->{$r};
779 foreach my $sres (@{$value}){
781 foreach my $dres (keys %{$sres}){
782 if (defined $sres->{$dres}){
783 $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
784 }
785 }
787 }
788 $item.= "</item>";
789 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
791 }
792 }
794 $xml_msg=~ s/<xxx><\/xxx>//;
796 }
798 # Return message
799 return ( $xml_msg );
800 }
803 ## @method opsi_list_clients
804 # Reports all Opsi clients.
805 # @param msg - STRING - xml message
806 # @param msg_hash - HASHREF - message information parsed into a hash
807 # @param session_id - INTEGER - POE session id of the processing of this message
808 # @return out_msg - STRING - feedback to GOsa in success and error case
809 sub opsi_list_clients {
810 my ($msg, $msg_hash, $session_id) = @_;
811 my $header = @{$msg_hash->{'header'}}[0];
812 my $source = @{$msg_hash->{'source'}}[0];
813 my $target = @{$msg_hash->{'target'}}[0];
814 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
816 # Build return message with twisted target and source
817 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
818 if (defined $forward_to_gosa) {
819 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
820 }
821 &add_content2xml_hash($out_hash, "xxx", "");
823 # Move to XML string
824 my $xml_msg= &create_xml_string($out_hash);
826 # JSON Query
827 my $callobj = {
828 method => 'getClients_listOfHashes',
829 params => [ ],
830 id => 1,
831 };
832 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
833 if (not &check_opsi_res($res)){
834 foreach my $host (@{$res->result}){
835 my $item= "<item><name>".$host->{'hostId'}."</name>";
836 if (defined($host->{'description'})){
837 $item.= "<description>".xml_quote($host->{'description'})."</description>";
838 }
839 if (defined($host->{'notes'})){
840 $item.= "<notes>".xml_quote($host->{'notes'})."</notes>";
841 }
843 $callobj = {
844 method => 'getIpAddress',
845 params => [ $host->{'hostId'} ],
846 id => 1,
847 };
848 my $sres= $main::opsi_client->call($main::opsi_url, $callobj);
849 if ( not &check_opsi_res($sres)){
850 $item.= "<ip>".xml_quote($sres->result)."</ip>";
851 }
853 $callobj = {
854 method => 'getMacAddress',
855 params => [ $host->{'hostId'} ],
856 id => 1,
857 };
858 $sres= $main::opsi_client->call($main::opsi_url, $callobj);
859 if ( not &check_opsi_res($sres)){
860 $item.= "<mac>".xml_quote($sres->result)."</mac>";
861 }
862 $item.= "</item>";
863 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
864 }
865 }
867 $xml_msg=~ s/<xxx><\/xxx>//;
868 return ( $xml_msg );
869 }
872 ## @method opsi_get_client_software
873 # Reports client software inventory.
874 # @param msg - STRING - xml message with tag hostId
875 # @param msg_hash - HASHREF - message information parsed into a hash
876 # @param session_id - INTEGER - POE session id of the processing of this message
877 # @return out_msg - STRING - feedback to GOsa in success and error case
878 sub opsi_get_client_software {
879 my ($msg, $msg_hash, $session_id) = @_;
880 my $header = @{$msg_hash->{'header'}}[0];
881 my $source = @{$msg_hash->{'source'}}[0];
882 my $target = @{$msg_hash->{'target'}}[0];
883 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
884 my $error = 0;
885 my $hostId;
886 my $xml_msg;
888 # Build return message with twisted target and source
889 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
890 if (defined $forward_to_gosa) {
891 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
892 }
894 # Sanity check of needed parameter
895 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
896 $error++;
897 &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
898 &add_content2xml_hash($out_hash, "error", "hostId");
899 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
900 }
902 if (not $error) {
904 # Get hostID
905 $hostId = @{$msg_hash->{'hostId'}}[0];
906 &add_content2xml_hash($out_hash, "hostId", "$hostId");
907 &add_content2xml_hash($out_hash, "xxx", "");
908 }
910 $xml_msg= &create_xml_string($out_hash);
912 if (not $error) {
914 # JSON Query
915 my $callobj = {
916 method => 'getSoftwareInformation_hash',
917 params => [ $hostId ],
918 id => 1,
919 };
921 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
922 if (not &check_opsi_res($res)){
923 my $result= $res->result;
924 # TODO : Ist das hier schon fertig???
925 }
927 $xml_msg=~ s/<xxx><\/xxx>//;
929 }
931 # Return message
932 return ( $xml_msg );
933 }
936 ## @method opsi_get_local_products
937 # Reports product for given hostId or globally.
938 # @param msg - STRING - xml message with optional tag hostId
939 # @param msg_hash - HASHREF - message information parsed into a hash
940 # @param session_id - INTEGER - POE session id of the processing of this message
941 # @return out_msg - STRING - feedback to GOsa in success and error case
942 sub opsi_get_local_products {
943 my ($msg, $msg_hash, $session_id) = @_;
944 my $header = @{$msg_hash->{'header'}}[0];
945 my $source = @{$msg_hash->{'source'}}[0];
946 my $target = @{$msg_hash->{'target'}}[0];
947 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
948 my $hostId;
950 # Build return message with twisted target and source
951 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
952 if (defined $forward_to_gosa) {
953 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
954 }
955 &add_content2xml_hash($out_hash, "xxx", "");
957 # Get hostID if defined
958 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} == 1)) {
959 $hostId = @{$msg_hash->{'hostId'}}[0];
960 &add_content2xml_hash($out_hash, "hostId", $hostId);
961 }
963 # Move to XML string
964 my $xml_msg= &create_xml_string($out_hash);
966 # For hosts, only return the products that are or get installed
967 my $callobj;
968 $callobj = {
969 method => 'getLocalBootProductIds_list',
970 params => [ ],
971 id => 1,
972 };
974 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
975 my %r = ();
976 for (@{$res->result}) { $r{$_} = 1 }
978 if (not &check_opsi_res($res)){
980 if (defined $hostId){
981 $callobj = {
982 method => 'getProductStates_hash',
983 params => [ $hostId ],
984 id => 1,
985 };
987 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
988 if (not &check_opsi_res($hres)){
989 my $htmp= $hres->result->{$hostId};
991 # Check state != not_installed or action == setup -> load and add
992 foreach my $product (@{$htmp}){
994 if (!defined ($r{$product->{'productId'}})){
995 next;
996 }
998 # Now we've a couple of hashes...
999 if ($product->{'installationStatus'} ne "not_installed" or
1000 $product->{'actionRequest'} eq "setup"){
1001 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
1003 $callobj = {
1004 method => 'getProduct_hash',
1005 params => [ $product->{'productId'} ],
1006 id => 1,
1007 };
1009 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1010 if (not &check_opsi_res($sres)){
1011 my $tres= $sres->result;
1013 my $name= xml_quote($tres->{'name'});
1014 my $r= $product->{'productId'};
1015 my $description= xml_quote($tres->{'description'});
1016 $name=~ s/\//\\\//;
1017 $description=~ s/\//\\\//;
1018 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
1019 }
1021 }
1022 }
1024 }
1026 } else {
1027 foreach my $r (@{$res->result}) {
1028 $callobj = {
1029 method => 'getProduct_hash',
1030 params => [ $r ],
1031 id => 1,
1032 };
1034 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1035 if (not &check_opsi_res($sres)){
1036 my $tres= $sres->result;
1038 my $name= xml_quote($tres->{'name'});
1039 my $description= xml_quote($tres->{'description'});
1040 $name=~ s/\//\\\//;
1041 $description=~ s/\//\\\//;
1042 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
1043 }
1045 }
1047 }
1048 }
1050 $xml_msg=~ s/<xxx><\/xxx>//;
1052 # Retrun Message
1053 return ( $xml_msg );
1054 }
1057 ## @method opsi_del_client
1058 # Deletes a client from Opsi.
1059 # @param msg - STRING - xml message with tag hostId
1060 # @param msg_hash - HASHREF - message information parsed into a hash
1061 # @param session_id - INTEGER - POE session id of the processing of this message
1062 # @return out_msg - STRING - feedback to GOsa in success and error case
1063 sub opsi_del_client {
1064 my ($msg, $msg_hash, $session_id) = @_;
1065 my $header = @{$msg_hash->{'header'}}[0];
1066 my $source = @{$msg_hash->{'source'}}[0];
1067 my $target = @{$msg_hash->{'target'}}[0];
1068 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1069 my $hostId;
1070 my $error = 0;
1072 # Build return message with twisted target and source
1073 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1074 if (defined $forward_to_gosa) {
1075 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1076 }
1078 # Sanity check of needed parameter
1079 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
1080 $error++;
1081 &add_content2xml_hash($out_hash, "error_string", "hostId contains no or more than one values");
1082 &add_content2xml_hash($out_hash, "error", "hostId");
1083 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
1084 }
1086 if (not $error) {
1088 # Get hostID
1089 $hostId = @{$msg_hash->{'hostId'}}[0];
1090 &add_content2xml_hash($out_hash, "hostId", "$hostId");
1092 # JSON Query
1093 my $callobj = {
1094 method => 'deleteClient',
1095 params => [ $hostId ],
1096 id => 1,
1097 };
1098 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1099 }
1101 # Move to XML string
1102 my $xml_msg= &create_xml_string($out_hash);
1104 # Return message
1105 return ( $xml_msg );
1106 }
1109 ## @method opsi_install_client
1110 # Set a client in Opsi to install and trigger a wake on lan message (WOL).
1111 # @param msg - STRING - xml message with tags hostId, macaddress
1112 # @param msg_hash - HASHREF - message information parsed into a hash
1113 # @param session_id - INTEGER - POE session id of the processing of this message
1114 # @return out_msg - STRING - feedback to GOsa in success and error case
1115 sub opsi_install_client {
1116 my ($msg, $msg_hash, $session_id) = @_;
1117 my $header = @{$msg_hash->{'header'}}[0];
1118 my $source = @{$msg_hash->{'source'}}[0];
1119 my $target = @{$msg_hash->{'target'}}[0];
1120 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1123 my ($hostId, $macaddress);
1125 my $error = 0;
1126 my @out_msg_l;
1128 # Build return message with twisted target and source
1129 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1130 if (defined $forward_to_gosa) {
1131 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1132 }
1134 # Sanity check of needed parameter
1135 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
1136 $error++;
1137 &add_content2xml_hash($out_hash, "error_string", "no hostId specified or hostId tag invalid");
1138 &add_content2xml_hash($out_hash, "error", "hostId");
1139 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
1140 }
1141 if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1)) {
1142 $error++;
1143 &add_content2xml_hash($out_hash, "error_string", "no macaddress specified or macaddress tag invalid");
1144 &add_content2xml_hash($out_hash, "error", "macaddress");
1145 &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1);
1146 } else {
1147 if ((exists $msg_hash->{'macaddress'}) &&
1148 ($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)) {
1149 $macaddress = $1;
1150 } else {
1151 $error ++;
1152 &add_content2xml_hash($out_hash, "error_string", "given mac address is not correct");
1153 &add_content2xml_hash($out_hash, "error", "macaddress");
1154 &main::daemon_log("$session_id ERROR: given mac address is not correct: $msg", 1);
1155 }
1156 }
1158 if (not $error) {
1160 # Get hostId
1161 $hostId = @{$msg_hash->{'hostId'}}[0];
1162 &add_content2xml_hash($out_hash, "hostId", "$hostId");
1164 # Load all products for this host with status != "not_installed" or actionRequest != "none"
1165 my $callobj = {
1166 method => 'getProductStates_hash',
1167 params => [ $hostId ],
1168 id => 1,
1169 };
1171 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
1172 if (not &check_opsi_res($hres)){
1173 my $htmp= $hres->result->{$hostId};
1175 # check state != not_installed or action == setup -> load and add
1176 foreach my $product (@{$htmp}){
1177 # Now we've a couple of hashes...
1178 if ($product->{'installationStatus'} ne "not_installed" or
1179 $product->{'actionRequest'} ne "none"){
1181 # Do an action request for all these -> "setup".
1182 $callobj = {
1183 method => 'setProductActionRequest',
1184 params => [ $product->{'productId'}, $hostId, "setup" ],
1185 id => 1,
1186 };
1187 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1188 my ($res_err, $res_err_string) = &check_opsi_res($res);
1189 if ($res_err){
1190 &main::daemon_log("$session_id ERROR: cannot set product action request for '$hostId': ".$product->{'productId'}, 1);
1191 } else {
1192 &main::daemon_log("$session_id INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
1193 }
1194 }
1195 }
1196 }
1197 push(@out_msg_l, &create_xml_string($out_hash));
1200 # Build wakeup message for client
1201 if (not $error) {
1202 my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
1203 &add_content2xml_hash($wakeup_hash, 'macAddress', $macaddress);
1204 my $wakeup_msg = &create_xml_string($wakeup_hash);
1205 push(@out_msg_l, $wakeup_msg);
1207 # invoke trigger wake for this gosa-si-server
1208 &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
1209 }
1210 }
1212 # Return messages
1213 return @out_msg_l;
1214 }
1217 ## @method _set_action
1218 # Set action for an Opsi client
1219 # @param product - STRING - Opsi product
1220 # @param action - STRING - action
1221 # @param hostId - STRING - Opsi hostId
1222 sub _set_action {
1223 my $product= shift;
1224 my $action = shift;
1225 my $hostId = shift;
1226 my $callobj;
1228 $callobj = {
1229 method => 'setProductActionRequest',
1230 params => [ $product, $hostId, $action],
1231 id => 1,
1232 };
1234 $main::opsi_client->call($main::opsi_url, $callobj);
1235 }
1237 ## @method _set_state
1238 # Set state for an Opsi client
1239 # @param product - STRING - Opsi product
1240 # @param action - STRING - state
1241 # @param hostId - STRING - Opsi hostId
1242 sub _set_state {
1243 my $product = shift;
1244 my $state = shift;
1245 my $hostId = shift;
1246 my $callobj;
1248 $callobj = {
1249 method => 'setProductState',
1250 params => [ $product, $hostId, $state ],
1251 id => 1,
1252 };
1254 $main::opsi_client->call($main::opsi_url, $callobj);
1255 }
1257 1;