Code

Backport from trunk
[gosa.git] / gosa-plugins / fai / admin / fai / class_faiDiskEntry.inc
index a0dc7891655ea722c2b6a3ab4408761304540918..0c63bf53617c2b2e1e475eee21044d765655c28d 100644 (file)
@@ -5,111 +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 $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,$disk,$type)
+  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");
-
-    /* Set disk type */
+  
+    // Set default attributes 
+    $this->parent = $parent;
     $this->FAIdiskType = $type;
 
-    /* Default status is new */
-    $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 */      
-      $this->status = $disk['status'];
+      // Get devices used in volume base disks.
+      if(isset($disk['FAIlvmDevice'])){
+        $this->lvmDevices = $disk['FAIlvmDevice'];
+      }
 
-      /* Walk through partitions */
-      foreach($disk['partitions'] as $name => $values){
+      // Load default attributes 
+      $this->DISKcn          = $disk['cn'];
+      $this->DISKdescription = $disk['description'];
+      $this->is_edit         = true;
+      $this->old_cn          = $disk['cn'];
 
-        /* If a partition is already marked as delete, attach it to deletePartitions only. */
-        if($values['status'] == "delete"){
-          unset($disk['partitions'][$name]);
-          $this->deletePartitions[]=$values;
-        }else{
+      // Load partition info 
+      foreach($disk['partitions'] as $values){
 
-          /* 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";
-          }
-     
-          $disk['partitions'][$name]['old_cn']= $disk['partitions'][$name]['cn'];
-          $disk['partitions'][$name]['FAIdiskType']= $this->FAIdiskType;
-          /* Assign empty attributes, if attribute is missing */
-          foreach($this->UsedAttrs as $attr){
-            if(!isset($values[$attr])){
-              $disk['partitions'][$name][$attr]="";  
-            }
-          }
+        $name = $values['FAIpartitionNr'];
 
-          if (preg_match('/^_/', $disk['partitions'][$name]['FAIfsType'])){
-            $disk['partitions'][$name]['FAIfsType']= preg_replace('/^_/', '', $disk['partitions'][$name]['FAIfsType']);
+        // Load partition attributes  
+        $disk['partitions'][$name]['old_cn']= $disk['partitions'][$name]['cn'];
+        $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']);
+        }
       }
 
-      /* 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 others 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),","));
+            $bootable = explode(",", 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 = explode(",", trim(preg_replace("/^resize:/","",$option),","));
+            foreach($resize as $id){
+              if(isset($this->partitions[$id])){
+                $this->partitions[$id]['resize'] = TRUE;  
+              }
+            }
+            continue;
+          }
+
+          // Load preserve_always flag for partitions 
+          if (preg_match("/^preserve_always:/", $option)){
+            $preserve = explode(",", trim(preg_replace("/^preserve_always:/","",$option),","));
+            foreach($preserve as $presflag){
+              if(isset($this->partitions[$presflag])){
+                $this->partitions[$presflag]['preserve'] = TRUE;  
+                $this->partitions[$presflag]['preserveType'] = 'always';  
+              }
             }
-            break;
+            continue;
+          }
+
+          // Load preserve_reinstall flag for partitions 
+          if (preg_match("/^preserve_reinstall:/", $option)){
+            $preserve = explode(",", 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'; 
+              } 
+            }
+            continue;
           }
         }
       } else {
         $this->fstabkey= "device";
       }
     }
+
+    // Prepare lists
+    $this->diskList = new sortableListing();
+    $this->diskList->setDeleteable(true);
+    $this->diskList->setEditable(true);
+    $this->diskList->setWidth("100%");
+    $this->diskList->setHeight("400px");
+    $this->diskList->setColspecs(array('200px','*'));
+    $this->diskList->setHeader(array("Name",_("Description"),_("Type"),_("Mount point"),_("Options")));
+    $this->diskList->setDefaultSortColumn(1);
+    $this->diskList->setAcl('rwcdm'); // All ACLs, we filter on our own here.
   }
 
 
@@ -118,108 +163,98 @@ 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 ");
-      }
+    // Add partition to lvm compilation.
+    if(isset($_POST['addLvmPartition']) && isset($_POST['lvmPartitionAdd'])){
+      $name = get_post('lvmPartitionAdd');
+      $this->lvmDevices[$name] = $name;
     }
 
-    /* Check all Posts if there is something usefull for us,
-     * For example : Delete is posted as Delete_1 
-     * The number specifies the index we want to delete
-     */
-    foreach($_POST as $name => $value){
-      if((preg_match("/Delete_.*/",$name)) && 
-          $this->acl_is_removeable() && 
-          !preg_match("/freeze/i",$this->FAIstate)){
-        $tmp = split("_",$name);
-        $s_action = "remove";
-        $s_entry  = $tmp[1]; 
+    // Remove partition from lvm compilation.
+    if(isset($_POST['delLvmPartition']) && isset($_POST['physicalPartition'])){
+      $names = get_post('physicalPartition');
+      foreach($names as $name){
+        if(isset($this->lvmDevices[$name])){
+          unset($this->lvmDevices[$name]);
+        }
       }
     }
 
-    /* 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;
+    // Get list actions
+    $this->diskList->save_object();
+    $action = $this->diskList->getAction();
+    if($action['action'] == 'edit'){
+        $id = $this->diskList->getKey($action['targets'][0]);
+        if(isset($this->partitions[$id])){
+            $this->dialog = new faiPartition($this->config,$this->partitions[$id], $this,$this->FAIdiskType);
+        }
     }
-
-
-    /* Add / Edit partitions here.
-     */    
-    foreach($_POST as $name => $value){
-      if(preg_match("/^EditPartition_/",$name)){
-        $id = preg_replace("/^EditPartition_/","",$name);
-        $id = preg_replace("/_.*$/","",$id);
+    if($action['action'] == 'delete'){
+        $id = $this->diskList->getKey($action['targets'][0]);
         if(isset($this->partitions[$id])){
-          $this->dialog = new faiPartition($this->config,$this->partitions[$id], $this->FAIdiskType);
-          break;
+            $this->removePartition($id);
         }
-      } 
     }
+
+    /* Create a new partition for this disk.
+     */
     if(isset($_POST['AddPartition']) && !preg_match("/freeze/i",$this->FAIstate)){
-      $this->dialog = new faiPartition($this->config, array(), $this->FAIdiskType);
+      $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;
+
+      // Validate new partition
+      $new_partition = $this->dialog->save(); 
+      $msgs = $this->dialog->check();
+      $msgs = array_merge($msgs,$this->check_disks($new_partition));
+
+      if(!count($msgs)){
+        $this->updatePartition($new_partition);
+        $this->dialog = null;
       }else{
-        $this->partitions[] = $attrs;
+        msg_dialog::displayChecks($msgs);
       }
-      $this->dialog = null;
     }
     if($this->dialog instanceOf plugin){
       $this->dialog->save_object();
       return($this->dialog->execute());
     }
 
+    // Assign checkbox related values.
+    foreach($this->attributes as $attrs){
+      $smarty->assign($attrs,set_post($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());
-    foreach($this->attributes as $attr){
-      $smarty->assign($attr,$this->$attr);
-    }
+    $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", set_post($this->disklabel));
+    $smarty->assign("FAIdiskType", $this->FAIdiskType);
+    $smarty->assign("plist", $this->getPartitionList());
+    $smarty->assign("physicalPartitionList", $this->getAvailablePartitions());
 
+    // Assign partitions
     $tmp = $this->plInfo();
     $sacl = "";
     foreach($tmp['plProvidedAcls'] as $name => $translated){
@@ -227,82 +262,301 @@ 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 generateParts()
-  {
 
-    $divlist = new divSelectBox("DiskEntries"); 
-    foreach($this->partitions as $key => $part){
-      $number =array(
-          "string" => $part['FAIpartitionNr'],
-          "attach" => "style='width:20px;'");
-      $size   =array(
-          "string" => $part['FAIpartitionSize'],
-          "attach" => "style='width:100px;'");
-      $fstype =array(
-          "string" => $part['FAIfsType'],
-          "attach" => "style='width:60px;'");
-      $type   =array(
-          "string" => $part['FAIpartitionType'],
-          "attach" => "style='width:80px;'");
-      $opt    =array(
-          "string" => $part['FAImountOptions'],
-          "attach" => "style='width:80px;'");
-      $fsopt  =array(
-          "string" => $part['FAIfsOptions'],
-          "attach" => "style='width:80px;'");
-      $flags  =array(
-          "string" => $part['FAIpartitionFlags'],
-          "attach" => "style='width:80px;'");
-      $mntp   =array("string" => $part['FAImountPoint']);
+  /* Creates a human readable list, that contains all physical 
+   *  devices that are used by the volume group.
+   * This list will then be displayed in a html select box.
+   * (lvm)
+   */
+  function getPartitionList()
+  {
+    /* Create a list of all available disks and partitions. 
+     * This list will then be used to display detailed info.
+     */
+    $disks = $this->parent->disks;
+    foreach($disks as $dname => $disk){
 
+      // Skip currently edited disk 
+      if($disk['cn'] == $this->old_cn) continue;
    
-      $action =array(
-          "string" => "<input type='image' src='images/lists/edit.png' name='EditPartition_".$key."'>",
-          "attach" => "style='width:40px;'");
+      // Add disk 
+      $objs[$dname] = $disk;
+
+      // Add disk partitions
+      foreach($disk['partitions'] as $id => $part){
+        $part['parentDisk'] = $disk;
+        $objs[$part['cn']] = $part;
+      }
+    }
+
+    // Attach current disk setup to the details list.
+    $data = $this->save();
+    $objs[$data['cn']] = $data;
+    foreach($data['partitions'] as $part){
+      $part['parentDisk'] = $data;
+      $objs[$part['cn']] = $part;
+    }
+
+    // Walk through physical partition combinations and build up 
+    //  user friendly list with partition details.
+    $list = array();
+    foreach($this->lvmDevices as $device){
+
+      // We've a html select box here, add spaces for better readability
+      $str = $device;
+      $str = preg_replace("/ /","&nbsp;",str_pad($str,20," "));
+
+      // Add disk/partition details.
+      if(isset($objs[$device])){
+        if(isset($objs[$device]['FAIpartitionSize'])){
+          if($objs[$device]['parentDisk']['FAIdiskType'] == "raid"){
+            $str .= _("Disks").":&nbsp;";
+            $str .= preg_replace("/(:spare|:missing)/i","",$objs[$device]['FAIpartitionSize']);
+          }else{
+            $str .= _("Size").":&nbsp;";
+            $str .= $objs[$device]['FAIpartitionSize'];
+          } 
+        }
+      }
+      $list[$device] = $str;
+    }
+    return($list);
+  }
 
  
-      $fields = array($number,$type,$mntp,$size,$fstype, $opt,$fsopt,$flags,$action);
-      $divlist->AddEntry($fields);
+  /* Returns a list of available partitions that are useable in 
+   *  lvm disk setups.
+   */ 
+  function getAvailablePartitions()
+  {
+    $may = $used = array();
+    foreach($this->parent->disks as $disk){
+
+      // Skip ourselves
+      if($disk['cn'] == $this->DISKcn) continue;
+
+      // Add partition from lvm combinations
+      if($disk['FAIdiskType'] == "lvm"){
+        $used = array_merge($used,$disk['FAIlvmDevice']);
+      }
+
+      foreach($disk['partitions'] as $key => $part){
+
+        // Add disks of raid arrays, to the used list.
+        if($disk['FAIdiskType'] == "raid"){
+          foreach(explode(",",$part['FAIpartitionSize']) as $rDevice){
+            $used[] = preg_replace("/:.*$/i","",$rDevice);
+          }
+        }
+
+        // Collect all available partitions
+        if($disk['FAIdiskType'] == "disk" || $disk['FAIdiskType'] == "raid"){
+          $name = $part['cn'];
+          if(!isset($this->lvmDevices[$name])){
+            $may[] = $name;
+          }
+        }
+      }
+    }
+
+    // Check which of the available disks are unused.
+    $ret = array();
+    foreach($may as $val){
+      if(!in_array_strict($val,$used)){
+        $ret[$val] = $val;
+      }
+    }
+    return($ret);
+  }
+
+
+  /* Remove the selected partition and shift the following partitions 
+   *  to fill the gap.
+   * Additionally update the partition numbers correspondingly.
+   *  (Checks if the partition is in use, too)
+   */
+  function removePartition($id)
+  {
+    $start = false;
+
+    /* Create a list of all partitions that are used in
+     *  lvm or raid compilations.
+     */
+    $list = array();
+    foreach($this->parent->disks as $dname => $disk){
+      if($disk['FAIdiskType'] != "disk"){
+        if($disk['FAIdiskType'] == "lvm"){
+          foreach($disk['FAIlvmDevice'] as $partname){
+            $list[preg_replace("/:.*$/","",$partname)][] = $disk;
+          }
+        }
+        foreach($disk['partitions'] as $partkey => $part){
+          if($disk['FAIdiskType'] == "raid"){
+            foreach(explode(",",$part['FAIpartitionSize']) as $partname){
+              $list[preg_replace("/:.*$/","",$partname)][] = $disk;
+            }
+          }
+        }
+      }
+    }
+
+    /* Now that we've a list of all partition references, lets check if
+     *  one of the partitions we are going to remove is still in use.
+     */
+    if(isset($list[$this->partitions[$id]['cn']])){
+      $used = array();
+      foreach($list[$this->partitions[$id]['cn']] as $disk){
+        $used[$disk['cn']] = $disk['cn'];
+      }
+      $used = implode(",",$used);
+      msg_dialog::display(_("Error"),
+          sprintf(_("The disk cannot be deleted while it is used in the '%s' disk definition!"),
+            $used), ERROR_DIALOG);
+    }else{
+      unset($this->partitions[$id]);
+    }
+  }
+
+  
+  function get_free_partition_number()
+  {
+    $used = array();
+    foreach($this->partitions as $key => $part){
+      $used[$key] = $part['FAIpartitionNr'];
     }
-    return($divlist->DrawList());    
+    $id = 1;
+    while(in_array_strict($id,$used) && $id < 16 ){
+      $id++;
+    }
+    return($id);
   }
 
+
+
+  /* Add or update a partition 
+   */
+  function updatePartition($part)
+  {
+    if(!isset($part['FAIpartitionNr']) || $part['FAIpartitionNr'] == "undefined"){
+      $part['FAIpartitionNr'] = $this->get_free_partition_number();
+    }
+
+    /* Update the disk cn -       
+     * Do NOT touch the partition 'cn' in case of lvm or raid devices. 
+     */
+    if($this->FAIdiskType == "disk"){
+      $part['cn'] = $this->DISKcn.$part['FAIpartitionNr'];
+    }
+
+    /* Check if we've to update partition names of lvm compilations.
+     */ 
+    if($this->FAIdiskType == "lvm"){
+      if(isset($this->partitions[$part['FAIpartitionNr']])){
+        $old_cn = $this->partitions[$part['FAIpartitionNr']]['cn'];
+        $new_cn = $part['cn'];
+        if(isset($this->lvmDevices[$old_cn])){
+          unset($this->lvmDevices[$old_cn]);
+          $this->lvmDevices[$new_cn] = $new_cn;
+        }
+      }
+    }
+
+    /* Set raid names to md#
+     */ 
+    if($this->FAIdiskType == "raid"){
+      $part['cn'] = 'md'.$part['FAIpartitionNr'];
+    }
+
+    $this->partitions[$part['FAIpartitionNr']] = $part;
+  }
+
+
+  /* This method generates the partition listing with all necessary info,
+   *  depending on the disk type.
+   */
+  function generateParts()
+  {
+    $data = $lData = array();
+    foreach($this->partitions as $key => $part){
+    
+      $cn       = $part['cn'];
+      $desc     = $part['description'];
+      $number   = $part['FAIpartitionNr'];
+      $size     = $part['FAIpartitionSize'];
+      $type     = $part['FAIpartitionType'];
+
+      // Remove encryption info from the mount point.
+      $mnt = $part['FAImountPoint'];
+      if(preg_match("/:encrypt/", $mnt)){
+        $mnt = preg_replace("/:encrypt/","",$mnt);
+      }
+
+      // create human readable strings out of the flags.
+      $opt = "";
+      if(isset($part['encrypted']) && $part['encrypted']){
+        $opt.= "&nbsp;"._("encrypted").", ";
+      }      
+      if(isset($part['bootable']) && $part['bootable']){
+        $opt.= "&nbsp;"._("boot able").", ";
+      }      
+      if(isset($part['preserve']) && $part['preserve']){
+        $opt.= "&nbsp;"._("preserve").":&nbsp;".$part['preserveType'].", ";
+      }     
+
+      // Combine options to a single table col. 
+      $opt = "<i>".preg_replace('/, $/',"",$opt)."&nbsp;</i>";
+
+      // Build up info table, depending on the disk type. 
+      $data[$key]=$key;
+      if($this->FAIdiskType == "lvm"){
+        $lData[$key]=array('data' => array($cn,$desc,"",$mnt,$opt,$size));
+      }elseif($this->FAIdiskType == "raid"){
+        $raid = $part['FAIpartitionType']." (".$part['FAIpartitionSize'].")";
+        $lData[$key]=array('data' => array($cn,$desc,$raid,$mnt,$opt));
+      }else{
+        $lData[$key]=array('data' => array("",$desc,$type,$mnt,$opt,$size));
+      }
+    }
+    $this->diskList->setListData($data,$lData);
+    $acl = "rwcdm";
+    if(preg_match("/freeze/", $this->FAIstate)) $acl = "r";
+    $this->diskList->setAcl($acl);;
+    $this->diskList->update();
+    return($this->diskList->render());
+  }
+
+
   function save()
   {
     $tmp = array();
     $tmp['cn']          = $this->DISKcn;
 
-    /* Attach partitions */
+    /* Attach partitions. 
+     * And prepare names and numbers.
+     */
     foreach($this->partitions as $key=>$val) {
       $this->partitions[$key]['FAIpartitionNr']=$key;
-    }
-
-    /* Attach deleted */
-    foreach($this->deletePartitions as $key=>$val) {
-      $this->partitions[$key."-delete"]=$val;
-      $this->partitions[$key."-delete"]['status']="delete";
+      if($this->FAIdiskType == "disk"){
+        $this->partitions[$key]['cn'] = $this->DISKcn.$key;
+      }elseif($this->FAIdiskType == "lvm"){
+        $this->partitions[$key]['FAIpartitionType'] = 'lvm';
+      }
     }
 
     $tmp['description'] = $this->DISKdescription;
     $tmp['partitions']  = $this->partitions;
-    $tmp['status']      = $this->status;
     $tmp['FAIdiskType'] = $this->FAIdiskType;
 
+    // Add lvm devices if available.
+    $tmp['FAIlvmDevice'] = array();
+    foreach($this->lvmDevices as $dev){
+      $tmp['FAIlvmDevice'][] = $dev;
+    } 
+
     /* Assemble flags */
     $tmp['FAIdiskOption'] = array("fstabkey:".$this->fstabkey, "disklabel:".$this->disklabel);
 
@@ -311,6 +565,53 @@ 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 = "";
+
+    /* Assemble boot, resize and preserve flags 
+     */
+    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.",";
+        }
+      }
+
+      // 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]);
+        }
+      }
+    }    
+
+    /* Assembe disk flags
+     */
+    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,",");
+    }
+
     return($tmp);
   }
 
@@ -320,6 +621,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= get_post('disklabel');
+      }
+      if (isset($_POST['fstabkey']) && preg_match("/^(device|label|uuid)$/", $_POST['fstabkey'])){
+        $this->fstabkey= get_post('fstabkey');
+      }
     }
   }
 
@@ -338,86 +647,46 @@ class faiDiskEntry extends plugin
     if(preg_match("/[^a-z0-9_\-]/i",$d)){
       $message[] = msgPool::invalid(_("Name"),$d,"/[a-z0-9_\-]/i");
     }
-       
-    /* check every partition.
-     * if there is an invalid value defined, append an errorstr to message
-     */
 
-    /* Array that contain every partitionname mountpoint etc already assigned */
-    $alreadyUsed    = array();
-    foreach($this->UsedAttrs as $attrs){
-      $alreadyUsed[$attrs] = array();
-    }      
+    return ($message);
+  }
 
-    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.");
-      }
+  /* Checks the disk combinations.
+   * 
+   */  
+  function check_disks($disk_to_add = array())
+  {
+    $msgs = array();
 
-      $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));
+    /* Check 'disk' combinations. 
+     *  - There can be four primary partitions.
+     *  - If there is at least one 'logical' partition, then there can be only 
+     *     three 'primary' partitions.
+     */    
+    if($this->FAIdiskType == "disk"){
+     
+      $types = array('logical' => array(), 'primary' => array());
+      $types[$disk_to_add['FAIpartitionType']][$disk_to_add['FAIpartitionNr']] = 1;
+      foreach($this->partitions as $key => $part){
+        $types[$part['FAIpartitionType']][$part['FAIpartitionNr']] = 1;
       }
 
-      foreach($this->UsedAttrs as $attrs){
-        $alreadyUsed[$attrs][$key] = $part[$attrs];
-      }      
-    }
-
-    $cnt = 0;
-    foreach($this->partitions as $key => $part){
-      if($part['FAIpartitionType'] == "primary"){
-        $cnt ++ ; 
+      // There can only be four primary partitions per disk - without any logical partition.
+      if(count($types['logical']) == 0){
+        if(count($types['primary']) > 4){
+          $msgs[] = _("You have more than four primary partition table entries in your configuration, please check your configuration twice.");
+        }
+      }else{
+        if(count($types['primary']) > 3){
+          $msgs[] = _("You cannot have more than three primary partition while using logical partitions, please check your configuration twice.");
+        }
       }
     }
-    if($cnt > 3){
-      $message[] = _("You have more than 3 primary partition table entries in your configuration, please check your configuration twice.");
-    }
 
-    return ($message);
-  }
+    return($msgs);
+  }  
 
-  
 
   /* Return plugin informations for acl handling */
   static function plInfo()
@@ -444,7 +713,6 @@ class faiDiskEntry extends plugin
             "FAIpartitionFlags" => _("Partition flags"))
           ));
   }
-
  
 }