Code

Updated FAI partition handling.
[gosa.git] / gosa-plugins / fai / admin / fai / class_faiDiskEntry.inc
1 <?php
3 class faiDiskEntry extends plugin
4 {
5   /* attribute list for save action */
6   var $ignore_account= TRUE;
7   var $attributes   = array("DISKcn","DISKdescription");
8   var $UsedAttrs            = array("cn","description","FAIpartitionType",
9       "FAIpartitionNr","FAIfsType","FAImountPoint","FAIpartitionSize",
10       "FAIfsTuneOptions", "FAIfsCreateOptions", "FAImountOptions",
11       "FAIfsOptions","FAIpartitionFlags","FAIdiskOption");
13   var $objectclasses= array();
15   var $DISKcn              = "";
16   var $DISKdescription     = "";
17   var $DISKFAIdiskOptions  = "";
18   
19   var $partitions          = array();
20   var $is_edit             = false;
21   var $old_cn              = "";
22   var $status              = "new";
23   var $deletePartitions    = array();
24   var $fstabkey            = "device";
25   var $disklabel           = "msdos";
26   var $FAIstate            = "";
27   var $FAIdiskType         = "disk";
28   
29   var $lvmDevices          = array();
31   function faiDiskEntry (&$config, $dn= NULL,$parent,$disk,$type)
32   {
33     plugin::plugin ($config, $dn);
34   
35     // Set default attributes 
36     $this->parent = $parent;
37     $this->FAIdiskType = $type;
38     $this->status = "new";    
40     // If disk is not empty, then we are going to edit 
41     //  an existing disk, load disk info now. 
42     if($disk){
44       // Get devices used in volume base disks.
45       if(isset($disk['FAIlvmDevice'])){
46         $this->lvmDevices = $disk['FAIlvmDevice'];
47       }
49       // Get disk status
50       $this->status = $disk['status'];
52       // Load default attributes 
53       $this->DISKcn          = $disk['cn'];
54       $this->DISKdescription = $disk['description'];
55       $this->is_edit         = true;
56       $this->old_cn          = $disk['cn'];
58       // Load partition info 
59       foreach($disk['partitions'] as $name => $values){
61         // Do not load removed partitions 
62         if($values['status'] == "delete"){
63           unset($disk['partitions'][$name]);
64           $this->deletePartitions[]=$values;
65         }else{
67           /* If status is not new, set to edit mode. 
68            * New means that this partition currently wasn't saved to ldap.
69            */
70           if($disk['partitions'][$name]['status']!="new"){
71             $disk['partitions'][$name]['status']="edited";
72           }
73     
74           // Load partition attributes  
75           $disk['partitions'][$name]['old_cn']= $disk['partitions'][$name]['cn'];
76           $disk['partitions'][$name]['FAIdiskType']= $this->FAIdiskType;
77           foreach($this->UsedAttrs as $attr){
78             if(!isset($values[$attr])){
79               $disk['partitions'][$name][$attr]="";  
80             }
81           }
82           if (preg_match('/^_/', $disk['partitions'][$name]['FAIfsType'])){
83             $disk['partitions'][$name]['FAIfsType']= 
84               preg_replace('/^_/', '', $disk['partitions'][$name]['FAIfsType']);
85           }
86         }
87       }
89       $this->partitions      = $disk['partitions'];
91       /* Load FAIdiskOptions.
92        * Some options are disk related and some are used for partitions.
93        *  - fstabkey    -> disk
94        *  - disklabel   -> disk
95        *  - bootable    -> partition
96        *  - preserve    -> partition
97        *  - resize      -> partition
98        */
99       if (isset($disk['FAIdiskOption'])){
100         foreach($disk['FAIdiskOption'] as $option) {
102           // Get fstab key  
103           if (preg_match("/fstabkey:(device|label|uuid)/", $option)){
104             $this->fstabkey= preg_replace("/^.*fstabkey:(device|label|uuid).*$/", "$1", $option);
105             continue;
106           }
108           // Get disk label
109           if (preg_match("/disklabel:(msdos|gpt)/", $option)){
110             $this->disklabel= preg_replace("/^.*disklabel:(msdos|gpt).*$/", "$1", $option);
111             continue;
112           }
114           // Load bootable flag for partitions 
115           if (preg_match("/^bootable:/", $option)){
116             $bootable = split(",", trim(preg_replace("/^bootable:/","",$option),","));
117             foreach($bootable as $bootflag){
118               if(isset($this->partitions[$bootflag])){
119                 $this->partitions[$bootflag]['bootable'] = TRUE;  
120               }
121             }
122             continue;
123           }
125           // Load resize flag for partitions 
126           if (preg_match("/^resize:/", $option)){
127             $resize = split(",", trim(preg_replace("/^resize:/","",$option),","));
128             foreach($resize as $id){
129               if(isset($this->partitions[$id])){
130                 $this->partitions[$id]['resize'] = TRUE;  
131               }
132             }
133             continue;
134           }
136           // Load preserve_always flag for partitions 
137           if (preg_match("/^preserve_always:/", $option)){
138             $preserve = split(",", trim(preg_replace("/^preserve_always:/","",$option),","));
139             foreach($preserve as $presflag){
140               if(isset($this->partitions[$presflag])){
141                 $this->partitions[$presflag]['preserve'] = TRUE;  
142                 $this->partitions[$presflag]['preserveType'] = 'always';  
143               }
144             }
145             continue;
146           }
148           // Load preserve_reinstall flag for partitions 
149           if (preg_match("/^preserve_reinstall:/", $option)){
150             $preserve = split(",", trim(preg_replace("/^preserve_reinstall:/","",$option),","));
151             foreach($preserve as $presflag){
152               if(isset($this->partitions[$bootflag])){
153                 $this->partitions[$presflag]['preserve'] = TRUE;  
154                 $this->partitions[$presflag]['preserveType'] = 'reinstall'; 
155               } 
156             }
157             continue;
158           }
159         }
160       } else {
161         $this->fstabkey= "device";
162       }
163     }
164   }
167   function execute()
168   {
169     /* Call parent execute */
170     plugin::execute();
172     // Fill templating stuff
173     $smarty     = get_smarty();
174     $s_action   = "";
175     $s_entry    = "";
176     $display    = "";
178     // Add partition to lvm compilation.
179     if(isset($_POST['addLvmPartition']) && isset($_POST['lvmPartitionAdd'])){
180       $name = get_post('lvmPartitionAdd');
181       $this->lvmDevices[$name] = $name;
182     }
184     // Remove partition from lvm compilation.
185     if(isset($_POST['delLvmPartition']) && isset($_POST['physicalPartition'])){
186       $names = $_POST['physicalPartition'];
187       foreach($names as $name){
188         if(isset($this->lvmDevices[$name])){
189           unset($this->lvmDevices[$name]);
190         }
191       }
192     }
194     /* Check all Posts if there is something usefull for us,
195      * For example : Delete is posted as Delete_1 
196      * The number specifies the index we want to delete
197      */
198     foreach($_POST as $name => $value){
199       if((preg_match("/RemovePartition_/",$name)) && 
200           $this->acl_is_removeable() && 
201           !preg_match("/freeze/i",$this->FAIstate)){
202         $tmp = split("_",$name);
203         $this->removePartition($tmp[1]);
204         break;
205       }
206       if(preg_match("/^EditPartition_/",$name)){
207         $id = preg_replace("/^EditPartition_/","",$name);
208         $id = preg_replace("/_.*$/","",$id);
209         if(isset($this->partitions[$id])){
210           $this->dialog = new faiPartition($this->config,$this->partitions[$id], $this,$this->FAIdiskType);
211           break;
212         }
213       } 
214     }
216     /* Act on _GET edit request
217      */
218     if(isset($_GET['act']) && $_GET['act'] == "editPart" && isset($_GET['id'])){
219       $id = $_GET['id'];
220       if(isset($this->partitions[$id])){
221         $this->dialog = new faiPartition($this->config,$this->partitions[$id], $this,$this->FAIdiskType);
222       }
223     }
225     /* Create a new partition for this disk.
226      */
227     if(isset($_POST['AddPartition']) && !preg_match("/freeze/i",$this->FAIstate)){
228       $this->dialog = new faiPartition($this->config, array(), $this,$this->FAIdiskType);
229     }
231     /* Handle partition dialogs.
232      */
233     if($this->dialog instanceOf plugin && isset($_POST['PartitionCancel'])){
234       $this->dialog = null;
235     }
236     if($this->dialog instanceOf plugin && isset($_POST['PartitionSave'])){
237       $this->dialog->save_object();
239       $new_partition = $this->dialog->save(); 
240       $msgs = $this->dialog->check();
241       $msgs = array_merge($msgs,$this->check_disks($new_partition));
243       if(!count($msgs)){
244         $this->updatePartition($new_partition);
245         $this->dialog = null;
246       }else{
247         msg_dialog::displayChecks($msgs);
248       }
249     }
250     if($this->dialog instanceOf plugin){
251       $this->dialog->save_object();
252       return($this->dialog->execute());
253     }
255     // Assign checkbox related values.
256     foreach($this->attributes as $attrs){
257       $smarty->assign($attrs,$this->$attrs);
258       if($this->$attrs){
259         $smarty->assign($attrs."CHK"," ");
260       }else{
261         $smarty->assign($attrs."CHK"," disabled ");
262       }
263     }
265     // Assign disk info to smarty.
266     $smarty->assign("setup", $this->generateParts());
267     $smarty->assign("sub_object_is_createable",$this->acl_is_createable());
268     $smarty->assign("freeze",preg_match("/freeze/i",$this->FAIstate));
269     $smarty->assign("fstabkeys", array("device" => _("Device"), "label" => _("Label"), "uuid" => _("UUID")));
270     $smarty->assign("disklabels", array("msdos" => "MSDOS", "gpt" => "GPT"));
271     $smarty->assign("fstabkey", $this->fstabkey);
272     $smarty->assign("disklabel", $this->disklabel);
273     $smarty->assign("FAIdiskType", $this->FAIdiskType);
274     $smarty->assign("plist", $this->getPartitionList());
275     $smarty->assign("physicalPartitionList", $this->getAvailablePartitions());
277     foreach($this->attributes as $attr){
278       $smarty->assign($attr,$this->$attr);
279     }
281     // Assign partitions
282     $tmp = $this->plInfo();
283     $sacl = "";
284     foreach($tmp['plProvidedAcls'] as $name => $translated){
285       $acl = $this->getacl($name, preg_match("/freeze/i",$this->FAIstate));
286       $smarty->assign($name."ACL",$acl);
287     }
288    
289     $display.= $smarty->fetch(get_template_path('faiDiskEntry.tpl', TRUE));
290     return($display);
291   }
293   function getPartitionList()
294   {
295     $divlist = new divSelectBox("RaidList");
297     /* Create a list of all available disks and partitions. 
298      * This list will then be used to display detailed info.
299      */
300     $disks = $this->parent->disks;
301     foreach($disks as $dname => $disk){
303       // Skip currently edited disk 
304       if($disk['cn'] == $this->old_cn) continue;
305    
306       // Add disk 
307       $objs[$dname] = $disk;
309       // Add disk partitions
310       foreach($disk['partitions'] as $id => $part){
311         $part['parentDisk'] = $disk;
312         $objs[$part['cn']] = $part;
313       }
314     }
316     // Attach current disk setup to the details list.
317     $data = $this->save();
318     $objs[$data['cn']] = $data;
319     foreach($data['partitions'] as $part){
320       $part['parentDisk'] = $data;
321       $objs[$part['cn']] = $part;
322     }
324     // Walk through physical partition combinations and build up 
325     //  user friendly list with partition details.
326     $list = array();
327     foreach($this->lvmDevices as $device){
329       // We've a html select box here, add spaces for better readability
330       $str = $device;
331       $str = preg_replace("/ /","&nbsp;",str_pad($str,20," "));
333       // Add disk/partition details.
334       if(isset($objs[$device])){
335         if(isset($objs[$device]['FAIpartitionSize'])){
336           if($objs[$device]['parentDisk']['FAIdiskType'] == "raid"){
337             $str .= _("Disks").":&nbsp;";
338             $str .= $objs[$device]['FAIpartitionSize'];
339           }else{
340             $str .= _("Size").":&nbsp;";
341             $str .= $objs[$device]['FAIpartitionSize'];
342           } 
343         }
344       }
345       $list[$device] = $str;
346     }
347     return($list);
348   }
350  
351   /* Returns a list of available partitions that are useable in this 
352    *  lvm disk setup.
353    */ 
354   function getAvailablePartitions()
355   {
356     $array = array();
357     foreach($this->parent->disks as $disk){
359       // We can't add ourselves to the available partitions
360       if($disk['cn'] == $this->old_cn) continue;
362       // Add partitions to the list.
363       foreach($disk['partitions'] as $key => $part){
364         $name = $part['cn'];
365         if(!isset($this->lvmDevices[$name])){
366           $array[$name] = $name;
367         }
368       }
369     }
370     return($array);
372   }
375   /* Remove the selected partition and shift the following partitions 
376    *  to fill gap.
377    * Additionally update the partition numbers correspondingly.
378    */
379   function removePartition($id)
380   {
381     $start = false;
382     foreach($this->partitions as $key => $part){
383       if($id == $key){
384         $start = true;
385       }
386       if($start){
387         if($this->partitions[$key]['status'] == "edited"){
388           $this->deletePartitions[$key]= $this->partitions[$key];
389           $this->deletePartitions[$key]['FAIpartitionNr']=$key;
390           unset($this->partitions[$key]);
391         }else{
392           unset($this->partitions[$key]);
393         }
394         if(isset($this->partitions[($key+1)])){
395           if(isset($this->deletePartitions[$key])){
396             unset($this->deletePartitions[$key]);
397           }
398           $this->partitions[$key] = $this->partitions[($key+1)];
399           $this->partitions[$key]['FAIpartitionNr'] = $key;
400           $this->partitions[$key]['status'] = "new";
401         }
402       }
403     }
404     $tmp= array();
405     foreach($this->partitions as $part){
406       $tmp[count($tmp)+1]=$part;
407     }
408     $this->partitions = $tmp;
409   }
412   /* Add or update a partition 
413    */
414   function updatePartition($part)
415   {
416     if(!isset($part['FAIpartitionNr']) || $part['FAIpartitionNr'] == "undefined"){
417       $part['FAIpartitionNr'] = count($this->partitions) + 1;
418     }
420     /* Update the disk cn -       
421      * Do NOT touch the partition 'cn' in case of lvm devices. 
422      */
423     if($this->FAIdiskType == "disk"){
424       $part['cn'] = $this->DISKcn.$part['FAIpartitionNr'];
425     }
427     /* Check if we've to update lvm compilations.
428      */ 
429     if($this->FAIdiskType == "lvm"){
430       if(isset($this->partitions[$part['FAIpartitionNr']])){
431         $old_cn = $this->partitions[$part['FAIpartitionNr']]['cn'];
432         $new_cn = $part['cn'];
433         if(isset($this->lvmDevices[$old_cn])){
434           unset($this->lvmDevices[$old_cn]);
435           $this->lvmDevices[$new_cn] = $new_cn;
436         }
437       }
438     }
440     /* Check if we've to update lvm compilations.
441      */ 
442     if($this->FAIdiskType == "raid"){
443       $part['cn'] = 'md'.$part['FAIpartitionNr'];
444     }
446     $this->partitions[$part['FAIpartitionNr']] = $part;
447   }
450   function generateParts()
451   {
453     $divlist = new divSelectBox("DiskEntries"); 
454     foreach($this->partitions as $key => $part){
456       $cn =array(
457           "string" => "<a href='?plug=".$_GET['plug']."&amp;act=editPart&amp;id={$key}'>".$part['cn']."</a>",
458           "attach" => "style='width:160px;'");
460       $desc =array(
461           "string" => "<a href='?plug=".$_GET['plug']."&amp;act=editPart&amp;id={$key}'>".
462               $part['description']."</a>",
463           "attach" => "style='width:200px;'");
465       $number =array(
466           "string" => $part['FAIpartitionNr'],
467           "attach" => "style='width:20px;'");
468       $size   =array(
469           "string" => $part['FAIpartitionSize'],
470           "attach" => "style='width:100px;'");
471       $type   =array(
472           "string" => $part['FAIpartitionType'],
473           "attach" => "style='width:80px;'");
475       $mnt = $part['FAImountPoint'];
476       if(preg_match("/:encrypt/", $mnt)){
477         $mnt = preg_replace("/:encrypt/","",$mnt);
478       }
479       $mntp   =array("string" => $mnt);
481       $opt = "";
482       if(isset($part['encrypted']) && $part['encrypted']){
483         $opt.= "&nbsp;"._("encrypted").", ";
484       }      
485       if(isset($part['bootable']) && $part['bootable']){
486         $opt.= "&nbsp;"._("bootable").", ";
487       }      
488       if(isset($part['preserve']) && $part['preserve']){
489         $opt.= "&nbsp;"._("preserve").":&nbsp;".$part['preserveType'].", ";
490       }      
491       $opt    =array(
492           "string" => "<i>".preg_replace('/, $/',"",$opt)."</i>");
494       $action =array(
495           "string" => "<input type='image' src='images/lists/edit.png' name='EditPartition_".$key."'>".
496                       "<input type='image' src='images/lists/trash.png' name='RemovePartition_".$key."'>",
497           "attach" => "style='width:40px; border-right: 0px;'");
499       if($this->FAIdiskType == "lvm"){ 
500         $fields = array($cn,$desc,$mntp,$opt,$size, $action);
501       }elseif($this->FAIdiskType == "raid"){
503         $raid_str = $part['FAIpartitionType']." (".$part['FAIpartitionSize'].")";
504         $raid = array("string" => $raid_str);
506         $fields = array($cn,$desc,$raid,$mntp,$opt,$action);
507       }else{
508         $fields = array($number,$desc,$type,$mntp,$opt,$size,$action);
509       }
510       $divlist->AddEntry($fields);
511     }
512     return($divlist->DrawList());    
513   }
516   function save()
517   {
518     $tmp = array();
519     $tmp['cn']          = $this->DISKcn;
521     /* Attach partitions */
522     foreach($this->partitions as $key=>$val) {
523       $this->partitions[$key]['FAIpartitionNr']=$key;
525       if($this->FAIdiskType == "disk"){
526         $this->partitions[$key]['cn'] = $this->DISKcn.$key;
527       }elseif($this->FAIdiskType == "lvm"){
528         $this->partitions[$key]['FAIpartitionType'] = 'lvm';
529       }
530     }
532     /* Attach deleted */
533     foreach($this->deletePartitions as $key=>$val) {
534       $this->partitions[$key."-delete"]=$val;
535       $this->partitions[$key."-delete"]['status']="delete";
536     }
538     $tmp['description'] = $this->DISKdescription;
539     $tmp['partitions']  = $this->partitions;
540     $tmp['status']      = $this->status;
541     $tmp['FAIdiskType'] = $this->FAIdiskType;
543     $tmp['FAIlvmDevice'] = array();
544     foreach($this->lvmDevices as $dev){
545       $tmp['FAIlvmDevice'][] = $dev;
546     } 
548     /* Assemble flags */
549     $tmp['FAIdiskOption'] = array("fstabkey:".$this->fstabkey, "disklabel:".$this->disklabel);
551     /* If hdd name has changed, tell partitionTable to rename it */
552     if(($this->is_edit)&&($this->old_cn != $this->DISKcn)){
553       $tmp['rename']['from']  = $this->old_cn;
554       $tmp['rename']['to']    = $this->DISKcn;
555     }
557     // Build up disk options 
558     $bootable = "";
559     $resize = "";
560     $preserve_always = "";
561     $preserve_reinstall = "";
563     foreach($tmp['partitions'] as $id => $part){
564       if(isset($part['bootable']) && $part['bootable']){
565         $bootable .= $id.",";
566       }
567       if(isset($part['resize']) && $part['resize']){
568         $resize .= $id.",";
569       }
570       if(isset($part['preserve']) && $part['preserve']){
571         if($part['preserveType'] == "always"){
572           $preserve_always .= $id.",";
573         }else{
574           $preserve_reinstall .= $id.",";
575         }
576       }
577       $tmp['partitions'][$id]['status'] = $part['status'];
579       // Unset non valid attributes 
580       foreach(array("bootable","encrypted","preserve","preserveType","resize","FAIdiskType") as $attr){
581         if(isset($tmp['partitions'][$id][$attr])){
582           unset($tmp['partitions'][$id][$attr]);
583         }
584       }
585     }    
587     if(!empty($bootable)){
588       $tmp['FAIdiskOption'][] = "bootable:".trim($bootable,",");
589     }
590     if(!empty($resize)){
591       $tmp['FAIdiskOption'][] = "resize:".trim($resize,",");
592     }
593     if(!empty($preserve_always)){
594       $tmp['FAIdiskOption'][] = "preserve_always:".trim($preserve_always,",");
595     }
596     if(!empty($preserve_reinstall)){
597       $tmp['FAIdiskOption'][] = "preserve_reinstall:".trim($preserve_reinstall,",");
598     }
600     $tmp['status'] = $this->status;
601     return($tmp);
602   }
605   /* Save data to object */
606   function save_object()
607   {
608     if((isset($_POST['TableEntryFrameSubmitted'])) && !preg_match("/freeze/", $this->FAIstate) ){
609       plugin::save_object();
611       // Save posted disk label and fstab key
612       if (isset($_POST['disklabel']) && preg_match("/^(msdos|gpt)$/", $_POST['disklabel'])){
613         $this->disklabel= $_POST['disklabel'];
614       }
615       if (isset($_POST['fstabkey']) && preg_match("/^(device|label|uuid)$/", $_POST['fstabkey'])){
616         $this->fstabkey= $_POST['fstabkey'];
617       }
618     }
619   }
622   /* Check supplied data */
623   function check()
624   {
625     /* Call common method to give check the hook */
626     $message= plugin::check();
627   
628     /* Check for an empty disk name */
629     $d = trim($this->DISKcn);
630     if($d == "" ){
631       $message[] = msgPool::required(_("Name"));
632     }
633     if(preg_match("/[^a-z0-9_\-]/i",$d)){
634       $message[] = msgPool::invalid(_("Name"),$d,"/[a-z0-9_\-]/i");
635     }
636     return ($message);
637   }
640   /* Checks the disk combinations.
641    * 
642    */  
643   function check_disks($disk_to_add = array())
644   {
645     $msgs = array();
647     /* Check 'disk' combinations. 
648      *  - There can be four primary partitions.
649      *  - If there is at least one 'logical' partition, then there can be only 
650      *     three 'primary' partitions.
651      */    
652     if($this->FAIdiskType == "disk"){
653      
654       $types = array('logical' => array(), 'primary' => array());
655       $types[$disk_to_add['FAIpartitionType']][$disk_to_add['FAIpartitionNr']] = 1;
656       foreach($this->partitions as $key => $part){
657         $types[$part['FAIpartitionType']][$part['FAIpartitionNr']] = 1;
658       }
660       // There can only be four primary partitions per disk - without any logical partition.
661       if(count($types['logical']) == 0){
662         if(count($types['primary']) > 4){
663           $msgs[] = _("You have more than four primary partition table entries in your configuration, please check your configuration twice.");
664         }
665       }else{
666         if(count($types['primary']) > 3){
667           $msgs[] = _("You cannot have more than three primary partition while using logical partitions, please check your configuration twice.");
668         }
669       }
670     }
672     return($msgs);
673   }  
676   /* Return plugin informations for acl handling */
677   static function plInfo()
678   {
679     return (array(
680           "plShortName" => _("Partition table entry"),
681           "plDescription" => _("FAI partition table entry"),
682           "plSelfModify"  => FALSE,
683           "plDepends"     => array(),
684           "plPriority"    => 27,
685           "plSection"     => array("administration"),
686           "plCategory"    => array("fai"),
687           "plProvidedAcls" => array(
688             "DISKcn"           => _("Name"),
689             "DISKdescription"  => _("Description"),
690             "DISKFAIdiskOption"  => _("Disk options"),
691             "FAIpartitionType"  => _("Partition type"),
692             "FAIpartitionNr"    => _("Partition no."),
693             "FAIfsType"         => _("File system type"),
694             "FAImountPoint"     => _("Mount point"),
695             "FAIpartitionSize"  => _("Partition size"),
696             "FAImountOptions"   => _("Mount options"),
697             "FAIfsOptions"      => _("File system options"),
698             "FAIpartitionFlags" => _("Partition flags"))
699           ));
700   }
702  
705 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
706 ?>