Code

Updated FAI partition handling
[gosa.git] / gosa-plugins / fai / admin / fai / class_faiDiskEntry.inc
index c2fcfa1076f658deff44dc197723306111b5e813..a1f0e420e8e9cf34b6938194007111b681e54a00 100644 (file)
@@ -5,101 +5,156 @@ class faiDiskEntry extends plugin
   /* attribute list for save action */
   var $ignore_account= TRUE;
   var $attributes   = array("DISKcn","DISKdescription");
+  var $UsedAttrs            = array("cn","description","FAIpartitionType",
+      "FAIpartitionNr","FAIfsType","FAImountPoint","FAIpartitionSize",
+      "FAIfsTuneOptions", "FAIfsCreateOptions", "FAImountOptions",
+      "FAIfsOptions","FAIpartitionFlags","FAIdiskOption");
+
   var $objectclasses= array();
 
   var $DISKcn              = "";
   var $DISKdescription     = "";
-  var $DISKFAIdiskOptions     = "";
+  var $DISKFAIdiskOptions  = "";
+  
+  var $partitions          = array();
+  var $is_edit             = false;
+  var $old_cn              = "";
+  var $status              = "new";
+  var $deletePartitions    = array();
+  var $fstabkey            = "device";
+  var $disklabel           = "msdos";
+  var $FAIstate            = "";
+  var $FAIdiskType         = "disk";
   
-  var $partitions           = array();
-  var $UsedAttrs            = array();
-  var $is_edit              = false;
-  var $old_cn               = "";
-  var $status               = "new";
-  var $deletePartitions     = array();
-  var $fstabkey             = "device";
-  var $disklabel            = "msdos";
-
-  var $FAIstate             = "";
-  var $FAIdiskType          = "disk";
-
-  function faiDiskEntry (&$config, $dn= NULL,$usedDiskNames=array(),$disk=false)
+  var $lvmDevices          = array();
+
+  function faiDiskEntry (&$config, $dn= NULL,$parent,$disk,$type)
   {
     plugin::plugin ($config, $dn);
-    $this->UsedAttrs  = array("cn","description","FAIpartitionType",
-        "FAIpartitionNr","FAIfsType","FAImountPoint","FAIpartitionSize",
-        "FAImountOptions","FAIfsOptions","FAIpartitionFlags","FAIdiskOption");
-
-    /* Default status is new */
+  
+    // Set default attributes 
+    $this->parent = $parent;
+    $this->FAIdiskType = $type;
     $this->status = "new";    
-    /* We want to edit an entry */
+
+    // If disk is not empty, then we are going to edit 
+    //  an existing disk, load disk info now. 
     if($disk){
 
-      /* Set disk status */      
+      // Get devices used in volume base disks.
+      if($disk['FAIlvmDevice']){
+        $this->lvmDevices = $disk['FAIlvmDevice'];
+      }
+
+      // Get disk status
       $this->status = $disk['status'];
 
-      /* Walk through partitions */
+      // Load default attributes 
+      $this->DISKcn          = $disk['cn'];
+      $this->DISKdescription = $disk['description'];
+      $this->is_edit         = true;
+      $this->old_cn          = $disk['cn'];
+
+      // Load partition info 
       foreach($disk['partitions'] as $name => $values){
 
-        /* If a partition is already marked as delete, attach it to deletePartitions only. */
+        // Do not load removed partitions 
         if($values['status'] == "delete"){
           unset($disk['partitions'][$name]);
           $this->deletePartitions[]=$values;
         }else{
 
-          /* Set status, to know which partition must be deleted from ldap
-             new    : Neu partition entry // save
-             edited : Update partition entry in ldap
-             deleted: Remove partition from ldap
-           */
-    
           /* If status is not new, set to edit mode. 
            * New means that this partition currently wasn't saved to ldap.
            */
           if($disk['partitions'][$name]['status']!="new"){
             $disk['partitions'][$name]['status']="edited";
           }
-     
+    
+          // Load partition attributes  
           $disk['partitions'][$name]['old_cn']= $disk['partitions'][$name]['cn'];
-          /* Assign empty attributes, if attribute is missing */
+          $disk['partitions'][$name]['FAIdiskType']= $this->FAIdiskType;
           foreach($this->UsedAttrs as $attr){
             if(!isset($values[$attr])){
               $disk['partitions'][$name][$attr]="";  
             }
           }
-
           if (preg_match('/^_/', $disk['partitions'][$name]['FAIfsType'])){
-            $disk['partitions'][$name]['FAIfsType']= preg_replace('/^_/', '', $disk['partitions'][$name]['FAIfsType']);
+            $disk['partitions'][$name]['FAIfsType']= 
+              preg_replace('/^_/', '', $disk['partitions'][$name]['FAIfsType']);
           }
         }
       }
 
-      /* Set default attributes */
-      $this->DISKcn          = $disk['cn'];
-      $this->DISKdescription = $disk['description'];
       $this->partitions      = $disk['partitions'];
-      $this->is_edit         = true;
-      $this->old_cn          = $disk['cn'];
 
-      /* Move faiDiskOption */
+      /* Load FAIdiskOptions.
+       * Some options are disk related and some are used for partitions.
+       *  - fstabkey    -> disk
+       *  - disklabel   -> disk
+       *  - bootable    -> partition
+       *  - preserve    -> partition
+       *  - resize      -> partition
+       */
       if (isset($disk['FAIdiskOption'])){
         foreach($disk['FAIdiskOption'] as $option) {
+
+          // Get fstab key  
           if (preg_match("/fstabkey:(device|label|uuid)/", $option)){
             $this->fstabkey= preg_replace("/^.*fstabkey:(device|label|uuid).*$/", "$1", $option);
             continue;
           }
+
+          // Get disk label
           if (preg_match("/disklabel:(msdos|gpt)/", $option)){
             $this->disklabel= preg_replace("/^.*disklabel:(msdos|gpt).*$/", "$1", $option);
             continue;
           }
+
+          // Load bootable flag for partitions 
           if (preg_match("/^bootable:/", $option)){
             $bootable = split(",", trim(preg_replace("/^bootable:/","",$option),","));
             foreach($bootable as $bootflag){
-              $this->partitions[$bootflag]['bootable'] = TRUE;  
+              if(isset($this->partitions[$bootflag])){
+                $this->partitions[$bootflag]['bootable'] = TRUE;  
+              }
+            }
+            continue;
+          }
+
+          // Load resize flag for partitions 
+          if (preg_match("/^resize:/", $option)){
+            $resize = split(",", trim(preg_replace("/^resize:/","",$option),","));
+            foreach($resize as $id){
+              if(isset($this->partitions[$bootflag])){
+                $this->partitions[$id]['resize'] = TRUE;  
+              }
+            }
+            continue;
+          }
+
+          // Load preserve_always flag for partitions 
+          if (preg_match("/^preserve_always:/", $option)){
+            $preserve = split(",", trim(preg_replace("/^preserve_always:/","",$option),","));
+            foreach($preserve as $presflag){
+              if(isset($this->partitions[$bootflag])){
+                $this->partitions[$presflag]['preserve'] = TRUE;  
+                $this->partitions[$presflag]['preserveType'] = 'always';  
+              }
+            }
+            continue;
+          }
+
+          // Load preserve_reinstall flag for partitions 
+          if (preg_match("/^preserve_reinstall:/", $option)){
+            $preserve = split(",", trim(preg_replace("/^preserve_reinstall:/","",$option),","));
+            foreach($preserve as $presflag){
+              if(isset($this->partitions[$bootflag])){
+                $this->partitions[$presflag]['preserve'] = TRUE;  
+                $this->partitions[$presflag]['preserveType'] = 'reinstall'; 
+              } 
             }
-            break;
+            continue;
           }
         }
       } else {
@@ -114,30 +169,16 @@ class faiDiskEntry extends plugin
     /* Call parent execute */
     plugin::execute();
 
-    /* Fill templating stuff */
+    // Fill templating stuff
     $smarty     = get_smarty();
     $s_action   = "";
     $s_entry    = "";
     $display    = "";
 
-    /* Load parameters */
-    if (isset($_POST['disklabel']) && preg_match("/^(msdos|gpt)$/", $_POST['disklabel'])){
-      $this->disklabel= $_POST['disklabel'];
-    }
-    if (isset($_POST['fstabkey']) && preg_match("/^(device|label|uuid)$/", $_POST['fstabkey'])){
-      $this->fstabkey= $_POST['fstabkey'];
-    }
-    
-    /* Assign values 
-     * And Checkbox selection
-     */
-    foreach($this->attributes as $attrs){
-      $smarty->assign($attrs,$this->$attrs);
-      if($this->$attrs){
-        $smarty->assign($attrs."CHK"," ");
-      }else{
-        $smarty->assign($attrs."CHK"," disabled ");
-      }
+    // Remove partition
+    if(isset($_POST['addLvmPartition']) && isset($_POST['lvmPartitionAdd'])){
+      $name = $_POST['lvmPartitionAdd'];
+      $this->lvmDevices[$name] = array("name" => $name);
     }
 
     /* Check all Posts if there is something usefull for us,
@@ -145,62 +186,37 @@ class faiDiskEntry extends plugin
      * The number specifies the index we want to delete
      */
     foreach($_POST as $name => $value){
-      if((preg_match("/Delete_.*/",$name)) && 
+      if((preg_match("/RemovePartition_/",$name)) && 
           $this->acl_is_removeable() && 
           !preg_match("/freeze/i",$this->FAIstate)){
         $tmp = split("_",$name);
-        $s_action = "remove";
-        $s_entry  = $tmp[1]; 
+        $this->removePartition($tmp[1]);
+        break;
       }
-    }
-
-    /* To remove a partition we unset the index posted.
-     * We must sort the index again, else we possibly got problems 
-     * with partitions order.
-     */
-    if($s_action == "remove" && $this->acl_is_removeable() && 
-        !preg_match("/freeze/i",$this->FAIstate)){
-      if($this->partitions[$s_entry]['status'] == "edited"){
-        $this->deletePartitions[$s_entry]= $this->partitions[$s_entry];
-        $this->deletePartitions[$s_entry]['FAIpartitionNr']=$s_entry;
-        unset($this->partitions[$s_entry]);
-      }else{
-        unset($this->partitions[$s_entry]);
-      }
-      $tmp= array();
-      foreach($this->partitions as $part){
-        $tmp[count($tmp)+1]=$part;
-      }
-      $this->partitions = $tmp;
-    }
-
-
-    /* Add / Edit partitions here.
-     */    
-    foreach($_POST as $name => $value){
       if(preg_match("/^EditPartition_/",$name)){
         $id = preg_replace("/^EditPartition_/","",$name);
         $id = preg_replace("/_.*$/","",$id);
         if(isset($this->partitions[$id])){
-          $this->dialog = new faiPartition($this->config,"disk",$this->partitions[$id]);
+          $this->dialog = new faiPartition($this->config,$this->partitions[$id], $this,$this->FAIdiskType);
           break;
         }
       } 
     }
+
+    /* Create a new partition for this disk.
+     */
     if(isset($_POST['AddPartition']) && !preg_match("/freeze/i",$this->FAIstate)){
-      $this->dialog = new faiPartition($this->config,"disk");
+      $this->dialog = new faiPartition($this->config, array(), $this,$this->FAIdiskType);
     }
+
+    /* Handle partition dialogs.
+     */
     if($this->dialog instanceOf plugin && isset($_POST['PartitionCancel'])){
       $this->dialog = null;
     }
     if($this->dialog instanceOf plugin && isset($_POST['PartitionSave'])){
       $this->dialog->save_object();
-      $attrs = $this->dialog->save();
-      if(isset($attrs['FAIpartitionNr'])){
-        $this->partitions[$attrs['FAIpartitionNr']] = $attrs;
-      }else{
-        $this->partitions[] = $attrs;
-      }
+      $this->updatePartition($this->dialog->save());
       $this->dialog = null;
     }
     if($this->dialog instanceOf plugin){
@@ -208,14 +224,33 @@ class faiDiskEntry extends plugin
       return($this->dialog->execute());
     }
 
+    // Assign checkbox related values.
+    foreach($this->attributes as $attrs){
+      $smarty->assign($attrs,$this->$attrs);
+      if($this->$attrs){
+        $smarty->assign($attrs."CHK"," ");
+      }else{
+        $smarty->assign($attrs."CHK"," disabled ");
+      }
+    }
 
-    /* $setup contains a table with the partitions. 
-     */
+    // Assign disk info to smarty.
     $smarty->assign("setup", $this->generateParts());
+    $smarty->assign("sub_object_is_createable",$this->acl_is_createable());
+    $smarty->assign("freeze",preg_match("/freeze/i",$this->FAIstate));
+    $smarty->assign("fstabkeys", array("device" => _("Device"), "label" => _("Label"), "uuid" => _("UUID")));
+    $smarty->assign("disklabels", array("msdos" => "MSDOS", "gpt" => "GPT"));
+    $smarty->assign("fstabkey", $this->fstabkey);
+    $smarty->assign("disklabel", $this->disklabel);
+    $smarty->assign("FAIdiskType", $this->FAIdiskType);
+    $smarty->assign("plist", $this->getPartitionList());
+    $smarty->assign("physicalPartitionList", $this->getAvailablePartitions());
+
     foreach($this->attributes as $attr){
       $smarty->assign($attr,$this->$attr);
     }
 
+    // Assign partitions
     $tmp = $this->plInfo();
     $sacl = "";
     foreach($tmp['plProvidedAcls'] as $name => $translated){
@@ -223,21 +258,98 @@ class faiDiskEntry extends plugin
       $smarty->assign($name."ACL",$acl);
     }
    
-    $smarty->assign("sub_object_is_createable",$this->acl_is_createable());
-    $smarty->assign("freeze",preg_match("/freeze/i",$this->FAIstate));
-
-    // Fill boxes
-    $smarty->assign("fstabkeys", array("device" => _("Device"), "label" => _("Label"), "uuid" => _("UUID")));
-    $smarty->assign("disklabels", array("msdos" => "MSDOS", "gpt" => "GPT"));
-    $smarty->assign("fstabkey", $this->fstabkey);
-    $smarty->assign("disklabel", $this->disklabel);
-    /* Fetch template and show the result
-     */
     $display.= $smarty->fetch(get_template_path('faiDiskEntry.tpl', TRUE));
     return($display);
   }
 
+  function getPartitionList()
+  {
+    $divlist = new divSelectBox("RaidList");
+    $disks = $this->parent->disks;
+    $objs = $disks;
+    foreach($disks as $disk){
+      foreach($disk['partitions'] as $id => $part){
+        $objs[$disk['cn'].$id] = $part;
+      }
+    }
+
+    $list = array();
+    foreach($this->lvmDevices as $device){
+      $list[$device] = $device;
+
+      if(isset($objs[$device]['FAIpartitionSize'])){
+        $list[$device].= _("Size").": ";
+        $list[$device].= $objs[$device]['FAIpartitionSize'];
+      }
+    }
+    return($list);
+  }
+
+  
+  function getAvailablePartitions(){
+    $array = array();
+    foreach($this->parent->disks as $disk){
+      foreach($disk['partitions'] as $key => $part){
+        $name = $disk['cn'].$key;
+        if(!isset($this->lvmDevices[$name])){
+          $array[$name] = $name;
+        }
+      }
+    }
+    return($array);
+
+  }
+
+
+  /* Remove the selected partition and shift the following partitions 
+   *  to fill gap.
+   * Additionally update the partition numbers correspondingly.
+   */
+  function removePartition($id)
+  {
+    $start = false;
+    foreach($this->partitions as $key => $part){
+      if($id == $key){
+        $start = true;
+      }
+      if($start){
+        if($this->partitions[$key]['status'] == "edited"){
+          $this->deletePartitions[$key]= $this->partitions[$key];
+          $this->deletePartitions[$key]['FAIpartitionNr']=$key;
+          unset($this->partitions[$key]);
+        }else{
+          unset($this->partitions[$key]);
+        }
+        if(isset($this->partitions[($key+1)])){
+          if(isset($this->deletePartitions[$key])){
+            unset($this->deletePartitions[$key]);
+          }
+          $this->partitions[$key] = $this->partitions[($key+1)];
+          $this->partitions[$key]['FAIpartitionNr'] = $key;
+          $this->partitions[$key]['status'] = "new";
+        }
+      }
+    }
+    $tmp= array();
+    foreach($this->partitions as $part){
+      $tmp[count($tmp)+1]=$part;
+    }
+    $this->partitions = $tmp;
+  }
+
+
+  /* Add or update a partition 
+   */
+  function updatePartition($part)
+  {
+    if(!isset($part['FAIpartitionNr']) || $part['FAIpartitionNr'] == "undefined"){
+      $part['FAIpartitionNr'] = count($this->partitions) + 1;
+      $part['cn'] = count($this->partitions) + 1;
+    }
+    $this->partitions[$part['FAIpartitionNr']] = $part;
+  }
+
+
   function generateParts()
   {
 
@@ -268,7 +380,8 @@ class faiDiskEntry extends plugin
 
    
       $action =array(
-          "string" => "<input type='image' src='images/lists/edit.png' name='EditPartition_".$key."'>",
+          "string" => "<input type='image' src='images/lists/edit.png' name='EditPartition_".$key."'>".
+                      "<input type='image' src='images/lists/trash.png' name='RemovePartition_".$key."'>",
           "attach" => "style='width:40px;'");
 
  
@@ -278,6 +391,7 @@ class faiDiskEntry extends plugin
     return($divlist->DrawList());    
   }
 
+
   function save()
   {
     $tmp = array();
@@ -286,6 +400,7 @@ class faiDiskEntry extends plugin
     /* Attach partitions */
     foreach($this->partitions as $key=>$val) {
       $this->partitions[$key]['FAIpartitionNr']=$key;
+      $this->partitions[$key]['cn']=$key;
     }
 
     /* Attach deleted */
@@ -299,6 +414,11 @@ class faiDiskEntry extends plugin
     $tmp['status']      = $this->status;
     $tmp['FAIdiskType'] = $this->FAIdiskType;
 
+    $tmp['FAIlvmDevice'] = array();
+    foreach($this->lvmDevices as $dev){
+      $tmp['FAIlvmDevice'][] = $dev;
+    } 
+
     /* Assemble flags */
     $tmp['FAIdiskOption'] = array("fstabkey:".$this->fstabkey, "disklabel:".$this->disklabel);
 
@@ -307,6 +427,51 @@ class faiDiskEntry extends plugin
       $tmp['rename']['from']  = $this->old_cn;
       $tmp['rename']['to']    = $this->DISKcn;
     }
+
+    // Build up disk options 
+    $bootable = "";
+    $resize = "";
+    $preserve_always = "";
+    $preserve_reinstall = "";
+
+    foreach($tmp['partitions'] as $id => $part){
+      if(isset($part['bootable']) && $part['bootable']){
+        $bootable .= $id.",";
+      }
+      if(isset($part['resize']) && $part['resize']){
+        $resize .= $id.",";
+      }
+      if(isset($part['preserve']) && $part['preserve']){
+        if($part['preserveType'] == "always"){
+          $preserve_always .= $id.",";
+        }else{
+          $preserve_reinstall .= $id.",";
+        }
+      }
+      $tmp['partitions'][$id]['status'] = $part['status'];
+
+      // Unset non valid attributes 
+      foreach(array("bootable","encrypted","preserve","preserveType","resize","FAIdiskType") as $attr){
+        if(isset($tmp['partitions'][$id][$attr])){
+          unset($tmp['partitions'][$id][$attr]);
+        }
+      }
+    }    
+
+    if(!empty($bootable)){
+      $tmp['FAIdiskOption'][] = "bootable:".trim($bootable,",");
+    }
+    if(!empty($resize)){
+      $tmp['FAIdiskOption'][] = "resize:".trim($resize,",");
+    }
+    if(!empty($preserve_always)){
+      $tmp['FAIdiskOption'][] = "preserve_always:".trim($preserve_always,",");
+    }
+    if(!empty($preserve_reinstall)){
+      $tmp['FAIdiskOption'][] = "preserve_reinstall:".trim($preserve_reinstall,",");
+    }
+
+    $tmp['status'] = $this->status;
     return($tmp);
   }
 
@@ -316,6 +481,14 @@ class faiDiskEntry extends plugin
   {
     if((isset($_POST['TableEntryFrameSubmitted'])) && !preg_match("/freeze/", $this->FAIstate) ){
       plugin::save_object();
+
+      // Save posted disk label and fstab key
+      if (isset($_POST['disklabel']) && preg_match("/^(msdos|gpt)$/", $_POST['disklabel'])){
+        $this->disklabel= $_POST['disklabel'];
+      }
+      if (isset($_POST['fstabkey']) && preg_match("/^(device|label|uuid)$/", $_POST['fstabkey'])){
+        $this->fstabkey= $_POST['fstabkey'];
+      }
     }
   }
 
@@ -345,61 +518,6 @@ class faiDiskEntry extends plugin
       $alreadyUsed[$attrs] = array();
     }      
 
-    foreach($this->partitions as $key => $part){
-  
-      /* Skip all checks, if preserve is set */ 
-      if($part['FAIpartitionFlags'] == "preserve"){
-        $this->partitions[$key]['FAIfsType']        = "preserve";
-        $this->partitions[$key]['FAIpartitionSize'] = "preserve";
-        continue;
-      }
-      if($part['FAImountPoint'] != "-" && (in_array($part['FAImountPoint'],$alreadyUsed['FAImountPoint']))&&($part['FAIfsType']!="swap")){
-        $message[]=sprintf(_("Please enter a unique mount point for partition %s"),($key));
-      }
-
-      if($part['FAIfsType']!="swap" && $part['FAImountPoint'] != "-"){
-        if((empty($part['FAImountPoint']))||(!((preg_match("/^\/.*/",$part['FAImountPoint']))||(preg_match("/^swap$/",$part['FAImountPoint']))))){
-          $message[]= msgPool::invalid(sprintf(_("partition %s mount point"),$key));
-        }
-      }
-      if($part['FAIfsType'] == "swap"){
-        if(in_array($part['FAIfsType'],$alreadyUsed['FAIfsType'])){
-          $message[]=sprintf(_("File system type 'swap' is already used, change file system type for partition %s."),$key);
-        }
-      }
-      if(($part['FAIfsType'] == "swap")&&(!empty($part['FAImountPoint']))&&($part['FAImountPoint']!="swap")){
-        $message[]=_("Please use 'swap' as mount point, if 'swap' is used as fs-type.");
-      }
-
-      $tmp = split("-",$part['FAIpartitionSize']);
-      switch (count($tmp)){
-        case 0:
-                $message[]= msgPool::invalid(sprintf(_("partition %s size"),$key));
-                break;
-        case 1:
-                if (!tests::is_id($tmp[0]) &&(!empty($tmp[1]))){
-                  $message[]=  msgPool::invalid(sprintf(_("partition %s size"),$key));
-                }
-                break;
-                
-        case 2:
-                if( !tests::is_id($tmp[0]) && !tests::is_id($tmp[1]) && !empty($tmp[1]) ){
-                  $message[]= msgPool::invalid(sprintf(_("partition %s size"),$key));
-                }elseif(!empty($tmp[1]) && $tmp[0]>=$tmp[1]){
-                  $message[]= msgPool::invalid(sprintf(_("partition %s size"),$key));
-                }
-                break;
-
-        default:
-                $message[]= msgPool::invalid(sprintf(_("partition %s size"),$key));
-      }
-
-      foreach($this->UsedAttrs as $attrs){
-        $alreadyUsed[$attrs][$key] = $part[$attrs];
-      }      
-    }
-
     $cnt = 0;
     foreach($this->partitions as $key => $part){
       if($part['FAIpartitionType'] == "primary"){