1 package opsi;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5 "get_events",
6 "_opsi_get_client_status",
7 "opsi_get_netboot_products",
8 "opsi_get_local_products",
9 "opsi_get_client_hardware",
10 "opsi_get_client_software",
11 "opsi_get_product_properties",
12 "opsi_set_product_properties",
13 "opsi_list_clients",
14 "opsi_del_client",
15 "opsi_install_client",
17 #"opsi_add_client",
18 # Client hinzufügen
19 # -> voll qualifizierter name
20 # -> IP
21 # -> MAC
22 # -> Description
23 # -> Notizen
25 #"opsi_modify_client",
27 #"opsi_add_product_to_client",
28 # -> set product state auf "setup"
29 # -> Abhängigkeit prüfen und evtl. erweitern
30 # createProductDependency('productId', 'action', '*requiredProductId', '*requiredProductClassId', '*requiredAction', '*requiredInstallationStatus', '*requirementType', '*depotIds')
32 #"opsi_del_product_from_client",
33 # -> Abhängigkeit prüfen und evtl. verweigern
34 # createProductDependency('productId', 'action', '*requiredProductId', '*requiredProductClassId', '*requiredAction', '*requiredInstallationStatus', '*requirementType', '*depotIds')
35 # -> delete nur wenn eine "uninstall" methode existiert
36 # -> set product state auf "none"
38 );
39 @EXPORT = @events;
41 use strict;
42 use warnings;
43 use Data::Dumper;
44 use GOSA::GosaSupportDaemon;
45 use JSON::RPC::Client;
46 use XML::Quote qw(:all);
48 BEGIN {}
50 END {}
52 ### Start ######################################################################
54 my $opsi_server;
55 my $opsi_admin;
56 my $opsi_password;
58 my %cfg_defaults = (
59 "opsi" => {
60 "server" => [\$opsi_server, "localhost"],
61 "admin" => [\$opsi_admin, "opsi-admin"],
62 "password" => [\$opsi_password, "secret"],
63 },
64 );
65 &read_configfile($main::cfg_file, %cfg_defaults);
67 # Assemble opsi URL
68 my $opsi_url= "https://".$opsi_admin.":".$opsi_password."@".$opsi_server.":4447/rpc";
69 my $client = new JSON::RPC::Client;
71 sub check_res {
72 my $res= shift;
73 # TODO: We need to return the outhash!?
74 my $out_hash;
76 if($res) {
77 if ($res->is_error) {
78 &main::daemon_log("ERROR: opsi configed communication failed: ".$res->error_message, 1);
79 &add_content2xml_hash($out_hash, "error", $res->error_message);
80 } else {
81 return 1;
82 }
83 } else {
84 &main::daemon_log("ERROR: opsi configed communication failed: ".$client->status_line, 1);
85 &add_content2xml_hash($out_hash, "error", $client->status_line);
86 }
88 return 0;
89 }
92 sub read_configfile {
93 my ($cfg_file, %cfg_defaults) = @_;
94 my $cfg;
96 if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
97 if( -r $cfg_file ) {
98 $cfg = Config::IniFiles->new( -file => $cfg_file );
99 } else {
100 &main::daemon_log("ERROR: opsi.pm couldn't read config file!", 1);
101 }
102 } else {
103 $cfg = Config::IniFiles->new() ;
104 }
105 foreach my $section (keys %cfg_defaults) {
106 foreach my $param (keys %{$cfg_defaults{ $section }}) {
107 my $pinfo = $cfg_defaults{ $section }{ $param };
108 ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
109 }
110 }
111 }
114 sub get_events { return \@events; }
117 sub opsi_get_netboot_products {
118 my ($msg, $msg_hash) = @_;
119 my $header = @{$msg_hash->{'header'}}[0];
120 my $source = @{$msg_hash->{'source'}}[0];
121 my $target = @{$msg_hash->{'target'}}[0];
122 my $session_id = @{$msg_hash->{'session_id'}}[0];
123 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
124 my $hostId;
126 # build return message with twisted target and source
127 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
128 &add_content2xml_hash($out_hash, "session_id", $session_id);
130 # Get hostID if defined
131 if (defined @{$msg_hash->{'hostId'}}[0]){
132 $hostId = @{$msg_hash->{'hostId'}}[0];
133 &add_content2xml_hash($out_hash, "hostId", $hostId);
134 }
136 if (defined $forward_to_gosa) {
137 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
138 }
139 &add_content2xml_hash($out_hash, "xxx", "");
140 my $xml_msg= &create_xml_string($out_hash);
142 # For hosts, only return the products that are or get installed
143 my $callobj;
144 $callobj = {
145 method => 'getNetBootProductIds_list',
146 params => [ ],
147 id => 1,
148 };
150 my $res = $client->call($opsi_url, $callobj);
151 my %r = ();
152 for (@{$res->result}) { $r{$_} = 1 }
154 if (check_res($res)){
156 if (defined $hostId){
157 $callobj = {
158 method => 'getProductStates_hash',
159 params => [ $hostId ],
160 id => 1,
161 };
163 my $hres = $client->call($opsi_url, $callobj);
164 if (check_res($hres)){
165 my $htmp= $hres->result->{$hostId};
167 # check state != not_installed or action == setup -> load and add
168 foreach my $product (@{$htmp}){
170 if (!defined ($r{$product->{'productId'}})){
171 next;
172 }
174 # Now we've a couple of hashes...
175 if ($product->{'installationStatus'} ne "not_installed" or
176 $product->{'actionRequest'} eq "setup"){
177 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
179 $callobj = {
180 method => 'getProduct_hash',
181 params => [ $product->{'productId'} ],
182 id => 1,
183 };
185 my $sres = $client->call($opsi_url, $callobj);
186 if (check_res($sres)){
187 my $tres= $sres->result;
189 my $name= xml_quote($tres->{'name'});
190 my $r= $product->{'productId'};
191 my $description= xml_quote($tres->{'description'});
192 $name=~ s/\//\\\//;
193 $description=~ s/\//\\\//;
194 $xml_msg=~ s/<xxx><\/xxx>/<item><ProductId>$r<\/ProductId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
195 }
197 }
198 }
200 }
202 } else {
203 foreach my $r (@{$res->result}) {
204 $callobj = {
205 method => 'getProduct_hash',
206 params => [ $r ],
207 id => 1,
208 };
210 my $sres = $client->call($opsi_url, $callobj);
211 if (check_res($sres)){
212 my $tres= $sres->result;
214 my $name= xml_quote($tres->{'name'});
215 my $description= xml_quote($tres->{'description'});
216 $name=~ s/\//\\\//;
217 $description=~ s/\//\\\//;
218 $xml_msg=~ s/<xxx><\/xxx>/<item><ProductId>$r<\/ProductId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
219 }
221 }
223 }
224 }
226 $xml_msg=~ s/<xxx><\/xxx>//;
228 return $xml_msg;
229 }
232 sub opsi_get_product_properties {
233 my ($msg, $msg_hash) = @_;
234 my $header = @{$msg_hash->{'header'}}[0];
235 my $source = @{$msg_hash->{'source'}}[0];
236 my $target = @{$msg_hash->{'target'}}[0];
237 my $session_id = @{$msg_hash->{'session_id'}}[0];
238 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
239 my $productId = @{$msg_hash->{'ProductId'}}[0];
240 my $hostId;
242 # build return message with twisted target and source
243 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
244 &add_content2xml_hash($out_hash, "session_id", $session_id);
246 # Get hostID if defined
247 if (defined @{$msg_hash->{'hostId'}}[0]){
248 $hostId = @{$msg_hash->{'hostId'}}[0];
249 &add_content2xml_hash($out_hash, "hostId", $hostId);
250 }
252 if (defined $forward_to_gosa) {
253 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
254 }
255 &add_content2xml_hash($out_hash, "ProducId", "$productId");
257 # Load actions
258 my $callobj = {
259 method => 'getPossibleProductActions_list',
260 params => [ $productId ],
261 id => 1,
262 };
263 my $res = $client->call($opsi_url, $callobj);
264 if (check_res($res)){
265 foreach my $action (@{$res->result}){
266 &add_content2xml_hash($out_hash, "action", $action);
267 }
268 }
270 # Add place holder
271 &add_content2xml_hash($out_hash, "xxx", "");
273 # Move to XML string
274 my $xml_msg= &create_xml_string($out_hash);
276 # JSON Query
277 $callobj = {
278 method => 'getProductProperties_hash',
279 params => [ $productId ],
280 id => 1,
281 };
283 $res = $client->call($opsi_url, $callobj);
285 if (check_res($res)){
286 my $r= $res->result;
287 foreach my $key (keys %{$r}) {
288 my $item= "<item>";
289 my $value= $r->{$key};
290 if (UNIVERSAL::isa( $value, "ARRAY" )){
291 foreach my $subval (@{$value}){
292 $item.= "<$key>".xml_quote($subval)."</$key>";
293 }
294 } else {
295 $item.= "<$key>".xml_quote($value)."</$key>";
296 }
297 $item.= "</item>";
298 $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
299 }
300 }
303 $xml_msg=~ s/<xxx><\/xxx>//;
305 return $xml_msg;
306 }
309 sub opsi_set_product_properties {
310 my ($msg, $msg_hash) = @_;
311 my $header = @{$msg_hash->{'header'}}[0];
312 my $source = @{$msg_hash->{'source'}}[0];
313 my $target = @{$msg_hash->{'target'}}[0];
314 my $session_id = @{$msg_hash->{'session_id'}}[0];
315 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
316 my $productId = @{$msg_hash->{'ProductId'}}[0];
317 my $hostId;
319 # build return message with twisted target and source
320 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
321 &add_content2xml_hash($out_hash, "session_id", $session_id);
322 &add_content2xml_hash($out_hash, "ProductId", $productId);
324 # Get hostID if defined
325 if (defined @{$msg_hash->{'hostId'}}[0]){
326 $hostId = @{$msg_hash->{'hostId'}}[0];
327 &add_content2xml_hash($out_hash, "hostId", $hostId);
328 }
330 # Set product states if requested
331 if (defined @{$msg_hash->{'action'}}[0]){
332 &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
333 }
334 if (defined @{$msg_hash->{'state'}}[0]){
335 &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
336 }
338 if (defined $forward_to_gosa) {
339 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
340 }
342 # Find properties
343 foreach my $item (@{$msg_hash->{'item'}}){
344 # JSON Query
345 my $callobj;
347 if (defined $hostId){
348 $callobj = {
349 method => 'setProductProperty',
350 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
351 id => 1,
352 };
353 } else {
354 $callobj = {
355 method => 'setProductProperty',
356 params => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
357 id => 1,
358 };
359 }
361 my $res = $client->call($opsi_url, $callobj);
363 if (!check_res($res)){
364 &main::daemon_log("ERROR: no communication failed while setting '".$item->{'name'}[0]."': ".$res->error_message, 1);
365 &add_content2xml_hash($out_hash, "error", $res->error_message);
366 }
368 }
370 # return message
371 return &create_xml_string($out_hash);
372 }
375 sub opsi_get_client_hardware {
376 my ($msg, $msg_hash) = @_;
377 my $header = @{$msg_hash->{'header'}}[0];
378 my $source = @{$msg_hash->{'source'}}[0];
379 my $target = @{$msg_hash->{'target'}}[0];
380 my $session_id = @{$msg_hash->{'session_id'}}[0];
381 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
382 my $hostId = @{$msg_hash->{'hostId'}}[0];
384 # build return message with twisted target and source
385 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
386 &add_content2xml_hash($out_hash, "session_id", $session_id);
388 if (defined $forward_to_gosa) {
389 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
390 }
391 &add_content2xml_hash($out_hash, "hostId", "$hostId");
392 &add_content2xml_hash($out_hash, "xxx", "");
393 my $xml_msg= &create_xml_string($out_hash);
395 # JSON Query
396 my $callobj = {
397 method => 'getHardwareInformation_hash',
398 params => [ $hostId ],
399 id => 1,
400 };
402 my $res = $client->call($opsi_url, $callobj);
403 if (check_res($res)){
404 my $result= $res->result;
405 foreach my $r (keys %{$result}){
406 my $item= "<item><id>".xml_quote($r)."</id>";
407 my $value= $result->{$r};
408 foreach my $sres (@{$value}){
410 foreach my $dres (keys %{$sres}){
411 if (defined $sres->{$dres}){
412 $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
413 }
414 }
416 }
417 $item.= "</item>";
418 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
420 }
421 }
423 $xml_msg=~ s/<xxx><\/xxx>//;
425 return $xml_msg;
426 }
429 sub opsi_list_clients {
430 my ($msg, $msg_hash) = @_;
431 my $header = @{$msg_hash->{'header'}}[0];
432 my $source = @{$msg_hash->{'source'}}[0];
433 my $target = @{$msg_hash->{'target'}}[0];
434 my $session_id = @{$msg_hash->{'session_id'}}[0];
435 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
437 # build return message with twisted target and source
438 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
439 &add_content2xml_hash($out_hash, "session_id", $session_id);
441 if (defined $forward_to_gosa) {
442 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
443 }
445 &add_content2xml_hash($out_hash, "xxx", "");
446 my $xml_msg= &create_xml_string($out_hash);
448 # JSON Query
449 my $callobj = {
450 method => 'getClients_listOfHashes',
451 params => [ ],
452 id => 1,
453 };
455 my $res = $client->call($opsi_url, $callobj);
456 if (check_res($res)){
458 foreach my $host (@{$res->result}){
459 my $item= "<item><name>".$host->{'hostId'}."</name>";
460 if (defined($host->{'description'})){
461 $item.= "<description>".xml_quote($host->{'description'})."</description>";
462 }
463 $item.= "</item>";
464 $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
465 }
467 }
469 $xml_msg=~ s/<xxx><\/xxx>//;
470 return $xml_msg;
471 }
474 sub opsi_get_client_software {
475 my ($msg, $msg_hash) = @_;
476 my $header = @{$msg_hash->{'header'}}[0];
477 my $source = @{$msg_hash->{'source'}}[0];
478 my $target = @{$msg_hash->{'target'}}[0];
479 my $session_id = @{$msg_hash->{'session_id'}}[0];
480 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
481 my $hostId = @{$msg_hash->{'hostId'}}[0];
483 # build return message with twisted target and source
484 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
485 &add_content2xml_hash($out_hash, "session_id", $session_id);
487 if (defined $forward_to_gosa) {
488 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
489 }
490 &add_content2xml_hash($out_hash, "hostId", "$hostId");
491 &add_content2xml_hash($out_hash, "xxx", "");
492 my $xml_msg= &create_xml_string($out_hash);
494 # JSON Query
495 my $callobj = {
496 method => 'getSoftwareInformation_hash',
497 params => [ $hostId ],
498 id => 1,
499 };
501 my $res = $client->call($opsi_url, $callobj);
502 if (check_res($res)){
503 my $result= $res->result;
504 }
506 $xml_msg=~ s/<xxx><\/xxx>//;
508 return $xml_msg;
509 }
512 sub opsi_get_local_products {
513 my ($msg, $msg_hash) = @_;
514 my $header = @{$msg_hash->{'header'}}[0];
515 my $source = @{$msg_hash->{'source'}}[0];
516 my $target = @{$msg_hash->{'target'}}[0];
517 my $session_id = @{$msg_hash->{'session_id'}}[0];
518 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
519 my $hostId;
521 # build return message with twisted target and source
522 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
523 &add_content2xml_hash($out_hash, "session_id", $session_id);
525 # Get hostID if defined
526 if (defined @{$msg_hash->{'hostId'}}[0]){
527 $hostId = @{$msg_hash->{'hostId'}}[0];
528 &add_content2xml_hash($out_hash, "hostId", $hostId);
529 }
531 if (defined $forward_to_gosa) {
532 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
533 }
534 &add_content2xml_hash($out_hash, "xxx", "");
535 my $xml_msg= &create_xml_string($out_hash);
537 # For hosts, only return the products that are or get installed
538 my $callobj;
539 $callobj = {
540 method => 'getLocalBootProductIds_list',
541 params => [ ],
542 id => 1,
543 };
545 my $res = $client->call($opsi_url, $callobj);
546 my %r = ();
547 for (@{$res->result}) { $r{$_} = 1 }
549 if (check_res($res)){
551 if (defined $hostId){
552 $callobj = {
553 method => 'getProductStates_hash',
554 params => [ $hostId ],
555 id => 1,
556 };
558 my $hres = $client->call($opsi_url, $callobj);
559 if (check_res($hres)){
560 my $htmp= $hres->result->{$hostId};
562 # check state != not_installed or action == setup -> load and add
563 foreach my $product (@{$htmp}){
565 if (!defined ($r{$product->{'productId'}})){
566 next;
567 }
569 # Now we've a couple of hashes...
570 if ($product->{'installationStatus'} ne "not_installed" or
571 $product->{'actionRequest'} eq "setup"){
572 my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
574 $callobj = {
575 method => 'getProduct_hash',
576 params => [ $product->{'productId'} ],
577 id => 1,
578 };
580 my $sres = $client->call($opsi_url, $callobj);
581 if (check_res($sres)){
582 my $tres= $sres->result;
584 my $name= xml_quote($tres->{'name'});
585 my $r= $product->{'productId'};
586 my $description= xml_quote($tres->{'description'});
587 $name=~ s/\//\\\//;
588 $description=~ s/\//\\\//;
589 $xml_msg=~ s/<xxx><\/xxx>/<item><ProductId>$r<\/ProductId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
590 }
592 }
593 }
595 }
597 } else {
598 foreach my $r (@{$res->result}) {
599 $callobj = {
600 method => 'getProduct_hash',
601 params => [ $r ],
602 id => 1,
603 };
605 my $sres = $client->call($opsi_url, $callobj);
606 if (check_res($sres)){
607 my $tres= $sres->result;
609 my $name= xml_quote($tres->{'name'});
610 my $description= xml_quote($tres->{'description'});
611 $name=~ s/\//\\\//;
612 $description=~ s/\//\\\//;
613 $xml_msg=~ s/<xxx><\/xxx>/<item><ProductId>$r<\/ProductId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
614 }
616 }
618 }
619 }
621 $xml_msg=~ s/<xxx><\/xxx>//;
623 return $xml_msg;
624 }
627 sub _opsi_get_client_status {
628 my $hostId = shift;
629 my $result= {};
631 # For hosts, only return the products that are or get installed
632 my $callobj;
633 $callobj = {
634 method => 'getProductStates_hash',
635 params => [ $hostId ],
636 id => 1,
637 };
639 my $hres = $client->call($opsi_url, $callobj);
640 if (check_res($hres)){
641 my $htmp= $hres->result->{$hostId};
643 # check state != not_installed or action == setup -> load and add
644 my $products= 0;
645 my $installed= 0;
646 my $error= 0;
647 foreach my $product (@{$htmp}){
649 if ($product->{'installationStatus'} ne "not_installed" or
650 $product->{'actionRequest'} eq "setup"){
652 # Increase number of products for this host
653 $products++;
655 if ($product->{'installationStatus'} eq "failed"){
656 $result->{$product->{'productId'}}= "error";
657 $error++;
658 }
659 if ($product->{'installationStatus'} eq "installed"){
660 $result->{$product->{'productId'}}= "installed";
661 $installed++;
662 }
663 if ($product->{'installationStatus'} eq "installing"){
664 $result->{$product->{'productId'}}= "installing";
665 }
666 }
667 }
669 # Estimate "rough" progress
670 $result->{'progress'}= int($installed * 100 / $products);
671 }
673 return $result;
674 }
677 sub opsi_del_client {
678 my ($msg, $msg_hash) = @_;
679 my $header = @{$msg_hash->{'header'}}[0];
680 my $source = @{$msg_hash->{'source'}}[0];
681 my $target = @{$msg_hash->{'target'}}[0];
682 my $session_id = @{$msg_hash->{'session_id'}}[0];
683 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
684 my $hostId = @{$msg_hash->{'hostId'}}[0];
686 # build return message with twisted target and source
687 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
688 &add_content2xml_hash($out_hash, "session_id", $session_id);
690 if (defined $forward_to_gosa) {
691 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
692 }
693 &add_content2xml_hash($out_hash, "hostId", "$hostId");
695 # JSON Query
696 my $callobj = {
697 method => 'deleteClient',
698 params => [ $hostId ],
699 id => 1,
700 };
702 my $res = $client->call($opsi_url, $callobj);
704 my $xml_msg= &create_xml_string($out_hash);
705 return $xml_msg;
706 }
709 # Setze alles was auf "installed" steht auf setup
710 sub opsi_install_client {
711 my ($msg, $msg_hash) = @_;
712 my $header = @{$msg_hash->{'header'}}[0];
713 my $source = @{$msg_hash->{'source'}}[0];
714 my $target = @{$msg_hash->{'target'}}[0];
715 my $session_id = @{$msg_hash->{'session_id'}}[0];
716 my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
717 my $hostId = @{$msg_hash->{'hostId'}}[0];
719 # build return message with twisted target and source
720 my $out_hash = &main::create_xml_hash("answer_$header", $target, $source);
721 &add_content2xml_hash($out_hash, "session_id", $session_id);
723 if (defined $forward_to_gosa) {
724 &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
725 }
726 &add_content2xml_hash($out_hash, "hostId", "$hostId");
728 # Schaue nach produkten für diesen Host
729 # Setze alle Produkte dieses Hosts auf "setup"
731 # # JSON Query
732 # my $callobj = {
733 # method => 'deleteClient',
734 # params => [ $hostId ],
735 # id => 1,
736 # };
737 #
738 # my $res = $client->call($opsi_url, $callobj);
740 my $xml_msg= &create_xml_string($out_hash);
741 return $xml_msg;
742 }
745 sub _set_action {
746 my $product= shift;
747 my $action = shift;
748 my $hostId = shift;
749 my $callobj;
751 $callobj = {
752 method => 'setProductActionRequest',
753 params => [ $product, $hostId, $action],
754 id => 1,
755 };
757 $client->call($opsi_url, $callobj);
758 }
761 sub _set_state {
762 my $product = shift;
763 my $hostId = shift;
764 my $action = shift;
765 my $callobj;
767 $callobj = {
768 method => 'setProductState',
769 params => [ $product, $hostId, $action ],
770 id => 1,
771 };
773 $client->call($opsi_url, $callobj);
774 }
776 1;