Code

Updated opsi class
[gosa.git] / gosa-plugins / opsi / admin / opsi / class_opsigeneric.inc
1 <?php
4 /*! \brief  The opsi client base class.
5             This class can be implemented in tow different ways:
6               * as standalone opsi client
7               * as part of the samba tabs 
8             both types will be detected automatically.
10             This class allows to edit the properties of an opsi client
11              and its products.
12  */
13 class opsiGeneric extends plugin
14 {
15   /* Contains a list of all available netboot products 
16    */
17   private $a_availableNetbootProducts = array();
18   private $s_selectedNetbootProduct = "";  
19   private $s_initial_selectedNetbootProduct = "";  
21   /* Contains a list of all available local products
22    */
23   private $a_availableLocalProducts = array();
24   private $a_selectedLocalProducts = array();
25   private $a_initial_selectedLocalProducts = array();
27   /* Internal veriables 
28    */ 
29   private $opsi;            // The opsi handle
30   public  $parent = NULL;   // The parent object (in case of samba)
32   private $hostId       = ""; // The host Id of the currently edit opsi host  
33   public  $mac          = ""; // The hosts mac address
34   public  $note         = ""; // A note
35   public  $description  = ""; // The client description
37   private $init_failed = FALSE; // Is true if the opsi communication failed
38   private $parent_mode = TRUE;  // Is true if this is a standlone plugin. (Not samba)
39   private $is_installed= FALSE; // Is true is the hast is already installed.
41   public $attributes = array("mac","note","description");
44   /*! \brief  Initialize this class 
45       @param  Object    The GOsa base config.
46       @param  String    The Id of the host that we want to edit.
47       @param  Object    The parent object. (in case of samba)
48    */
49   public function __construct($config,$hostId,&$parent = NULL)
50   {
51     /* Create opsi handle
52      */
53     $this->opsi = new opsi($config); 
54     
55     /* Check if we are are part of a windows workstation 
56      */
57     $this->parent = $parent;
58     if($parent instanceof wingeneric){
59       $this->parent_mode = FALSE;
60     }
62     /* Get hostId 
63      */
64     if($hostId != "new"){
65       if(preg_match("/^opsi:/",$hostId)){
66         $this->hostId = preg_replace("/^opsi:=([^,]*),.*$/","\\1",$hostId);
67       }elseif($this->parent instanceof wingeneric){
68         $this->hostId = $this->parent->cn;
69         $this->hostId = preg_replace('/\$$/',"",$this->hostId);
70       }
71     }
72   
73     /* Try to plugin */
74     $this->init();
75   }
76   
78   /*! \brief  Try to load opsi client informations from the 
79                gosa support daemon.
80    */
81   private function init()
82   {
83     $err = FALSE;
84     $this->init_failed = FALSE;
85     $this->initially_was_account = FALSE; 
87     /* Try to load client infos from the gosa support daemon
88      */
89     if($this->hostId != "new"){
90       $list = $this->opsi->list_clients($this->hostId);
91       $err |= $this->opsi->is_error();
93       /* Walk through all returned opsi clients and try to detect 
94           one that matches our hostId.
95          #FIXME Implement an opsi method which returns infos for only one opsi client, not all. 
96        */
97       foreach($list as $entry){
98         if(preg_match("/^".normalizePreg($this->hostId)."$/i",$entry['NAME'][0]['VALUE'])){
99           $this->initially_was_account = TRUE; 
100           foreach(array(
101                 "is_installed" => "LASTSEEN",
102                 "description"  => "DESCRIPTION",
103                 "mac"          => "MAC", 
104                 "note"         => "NOTES") as $des => $src){
105             $this->$des = $entry[$src][0]['VALUE'];
106           } 
107           break;
108         }
109       }
110     }
112     /* Fetch all product infos from support daemon
113      */     
114     if(!$err){
115       $this->a_availableNetbootProducts = $this->opsi->get_netboot_products();
116       $err |= $this->opsi->is_error();
117     }
118     if(!$err) {
119       $this->a_availableLocalProducts   = $this->opsi->get_local_products();
120       $err |= $this->opsi->is_error();
121     }
123     /* Get products selected by this host.
124      */
125     if(!$err && !empty($this->hostId)) {
126       $tmp = array_keys($this->opsi->get_netboot_products($this->hostId));
127       if(count($tmp)){
128         $this->s_selectedNetbootProduct = $tmp[0];
129       }
130       $err |= $this->opsi->is_error();
131     }
132     if(!$err && !empty($this->hostId)) {
133       $tmp = $this->opsi->get_local_products($this->hostId); 
134       $err |= $this->opsi->is_error();
135       $this->a_selectedLocalProducts = $tmp;
136     }
138     /* Load product configuration for all already selected products.
139      */
140     if(!$err && !empty($this->hostId)) {
141       foreach($this->a_selectedLocalProducts as $name => $data){
142         $CFG = $this->opsi->get_product_properties($name,$this->hostId);
143         $err |= $this->opsi->is_error();
144         $this->a_selectedLocalProducts[$name]['CFG'] = $CFG;
145       }
146     }
147   
148     /* Check if everything went fine else reset everything and display a retry button 
149      */
150     if($err){
151       $this->a_availableNetbootProducts = array();
152       $this->s_selectedNetbootProduct = "";  
153       $this->s_initial_selectedNetbootProduct = "";  
154       $this->a_availableLocalProducts = array();
155       $this->a_selectedLocalProducts = array();
156       $this->a_initial_selectedLocalProducts = array();
157       $this->init_failed = TRUE;
158     }else{
160       /* Remember initial settings */ 
161       $this->is_account = $this->initially_was_account;
162       $this->a_initial_selectedLocalProducts = $this->a_selectedLocalProducts;
163       $this->s_initial_selectedNetbootProduct = $this->s_selectedNetbootProduct;
164     }
165   }
168   /*! \brief  Check given data.
169       @return Array   Returns an array with all issues.
170    */
171   public function check()
172   {
173     return(array());
174     $messages = plugin::check();
176     if(empty($this->hostId)){
177       $messages[] = msgPool::required(_("Name"));
178     }elseif(!preg_match("/\./",$this->hostId)){
180       /* The hostId must contain a domain part 
181        */
182       $messages[] = msgPool::invalid(_("Name"),$this->hostId,"",
183           _("The client name must contain a domain part (e.g. '.company.de')."));
184     }elseif(preg_match("/[^a-z0-9\.\-_]/",$this->hostId)){
185       $messages[] = msgPool::invalid(_("Name"),$this->hostId,"/[a-z0-9\.\-_]/");
186     }
188     /* Ensure that the mac address is valid
189      */
190     if(!tests::is_mac($this->mac) || empty($this->mac)){
191       $messages[] = msgPool::invalid(_("MAC address"),$this->mac,"","00:0C:7F:31:33:F1");
192     }
193     return($messages);
194   }
197   /*! \brief  Create the html ui of this plugin
198       @return String  HTML content.
199    */
200   public function execute()
201   {
202     $display ="";
204     /* The pluign initialization failed due to communication problems with the gosa daemon. 
205        A retry button will be displayed here.
206      */
207     if($this->init_failed){
208       $smarty = get_smarty();
209       $smarty->assign("init_failed",TRUE);
210       $smarty->assign("message",$this->opsi->get_error());
211       return($smarty->fetch(get_template_path("generic.tpl",TRUE,dirname(__FILE__))));
212     }  
214     /* If we are not a stand alone opsi client, we must be a samba client 
215        which has the opsi tab enabled.
216        Check if the opsi is added or removed and display state buttons.
217      */
218     if(!$this->parent_mode){
219       if(isset($_POST['modify_state'])){
220         if($this->is_account){
221           $this->is_account= FALSE;
222         }elseif(!$this->is_account){
223           $this->is_account= TRUE;
224         }
225       }
226       if($this->is_account){
227         $display = $this->show_disable_header(msgPool::removeFeaturesButton(_("Opsi")), 
228             msgPool::featuresEnabled(_("Opsi")));
229       }else{
230         $display = $this->show_enable_header(msgPool::addFeaturesButton(_("Opsi")), 
231             msgPool::featuresDisabled(_("Opsi")));
232         return($display);
233       } 
234     } 
236     /* Check if we have a sub dialog opened
237      */
238     if(is_object($this->dialog)){
239       $this->dialog->save_object();
240       return($this->dialog->execute());
241     }
243     /* Create HTML output of this plugin
244      */
245     $smarty = get_smarty();
246     foreach($this->attributes as $attr){
247       $smarty->assign($attr,$this->$attr);
248     }
250     $smarty->assign("parent_mode", $this->parent_mode);
251     $smarty->assign("is_installed", $this->is_installed);
252     $smarty->assign("init_failed",FALSE);
253     $divSLP = new divSelectBox();
254     $divALP = new divSelectBox();
256     /* Create list of available local products 
257      */
258     ksort($this->a_availableLocalProducts);
259     foreach($this->a_availableLocalProducts as $name => $data){
260       if(isset($this->a_selectedLocalProducts[$name])) continue;
262       $add_tab  = array("string"   => "<input type='image' src='images/back.png' name='add_lp_".$name."'>");
263       $name_tab = array("string"   => $name);
264       $desc_tab = array("string"   => "<div style='height: 14px;overflow:hidden;'>".$data['DESC']."</div>",
265           "attach"   => "title='".$data['DESC']."' style='border-right:0px;'");
266       $divALP->AddEntry(array($add_tab,$name_tab,$desc_tab));
267     }
269     /* Create list of selected local products 
270      */
271     ksort($this->a_selectedLocalProducts);
272     foreach($this->a_selectedLocalProducts as $name => $data){
274       $name_tab = array("string"   => $name);
275       $desc_tab = array(
276           "string" => "<div style='height: 14px;overflow:hidden;'>".$data['DESC']."</div>",
277           "attach" => "title='".$data['DESC']."'");
279       /* Only display edit button, if there is something to edit 
280        */
281       $edit = "<img src='images/empty.png' alt=' '>";
282       if(count($data['CFG'])){
283         $edit = "<input type='image' src='images/lists/edit.png' name='edit_lp_".$name."'>";
284       }
285       $del  = "<input type='image' src='images/lists/trash.png' name='del_lp_".$name."'>";  
287       $opt_tab  = array("string" => $edit.$del,
288           "attach" => "style='border-right:0px; width: 40px; text-align:right;'");
289       $divSLP->AddEntry(array($name_tab,$desc_tab,$opt_tab));
290     }
292     ksort($this->a_availableNetbootProducts);
293     $smarty->assign("hostId", $this->hostId);
294     $smarty->assign("divSLP", $divSLP->DrawList());
295     $smarty->assign("divALP", $divALP->DrawList());
296     $smarty->assign("SNP", $this->s_selectedNetbootProduct);
297     $smarty->assign("ANP", $this->a_availableNetbootProducts);
298     return($display.$smarty->fetch(get_template_path("generic.tpl",TRUE,dirname(__FILE__))));
299   }
302   /*! \brief  Save modifications using the gosa support daemon.
303    */
304   public function save()
305   {
306     
307     /* Check if we have to create a new opsi client
308         or just have to save client modifications.
309      */
310     if(!$this->initially_was_account && $this->is_account){
311       $res = $this->opsi->add_client($this->hostId,$this->mac,$this->note,$this->description);
312       if($this->opsi->is_error()){
313         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
314         return;
315       }
316     }else{
318       /* Update client modifcations 
319        */
320       $this->opsi->modify_client($this->hostId,$this->mac,$this->note,$this->description);
321       if($this->opsi->is_error()){
322         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);
323         return;
324       }
325     }
327     /* Detect which products were removed an which added.
328      */
329     $add = array_diff_assoc($this->a_selectedLocalProducts,$this->a_initial_selectedLocalProducts);
330     $del = array_diff_assoc($this->a_initial_selectedLocalProducts,$this->a_selectedLocalProducts);
332     /* Remove products from client
333      */
334     foreach($del as $name => $data){
335       $this->opsi->del_product_from_client($name,$this->hostId);
336       if($this->opsi->is_error()){
337         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
338         return;
339       }
340     }
341     
342     /* Add products to client
343      */
344     foreach($add as $name => $data){
345       $this->opsi->add_product_to_client($name,$this->hostId);
346       if($this->opsi->is_error()){
347         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
348         return;
349       }
350       if(!empty($data['CFG'])){
351         $this->opsi->set_product_properties($name,$data['CFG'],$this->hostId);
352         if($this->opsi->is_error()){
353           msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
354           return;
355         }
356       }
357     }
359     /* Save local product properties 
360      */
361     foreach($this->a_selectedLocalProducts as $name => $data){
362       if(isset($del[$name]) || isset($add[$name])) continue;
363       $diff = array_diff($data['CFG'],$this->a_initial_selectedLocalProducts[$name]['CFG']);
364       if(count($diff)){
365         $this->opsi->set_product_properties($name,$diff,$this->hostId);
366         if($this->opsi->is_error()){
367           msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
368           return;
369         }
370       }
371     }
373     /* Update used netboot product. 
374      */
375     if($this->s_selectedNetbootProduct != $this->s_initial_selectedNetbootProduct){
376       if(!empty($this->s_initial_selectedNetbootProduct)){
377         $this->opsi->del_product_from_client($this->s_initial_selectedNetbootProduct,$this->hostId);
378         if($this->opsi->is_error()){
379           msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
380           return;
381         }
382       }
383       $this->opsi->add_product_to_client($this->s_selectedNetbootProduct,$this->hostId);
384       if($this->opsi->is_error()){
385         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);    
386         return;
387       }
388     }
389   }
392   /*! \brief  Removes the opsi client 
393    */  
394   public function remove_from_parent()
395   {
396     $this->opsi->del_client($this->hostId);
397     if($this->opsi->is_error()){
398       msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);
399       return;
400     }
401   }
404   /*! \brief  Save html posts 
405    */
406   public function save_object()
407   {
408     /* Init failed; reinit is triggered here.
409      */
410     if(isset($_POST['reinit']) && $this->init_failed){
411       $this->init();
412     }
414     /* Property are currently edited, close the dialog. 
415      */
416     if(isset($_POST['cancel_properties']) && is_object($this->dialog)){
417       $this->dialog = NULL;
418     }
419   
420     /* Save product property changes 
421      */
422     if(isset($_POST['save_properties']) && ($this->dialog instanceof opsiProperties)){
423       $this->dialog->save_object();
424       $pro = $this->dialog->get_product();
425       $CFG = $this->dialog->get_cfg();
426       if(isset($this->a_selectedLocalProducts[$pro])){
427         $this->a_selectedLocalProducts[$pro]['CFG'] = $CFG;
428       }
429       $this->dialog = NULL;
430     }
432     /* Save html post
433      */
434     if(isset($_POST['opsiGeneric_posted'])){
436       plugin::save_object();
438       /* Get hostId 
439        */
440       if(isset($_POST['hostId']) && $this->parent_mode){
441         $this->hostId = get_post('hostId');
442       }
444       /* Send actions like 'install' or 'wake' to the si server 
445        */
446       if(isset($_POST['opsi_action']) && isset($_POST['opsi_trigger_action']) && $this->parent_mode){
447         $action = $_POST['opsi_action'];
448         if($action == "install"){
449           $this->install_client(); 
450         }
451       }
453       /* Get selected netboot product.
454        */
455       if(isset($_POST['opsi_netboot_product'])){
456         $SNP = trim($_POST['opsi_netboot_product']);
457         if(isset($this->a_availableNetbootProducts[$SNP])){
458           $this->s_selectedNetbootProduct = $SNP;
459         }
460       }
462       /* Add/remove/edit local products 
463        */
464       foreach($_POST as $name => $value){
465       
466         /* Add product 
467          */
468         if(preg_match("/^add_lp_/",$name)){
469           $product = preg_replace("/^add_lp_(.*)_.$/","\\1",$name);
470           if(isset($this->a_availableLocalProducts[$product]) && !isset($this->a_selectedLocalProducts[$product])){
471             $this->a_selectedLocalProducts[$product] = $this->a_availableLocalProducts[$product];
472             $CFG = $this->opsi->get_product_properties($product);
473             $this->a_selectedLocalProducts[$product]['CFG'] = $CFG;
474           }
475           break;
476         }
477   
478         /* Delete product 
479          */
480         if(preg_match("/^del_lp_/",$name)){
481           $product = preg_replace("/^del_lp_(.*)_.$/","\\1",$name);
482           if(isset($this->a_selectedLocalProducts[$product])){
483             unset($this->a_selectedLocalProducts[$product]);
484           }
485           break;
486         }
487       
488         /* Edit a product  
489          */
490         if(preg_match("/^edit_lp_/",$name)){
491           $product = preg_replace("/^edit_lp_(.*)_.$/","\\1",$name);
492           $this->dialog = new opsiProperties($this->config,
493               $product,$this->a_selectedLocalProducts[$product]['CFG'],$this->hostId);
494           break;
495         }
496       }   
497     }
498   }
501   /* Triggers client installation 
502    */
503   function install_client()
504   {
505     $this->opsi->send_action("install",$this->hostId,$this->mac);
506     if($this->opsi->is_error()){
507       msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);
508     }
509   }
512   /* Return plugin informations for acl handling */
513   static function plInfo()
514   {
515     return (array(
516           "plShortName"   => _("Generic"),
517           "plDescription" => _("Opsi generic"),
518           "plSelfModify"  => FALSE,
519           "plDepends"     => array(),
520           "plPriority"    => 1,
521           "plSection"     => array("administration"),
522           "plCategory"    => array("opsi" => array("description"  => _("Opsi client"),
523                                                      "objectClass"  => "dummy_class_opsi")),
524           "plProvidedAcls"=> array()
525           ));
526   }
531 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
532 ?>