1 ## @file
2 # @details A GOsa-SI-server event module containing all functions for message handling.
3 # @brief Implementation of an event module for GOsa-SI-server.
6 package opsi_com;
7 use Exporter;
8 @ISA = qw(Exporter);
9 my @events = (
10 "get_events",
11 "opsi_install_client",
12 "opsi_get_netboot_products",
13 "opsi_get_local_products",
14 "opsi_get_client_hardware",
15 "opsi_get_client_software",
16 "opsi_get_product_properties",
17 "opsi_set_product_properties",
18 "opsi_list_clients",
19 "opsi_del_client",
20 "opsi_add_client",
21 "opsi_modify_client",
22 "opsi_add_product_to_client",
23 "opsi_del_product_from_client",
24 );
25 @EXPORT = @events;
27 use strict;
28 use warnings;
29 use GOSA::GosaSupportDaemon;
30 use Data::Dumper;
31 use XML::Quote qw(:all);
34 BEGIN {}
36 END {}
38 ## @method get_events()
39 # A brief function returning a list of functions which are exported by importing the module.
40 # @return List of all provided functions
41 sub get_events {
42 return \@events;
43 }
45 ## @method opsi_add_product_to_client
46 # Adds an Opsi product to an Opsi client.
47 # @param msg - STRING - xml message with tags hostId and productId
48 # @param msg_hash - HASHREF - message information parsed into a hash
49 # @param session_id - INTEGER - POE session id of the processing of this message
50 # @return out_msg - STRING - feedback to GOsa in success and error case
51 sub opsi_add_product_to_client {
52 my ($msg, $msg_hash, $session_id) = @_;
53 my $header = @{$msg_hash->{'header'}}[0];
54 my $source = @{$msg_hash->{'source'}}[0];
55 my $target = @{$msg_hash->{'target'}}[0];
56 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
57 my ($hostId, $productId);
58 my $error = 0;
60 # Build return message
61 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
62 if (defined $forward_to_gosa) {
63 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
64 }
66 # Sanity check of needed parameter
67 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
68 $error++;
69 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
70 &add_content2xml_hash($out_hash, "error", "hostId");
71 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
73 }
74 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
75 $error++;
76 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
77 &add_content2xml_hash($out_hash, "error", "productId");
78 &main::daemon_log("$session_id ERROR: no productId specified or procutId tag invalid: $msg", 1);
79 }
81 if (not $error) {
82 # Get hostID
83 $hostId = @{$msg_hash->{'hostId'}}[0];
84 &add_content2xml_hash($out_hash, "hostId", $hostId);
86 # Get productID
87 $productId = @{$msg_hash->{'productId'}}[0];
88 &add_content2xml_hash($out_hash, "productId", $productId);
90 # Do an action request for all these -> "setup".
91 my $callobj = {
92 method => 'setProductActionRequest',
93 params => [ $productId, $hostId, "setup" ],
94 id => 1, };
96 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
97 my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
98 if ($sres_err){
99 &main::daemon_log("$session_id ERROR: cannot add product: ".$sres_err_string, 1);
100 &add_content2xml_hash($out_hash, "error", $sres_err_string);
101 }
102 }
104 # return message
105 return ( &create_xml_string($out_hash) );
106 }
108 ## @method opsi_del_product_from_client
109 # Deletes an Opsi-product from an Opsi-client.
110 # @param msg - STRING - xml message with tags hostId and productId
111 # @param msg_hash - HASHREF - message information parsed into a hash
112 # @param session_id - INTEGER - POE session id of the processing of this message
113 # @return out_msg - STRING - feedback to GOsa in success and error case
114 sub opsi_del_product_from_client {
115 my ($msg, $msg_hash, $session_id) = @_;
116 my $header = @{$msg_hash->{'header'}}[0];
117 my $source = @{$msg_hash->{'source'}}[0];
118 my $target = @{$msg_hash->{'target'}}[0];
119 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
120 my ($hostId, $productId);
121 my $error = 0;
122 my ($sres, $sres_err, $sres_err_string);
124 # Build return message
125 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
126 if (defined $forward_to_gosa) {
127 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
128 }
130 # Sanity check of needed parameter
131 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
132 $error++;
133 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
134 &add_content2xml_hash($out_hash, "error", "hostId");
135 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
137 }
138 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
139 $error++;
140 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
141 &add_content2xml_hash($out_hash, "error", "productId");
142 &main::daemon_log("$session_id ERROR: no productId specified or procutId tag invalid: $msg", 1);
143 }
145 # All parameter available
146 if (not $error) {
147 # Get hostID
148 $hostId = @{$msg_hash->{'hostId'}}[0];
149 &add_content2xml_hash($out_hash, "hostId", $hostId);
151 # Get productID
152 $productId = @{$msg_hash->{'productId'}}[0];
153 &add_content2xml_hash($out_hash, "productId", $productId);
156 #TODO: check the results for more than one entry which is currently installed
157 #$callobj = {
158 # method => 'getProductDependencies_listOfHashes',
159 # params => [ $productId ],
160 # id => 1, };
161 #
162 #my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
163 #my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
164 #if ($sres_err){
165 # &main::daemon_log("ERROR: cannot perform dependency check: ".$sres_err_string, 1);
166 # &add_content2xml_hash($out_hash, "error", $sres_err_string);
167 # return ( &create_xml_string($out_hash) );
168 #}
171 # Check to get product action list
172 my $callobj = {
173 method => 'getPossibleProductActions_list',
174 params => [ $productId ],
175 id => 1, };
176 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
177 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
178 if ($sres_err){
179 &main::daemon_log("$session_id ERROR: cannot get product action list: ".$sres_err_string, 1);
180 &add_content2xml_hash($out_hash, "error", $sres_err_string);
181 $error++;
182 }
183 }
185 # Check action uninstall of product
186 if (not $error) {
187 my $uninst_possible= 0;
188 foreach my $r (@{$sres->result}) {
189 if ($r eq 'uninstall') {
190 $uninst_possible= 1;
191 }
192 }
193 if (!$uninst_possible){
194 &main::daemon_log("$session_id ERROR: cannot uninstall product '$productId', product do not has the action 'uninstall'", 1);
195 &add_content2xml_hash($out_hash, "error", "cannot uninstall product '$productId', product do not has the action 'uninstall'");
196 $error++;
197 }
198 }
200 # Set product state to "none"
201 # Do an action request for all these -> "setup".
202 if (not $error) {
203 my $callobj = {
204 method => 'setProductActionRequest',
205 params => [ $productId, $hostId, "none" ],
206 id => 1,
207 };
208 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
209 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
210 if ($sres_err){
211 &main::daemon_log("$session_id ERROR: cannot delete product: ".$sres_err_string, 1);
212 &add_content2xml_hash($out_hash, "error", $sres_err_string);
213 }
214 }
216 # Return message
217 return ( &create_xml_string($out_hash) );
218 }
220 ## @method opsi_add_client
221 # Adds an Opsi client to Opsi.
222 # @param msg - STRING - xml message with tags hostId and macaddress
223 # @param msg_hash - HASHREF - message information parsed into a hash
224 # @param session_id - INTEGER - POE session id of the processing of this message
225 # @return out_msg - STRING - feedback to GOsa in success and error case
226 sub opsi_add_client {
227 my ($msg, $msg_hash, $session_id) = @_;
228 my $header = @{$msg_hash->{'header'}}[0];
229 my $source = @{$msg_hash->{'source'}}[0];
230 my $target = @{$msg_hash->{'target'}}[0];
231 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
232 my ($hostId, $mac);
233 my $error = 0;
234 my ($sres, $sres_err, $sres_err_string);
236 # build return message with twisted target and source
237 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
238 if (defined $forward_to_gosa) {
239 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
240 }
242 # Sanity check of needed parameter
243 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
244 $error++;
245 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
246 &add_content2xml_hash($out_hash, "error", "hostId");
247 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
248 }
249 if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1)) {
250 $error++;
251 &add_content2xml_hash($out_hash, "macaddress_error", "no macaddress specified or macaddress tag invalid");
252 &add_content2xml_hash($out_hash, "error", "macaddress");
253 &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1);
254 }
256 if (not $error) {
257 # Get hostID
258 $hostId = @{$msg_hash->{'hostId'}}[0];
259 &add_content2xml_hash($out_hash, "hostId", $hostId);
261 # Get macaddress
262 $mac = @{$msg_hash->{'macaddress'}}[0];
263 &add_content2xml_hash($out_hash, "macaddress", $mac);
265 my $name= $hostId;
266 $name=~ s/^([^.]+).*$/$1/;
267 my $domain= $hostId;
268 $domain=~ s/^[^.]+\.(.*)$/$1/;
269 my ($description, $notes, $ip);
271 if (defined @{$msg_hash->{'description'}}[0]){
272 $description = @{$msg_hash->{'description'}}[0];
273 }
274 if (defined @{$msg_hash->{'notes'}}[0]){
275 $notes = @{$msg_hash->{'notes'}}[0];
276 }
277 if (defined @{$msg_hash->{'ip'}}[0]){
278 $ip = @{$msg_hash->{'ip'}}[0];
279 }
281 my $callobj;
282 $callobj = {
283 method => 'createClient',
284 params => [ $name, $domain, $description, $notes, $ip, $mac ],
285 id => 1,
286 };
288 $sres = $main::opsi_client->call($main::opsi_url, $callobj);
289 ($sres_err, $sres_err_string) = &check_opsi_res($sres);
290 if ($sres_err){
291 &main::daemon_log("$session_id ERROR: cannot create client: ".$sres_err_string, 1);
292 &add_content2xml_hash($out_hash, "error", $sres_err_string);
293 } 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, "hostId_error", "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 $error = 0;
407 my $xml_msg;
409 # Build return message with twisted target and source
410 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
411 if (defined $forward_to_gosa) {
412 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
413 }
415 # Sanity check of needed parameter
416 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
417 $error++;
418 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
419 &add_content2xml_hash($out_hash, "error", "hostId");
420 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
421 }
423 if (not $error) {
425 # Get hostID if defined
426 $hostId = @{$msg_hash->{'hostId'}}[0];
427 &add_content2xml_hash($out_hash, "hostId", $hostId);
429 &add_content2xml_hash($out_hash, "xxx", "");
430 $xml_msg= &create_xml_string($out_hash);
432 # For hosts, only return the products that are or get installed
433 my $callobj;
434 $callobj = {
435 method => 'getNetBootProductIds_list',
436 params => [ ],
437 id => 1,
438 };
440 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
441 my %r = ();
442 for (@{$res->result}) { $r{$_} = 1 }
444 if (not &check_opsi_res($res)){
446 if (defined $hostId){
447 $callobj = {
448 method => 'getProductStates_hash',
449 params => [ $hostId ],
450 id => 1,
451 };
453 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
454 if (not &check_opsi_res($hres)){
455 my $htmp= $hres->result->{$hostId};
457 # check state != not_installed or action == setup -> load and add
458 foreach my $product (@{$htmp}){
460 if (!defined ($r{$product->{'productId'}})){
461 next;
462 }
464 # Now we've a couple of hashes...
465 if ($product->{'installationStatus'} ne "not_installed" or
466 $product->{'actionRequest'} eq "setup"){
467 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
469 $callobj = {
470 method => 'getProduct_hash',
471 params => [ $product->{'productId'} ],
472 id => 1,
473 };
475 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
476 if (not &check_opsi_res($sres)){
477 my $tres= $sres->result;
479 my $name= xml_quote($tres->{'name'});
480 my $r= $product->{'productId'};
481 my $description= xml_quote($tres->{'description'});
482 $name=~ s/\//\\\//;
483 $description=~ s/\//\\\//;
484 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
485 }
486 }
487 }
489 }
491 } else {
492 foreach my $r (@{$res->result}) {
493 $callobj = {
494 method => 'getProduct_hash',
495 params => [ $r ],
496 id => 1,
497 };
499 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
500 if (not &check_opsi_res($sres)){
501 my $tres= $sres->result;
503 my $name= xml_quote($tres->{'name'});
504 my $description= xml_quote($tres->{'description'});
505 $name=~ s/\//\\\//;
506 $description=~ s/\//\\\//;
507 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
508 }
509 }
511 }
512 }
513 $xml_msg=~ s/<xxx><\/xxx>//;
514 }
516 # Return message
517 return ( $xml_msg );
518 }
521 ## @method opsi_get_product_properties
522 # Get product properties for a product and a specific host or gobally for a product.
523 # @param msg - STRING - xml message with tags productId and optional hostId
524 # @param msg_hash - HASHREF - message information parsed into a hash
525 # @param session_id - INTEGER - POE session id of the processing of this message
526 # @return out_msg - STRING - feedback to GOsa in success and error case
527 sub opsi_get_product_properties {
528 my ($msg, $msg_hash, $session_id) = @_;
529 my $header = @{$msg_hash->{'header'}}[0];
530 my $source = @{$msg_hash->{'source'}}[0];
531 my $target = @{$msg_hash->{'target'}}[0];
532 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
533 my ($hostId, $productId);
534 my $xml_msg;
536 # build return message with twisted target and source
537 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
538 if (defined $forward_to_gosa) {
539 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
540 }
542 # Sanity check of needed parameter
543 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
544 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
545 &add_content2xml_hash($out_hash, "error", "productId");
546 &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1);
548 # Return message
549 return ( &create_xml_string($out_hash) );
550 }
552 # Get productid
553 $productId = @{$msg_hash->{'productId'}}[0];
554 &add_content2xml_hash($out_hash, "producId", "$productId");
556 # Get hostID if defined
557 if (defined @{$msg_hash->{'hostId'}}[0]){
558 $hostId = @{$msg_hash->{'hostId'}}[0];
559 &add_content2xml_hash($out_hash, "hostId", $hostId);
560 }
562 # Load actions
563 my $callobj = {
564 method => 'getPossibleProductActions_list',
565 params => [ $productId ],
566 id => 1,
567 };
568 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
569 if (not &check_opsi_res($res)){
570 foreach my $action (@{$res->result}){
571 &add_content2xml_hash($out_hash, "action", $action);
572 }
573 }
575 # Add place holder
576 &add_content2xml_hash($out_hash, "xxx", "");
578 # Move to XML string
579 $xml_msg= &create_xml_string($out_hash);
581 # JSON Query
582 if (defined $hostId){
583 $callobj = {
584 method => 'getProductProperties_hash',
585 params => [ $productId, $hostId ],
586 id => 1,
587 };
588 } else {
589 $callobj = {
590 method => 'getProductProperties_hash',
591 params => [ $productId ],
592 id => 1,
593 };
594 }
596 $res = $main::opsi_client->call($main::opsi_url, $callobj);
597 if (not &check_opsi_res($res)){
598 my $r= $res->result;
599 foreach my $key (keys %{$r}) {
600 my $item= "<item>";
601 my $value= $r->{$key};
602 if (UNIVERSAL::isa( $value, "ARRAY" )){
603 foreach my $subval (@{$value}){
604 $item.= "<$key>".xml_quote($subval)."</$key>";
605 }
606 } else {
607 $item.= "<$key>".xml_quote($value)."</$key>";
608 }
609 $item.= "</item>";
610 $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
611 }
612 }
614 $xml_msg=~ s/<xxx><\/xxx>//;
616 # Return message
617 return ( $xml_msg );
618 }
621 ## @method opsi_set_product_properties
622 # 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.
623 # @param msg - STRING - xml message with tags productId, action, state and optional hostId, action and state
624 # @param msg_hash - HASHREF - message information parsed into a hash
625 # @param session_id - INTEGER - POE session id of the processing of this message
626 # @return out_msg - STRING - feedback to GOsa in success and error case
627 sub opsi_set_product_properties {
628 my ($msg, $msg_hash, $session_id) = @_;
629 my $header = @{$msg_hash->{'header'}}[0];
630 my $source = @{$msg_hash->{'source'}}[0];
631 my $target = @{$msg_hash->{'target'}}[0];
632 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
633 my ($productId, $hostId);
634 print STDERR Dumper($msg_hash);
635 # Build return message with twisted target and source
636 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
637 if (defined $forward_to_gosa) {
638 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
639 }
641 # Sanity check of needed parameter
642 if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1)) {
643 &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
644 &add_content2xml_hash($out_hash, "error", "productId");
645 &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1);
646 return ( &create_xml_string($out_hash) );
647 }
648 if (not exists $msg_hash->{'item'}) {
649 &add_content2xml_hash($out_hash, "item_error", "message needs one xml-tag 'item' and within the xml-tags 'name' and 'value'");
650 &add_content2xml_hash($out_hash, "error", "item");
651 &main::daemon_log("$session_id ERROR: message needs one xml-tag 'item' and within the xml-tags 'name' and 'value': $msg", 1);
652 return ( &create_xml_string($out_hash) );
653 } else {
654 if ((not exists @{$msg_hash->{'item'}}[0]->{'name'}) || (@{@{$msg_hash->{'item'}}[0]->{'name'}} != 1 )) {
655 &add_content2xml_hash($out_hash, "name_error", "message needs within the xml-tag 'item' one xml-tags 'name'");
656 &add_content2xml_hash($out_hash, "error", "name");
657 &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'name': $msg", 1);
658 return ( &create_xml_string($out_hash) );
659 }
660 if ((not exists @{$msg_hash->{'item'}}[0]->{'value'}) || (@{@{$msg_hash->{'item'}}[0]->{'value'}} != 1 )) {
661 &add_content2xml_hash($out_hash, "value_error", "message needs within the xml-tag 'item' one xml-tags 'value'");
662 &add_content2xml_hash($out_hash, "error", "value");
663 &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'value': $msg", 1);
664 return ( &create_xml_string($out_hash) );
665 }
666 }
667 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
668 &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
669 &add_content2xml_hash($out_hash, "error", "hostId");
670 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
671 return ( &create_xml_string($out_hash) );
672 }
675 # Get productId
676 $productId = @{$msg_hash->{'productId'}}[0];
677 &add_content2xml_hash($out_hash, "productId", $productId);
679 # Get hostID if defined
680 if (exists $msg_hash->{'hostId'}){
681 $hostId = @{$msg_hash->{'hostId'}}[0];
682 &add_content2xml_hash($out_hash, "hostId", $hostId);
683 }
685 # Set product states if requested
686 if (defined @{$msg_hash->{'action'}}[0]){
687 &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
688 }
689 if (defined @{$msg_hash->{'state'}}[0]){
690 &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
691 }
693 # Find properties
694 foreach my $item (@{$msg_hash->{'item'}}){
695 # JSON Query
696 my $callobj;
698 if (defined $hostId){
699 $callobj = {
700 method => 'setProductProperty',
701 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
702 id => 1,
703 };
704 } else {
705 $callobj = {
706 method => 'setProductProperty',
707 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
708 id => 1,
709 };
710 }
712 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
713 my ($res_err, $res_err_string) = &check_opsi_res($res);
715 if ($res_err){
716 &man::daemon_log("$session_id ERROR: communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
717 &add_content2xml_hash($out_hash, "error", $res_err_string);
718 }
719 }
722 # Return message
723 return ( &create_xml_string($out_hash) );
724 }
727 ## @method opsi_get_client_hardware
728 # Reports client hardware inventory.
729 # @param msg - STRING - xml message with tag hostId
730 # @param msg_hash - HASHREF - message information parsed into a hash
731 # @param session_id - INTEGER - POE session id of the processing of this message
732 # @return out_msg - STRING - feedback to GOsa in success and error case
733 sub opsi_get_client_hardware {
734 my ($msg, $msg_hash, $session_id) = @_;
735 my $header = @{$msg_hash->{'header'}}[0];
736 my $source = @{$msg_hash->{'source'}}[0];
737 my $target = @{$msg_hash->{'target'}}[0];
738 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
739 my $hostId;
740 my $error = 0;
741 my $xml_msg;
743 # build return message with twisted target and source
744 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
745 if (defined $forward_to_gosa) {
746 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
747 }
749 # Sanity check of needed parameter
750 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
751 $error++;
752 &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
753 &add_content2xml_hash($out_hash, "error", "hostId");
754 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
755 }
757 if (not $error) {
759 # Get hostID
760 $hostId = @{$msg_hash->{'hostId'}}[0];
761 &add_content2xml_hash($out_hash, "hostId", "$hostId");
762 &add_content2xml_hash($out_hash, "xxx", "");
763 }
765 # Move to XML string
766 $xml_msg= &create_xml_string($out_hash);
768 if (not $error) {
770 # JSON Query
771 my $callobj = {
772 method => 'getHardwareInformation_hash',
773 params => [ $hostId ],
774 id => 1,
775 };
777 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
778 if (not &check_opsi_res($res)){
779 my $result= $res->result;
780 foreach my $r (keys %{$result}){
781 my $item= "<item><id>".xml_quote($r)."</id>";
782 my $value= $result->{$r};
783 foreach my $sres (@{$value}){
785 foreach my $dres (keys %{$sres}){
786 if (defined $sres->{$dres}){
787 $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
788 }
789 }
791 }
792 $item.= "</item>";
793 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
795 }
796 }
798 $xml_msg=~ s/<xxx><\/xxx>//;
800 }
802 # Return message
803 return ( $xml_msg );
804 }
807 ## @method opsi_list_clients
808 # Reports all Opsi clients.
809 # @param msg - STRING - xml message
810 # @param msg_hash - HASHREF - message information parsed into a hash
811 # @param session_id - INTEGER - POE session id of the processing of this message
812 # @return out_msg - STRING - feedback to GOsa in success and error case
813 sub opsi_list_clients {
814 my ($msg, $msg_hash, $session_id) = @_;
815 my $header = @{$msg_hash->{'header'}}[0];
816 my $source = @{$msg_hash->{'source'}}[0];
817 my $target = @{$msg_hash->{'target'}}[0];
818 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
820 # build return message with twisted target and source
821 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
822 if (defined $forward_to_gosa) {
823 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
824 }
825 &add_content2xml_hash($out_hash, "xxx", "");
827 # Move to XML string
828 my $xml_msg= &create_xml_string($out_hash);
830 # JSON Query
831 my $callobj = {
832 method => 'getClients_listOfHashes',
833 params => [ ],
834 id => 1,
835 };
836 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
837 if (not &check_opsi_res($res)){
838 foreach my $host (@{$res->result}){
839 my $item= "<item><name>".$host->{'hostId'}."</name>";
840 if (defined($host->{'description'})){
841 $item.= "<description>".xml_quote($host->{'description'})."</description>";
842 }
843 if (defined($host->{'notes'})){
844 $item.= "<notes>".xml_quote($host->{'notes'})."</notes>";
845 }
847 $callobj = {
848 method => 'getIpAddress',
849 params => [ $host->{'hostId'} ],
850 id => 1,
851 };
852 my $sres= $main::opsi_client->call($main::opsi_url, $callobj);
853 if ( not &check_opsi_res($sres)){
854 $item.= "<ip>".xml_quote($sres->result)."</ip>";
855 }
857 $callobj = {
858 method => 'getMacAddress',
859 params => [ $host->{'hostId'} ],
860 id => 1,
861 };
862 $sres= $main::opsi_client->call($main::opsi_url, $callobj);
863 if ( not &check_opsi_res($sres)){
864 $item.= "<mac>".xml_quote($sres->result)."</mac>";
865 }
866 $item.= "</item>";
867 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
868 }
869 }
871 $xml_msg=~ s/<xxx><\/xxx>//;
872 return ( $xml_msg );
873 }
876 ## @method opsi_get_client_software
877 # Reports client software inventory.
878 # @param msg - STRING - xml message with tag hostId
879 # @param msg_hash - HASHREF - message information parsed into a hash
880 # @param session_id - INTEGER - POE session id of the processing of this message
881 # @return out_msg - STRING - feedback to GOsa in success and error case
882 sub opsi_get_client_software {
883 my ($msg, $msg_hash, $session_id) = @_;
884 my $header = @{$msg_hash->{'header'}}[0];
885 my $source = @{$msg_hash->{'source'}}[0];
886 my $target = @{$msg_hash->{'target'}}[0];
887 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
888 my $error = 0;
889 my $hostId;
890 my $xml_msg;
892 # build return message with twisted target and source
893 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
894 if (defined $forward_to_gosa) {
895 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
896 }
898 # Sanity check of needed parameter
899 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
900 $error++;
901 &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
902 &add_content2xml_hash($out_hash, "error", "hostId");
903 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
904 }
906 if (not $error) {
908 # Get hostID
909 $hostId = @{$msg_hash->{'hostId'}}[0];
910 &add_content2xml_hash($out_hash, "hostId", "$hostId");
911 &add_content2xml_hash($out_hash, "xxx", "");
912 }
914 $xml_msg= &create_xml_string($out_hash);
916 if (not $error) {
918 # JSON Query
919 my $callobj = {
920 method => 'getSoftwareInformation_hash',
921 params => [ $hostId ],
922 id => 1,
923 };
925 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
926 if (not &check_opsi_res($res)){
927 my $result= $res->result;
928 # TODO : Ist das hier schon fertig???
929 }
931 $xml_msg=~ s/<xxx><\/xxx>//;
933 }
935 # Return message
936 return ( $xml_msg );
937 }
940 ## @method opsi_get_local_products
941 # Reports product for given hostId or globally.
942 # @param msg - STRING - xml message with optional tag hostId
943 # @param msg_hash - HASHREF - message information parsed into a hash
944 # @param session_id - INTEGER - POE session id of the processing of this message
945 # @return out_msg - STRING - feedback to GOsa in success and error case
946 sub opsi_get_local_products {
947 my ($msg, $msg_hash, $session_id) = @_;
948 my $header = @{$msg_hash->{'header'}}[0];
949 my $source = @{$msg_hash->{'source'}}[0];
950 my $target = @{$msg_hash->{'target'}}[0];
951 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
952 my $hostId;
954 # Build return message with twisted target and source
955 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
956 if (defined $forward_to_gosa) {
957 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
958 }
959 &add_content2xml_hash($out_hash, "xxx", "");
961 # Get hostID if defined
962 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} == 1)) {
963 $hostId = @{$msg_hash->{'hostId'}}[0];
964 &add_content2xml_hash($out_hash, "hostId", $hostId);
965 }
967 # Move to XML string
968 my $xml_msg= &create_xml_string($out_hash);
970 # For hosts, only return the products that are or get installed
971 my $callobj;
972 $callobj = {
973 method => 'getLocalBootProductIds_list',
974 params => [ ],
975 id => 1,
976 };
978 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
979 my %r = ();
980 for (@{$res->result}) { $r{$_} = 1 }
982 if (not &check_opsi_res($res)){
984 if (defined $hostId){
985 $callobj = {
986 method => 'getProductStates_hash',
987 params => [ $hostId ],
988 id => 1,
989 };
991 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
992 if (not &check_opsi_res($hres)){
993 my $htmp= $hres->result->{$hostId};
995 # Check state != not_installed or action == setup -> load and add
996 foreach my $product (@{$htmp}){
998 if (!defined ($r{$product->{'productId'}})){
999 next;
1000 }
1002 # Now we've a couple of hashes...
1003 if ($product->{'installationStatus'} ne "not_installed" or
1004 $product->{'actionRequest'} eq "setup"){
1005 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
1007 $callobj = {
1008 method => 'getProduct_hash',
1009 params => [ $product->{'productId'} ],
1010 id => 1,
1011 };
1013 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1014 if (not &check_opsi_res($sres)){
1015 my $tres= $sres->result;
1017 my $name= xml_quote($tres->{'name'});
1018 my $r= $product->{'productId'};
1019 my $description= xml_quote($tres->{'description'});
1020 $name=~ s/\//\\\//;
1021 $description=~ s/\//\\\//;
1022 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
1023 }
1025 }
1026 }
1028 }
1030 } else {
1031 foreach my $r (@{$res->result}) {
1032 $callobj = {
1033 method => 'getProduct_hash',
1034 params => [ $r ],
1035 id => 1,
1036 };
1038 my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
1039 if (not &check_opsi_res($sres)){
1040 my $tres= $sres->result;
1042 my $name= xml_quote($tres->{'name'});
1043 my $description= xml_quote($tres->{'description'});
1044 $name=~ s/\//\\\//;
1045 $description=~ s/\//\\\//;
1046 $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
1047 }
1049 }
1051 }
1052 }
1054 $xml_msg=~ s/<xxx><\/xxx>//;
1056 # Retrun Message
1057 return ( $xml_msg );
1058 }
1061 ## @method opsi_del_client
1062 # Deletes a client from Opsi.
1063 # @param msg - STRING - xml message with tag hostId
1064 # @param msg_hash - HASHREF - message information parsed into a hash
1065 # @param session_id - INTEGER - POE session id of the processing of this message
1066 # @return out_msg - STRING - feedback to GOsa in success and error case
1067 sub opsi_del_client {
1068 my ($msg, $msg_hash, $session_id) = @_;
1069 my $header = @{$msg_hash->{'header'}}[0];
1070 my $source = @{$msg_hash->{'source'}}[0];
1071 my $target = @{$msg_hash->{'target'}}[0];
1072 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1073 my $hostId;
1074 my $error = 0;
1076 # Build return message with twisted target and source
1077 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1078 if (defined $forward_to_gosa) {
1079 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1080 }
1082 # Sanity check of needed parameter
1083 if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1)) {
1084 $error++;
1085 &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
1086 &add_content2xml_hash($out_hash, "error", "hostId");
1087 &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1);
1088 }
1090 if (not $error) {
1092 # Get hostID
1093 $hostId = @{$msg_hash->{'hostId'}}[0];
1094 &add_content2xml_hash($out_hash, "hostId", "$hostId");
1096 # JSON Query
1097 my $callobj = {
1098 method => 'deleteClient',
1099 params => [ $hostId ],
1100 id => 1,
1101 };
1102 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1103 }
1105 # Move to XML string
1106 my $xml_msg= &create_xml_string($out_hash);
1108 # Return message
1109 return ( $xml_msg );
1110 }
1113 ## @method opsi_install_client
1114 # Set a client in Opsi to install and trigger a wake on lan message (WOL).
1115 # @param msg - STRING - xml message with tags hostId, macaddress
1116 # @param msg_hash - HASHREF - message information parsed into a hash
1117 # @param session_id - INTEGER - POE session id of the processing of this message
1118 # @return out_msg - STRING - feedback to GOsa in success and error case
1119 sub opsi_install_client {
1120 my ($msg, $msg_hash, $session_id) = @_;
1121 my $header = @{$msg_hash->{'header'}}[0];
1122 my $source = @{$msg_hash->{'source'}}[0];
1123 my $target = @{$msg_hash->{'target'}}[0];
1124 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
1127 my ($hostId, $macaddress);
1129 my $error = 0;
1130 my @out_msg_l;
1132 # Build return message with twisted target and source
1133 my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
1134 if (defined $forward_to_gosa) {
1135 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
1136 }
1138 # Sanity check of needed parameter
1139 if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1)) {
1140 $error++;
1141 &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
1142 &add_content2xml_hash($out_hash, "error", "hostId");
1143 &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1);
1144 }
1145 if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1)) {
1146 $error++;
1147 &add_content2xml_hash($out_hash, "macaddress_error", "no macaddress specified or macaddress tag invalid");
1148 &add_content2xml_hash($out_hash, "error", "macaddress");
1149 &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1);
1150 } else {
1151 if ((exists $msg_hash->{'macaddress'}) &&
1152 ($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)) {
1153 $macaddress = $1;
1154 } else {
1155 $error ++;
1156 &add_content2xml_hash($out_hash, "macaddress_error", "given mac address is not correct");
1157 &add_content2xml_hash($out_hash, "error", "macaddress");
1158 &main::daemon_log("$session_id ERROR: given mac address is not correct: $msg", 1);
1159 }
1160 }
1162 if (not $error) {
1164 # Get hostId
1165 $hostId = @{$msg_hash->{'hostId'}}[0];
1166 &add_content2xml_hash($out_hash, "hostId", "$hostId");
1168 # Load all products for this host with status != "not_installed" or actionRequest != "none"
1169 my $callobj = {
1170 method => 'getProductStates_hash',
1171 params => [ $hostId ],
1172 id => 1,
1173 };
1175 my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
1176 if (not &check_opsi_res($hres)){
1177 my $htmp= $hres->result->{$hostId};
1179 # check state != not_installed or action == setup -> load and add
1180 foreach my $product (@{$htmp}){
1181 # Now we've a couple of hashes...
1182 if ($product->{'installationStatus'} ne "not_installed" or
1183 $product->{'actionRequest'} ne "none"){
1185 # Do an action request for all these -> "setup".
1186 $callobj = {
1187 method => 'setProductActionRequest',
1188 params => [ $product->{'productId'}, $hostId, "setup" ],
1189 id => 1,
1190 };
1191 my $res = $main::opsi_client->call($main::opsi_url, $callobj);
1192 my ($res_err, $res_err_string) = &check_opsi_res($res);
1193 if ($res_err){
1194 &main::daemon_log("$session_id ERROR: cannot set product action request for '$hostId': ".$product->{'productId'}, 1);
1195 } else {
1196 &main::daemon_log("$session_id INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
1197 }
1198 }
1199 }
1200 }
1201 push(@out_msg_l, &create_xml_string($out_hash));
1204 # Build wakeup message for client
1205 if (not $error) {
1206 my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
1207 &add_content2xml_hash($wakeup_hash, 'macAddress', $macaddress);
1208 my $wakeup_msg = &create_xml_string($wakeup_hash);
1209 push(@out_msg_l, $wakeup_msg);
1211 # invoke trigger wake for this gosa-si-server
1212 &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
1213 }
1214 }
1216 # Return messages
1217 return @out_msg_l;
1218 }
1221 ## @method _set_action
1222 # Set action for an Opsi client
1223 # @param product - STRING - Opsi product
1224 # @param action - STRING - action
1225 # @param hostId - STRING - Opsi hostId
1226 sub _set_action {
1227 my $product= shift;
1228 my $action = shift;
1229 my $hostId = shift;
1230 my $callobj;
1232 $callobj = {
1233 method => 'setProductActionRequest',
1234 params => [ $product, $hostId, $action],
1235 id => 1,
1236 };
1238 $main::opsi_client->call($main::opsi_url, $callobj);
1239 }
1241 ## @method _set_state
1242 # Set state for an Opsi client
1243 # @param product - STRING - Opsi product
1244 # @param action - STRING - state
1245 # @param hostId - STRING - Opsi hostId
1246 sub _set_state {
1247 my $product = shift;
1248 my $state = shift;
1249 my $hostId = shift;
1250 my $callobj;
1252 $callobj = {
1253 method => 'setProductState',
1254 params => [ $product, $hostId, $state ],
1255 id => 1,
1256 };
1258 $main::opsi_client->call($main::opsi_url, $callobj);
1259 }
1261 1;