Code

update: opsi_com complete with sanity checks and doxygen lines
authorrettenbe <rettenbe@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 7 Aug 2008 13:52:12 +0000 (13:52 +0000)
committerrettenbe <rettenbe@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 7 Aug 2008 13:52:12 +0000 (13:52 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@12178 594d385d-05f5-0310-b6e9-bd551577e9d8

gosa-si/server/events/opsi_com.pm
gosa-si/tests/client.php

index 10778ca23094528726871708877a396758b406ce..0e620426305f55f6174d05380df51e889b28858e 100644 (file)
@@ -297,453 +297,561 @@ sub opsi_add_client {
     return ( &create_xml_string($out_hash) );
 }
 
-## @method 
-# ???
-# @param msg - STRING - xml message with tag hostId
+## @method opsi_modify_client
+# Modifies the parameters description, mac or notes for an Opsi client if the corresponding message tags are given.
+# @param msg - STRING - xml message with tag hostId and optional description, mac or notes
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message    
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_modify_client {
-  my ($msg, $msg_hash, $session_id) = @_;
-  my $header = @{$msg_hash->{'header'}}[0];
-  my $source = @{$msg_hash->{'source'}}[0];
-  my $target = @{$msg_hash->{'target'}}[0];
-  my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-  my $hostId;
-
-  # build return message with twisted target and source
-  my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-  if (defined $forward_to_gosa) {
-    &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
-  }
-
-  # Get hostID
-  $hostId = @{$msg_hash->{'hostId'}}[0];
-  &add_content2xml_hash($out_hash, "hostId", $hostId);
-  my $name= $hostId;
-  $name=~ s/^([^.]+).*$/$1/;
-  my $domain= $hostId;
-  $domain=~ s/^[^.]+(.*)$/$1/;
-  my ($description, $notes, $ip, $mac);
-
-  my $callobj;
+    my ($msg, $msg_hash, $session_id) = @_;
+    my $header = @{$msg_hash->{'header'}}[0];
+    my $source = @{$msg_hash->{'source'}}[0];
+    my $target = @{$msg_hash->{'target'}}[0];
+    my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
+    my $hostId;
+    my $error = 0;
+    my ($sres, $sres_err, $sres_err_string);
 
-  if (defined @{$msg_hash->{'description'}}[0]){
-    $description = @{$msg_hash->{'description'}}[0];
-    $callobj = {
-      method  => 'setHostDescription',
-      params  => [ $hostId, $description ],
-      id  => 1,
-    };
-    my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-    my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
-    if ($sres_err){
-      &main::daemon_log("ERROR: cannot set description: ".$sres_err_string, 1);
-      &add_content2xml_hash($out_hash, "error", $sres_err_string);
-      return ( &create_xml_string($out_hash) );
+    # Build return message with twisted target and source
+    my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
+    if (defined $forward_to_gosa) {
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-  }
-  if (defined @{$msg_hash->{'notes'}}[0]){
-    $notes = @{$msg_hash->{'notes'}}[0];
-    $callobj = {
-      method  => 'setHostNotes',
-      params  => [ $hostId, $notes ],
-      id  => 1,
-    };
-    my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-    my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
-    if ($sres_err){
-      &main::daemon_log("ERROR: cannot set notes: ".$sres_err_string, 1);
-      &add_content2xml_hash($out_hash, "error", $sres_err_string);
-      return ( &create_xml_string($out_hash) );
+
+    # Sanity check of needed parameter
+    if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1); 
     }
-  }
-  if (defined @{$msg_hash->{'mac'}}[0]){
-    $mac = @{$msg_hash->{'mac'}}[0];
-    $callobj = {
-      method  => 'setMacAddress',
-      params  => [ $hostId, $mac ],
-      id  => 1,
-    };
-    my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-    my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
-    if ($sres_err){
-      &main::daemon_log("ERROR: cannot set mac address: ".$sres_err_string, 1);
-      &add_content2xml_hash($out_hash, "error", $sres_err_string);
-      return ( &create_xml_string($out_hash) );
+
+    if (not $error) {
+        # Get hostID
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", $hostId);
+        my $name= $hostId;
+        $name=~ s/^([^.]+).*$/$1/;
+        my $domain= $hostId;
+        $domain=~ s/^[^.]+(.*)$/$1/;
+
+        # Modify description, notes or mac if defined
+        my ($description, $notes, $mac);
+        my $callobj;
+        if ((exists $msg_hash->{'description'}) && (@{$msg_hash->{'description'}} == 1) ){
+            $description = @{$msg_hash->{'description'}}[0];
+            $callobj = {
+                method  => 'setHostDescription',
+                params  => [ $hostId, $description ],
+                id  => 1,
+            };
+            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+            my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
+            if ($sres_err){
+                &main::daemon_log("ERROR: cannot set description: ".$sres_err_string, 1);
+                &add_content2xml_hash($out_hash, "error", $sres_err_string);
+            }
+        }
+        if ((exists $msg_hash->{'notes'}) && (@{$msg_hash->{'notes'}} == 1)) {
+            $notes = @{$msg_hash->{'notes'}}[0];
+            $callobj = {
+                method  => 'setHostNotes',
+                params  => [ $hostId, $notes ],
+                id  => 1,
+            };
+            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+            my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
+            if ($sres_err){
+                &main::daemon_log("ERROR: cannot set notes: ".$sres_err_string, 1);
+                &add_content2xml_hash($out_hash, "error", $sres_err_string);
+            }
+        }
+        if ((exists $msg_hash->{'mac'}) && (@{$msg_hash->{'mac'}} == 1)){
+            $mac = @{$msg_hash->{'mac'}}[0];
+            $callobj = {
+                method  => 'setMacAddress',
+                params  => [ $hostId, $mac ],
+                id  => 1,
+            };
+            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+            my ($sres_err, $sres_err_string) = &check_opsi_res($sres);
+            if ($sres_err){
+                &main::daemon_log("ERROR: cannot set mac address: ".$sres_err_string, 1);
+                &add_content2xml_hash($out_hash, "error", $sres_err_string);
+            }
+        }
     }
-  }
-  
-  # return message
-  return ( &create_xml_string($out_hash) );
+
+    # Return message
+    return ( &create_xml_string($out_hash) );
 }
 
     
 ## @method opsi_get_netboot_products
-# ???
+# Get netboot products for specific host.
 # @param msg - STRING - xml message with tag hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_get_netboot_products {
-  my ($msg, $msg_hash, $session_id) = @_;
-  my $header = @{$msg_hash->{'header'}}[0];
-  my $source = @{$msg_hash->{'source'}}[0];
-  my $target = @{$msg_hash->{'target'}}[0];
-  my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-  my $hostId;
-
-  # build return message with twisted target and source
-  my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-  if (defined $forward_to_gosa) {
-    &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
-  }
-
-  # Get hostID if defined
-  if (defined @{$msg_hash->{'hostId'}}[0]){
-    $hostId = @{$msg_hash->{'hostId'}}[0];
-    &add_content2xml_hash($out_hash, "hostId", $hostId);
-  }
-
-  &add_content2xml_hash($out_hash, "xxx", "");
-  my $xml_msg= &create_xml_string($out_hash);
-
-  # For hosts, only return the products that are or get installed
-  my $callobj;
-  $callobj = {
-    method  => 'getNetBootProductIds_list',
-    params  => [ ],
-    id  => 1,
-  };
+    my ($msg, $msg_hash, $session_id) = @_;
+    my $header = @{$msg_hash->{'header'}}[0];
+    my $source = @{$msg_hash->{'source'}}[0];
+    my $target = @{$msg_hash->{'target'}}[0];
+    my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
+    my $hostId;
+    my $error = 0;
+    my $xml_msg;
 
-  my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-  my %r = ();
-  for (@{$res->result}) { $r{$_} = 1 }
+    # Build return message with twisted target and source
+    my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
+    if (defined $forward_to_gosa) {
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
+    }
 
-  if (&check_opsi_res($res)){
+    # Sanity check of needed parameter
+    if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1); 
+    }
 
-    if (defined $hostId){
-      $callobj = {
-        method  => 'getProductStates_hash',
-        params  => [ $hostId ],
-        id  => 1,
-      };
+    if (not $error) {
 
-      my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
-      if (&check_opsi_res($hres)){
-        my $htmp= $hres->result->{$hostId};
+        # Get hostID if defined
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", $hostId);
 
-        # check state != not_installed or action == setup -> load and add
-        foreach my $product (@{$htmp}){
+        &add_content2xml_hash($out_hash, "xxx", "");
+        $xml_msg= &create_xml_string($out_hash);
 
-          if (!defined ($r{$product->{'productId'}})){
-            next;
-          }
+        # For hosts, only return the products that are or get installed
+        my $callobj;
+        $callobj = {
+            method  => 'getNetBootProductIds_list',
+            params  => [ ],
+            id  => 1,
+        };
 
-          # Now we've a couple of hashes...
-          if ($product->{'installationStatus'} ne "not_installed" or
-              $product->{'actionRequest'} eq "setup"){
-            my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        my %r = ();
+        for (@{$res->result}) { $r{$_} = 1 }
 
-            $callobj = {
-              method  => 'getProduct_hash',
-              params  => [ $product->{'productId'} ],
-              id  => 1,
-            };
+        if (not &check_opsi_res($res)){
 
-            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-            if (&check_opsi_res($sres)){
-              my $tres= $sres->result;
-
-              my $name= xml_quote($tres->{'name'});
-              my $r= $product->{'productId'};
-              my $description= xml_quote($tres->{'description'});
-              $name=~ s/\//\\\//;
-              $description=~ s/\//\\\//;
-              $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
-            }
+            if (defined $hostId){
+                $callobj = {
+                    method  => 'getProductStates_hash',
+                    params  => [ $hostId ],
+                    id  => 1,
+                };
 
-          }
-        }
+                my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
+                if (not &check_opsi_res($hres)){
+                    my $htmp= $hres->result->{$hostId};
 
-      }
+                    # check state != not_installed or action == setup -> load and add
+                    foreach my $product (@{$htmp}){
 
-    } else {
-      foreach my $r (@{$res->result}) {
-        $callobj = {
-          method  => 'getProduct_hash',
-          params  => [ $r ],
-          id  => 1,
-        };
+                        if (!defined ($r{$product->{'productId'}})){
+                            next;
+                        }
 
-        my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-        if (&check_opsi_res($sres)){
-          my $tres= $sres->result;
-
-          my $name= xml_quote($tres->{'name'});
-          my $description= xml_quote($tres->{'description'});
-          $name=~ s/\//\\\//;
-          $description=~ s/\//\\\//;
-          $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
-        }
+                        # Now we've a couple of hashes...
+                        if ($product->{'installationStatus'} ne "not_installed" or
+                                $product->{'actionRequest'} eq "setup"){
+                            my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
+
+                            $callobj = {
+                                method  => 'getProduct_hash',
+                                params  => [ $product->{'productId'} ],
+                                id  => 1,
+                            };
+
+                            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+                            if (not &check_opsi_res($sres)){
+                                my $tres= $sres->result;
+
+                                my $name= xml_quote($tres->{'name'});
+                                my $r= $product->{'productId'};
+                                my $description= xml_quote($tres->{'description'});
+                                $name=~ s/\//\\\//;
+                                $description=~ s/\//\\\//;
+                                $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
+                            }
+                        }
+                    }
 
-      }
+                }
 
-    }
-  }
+            } else {
+                foreach my $r (@{$res->result}) {
+                    $callobj = {
+                        method  => 'getProduct_hash',
+                        params  => [ $r ],
+                        id  => 1,
+                    };
+
+                    my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+                    if (not &check_opsi_res($sres)){
+                        my $tres= $sres->result;
+
+                        my $name= xml_quote($tres->{'name'});
+                        my $description= xml_quote($tres->{'description'});
+                        $name=~ s/\//\\\//;
+                        $description=~ s/\//\\\//;
+                        $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
+                    }
+                }
 
-  $xml_msg=~ s/<xxx><\/xxx>//;
+            }
+        }
+        $xml_msg=~ s/<xxx><\/xxx>//;
+    }
 
-  return ($xml_msg);
+    # Return message
+    return ( $xml_msg );
 }
 
 
 ## @method opsi_get_product_properties
-# ???
-# @param msg - STRING - xml message with tags ProductId and hostId
+# Get product properties for a product and a specific host or gobally for a product.
+# @param msg - STRING - xml message with tags productId and optional hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_get_product_properties {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $productId = @{$msg_hash->{'productId'}}[0];
-    my $hostId;
+    my ($hostId, $productId);
+    my $error = 0;
+    my $xml_msg;
 
     # build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
-    # Get hostID if defined
-    if (defined @{$msg_hash->{'hostId'}}[0]){
-      $hostId = @{$msg_hash->{'hostId'}}[0];
-      &add_content2xml_hash($out_hash, "hostId", $hostId);
-    }
-
     if (defined $forward_to_gosa) {
-      &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-    &add_content2xml_hash($out_hash, "ProducId", "$productId");
 
-    # Load actions
-    my $callobj = {
-      method  => 'getPossibleProductActions_list',
-      params  => [ $productId ],
-      id  => 1,
-    };
-    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-    if (&check_opsi_res($res)){
-      foreach my $action (@{$res->result}){
-        &add_content2xml_hash($out_hash, "action", $action);
-      }
+    # Sanity check of needed parameter
+    if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
+        &add_content2xml_hash($out_hash, "error", "productId");
+        &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1); 
     }
 
-    # Add place holder
-    &add_content2xml_hash($out_hash, "xxx", "");
+    if (not $error) {
 
-    # Move to XML string
-    my $xml_msg= &create_xml_string($out_hash);
+        # Get productid
+        $productId = @{$msg_hash->{'productId'}}[0];
+        &add_content2xml_hash($out_hash, "producId", "$productId");
 
-    # JSON Query
-    $callobj = {
-      method  => 'getProductProperties_hash',
-      params  => [ $productId ],
-      id  => 1,
-    };
 
-    $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", $hostId);
 
-    if (&check_opsi_res($res)){
-        my $r= $res->result;
-        foreach my $key (keys %{$r}) {
-          my $item= "<item>";
-          my $value= $r->{$key};
-          if (UNIVERSAL::isa( $value, "ARRAY" )){
-            foreach my $subval (@{$value}){
-              $item.= "<$key>".xml_quote($subval)."</$key>";
+        # Load actions
+        my $callobj = {
+            method  => 'getPossibleProductActions_list',
+            params  => [ $productId ],
+            id  => 1,
+        };
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($res)){
+            foreach my $action (@{$res->result}){
+                &add_content2xml_hash($out_hash, "action", $action);
             }
-          } else {
-            $item.= "<$key>".xml_quote($value)."</$key>";
-          }
-          $item.= "</item>";
-          $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
         }
+
+        # Add place holder
+        &add_content2xml_hash($out_hash, "xxx", "");
+
     }
 
+    # Move to XML string
+    $xml_msg= &create_xml_string($out_hash);
 
-  $xml_msg=~ s/<xxx><\/xxx>//;
+    if (not $error) {
 
-  return ($xml_msg);
+        # JSON Query
+        my $callobj = {
+            method  => 'getProductProperties_hash',
+            params  => [ $productId ],
+            id  => 1,
+        };
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($res)){
+            my $r= $res->result;
+            foreach my $key (keys %{$r}) {
+                my $item= "<item>";
+                my $value= $r->{$key};
+                if (UNIVERSAL::isa( $value, "ARRAY" )){
+                    foreach my $subval (@{$value}){
+                        $item.= "<$key>".xml_quote($subval)."</$key>";
+                    }
+                } else {
+                    $item.= "<$key>".xml_quote($value)."</$key>";
+                }
+                $item.= "</item>";
+                $xml_msg=~ s/<xxx><\/xxx>/$item<xxx><\/xxx>/;
+            }
+        }
+
+        $xml_msg=~ s/<xxx><\/xxx>//;
+    }
+
+    # Return message
+    return ( $xml_msg );
 }
 
 
 ## @method opsi_set_product_properties
-# ???
-# @param msg - STRING - xml message with tags ProductId, hostId, action and state
+# 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.
+# @param msg - STRING - xml message with tags productId, action, state and optional hostId, action and state
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_set_product_properties {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $productId = @{$msg_hash->{'productId'}}[0];
-    my $hostId;
+    my ($productId, $hostId);
+    my $error = 0;
 
-    # build return message with twisted target and source
+    # Build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-    &add_content2xml_hash($out_hash, "productId", $productId);
-
-    # Get hostID if defined
-    if (defined @{$msg_hash->{'hostId'}}[0]){
-      $hostId = @{$msg_hash->{'hostId'}}[0];
-      &add_content2xml_hash($out_hash, "hostId", $hostId);
+    if (defined $forward_to_gosa) {
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
 
-    # Set product states if requested
-    if (defined @{$msg_hash->{'action'}}[0]){
-      &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
+    # Sanity check of needed parameter
+    if ((not exists $msg_hash->{'productId'}) || (@{$msg_hash->{'productId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "productId_error", "no productId specified or productId tag invalid");
+        &add_content2xml_hash($out_hash, "error", "productId");
+        &main::daemon_log("$session_id ERROR: no productId specified or productId tag invalid: $msg", 1); 
     }
-    if (defined @{$msg_hash->{'state'}}[0]){
-      &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
+    if ((not exists $msg_hash->{'item'}) || (@{$msg_hash->{'item'}}[0] != 1)) {
+        $error++;
+        &add_content2xml_hash($out_hash, "item_error", "message needs one xml-tag 'item' and within the xml-tags 'name' and 'value'");
+        &add_content2xml_hash($out_hash, "error", "item");
+        &main::daemon_log("$session_id ERROR: message needs one xml-tag 'item' and within the xml-tags 'name' and 'value': $msg", 1); 
+    } else {
+        if ((not exists $msg_hash->{'item'}->{'name'}) || (@{$msg_hash->{'item'}->{'name'}}[0] != 1)) {
+            $error++;
+            &add_content2xml_hash($out_hash, "name_error", "message needs within the xml-tag 'item' one xml-tags 'name'");
+            &add_content2xml_hash($out_hash, "error", "name");
+            &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'name': $msg", 1); 
+        }
+        if ((not exists $msg_hash->{'item'}->{'value'}) || (@{$msg_hash->{'item'}->{'value'}}[0] != 1)) {
+            $error++;
+            &add_content2xml_hash($out_hash, "value_error", "message needs within the xml-tag 'item' one xml-tags 'value'");
+            &add_content2xml_hash($out_hash, "error", "value");
+            &main::daemon_log("$session_id ERROR: message needs within the xml-tag 'item' one xml-tags 'value': $msg", 1); 
+        }
     }
-
-    if (defined $forward_to_gosa) {
-        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
+    if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
     }
 
-    # Find properties
-    foreach my $item (@{$msg_hash->{'item'}}){
-      # JSON Query
-      my $callobj;
+    if (not $error) {
+        
+    # Get productId
+        $productId =  @{$msg_hash->{'productId'}}[0];
+        &add_content2xml_hash($out_hash, "productId", $productId);
 
-      if (defined $hostId){
-        $callobj = {
-          method  => 'setProductProperty',
-          params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
-          id  => 1,
-        };
-      } else {
-        $callobj = {
-          method  => 'setProductProperty',
-          params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
-          id  => 1,
-        };
-      }
+    # Get hostID if defined
+        if (exists $msg_hash->{'hostId'}){
+            $hostId = @{$msg_hash->{'hostId'}}[0];
+            &add_content2xml_hash($out_hash, "hostId", $hostId);
+        }
+
+    # Set product states if requested
+        if (defined @{$msg_hash->{'action'}}[0]){
+            &_set_action($productId, @{$msg_hash->{'action'}}[0], $hostId);
+        }
+        if (defined @{$msg_hash->{'state'}}[0]){
+            &_set_state($productId, @{$msg_hash->{'state'}}[0], $hostId);
+        }
+
+    # Find properties
+        foreach my $item (@{$msg_hash->{'item'}}){
+            # JSON Query
+            my $callobj;
+
+            if (defined $hostId){
+                $callobj = {
+                    method  => 'setProductProperty',
+                    params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0], $hostId ],
+                    id  => 1,
+                };
+            } else {
+                $callobj = {
+                    method  => 'setProductProperty',
+                    params  => [ $productId, $item->{'name'}[0], $item->{'value'}[0] ],
+                    id  => 1,
+                };
+            }
 
-      my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-      my ($res_err, $res_err_string) = &check_opsi_res($res);
+            my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+            my ($res_err, $res_err_string) = &check_opsi_res($res);
 # TODO : This error message sounds strange
-      if ($res_err){
-        &man::daemon_log("$session_id ERROR: no communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
-        &add_content2xml_hash($out_hash, "error", $res_err_string);
-      }
+            if ($res_err){
+                &man::daemon_log("$session_id ERROR: no communication failed while setting '".$item->{'name'}[0]."': ".$res_err_string, 1);
+                &add_content2xml_hash($out_hash, "error", $res_err_string);
+            }
+        }
 
     }
 
-    # return message
+    # Return message
     return ( &create_xml_string($out_hash) );
 }
 
 
 ## @method opsi_get_client_hardware
-# ???
+# Reports client hardware inventory.
 # @param msg - STRING - xml message with tag hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_get_client_hardware {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $hostId = @{$msg_hash->{'hostId'}}[0];
+    my $hostId;
+    my $error = 0;
+    my $xml_msg;
 
     # build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
     if (defined $forward_to_gosa) {
       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-    &add_content2xml_hash($out_hash, "hostId", "$hostId");
-    &add_content2xml_hash($out_hash, "xxx", "");
-    my $xml_msg= &create_xml_string($out_hash);
+
+    # Sanity check of needed parameter
+    if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
+    }
+
+    if (not $error) {
+
+    # Get hostID
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", "$hostId");
+        &add_content2xml_hash($out_hash, "xxx", "");
+    }    
+
+    # Move to XML string
+    $xml_msg= &create_xml_string($out_hash);
+    
+    if (not $error) {
 
     # JSON Query
-    my $callobj = {
-      method  => 'getHardwareInformation_hash',
-      params  => [ $hostId ],
-      id  => 1,
-    };
+        my $callobj = {
+            method  => 'getHardwareInformation_hash',
+            params  => [ $hostId ],
+            id  => 1,
+        };
 
-    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-    if (&check_opsi_res($res)){
-      my $result= $res->result;
-      foreach my $r (keys %{$result}){
-        my $item= "<item><id>".xml_quote($r)."</id>";
-        my $value= $result->{$r};
-        foreach my $sres (@{$value}){
-
-          foreach my $dres (keys %{$sres}){
-            if (defined $sres->{$dres}){
-              $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
-            }
-          }
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($res)){
+            my $result= $res->result;
+            foreach my $r (keys %{$result}){
+                my $item= "<item><id>".xml_quote($r)."</id>";
+                my $value= $result->{$r};
+                foreach my $sres (@{$value}){
+
+                    foreach my $dres (keys %{$sres}){
+                        if (defined $sres->{$dres}){
+                            $item.= "<$dres>".xml_quote($sres->{$dres})."</$dres>";
+                        }
+                    }
 
+                }
+                $item.= "</item>";
+                $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
+
+            }
         }
-          $item.= "</item>";
-          $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
 
-      }
-    }
+        $xml_msg=~ s/<xxx><\/xxx>//;
 
-    $xml_msg=~ s/<xxx><\/xxx>//;
+    }
 
+    # Return message
     return ( $xml_msg );
 }
 
 
 ## @method opsi_list_clients
-# ???
+# Reports all Opsi clients. 
 # @param msg - STRING - xml message 
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_list_clients {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
+    my $error = 0;
 
     # build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
     if (defined $forward_to_gosa) {
       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-
     &add_content2xml_hash($out_hash, "xxx", "");
-    my $xml_msg= &create_xml_string($out_hash);
 
-    # JSON Query
-    my $callobj = {
-      method  => 'getClients_listOfHashes',
-      params  => [ ],
-      id  => 1,
-    };
+    # Move to XML string
+    my $xml_msg= &create_xml_string($out_hash);
 
-    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-    if (&check_opsi_res($res)){
+    if (not $error) {
 
-      foreach my $host (@{$res->result}){
-        my $item= "<item><name>".$host->{'hostId'}."</name>";
-        if (defined($host->{'description'})){
-          $item.= "<description>".xml_quote($host->{'description'})."</description>";
+    # JSON Query
+        my $callobj = {
+            method  => 'getClients_listOfHashes',
+            params  => [ ],
+            id  => 1,
+        };
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($res)){
+            foreach my $host (@{$res->result}){
+                my $item= "<item><name>".$host->{'hostId'}."</name>";
+                if (defined($host->{'description'})){
+                    $item.= "<description>".xml_quote($host->{'description'})."</description>";
+                }
+                if (defined($host->{'ip'})){
+                    $item.= "<ip>".xml_quote($host->{'ip'})."</ip>";
+                }
+                if (defined($host->{'mac'})){
+                    $item.= "<mac>".xml_quote($host->{'mac'})."</mac>";
+                }
+                if (defined($host->{'notes'})){
+                    $item.= "<notes>".xml_quote($host->{'notes'})."</notes>";
+                }
+                $item.= "</item>";
+                $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
+            }
         }
-        $item.= "</item>";
-        $xml_msg=~ s%<xxx></xxx>%$item<xxx></xxx>%;
-      }
-
     }
 
     $xml_msg=~ s/<xxx><\/xxx>//;
@@ -752,301 +860,357 @@ sub opsi_list_clients {
 
 
 ## @method opsi_get_client_software
-# ???
+# Reports client software inventory.
 # @param msg - STRING - xml message with tag hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_get_client_software {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $hostId = @{$msg_hash->{'hostId'}}[0];
+    my $error = 0;
+    my $hostId;
+    my $xml_msg;
 
     # build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
     if (defined $forward_to_gosa) {
       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-    &add_content2xml_hash($out_hash, "hostId", "$hostId");
-    &add_content2xml_hash($out_hash, "xxx", "");
-    my $xml_msg= &create_xml_string($out_hash);
 
-    # JSON Query
-    my $callobj = {
-      method  => 'getSoftwareInformation_hash',
-      params  => [ $hostId ],
-      id  => 1,
-    };
+    # Sanity check of needed parameter
+    if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
+    }
 
-    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-    if (&check_opsi_res($res)){
-      my $result= $res->result;
+    if (not $error) {
+
+    # Get hostID
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", "$hostId");
+        &add_content2xml_hash($out_hash, "xxx", "");
     }
 
-    $xml_msg=~ s/<xxx><\/xxx>//;
+    $xml_msg= &create_xml_string($out_hash);
+
+    if (not $error) {
+
+    # JSON Query
+        my $callobj = {
+            method  => 'getSoftwareInformation_hash',
+            params  => [ $hostId ],
+            id  => 1,
+        };
+
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($res)){
+            my $result= $res->result;
+# TODO : fertig???   
+        }
 
+        $xml_msg=~ s/<xxx><\/xxx>//;
+
+    }
+
+    # Return message
     return ( $xml_msg );
 }
 
 
 ## @method opsi_get_local_products
-# ???
-# @param msg - STRING - xml message with tag hostId
+# Reports product for given hostId or globally.
+# @param msg - STRING - xml message with optional tag hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_get_local_products {
-  my ($msg, $msg_hash, $session_id) = @_;
-  my $header = @{$msg_hash->{'header'}}[0];
-  my $source = @{$msg_hash->{'source'}}[0];
-  my $target = @{$msg_hash->{'target'}}[0];
-  my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-  my $hostId;
-
-  # build return message with twisted target and source
-  my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
-  # Get hostID if defined
-  if (defined @{$msg_hash->{'hostId'}}[0]){
-    $hostId = @{$msg_hash->{'hostId'}}[0];
-    &add_content2xml_hash($out_hash, "hostId", $hostId);
-  }
-
-  if (defined $forward_to_gosa) {
-    &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
-  }
-  &add_content2xml_hash($out_hash, "xxx", "");
-  my $xml_msg= &create_xml_string($out_hash);
-
-  # For hosts, only return the products that are or get installed
-  my $callobj;
-  $callobj = {
-    method  => 'getLocalBootProductIds_list',
-    params  => [ ],
-    id  => 1,
-  };
-
-  my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-  my %r = ();
-  for (@{$res->result}) { $r{$_} = 1 }
+    my ($msg, $msg_hash, $session_id) = @_;
+    my $header = @{$msg_hash->{'header'}}[0];
+    my $source = @{$msg_hash->{'source'}}[0];
+    my $target = @{$msg_hash->{'target'}}[0];
+    my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
+    my $hostId;
+    my $error = 0;
+    my $xml_msg;
 
-  if (&check_opsi_res($res)){
+    # Build return message with twisted target and source
+    my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
+    if (defined $forward_to_gosa) {
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
+    }
+    &add_content2xml_hash($out_hash, "xxx", "");
 
-    if (defined $hostId){
-      $callobj = {
-        method  => 'getProductStates_hash',
-        params  => [ $hostId ],
-        id  => 1,
-      };
+    # Get hostID if defined
+    if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} == 1))  {
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", $hostId);
+    }
 
-      my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
-      if (&check_opsi_res($hres)){
-        my $htmp= $hres->result->{$hostId};
+    # Move to XML string
+    my $xml_msg= &create_xml_string($out_hash);
 
-        # check state != not_installed or action == setup -> load and add
-        foreach my $product (@{$htmp}){
+    # For hosts, only return the products that are or get installed
+    my $callobj;
+    $callobj = {
+        method  => 'getLocalBootProductIds_list',
+        params  => [ ],
+        id  => 1,
+    };
 
-          if (!defined ($r{$product->{'productId'}})){
-            next;
-          }
+    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+    my %r = ();
+    for (@{$res->result}) { $r{$_} = 1 }
 
-          # Now we've a couple of hashes...
-          if ($product->{'installationStatus'} ne "not_installed" or
-              $product->{'actionRequest'} eq "setup"){
-            my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
+    if (not &check_opsi_res($res)){
 
+        if (defined $hostId){
             $callobj = {
-              method  => 'getProduct_hash',
-              params  => [ $product->{'productId'} ],
-              id  => 1,
+                method  => 'getProductStates_hash',
+                params  => [ $hostId ],
+                id  => 1,
             };
 
-            my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-            if (&check_opsi_res($sres)){
-              my $tres= $sres->result;
-
-              my $name= xml_quote($tres->{'name'});
-              my $r= $product->{'productId'};
-              my $description= xml_quote($tres->{'description'});
-              $name=~ s/\//\\\//;
-              $description=~ s/\//\\\//;
-              $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
-            }
+            my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
+            if (not &check_opsi_res($hres)){
+                my $htmp= $hres->result->{$hostId};
 
-          }
-        }
+                # Check state != not_installed or action == setup -> load and add
+                foreach my $product (@{$htmp}){
 
-      }
+                    if (!defined ($r{$product->{'productId'}})){
+                        next;
+                    }
 
-    } else {
-      foreach my $r (@{$res->result}) {
-        $callobj = {
-          method  => 'getProduct_hash',
-          params  => [ $r ],
-          id  => 1,
-        };
+                    # Now we've a couple of hashes...
+                    if ($product->{'installationStatus'} ne "not_installed" or
+                            $product->{'actionRequest'} eq "setup"){
+                        my $state= "<state>".$product->{'installationStatus'}."</state><action>".$product->{'actionRequest'}."</action>";
 
-        my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
-        if (&check_opsi_res($sres)){
-          my $tres= $sres->result;
-
-          my $name= xml_quote($tres->{'name'});
-          my $description= xml_quote($tres->{'description'});
-          $name=~ s/\//\\\//;
-          $description=~ s/\//\\\//;
-          $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
-        }
+                        $callobj = {
+                            method  => 'getProduct_hash',
+                            params  => [ $product->{'productId'} ],
+                            id  => 1,
+                        };
 
-      }
+                        my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+                        if (not &check_opsi_res($sres)){
+                            my $tres= $sres->result;
 
+                            my $name= xml_quote($tres->{'name'});
+                            my $r= $product->{'productId'};
+                            my $description= xml_quote($tres->{'description'});
+                            $name=~ s/\//\\\//;
+                            $description=~ s/\//\\\//;
+                            $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item>$state<xxx><\/xxx>/;
+                        }
+
+                    }
+                }
+
+            }
+
+        } else {
+            foreach my $r (@{$res->result}) {
+                $callobj = {
+                    method  => 'getProduct_hash',
+                    params  => [ $r ],
+                    id  => 1,
+                };
+
+                my $sres = $main::opsi_client->call($main::opsi_url, $callobj);
+                if (not &check_opsi_res($sres)){
+                    my $tres= $sres->result;
+
+                    my $name= xml_quote($tres->{'name'});
+                    my $description= xml_quote($tres->{'description'});
+                    $name=~ s/\//\\\//;
+                    $description=~ s/\//\\\//;
+                    $xml_msg=~ s/<xxx><\/xxx>/<item><productId>$r<\/productId><name><\/name><description>$description<\/description><\/item><xxx><\/xxx>/;
+                }
+
+            }
+
+        }
     }
-  }
 
-  $xml_msg=~ s/<xxx><\/xxx>//;
+    $xml_msg=~ s/<xxx><\/xxx>//;
 
-  return ( $xml_msg );
+    # Retrun Message
+    return ( $xml_msg );
 }
 
 
 ## @method opsi_del_client
-# ???
+# Deletes a client from Opsi.
 # @param msg - STRING - xml message with tag hostId
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_del_client {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $hostId = @{$msg_hash->{'hostId'}}[0];
+    my $hostId;
+    my $error = 0;
 
-    # build return message with twisted target and source
+    # Build return message with twisted target and source
     my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
-
     if (defined $forward_to_gosa) {
       &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
     }
-    &add_content2xml_hash($out_hash, "hostId", "$hostId");
 
-    # JSON Query
-    my $callobj = {
-      method  => 'deleteClient',
-      params  => [ $hostId ],
-      id  => 1,
-    };
+    # Sanity check of needed parameter
+    if ((exists $msg_hash->{'hostId'}) && (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "hostId contains no or more than one values");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: hostId contains no or more than one values: $msg", 1); 
+    }
 
-    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+    if (not $error) {
 
+    # Get hostID
+        $hostId = @{$msg_hash->{'hostId'}}[0];
+        &add_content2xml_hash($out_hash, "hostId", "$hostId");
+
+    # JSON Query
+        my $callobj = {
+            method  => 'deleteClient',
+            params  => [ $hostId ],
+            id  => 1,
+        };
+        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+    }
+
+    # Move to XML string
     my $xml_msg= &create_xml_string($out_hash);
+
+    # Return message
     return ( $xml_msg );
 }
 
 
 ## @method opsi_install_client
-# ???
+# Set a client in Opsi to install and trigger a wake on lan message (WOL).  
 # @param msg - STRING - xml message with tags hostId, macaddress
 # @param msg_hash - HASHREF - message information parsed into a hash
 # @param session_id - INTEGER - POE session id of the processing of this message
+# @return out_msg - STRING - feedback to GOsa in success and error case
 sub opsi_install_client {
     my ($msg, $msg_hash, $session_id) = @_;
     my $header = @{$msg_hash->{'header'}}[0];
     my $source = @{$msg_hash->{'source'}}[0];
     my $target = @{$msg_hash->{'target'}}[0];
     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
-    my $hostId = @{$msg_hash->{'hostId'}}[0];
+
+
+    my ($hostId, $macaddress);
+
     my $error = 0;
     my @out_msg_l;
 
-    # If no macaddress is specified, raise error  
-    my $macaddress; 
-    if ((exists $msg_hash->{'macaddress'}) && 
-            ($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)) {  
-        $macaddress = $1; 
-    } else { 
-        $error ++; 
-        my $out_msg = "<xml>". 
-            "<header>answer</header>". 
-            "<source>$main::server_address</source>". 
-            "<target>GOSA</target>". 
-            "<answer1>1</answer1>". 
-            "<error_string>no mac address specified in macaddres-tag</error_string>". 
-            "</xml>"; 
-        push(@out_msg_l, $out_msg);
-    } 
+    # Build return message with twisted target and source
+    my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
+    if (defined $forward_to_gosa) {
+        &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
+    }
+
+    # Sanity check of needed parameter
+    if ((not exists $msg_hash->{'hostId'}) || (@{$msg_hash->{'hostId'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "hostId_error", "no hostId specified or hostId tag invalid");
+        &add_content2xml_hash($out_hash, "error", "hostId");
+        &main::daemon_log("$session_id ERROR: no hostId specified or hostId tag invalid: $msg", 1); 
+    }
+    if ((not exists $msg_hash->{'macaddress'}) || (@{$msg_hash->{'macaddress'}} != 1))  {
+        $error++;
+        &add_content2xml_hash($out_hash, "macaddress_error", "no macaddress specified or macaddress tag invalid");
+        &add_content2xml_hash($out_hash, "error", "macaddress");
+        &main::daemon_log("$session_id ERROR: no macaddress specified or macaddress tag invalid: $msg", 1); 
+    } else {
+        if ((exists $msg_hash->{'macaddress'}) && 
+                ($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)) {  
+            $macaddress = $1; 
+        } else { 
+            $error ++; 
+            &add_content2xml_hash($out_hash, "macaddress_error", "given mac address is not correct");
+            &add_content2xml_hash($out_hash, "error", "macaddress");
+            &main::daemon_log("$session_id ERROR: given mac address is not correct: $msg", 1); 
+        }
+    }
 
-    # Set parameters in opsi
     if (not $error) {
-        # build return message with twisted target and source
-        my $out_hash = &main::create_xml_hash("answer_$header", $main::server_address, $source);
 
-        if (defined $forward_to_gosa) {
-            &add_content2xml_hash($out_hash, "forward_to_gosa", $forward_to_gosa);
-        }
+    # Get hostId
+        $hostId = @{$msg_hash->{'hostId'}}[0];
         &add_content2xml_hash($out_hash, "hostId", "$hostId");
 
         # Load all products for this host with status != "not_installed" or actionRequest != "none"
-        if (defined $hostId){
-            my $callobj = {
-                method  => 'getProductStates_hash',
-                params  => [ $hostId ],
-                id  => 1,
-            };
-
-            my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
-            if (&check_opsi_res($hres)){
-                my $htmp= $hres->result->{$hostId};
-
-                # check state != not_installed or action == setup -> load and add
-                foreach my $product (@{$htmp}){
-                    # Now we've a couple of hashes...
-                    if ($product->{'installationStatus'} ne "not_installed" or
-                            $product->{'actionRequest'} ne "none"){
-
-                        # Do an action request for all these -> "setup".
-                        $callobj = {
-                            method  => 'setProductActionRequest',
-                            params  => [ $product->{'productId'}, $hostId, "setup" ],
-                            id  => 1,
-                        };
-                        my $res = $main::opsi_client->call($main::opsi_url, $callobj);
-                        if (!&check_opsi_res($res)){
-                            &main::daemon_log("ERROR: cannot set product action request for $hostId!", 1);
-                        } else {
-                            &main::daemon_log("INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
-                        }
+        my $callobj = {
+            method  => 'getProductStates_hash',
+            params  => [ $hostId ],
+            id  => 1,
+        };
 
+        my $hres = $main::opsi_client->call($main::opsi_url, $callobj);
+        if (not &check_opsi_res($hres)){
+            my $htmp= $hres->result->{$hostId};
+
+            # check state != not_installed or action == setup -> load and add
+            foreach my $product (@{$htmp}){
+                # Now we've a couple of hashes...
+                if ($product->{'installationStatus'} ne "not_installed" or
+                        $product->{'actionRequest'} ne "none"){
+
+                    # Do an action request for all these -> "setup".
+                    $callobj = {
+                        method  => 'setProductActionRequest',
+                        params  => [ $product->{'productId'}, $hostId, "setup" ],
+                        id  => 1,
+                    };
+                    my $res = $main::opsi_client->call($main::opsi_url, $callobj);
+                    my ($res_err, $res_err_string) = &check_opsi_res($res);
+                    if ($res_err){
+                        &main::daemon_log("$session_id ERROR: cannot set product action request for '$hostId': ".$product->{'productId'}, 1);
+                    } else {
+                        &main::daemon_log("$session_id INFO: requesting 'setup' for '".$product->{'productId'}."' on $hostId", 1);
                     }
                 }
             }
         }
-
         push(@out_msg_l, &create_xml_string($out_hash));
-    }
+    
 
     # Build wakeup message for client
-    if (not $error) {
-        my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
-        &add_content2xml_hash($wakeup_hash, 'macAddress', $macaddress);
-        my $wakeup_msg = &create_xml_string($wakeup_hash);
-        push(@out_msg_l, $wakeup_msg);
-
-        # invoke trigger wake for this gosa-si-server
-        &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
+        if (not $error) {
+            my $wakeup_hash = &create_xml_hash("trigger_wake", "GOSA", "KNOWN_SERVER");
+            &add_content2xml_hash($wakeup_hash, 'macAddress', $macaddress);
+            my $wakeup_msg = &create_xml_string($wakeup_hash);
+            push(@out_msg_l, $wakeup_msg);
+
+            # invoke trigger wake for this gosa-si-server
+            &main::server_server_com::trigger_wake($wakeup_msg, $wakeup_hash, $session_id);
+        }
     }
-
-
+    
+    # Return messages
     return @out_msg_l;
 }
 
 
 ## @method _set_action
-# ???
-# @param product - STRING - ???
-# @param action - STRING - ???
-# @param hostId - STRING - ???
+# Set action for an Opsi client
+# @param product - STRING - Opsi product
+# @param action - STRING - action
+# @param hostId - STRING - Opsi hostId
 sub _set_action {
   my $product= shift;
   my $action = shift;
@@ -1063,19 +1227,19 @@ sub _set_action {
 }
 
 ## @method _set_state
-# ???
-# @param product - STRING - ???
-# @param action - STRING - ???
-# @param hostId - STRING - ???
+# Set state for an Opsi client
+# @param product - STRING - Opsi product
+# @param action - STRING - state
+# @param hostId - STRING - Opsi hostId
 sub _set_state {
   my $product = shift;
+  my $state = shift;
   my $hostId = shift;
-  my $action = shift;
   my $callobj;
 
   $callobj = {
     method  => 'setProductState',
-    params  => [ $product, $hostId, $action ],
+    params  => [ $product, $hostId, $state ],
     id  => 1,
   };
 
index 3481915dffdc3278a3864b3e3f3268b421c92608..a228df5ff65d19921ce3feb672429de6e8f9774b 100755 (executable)
@@ -130,16 +130,16 @@ for($count = 1; $count <= $zahl; $count++)
     #$data = "<xml> <header>gosa_opsi_get_local_products</header> <source>GOSA</source> <target>GOSA</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId></xml>";
 
     # Get product properties - global
-    #$data = "<xml> <header>gosa_opsi_get_product_properties</header> <source>GOSA</source> <target>GOSA</target> <productId>winxppro</ProductId></xml>";
+    #$data = "<xml> <header>gosa_opsi_get_product_properties</header> <source>GOSA</source> <target>GOSA</target> <productId>firefox</productId></xml>";
 
     # Get product properties - per host
-    #$data = "<xml> <header>gosa_opsi_get_product_properties</header> <source>GOSA</source> <target>GOSA</target> <productId>firefox</ProductId> <hostId>limux-cl-2.intranet.gonicus.de</hostId> </xml>";
+    #$data = "<xml> <header>gosa_opsi_get_product_properties</header> <source>GOSA</source> <target>GOSA</target> <productId>firefox</productId> <hostId>limux-cl-2.intranet.gonicus.de</hostId> </xml>";
 
     # Set product properties - global
-    #$data = "<xml> <header>gosa_opsi_set_product_properties</header> <source>GOSA</source> <target>00:01:6c:9d:aa:16</target> <productId>winxppro</ProductId> <item><name>askbeforeinst</name><value>false</value></item></xml>";
+    #$data = "<xml> <header>gosa_opsi_set_product_properties</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <productId>firefox</productId> <item><name>askbeforeinst</name><value>false</value></item></xml>";
 
     # Set product properties - per host
-    #$data = "<xml> <header>gosa_opsi_set_product_properties</header> <source>GOSA</source> <target>00:01:6c:9d:aa:16</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId> <productId>winxppro</ProductId> <item><name>askbeforeinst</name><value>false</value></item></xml>";
+    #$data = "<xml> <header>gosa_opsi_set_product_properties</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId> <productId>firefox</productId> <item> <name>askbeforeinst</name> <value>false</value> </item> </xml>";
 
     # Get hardware inventory
     #$data = "<xml> <header>gosa_opsi_get_client_hardware</header> <source>GOSA</source> <target>GOSA</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId> </xml>";
@@ -151,21 +151,21 @@ for($count = 1; $count <= $zahl; $count++)
     #$data = "<xml> <header>gosa_opsi_list_clients</header> <source>GOSA</source> <target>GOSA</target> </xml>";
 
     # Delete Opsi client
-    #$data = "<xml> <header>gosa_opsi_del_client</header> <source>GOSA</source> <target>00:01:6c:9d:aa:16</target> <hostId>sdfgsg.intranet.gonicus.de</hostId></xml>";
+    #$data = "<xml> <header>gosa_opsi_del_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId></xml>";
 
     # Install Opsi client
+    # Please do always use 'job_...' and never 'gosa_...' otherways the job will never appear in job queue
     #$data = "<xml> <header>job_opsi_install_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId> <macaddress>00:11:25:4b:8c:e5</macaddress> </xml>";
 
     # Add Opsi client
-    $data = "<xml> <header>gosa_opsi_add_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-1.intranet.gonicus.de</hostId> <macaddress>00:11:25:4b:8c:e6</macaddress> <description>Test halt</description> <ip>1.2.3.4</ip> <notes>Im a note</notes> </xml>";
-    #$data = "<xml> <header>gosa_opsi_add_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> </xml>";
+    #$data = "<xml> <header>gosa_opsi_add_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-2.intranet.gonicus.de</hostId> <macaddress>00:11:25:4b:8c:e5</macaddress> <description>Test halt</description> <ip>1.2.3.4</ip> <notes>Im a note</notes> </xml>";
 
     # Add product to Opsi client
-    #$data = "<xml> <header>gosa_opsi_add_product_to_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <macaddress>00:11:25:4b:8c:e6</macaddress> </xml>";
+    #$data = "<xml> <header>gosa_opsi_add_product_to_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <macaddress>00:11:25:4b:8c:e5</macaddress> <hostId>limux-cl-2.intranet.gonicus.de</hostId> <productId>winxppro</productId> </xml>";
 
     # Delete product from Opsi client
-    #$data = "<xml> <header>gosa_opsi_del_product_from_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-1.intranet.gonicus.de</hostId> <macaddress>00:11:25:4b:8c:e6</macaddress> <productId>softprod</productId>  </xml>";
-    #$data = "<xml> <header>gosa_opsi_del_product_from_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> </xml>";
+    #$data = "<xml> <header>gosa_opsi_del_product_from_client</header> <source>GOSA</source> <target>00:01:6c:9d:b9:fa</target> <hostId>limux-cl-1.intranet.gonicus.de</hostId> <macaddress>00:11:25:4b:8c:e5</macaddress> <productId>softprod</productId>  </xml>";
+
 
     #########################
     # Mailqueue communication