Code

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