[Fai-commit] r4954 - people/michael/features/setup_harddisks_2/implementation/lib trunk/lib/setup-storage

lange at alioth.debian.org lange at alioth.debian.org
Thu Jun 12 11:37:52 UTC 2008


Author: lange
Date: 2008-06-12 11:37:51 +0000 (Thu, 12 Jun 2008)
New Revision: 4954

Added:
   trunk/lib/setup-storage/Sizes.pm
Removed:
   people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm
Log:
moving setup-storage to trunk

Deleted: people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm	2008-06-12 11:37:48 UTC (rev 4953)
+++ people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm	2008-06-12 11:37:51 UTC (rev 4954)
@@ -1,692 +0,0 @@
-#!/usr/bin/perl -w
-
-#*********************************************************************
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# A copy of the GNU General Public License is available as
-# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
-# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
-# can also obtain it by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-#*********************************************************************
-
-use strict;
-
-################################################################################
-#
-# @file sizes.pm
-#
-# @brief Compute the size of the partitions and volumes to be created
-#
-# $Id$
-#
-# @author Christian Kern, Michael Tautschnig
-# @date Sun Jul 23 16:09:36 CEST 2006
-#
-################################################################################
-
-package FAI;
-
-################################################################################
-#
-# @brief Build an array $start,$end from ($start-$end)
-#
-# @param $rstr Range string
-# @param $size Size and unit
-#
-# @return ($start,$end) in bytes
-#
-################################################################################
-sub make_range {
-
-  use POSIX qw(ceil floor);
-
-  my ($rstr, $size) = @_;
-  # convert size to Bytes
-  my $size_b = &FAI::convert_unit($size) * 1024.0 * 1024.0;
-  # check the format of the string
-  ($rstr =~ /^(\d+(\.\d+)?%?)-(\d+(\.\d+)?%?)$/) or &FAI::internal_error("Invalid range");
-  my ($start, $end) = ($1, $3);
-  # start may be given in percents of the size
-  if ($start =~ /^(\d+(\.\d+)?)%$/) {
-    # rewrite it to bytes
-    $start = POSIX::floor($size_b * $1 / 100);
-  } else {
-    # it is given in megabytes, make it bytes
-    $start = $start * 1024.0 * 1024.0;
-  }
-
-  # end may be given in percents of the size
-  if ( $end =~ /^(\d+(\.\d+)?)%$/ ) {
-    # rewrite it to bytes
-    $end = POSIX::ceil($size_b * $1 / 100);
-  } else {
-    # it is given in megabytes, make it bytes
-    $end = $end * 1024.0 * 1024.0;
-  }
-
-  # make sure that $end >= $start
-  ($end >= $start) or &FAI::internal_error("end < start");
-
-  return ($start, $end);
-}
-
-################################################################################
-#
-# @brief Estimate the size of the device $dev
-#
-# @param $dev Device the size of which should be determined. This may be a
-# a partition, a RAID device or an entire disk.
-#
-# @return the size of the device in megabytes
-#
-################################################################################
-sub estimate_size {
-  my ($dev) = @_;
-
-  # try the entire disk first; we then use the data from the current
-  # configuration; this matches in fact for than the allowable strings, but
-  # this should be caught later on
-  my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($dev);
-  if (1 == $i_p_d && -1 == $part_no) {
-    defined ($FAI::current_config{$dev}{end_byte})
-      or die "$dev is not a valid block device\n";
-
-    # the size is known, return it
-    return ($FAI::current_config{$dev}{end_byte} -
-        $FAI::current_config{$dev}{begin_byte}) / (1024 * 1024);
-  }
-
-  # try a partition
-  elsif (1 == $i_p_d && $part_no > -1) {
-    # the size is configured, return it
-    defined ($FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{eff_size})
-      and return $FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{eff_size} /
-      (1024 * 1024);
-
-    # the size is known from the current configuration on disk, return it
-    defined ($FAI::current_config{$disk}{partitions}{$part_no}{count_byte})
-      and return $FAI::current_config{$disk}{partitions}{$part_no}{count_byte} /
-      (1024 * 1024);
-
-    # the size is not known (yet?)
-    warn "Cannot determine size of $dev\n";
-    return 0;
-  }
-
-  # try RAID; estimations here are very limited and possible imprecise
-  elsif ($dev =~ /^\/dev\/md(\d+)$/) {
-
-    # the list of underlying devices
-    my @devs = ();
-
-    # the raid level, like raid0, raid5, linear, etc.
-    my $level = "";
-
-    # let's see, whether there is a configuration of this volume
-    if (defined ($FAI::configs{RAID}{volumes}{$1}{devices})) {
-      @devs  = keys %{ $FAI::configs{RAID}{volumes}{$1}{devices} };
-      $level = $FAI::configs{RAID}{volumes}{$1}{mode};
-    } elsif (defined ($FAI::current_raid_config{$1}{devices})) {
-      @devs  = $FAI::current_raid_config{$1}{devices};
-      $level = $FAI::current_raid_config{$1}{mode};
-    } else {
-      die "$dev is not a known RAID device\n";
-    }
-
-    # prepend "raid", if the mode is numeric-only
-    $level = "raid$level" if ($level =~ /^\d+$/);
-
-    # the number of devices in the volume
-    my $dev_count = scalar (@devs);
-
-    # now do the mode-specific size estimations
-    if ($level =~ /^raid[015]$/) {
-      my $min_size = &estimate_size(shift @devs);
-      foreach (@devs) {
-        my $s = &FAI::estimate_size($_);
-        $min_size = $s if ($s < $min_size);
-      }
-
-      return $min_size * POSIX::floor($dev_count / 2)
-        if ($level eq "raid1");
-      return $min_size * $dev_count if ($level eq "raid0");
-      return $min_size * ($dev_count - 1) if ($level eq "raid5");
-    } else {
-
-      # probably some more should be implemented
-      die "Don't know how to estimate the size of a $level device\n";
-    }
-  }
-
-  # otherwise we are clueless
-  else {
-    die "Cannot determine size of $dev - scheme unknown\n";
-  }
-}
-
-################################################################################
-#
-# @brief Compute the desired sizes of logical volumes
-#
-################################################################################
-sub compute_lv_sizes {
-
-  # loop through all device configurations
-  foreach my $config (keys %FAI::configs) {
-
-    # for RAID or physical disks there is nothing to be done here
-    next if ($config eq "RAID" || $config =~ /^PHY_./);
-    ($config =~ /^VG_(.+)$/) or &FAI::internal_error("invalid config entry $config");
-    next if ($1 eq "--ANY--");
-    my $vg = $1; # the volume group name
-
-    # compute the size of the volume group; this is not exact, but should at
-    # least give a rough estimation, we assume 1 % of overhead; the value is
-    # stored in megabytes
-    my $vg_size = 0;
-    foreach my $dev (keys %{ $FAI::configs{$config}{devices} }) {
-
-      # $dev may be a partition, an entire disk or a RAID device; otherwise we
-      # cannot deal with it
-      $vg_size += &FAI::estimate_size($dev);
-    }
-
-    # now subtract 1% of overhead
-    $vg_size *= 0.99;
-
-    # the volumes that require redistribution of free space
-    my @redist_list = ();
-
-    # the minimum and maximum space required in this volume group
-    my $min_space = 0;
-    my $max_space = 0;
-
-    # set effective sizes where available
-    foreach my $lv (keys %{ $FAI::configs{$config}{volumes} }) {
-      # reference to the size of the current logical volume
-      my $lv_size = (\%FAI::configs)->{$config}->{volumes}->{$lv}->{size};
-      # get the effective sizes (in Bytes) from the range
-      my ($start, $end) = &FAI::make_range($lv_size->{range}, "${vg_size}MB");
-      # make them MB
-      $start /= 1024.0 * 1024.0;
-      $end /= 1024.0 * 1024.0;
-
-      # increase the used space
-      $min_space += $start;
-      $max_space += $end;
-
-      # write back the range in MB
-      $lv_size->{range} = "$start-$end";
-
-      # the size is fixed
-      if ($start == $end) { 
-        # write the size back to the configuration
-        $lv_size->{eff_size} = $start;
-      } else {
-
-        # add this volume to the redistribution list
-        push @redist_list, $lv;
-      }
-    }
-
-    # test, whether the configuration fits on the volume group at all
-    ($min_space < $vg_size)
-      or die "Volume group $vg requires $min_space MB, but available space was estimated to be $vg_size\n";
-
-    # the extension factor
-    my $redist_factor = 0;
-    $redist_factor = ($vg_size - $min_space) / ($max_space - $min_space)
-      if ($max_space > $min_space);
-
-    # update all sizes that are still ranges
-    foreach my $lv (@redist_list) {
-
-      # get the range again
-      my ($start, $end) =
-      &FAI::make_range($FAI::configs{$config}{volumes}{$lv}{size}{range}, "${vg_size}MB");
-      # make them MB
-      $start /= 1024.0 * 1024.0;
-      $end /= 1024.0 * 1024.0;
-
-      # write the final size
-      $FAI::configs{$config}{volumes}{$lv}{size}{eff_size} =
-        $start + (($end - $start) * $redist_factor);
-    }
-  }
-}
-        
-################################################################################
-#
-# @brief Handle preserved partitions while computing the size of partitions
-#
-# @param $part_id Partition id within $config
-# @param $config Disk config
-# @param $current_disk Current config of this disk
-# @param $next_start Start of the next partition
-# @param $min_req_total_space Minimum space required on disk
-#
-# @return Updated values of ($next_start, $min_req_total_space)
-#
-################################################################################
-sub do_partition_preserve {
-
-  my ($part_id, $config, $current_disk, $next_start, $min_req_total_space) = @_;
-      
-  # reference to the current partition
-  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
-
-  # a partition that should be preserved must exist already
-  defined($current_disk->{partitions}->{$part_id})
-    or die "$part_id can't be preserved, it does not exist.\n";
-
-  my $curr_part = $current_disk->{partitions}->{$part_id};
-
-  ($next_start > $curr_part->{begin_byte})
-    and die "Previous partitions overflow begin of preserved partition $part_id\n";
-
-  # set the effective size to the value known already
-  $part->{size}->{eff_size} = $curr_part->{count_byte};
-
-  # copy the start_byte and end_byte information
-  $part->{start_byte} = $curr_part->{begin_byte};
-  $part->{end_byte} = $curr_part->{end_byte};
-
-  # and add it to the total disk space required by this config
-  $min_req_total_space += $part->{size}->{eff_size};
-
-  # set the next start
-  $next_start = $part->{end_byte} + 1;
-
-  # several msdos specific parts
-  if ($FAI::configs{$config}{disklabel} eq "msdos") {
-
-    # make sure the partition ends at a cylinder boundary
-    (0 == ($curr_part->{end_byte} + 1)
-        % ($current_disk->{sector_size} *
-          $current_disk->{bios_sectors_per_track} *
-          $current_disk->{bios_heads})) or 
-      die "Preserved partition $part_id does not end at a cylinder boundary\n";
-
-    # add one head of disk usage if this is a logical partition
-    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size} if ($part_id > 4);
-
-    # extended partitions consume no space
-    if ($part->{size}->{extended}) {
-
-      # revert the addition of the size
-      $min_req_total_space -= $part->{size}->{eff_size};
-
-      # set the next start to the start of the extended partition
-      $next_start = $part->{start_byte};
-    }
-  }
-
-  # on gpt, ensure that the partition ends at a sector boundary
-  if ($FAI::configs{$config}{disklabel} eq "gpt") {
-    (0 == ($current_disk->{partitions}{$part_id}{end_byte} + 1)
-        % $current_disk->{sector_size})
-      or die "Preserved partition $part_id does not end at a sector boundary\n";
-  }
-
-  return ($next_start, $min_req_total_space);
-}
-
-################################################################################
-#
-# @brief Handle extended partitions while computing the size of partitions
-#
-# @param $part_id Partition id within $config
-# @param $config Disk config
-# @param $current_disk Current config of this disk
-#
-################################################################################
-sub do_partition_extended {
-
-  my ($part_id, $config, $current_disk) = @_;
-      
-  # reference to the current partition
-  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
-
-  ($FAI::configs{$config}{disklabel} eq "msdos")
-    or die "found an extended partition on a non-msdos disklabel\n";
-
-  # ensure that it is a primary partition
-  ($part_id <= 4) or
-    &FAI::internal_error("Extended partition wouldn't be a primary one");
-
-  my $epbr_size = $current_disk->{bios_sectors_per_track} *
-    $current_disk->{sector_size};
-
-  # initialise the size and the start byte
-  $part->{size}->{eff_size} = 0;
-  $part->{start_byte} = -1;
-
-  foreach my $p (&numsort(keys %{ $FAI::configs{$config}{partitions} })) {
-    next if ($p < 5);
-
-    $part->{start_byte} = $FAI::configs{$config}{partitions}{$p}{start_byte} -
-      $epbr_size if (-1 == $part->{start_byte});
-
-    $part->{size}->{eff_size} += $FAI::configs{$config}{partitions}{$p}{size}{eff_size} +
-      $epbr_size;
-
-    $part->{end_byte} = $FAI::configs{$config}{partitions}{$p}{end_byte};
-  }
-
-  ($part->{size}->{eff_size} > 0)
-    or die "Extended partition has a size of 0\n";
-}
-
-################################################################################
-#
-# @brief Handle all other partitions while computing the size of partitions
-#
-# @param $part_id Partition id within $config
-# @param $config Disk config
-# @param $current_disk Current config of this disk
-# @param $next_start Start of the next partition
-# @param $min_req_total_space Minimum space required on disk
-# @param $worklist Reference to the remaining partitions
-#
-# @return Updated values of ($next_start, $min_req_total_space)
-#
-################################################################################
-sub do_partition_real {
-
-  my ($part_id, $config, $current_disk, $next_start, $min_req_total_space,
-    $worklist) = @_;
-      
-  # reference to the current partition
-  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
-        
-  my ($start, $end) = &FAI::make_range($part->{size}->{range},
-    $current_disk->{size} . "B");
-
-  # check, whether the size is fixed
-  if ($end != $start) {
-
-    # the end of the current range (may be the end of the disk or some
-    # preserved partition or an ntfs volume to be resized)
-    my $end_of_range = -1;
-
-   # minimum space required by all partitions, i.e., the lower ends of the
-   # ranges
-   # $min_req_space counts up to the next preserved partition or the
-   # end of the disk
-    my $min_req_space = 0;
-
-    # maximum useful space
-    my $max_space = 0;
-
-    # inspect all remaining entries in the worklist
-    foreach my $p (@{$worklist}) {
-
-      # we have found the delimiter
-      if ($FAI::configs{$config}{partitions}{$p}{size}{preserve} ||
-        ($FAI::configs{$config}{partitions}{$p}{size}{resize} &&
-          ($current_disk->{partitions}->{$p}->{filesystem} eq "ntfs"))) {
-        $end_of_range = $current_disk->{partitions}->{$p}->{begin_byte};
-
-        # logical partitions require the space for the EPBR to be left
-        # out
-        if (($FAI::configs{$config}{disklabel} eq "msdos")
-          && ($p > 4)) {
-          $end_of_range -= $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
-        }
-        last;
-      } elsif ($FAI::configs{$config}{partitions}{$p}{size}{extended}) {
-        next;
-      } else {
-        my ($min_size, $max_size) = &FAI::make_range(
-          $FAI::configs{$config}{partitions}{$p}{size}{range},
-          $current_disk->{size} . "B");
-
-        # logical partitions require the space for the EPBR to be left
-        # out
-        if (($FAI::configs{$config}{disklabel} eq "msdos")
-          && ($p > 4)) {
-          $min_size += $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
-          $max_size += $current_disk->{bios_sectors_per_track} *
-            $current_disk->{sector_size};
-        }
-
-        $min_req_space += $min_size;
-        $max_space     += $max_size;
-      }
-    }
-
-    # set the end if we have reached the end of the disk
-    $end_of_range = $current_disk->{end_byte} if (-1 == $end_of_range);
-
-    my $available_space = $end_of_range - $next_start + 1;
-
-    # the next boundary is closer than the minimal space that we need
-    ($available_space < $min_req_space)
-      and die "Insufficient space available for partition $part_id\n";
-
-    # the new size
-    my $scaled_size = $end;
-    $scaled_size = POSIX::floor(($end - $start) * 
-      (($available_space - $min_req_space) /
-          ($max_space - $min_req_space))) + $start
-      if ($max_space > $available_space);
-
-    ($scaled_size >= $start)
-      or &FAI::internal_error("scaled size is smaller than the desired minimum");
-
-    $start = $scaled_size;
-    $end   = $start;
-  }
-
-  # now we compute the effective locations on the disk
-  # msdos specific offset for logical partitions
-  if (($FAI::configs{$config}{disklabel} eq "msdos")
-    && ($part_id > 4)) {
-
-    # add one head of disk usage if this is a logical partition
-    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size};
-
-    # move the start byte as well
-    $next_start += $current_disk->{bios_sectors_per_track} *
-      $current_disk->{sector_size};
-  }
-
-  # partition starts at where we currently are, or remains fixed in case of
-  # resized ntfs
-  if ($FAI::configs{$config}{partitions}{$part_id}{size}{resize} &&
-    ($current_disk->{partitions}->{$part_id}->{filesystem} eq "ntfs")) {
-    ($next_start <= $current_disk->{partitions}->{$part_id}->{begin_byte}) 
-      or die "Cannot preserve start byte of ntfs volume on partition $part_id, space before it is too small\n";
-    $next_start = $current_disk->{partitions}->{$part_id}->{begin_byte};
-  }
-  $FAI::configs{$config}{partitions}{$part_id}{start_byte} =
-    $next_start;
-
-  # the end may need some alignment, depending on the disk label
-  my $end_byte = $next_start + $start - 1;
-
-  # on msdos, ensure that the partition ends at a cylinder boundary
-  if ($FAI::configs{$config}{disklabel} eq "msdos") {
-    $end_byte -=
-      ($end_byte + 1) % ($current_disk->{sector_size} *
-        $current_disk->{bios_sectors_per_track} *
-        $current_disk->{bios_heads});
-  }
-
-  # on gpt, ensure that the partition ends at a sector boundary
-  if ($FAI::configs{$config}{disklabel} eq "gpt") {
-    $end_byte -=
-      ($end_byte + 1) % $current_disk->{sector_size};
-  }
-
-  # set $start and $end to the effective values
-  $start = $end_byte - $next_start + 1;
-  $end   = $start;
-
-  # write back the size spec in bytes
-  $part->{size}->{range} = $start . "-" . $end;
-
-  # then set eff_size to a proper value
-  $part->{size}->{eff_size} = $start;
-
-  # write the end byte to the configuration
-  $part->{end_byte} = $end_byte;
-
-  # and add it to the total disk space required by this config
-  $min_req_total_space += $part->{size}->{eff_size};
-
-  # set the next start
-  $next_start = $part->{end_byte} + 1;
-
-  return ($next_start, $min_req_total_space);
-}
-
-################################################################################
-#
-# @brief Compute the desired sizes of the partitions and test feasibility
-# thereof.
-#
-################################################################################
-sub compute_partition_sizes
-{
-
-  # loop through all device configurations
-  foreach my $config (keys %FAI::configs) {
-
-    # for RAID or LVM, there is nothing to be done here
-    next if ($config eq "RAID" || $config =~ /^VG_./);
-    ($config =~ /^PHY_(.+)$/) or &FAI::internal_error("invalid config entry $config");
-    # nothing to be done, if this is a configuration for a virtual disk
-    next if $FAI::configs{$config}{virtual};
-    my $disk = $1; # the device name of the disk
-    # test, whether $disk is a block special device
-    (-b $disk) or die "$disk is not a valid device name\n";
-    # reference to the current disk config
-    my $current_disk = $FAI::current_config{$disk};
-
-    # at various points the following code highly depends on the desired disk label!
-    # initialise variables
-    # the id of the extended partition to be created, if required
-    my $extended = -1;
-
-    # the id of the current extended partition, if any; this setup only caters
-    # for a single existing extended partition!
-    my $current_extended = -1;
-
-    # find the first existing extended partition
-    foreach my $part_id (&numsort(keys %{ $current_disk->{partitions} })) {
-      if ($current_disk->{partitions}->{$part_id}->{is_extended}) {
-        $current_extended = $part_id;
-        last;
-      }
-    }
-
-    # the space required on the disk
-    my $min_req_total_space = 0;
-
-    # the start byte for the next partition
-    my $next_start = 0;
-
-    # on msdos disk labels, the first partitions starts at head #1
-    if ($FAI::configs{$config}{disklabel} eq "msdos") {
-      $next_start = $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
-
-      # the MBR requires space, too
-      $min_req_total_space += $current_disk->{bios_sectors_per_track} *
-        $current_disk->{sector_size};
-    }
-
-    # on GPT disk labels the first 34 and last 34 sectors must be left alone
-    if ($FAI::configs{$config}{disklabel} eq "gpt") {
-      $next_start = 34 * $current_disk->{sector_size};
-
-      # modify the disk to claim the space for the second partition table
-      $current_disk->{end_byte} -= 34 * $current_disk->{sector_size};
-
-      # the space required by the GPTs
-      $min_req_total_space += 2 * 34 * $current_disk->{sector_size};
-    }
-
-    # the list of partitions that we need to find start and end bytes for
-    my @worklist = (&numsort(keys %{ $FAI::configs{$config}{partitions} }));
-
-    while (scalar (@worklist))
-    {
-
-      # work on the first entry of the list
-      my $part_id = $worklist[0];
-      # reference to the current partition
-      my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
-
-      # the partition $part_id must be preserved
-      if ($part->{size}->{preserve}) {
-        ($next_start, $min_req_total_space) = &FAI::do_partition_preserve($part_id, 
-          $config, $current_disk, $next_start, $min_req_total_space);
-
-        # partition done
-        shift @worklist;
-      }
-
-      # msdos specific: deal with extended partitions
-      elsif ($part->{size}->{extended}) {
-        # make sure that there is only one extended partition
-        ($extended == -1 || 1 == scalar (@worklist))
-          or &FAI::internal_error("More than 1 extended partition");
-
-        # set the local variable to this id
-        $extended = $part_id;
-
-        # the size cannot be determined now, push it to the end of the
-        # worklist; the check against $extended being == -1 ensures that
-        # there is no indefinite loop
-        if (scalar (@worklist) > 1) {
-          push @worklist, shift @worklist;
-          next;
-        }
-
-        # determine the size of the extended partition
-        &FAI::do_partition_extended($part_id, $config, $current_disk);
-
-        # partition done
-        shift @worklist;
-      } else {
-        ($next_start, $min_req_total_space) = &FAI::do_partition_real($part_id, 
-          $config, $current_disk, $next_start, $min_req_total_space, \@worklist);
-
-        # partition done
-        shift @worklist;
-      }
-    }
-
-    # check, whether there is sufficient space on the disk
-    ($min_req_total_space > $current_disk->{size})
-      and die "Disk $disk is too small - at least $min_req_total_space bytes are required\n";
-
-    # make sure, extended partitions are only created on msdos disklabels
-    ($FAI::configs{$config}{disklabel} ne "msdos" && $extended > -1)
-      and &FAI::internal_error("extended partitions are not supported by this disklabel");
-
-    # ensure that we have done our work
-    (defined ($FAI::configs{$config}{partitions}{$_}{start_byte})
-        && defined ($FAI::configs{$config}{partitions}{$_}{end_byte}))
-      or &FAI::internal_error("start or end of partition $_ not set")
-        foreach (&numsort(keys %{ $FAI::configs{$config}{partitions} }));
-  }
-}
-
-1;
-

Copied: trunk/lib/setup-storage/Sizes.pm (from rev 4953, people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm)
===================================================================
--- trunk/lib/setup-storage/Sizes.pm	                        (rev 0)
+++ trunk/lib/setup-storage/Sizes.pm	2008-06-12 11:37:51 UTC (rev 4954)
@@ -0,0 +1,692 @@
+#!/usr/bin/perl -w
+
+#*********************************************************************
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available as
+# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
+# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
+# can also obtain it by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#*********************************************************************
+
+use strict;
+
+################################################################################
+#
+# @file sizes.pm
+#
+# @brief Compute the size of the partitions and volumes to be created
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
+package FAI;
+
+################################################################################
+#
+# @brief Build an array $start,$end from ($start-$end)
+#
+# @param $rstr Range string
+# @param $size Size and unit
+#
+# @return ($start,$end) in bytes
+#
+################################################################################
+sub make_range {
+
+  use POSIX qw(ceil floor);
+
+  my ($rstr, $size) = @_;
+  # convert size to Bytes
+  my $size_b = &FAI::convert_unit($size) * 1024.0 * 1024.0;
+  # check the format of the string
+  ($rstr =~ /^(\d+(\.\d+)?%?)-(\d+(\.\d+)?%?)$/) or &FAI::internal_error("Invalid range");
+  my ($start, $end) = ($1, $3);
+  # start may be given in percents of the size
+  if ($start =~ /^(\d+(\.\d+)?)%$/) {
+    # rewrite it to bytes
+    $start = POSIX::floor($size_b * $1 / 100);
+  } else {
+    # it is given in megabytes, make it bytes
+    $start = $start * 1024.0 * 1024.0;
+  }
+
+  # end may be given in percents of the size
+  if ( $end =~ /^(\d+(\.\d+)?)%$/ ) {
+    # rewrite it to bytes
+    $end = POSIX::ceil($size_b * $1 / 100);
+  } else {
+    # it is given in megabytes, make it bytes
+    $end = $end * 1024.0 * 1024.0;
+  }
+
+  # make sure that $end >= $start
+  ($end >= $start) or &FAI::internal_error("end < start");
+
+  return ($start, $end);
+}
+
+################################################################################
+#
+# @brief Estimate the size of the device $dev
+#
+# @param $dev Device the size of which should be determined. This may be a
+# a partition, a RAID device or an entire disk.
+#
+# @return the size of the device in megabytes
+#
+################################################################################
+sub estimate_size {
+  my ($dev) = @_;
+
+  # try the entire disk first; we then use the data from the current
+  # configuration; this matches in fact for than the allowable strings, but
+  # this should be caught later on
+  my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($dev);
+  if (1 == $i_p_d && -1 == $part_no) {
+    defined ($FAI::current_config{$dev}{end_byte})
+      or die "$dev is not a valid block device\n";
+
+    # the size is known, return it
+    return ($FAI::current_config{$dev}{end_byte} -
+        $FAI::current_config{$dev}{begin_byte}) / (1024 * 1024);
+  }
+
+  # try a partition
+  elsif (1 == $i_p_d && $part_no > -1) {
+    # the size is configured, return it
+    defined ($FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{eff_size})
+      and return $FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{eff_size} /
+      (1024 * 1024);
+
+    # the size is known from the current configuration on disk, return it
+    defined ($FAI::current_config{$disk}{partitions}{$part_no}{count_byte})
+      and return $FAI::current_config{$disk}{partitions}{$part_no}{count_byte} /
+      (1024 * 1024);
+
+    # the size is not known (yet?)
+    warn "Cannot determine size of $dev\n";
+    return 0;
+  }
+
+  # try RAID; estimations here are very limited and possible imprecise
+  elsif ($dev =~ /^\/dev\/md(\d+)$/) {
+
+    # the list of underlying devices
+    my @devs = ();
+
+    # the raid level, like raid0, raid5, linear, etc.
+    my $level = "";
+
+    # let's see, whether there is a configuration of this volume
+    if (defined ($FAI::configs{RAID}{volumes}{$1}{devices})) {
+      @devs  = keys %{ $FAI::configs{RAID}{volumes}{$1}{devices} };
+      $level = $FAI::configs{RAID}{volumes}{$1}{mode};
+    } elsif (defined ($FAI::current_raid_config{$1}{devices})) {
+      @devs  = $FAI::current_raid_config{$1}{devices};
+      $level = $FAI::current_raid_config{$1}{mode};
+    } else {
+      die "$dev is not a known RAID device\n";
+    }
+
+    # prepend "raid", if the mode is numeric-only
+    $level = "raid$level" if ($level =~ /^\d+$/);
+
+    # the number of devices in the volume
+    my $dev_count = scalar (@devs);
+
+    # now do the mode-specific size estimations
+    if ($level =~ /^raid[015]$/) {
+      my $min_size = &estimate_size(shift @devs);
+      foreach (@devs) {
+        my $s = &FAI::estimate_size($_);
+        $min_size = $s if ($s < $min_size);
+      }
+
+      return $min_size * POSIX::floor($dev_count / 2)
+        if ($level eq "raid1");
+      return $min_size * $dev_count if ($level eq "raid0");
+      return $min_size * ($dev_count - 1) if ($level eq "raid5");
+    } else {
+
+      # probably some more should be implemented
+      die "Don't know how to estimate the size of a $level device\n";
+    }
+  }
+
+  # otherwise we are clueless
+  else {
+    die "Cannot determine size of $dev - scheme unknown\n";
+  }
+}
+
+################################################################################
+#
+# @brief Compute the desired sizes of logical volumes
+#
+################################################################################
+sub compute_lv_sizes {
+
+  # loop through all device configurations
+  foreach my $config (keys %FAI::configs) {
+
+    # for RAID or physical disks there is nothing to be done here
+    next if ($config eq "RAID" || $config =~ /^PHY_./);
+    ($config =~ /^VG_(.+)$/) or &FAI::internal_error("invalid config entry $config");
+    next if ($1 eq "--ANY--");
+    my $vg = $1; # the volume group name
+
+    # compute the size of the volume group; this is not exact, but should at
+    # least give a rough estimation, we assume 1 % of overhead; the value is
+    # stored in megabytes
+    my $vg_size = 0;
+    foreach my $dev (keys %{ $FAI::configs{$config}{devices} }) {
+
+      # $dev may be a partition, an entire disk or a RAID device; otherwise we
+      # cannot deal with it
+      $vg_size += &FAI::estimate_size($dev);
+    }
+
+    # now subtract 1% of overhead
+    $vg_size *= 0.99;
+
+    # the volumes that require redistribution of free space
+    my @redist_list = ();
+
+    # the minimum and maximum space required in this volume group
+    my $min_space = 0;
+    my $max_space = 0;
+
+    # set effective sizes where available
+    foreach my $lv (keys %{ $FAI::configs{$config}{volumes} }) {
+      # reference to the size of the current logical volume
+      my $lv_size = (\%FAI::configs)->{$config}->{volumes}->{$lv}->{size};
+      # get the effective sizes (in Bytes) from the range
+      my ($start, $end) = &FAI::make_range($lv_size->{range}, "${vg_size}MB");
+      # make them MB
+      $start /= 1024.0 * 1024.0;
+      $end /= 1024.0 * 1024.0;
+
+      # increase the used space
+      $min_space += $start;
+      $max_space += $end;
+
+      # write back the range in MB
+      $lv_size->{range} = "$start-$end";
+
+      # the size is fixed
+      if ($start == $end) { 
+        # write the size back to the configuration
+        $lv_size->{eff_size} = $start;
+      } else {
+
+        # add this volume to the redistribution list
+        push @redist_list, $lv;
+      }
+    }
+
+    # test, whether the configuration fits on the volume group at all
+    ($min_space < $vg_size)
+      or die "Volume group $vg requires $min_space MB, but available space was estimated to be $vg_size\n";
+
+    # the extension factor
+    my $redist_factor = 0;
+    $redist_factor = ($vg_size - $min_space) / ($max_space - $min_space)
+      if ($max_space > $min_space);
+
+    # update all sizes that are still ranges
+    foreach my $lv (@redist_list) {
+
+      # get the range again
+      my ($start, $end) =
+      &FAI::make_range($FAI::configs{$config}{volumes}{$lv}{size}{range}, "${vg_size}MB");
+      # make them MB
+      $start /= 1024.0 * 1024.0;
+      $end /= 1024.0 * 1024.0;
+
+      # write the final size
+      $FAI::configs{$config}{volumes}{$lv}{size}{eff_size} =
+        $start + (($end - $start) * $redist_factor);
+    }
+  }
+}
+        
+################################################################################
+#
+# @brief Handle preserved partitions while computing the size of partitions
+#
+# @param $part_id Partition id within $config
+# @param $config Disk config
+# @param $current_disk Current config of this disk
+# @param $next_start Start of the next partition
+# @param $min_req_total_space Minimum space required on disk
+#
+# @return Updated values of ($next_start, $min_req_total_space)
+#
+################################################################################
+sub do_partition_preserve {
+
+  my ($part_id, $config, $current_disk, $next_start, $min_req_total_space) = @_;
+      
+  # reference to the current partition
+  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
+
+  # a partition that should be preserved must exist already
+  defined($current_disk->{partitions}->{$part_id})
+    or die "$part_id can't be preserved, it does not exist.\n";
+
+  my $curr_part = $current_disk->{partitions}->{$part_id};
+
+  ($next_start > $curr_part->{begin_byte})
+    and die "Previous partitions overflow begin of preserved partition $part_id\n";
+
+  # set the effective size to the value known already
+  $part->{size}->{eff_size} = $curr_part->{count_byte};
+
+  # copy the start_byte and end_byte information
+  $part->{start_byte} = $curr_part->{begin_byte};
+  $part->{end_byte} = $curr_part->{end_byte};
+
+  # and add it to the total disk space required by this config
+  $min_req_total_space += $part->{size}->{eff_size};
+
+  # set the next start
+  $next_start = $part->{end_byte} + 1;
+
+  # several msdos specific parts
+  if ($FAI::configs{$config}{disklabel} eq "msdos") {
+
+    # make sure the partition ends at a cylinder boundary
+    (0 == ($curr_part->{end_byte} + 1)
+        % ($current_disk->{sector_size} *
+          $current_disk->{bios_sectors_per_track} *
+          $current_disk->{bios_heads})) or 
+      die "Preserved partition $part_id does not end at a cylinder boundary\n";
+
+    # add one head of disk usage if this is a logical partition
+    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
+      $current_disk->{sector_size} if ($part_id > 4);
+
+    # extended partitions consume no space
+    if ($part->{size}->{extended}) {
+
+      # revert the addition of the size
+      $min_req_total_space -= $part->{size}->{eff_size};
+
+      # set the next start to the start of the extended partition
+      $next_start = $part->{start_byte};
+    }
+  }
+
+  # on gpt, ensure that the partition ends at a sector boundary
+  if ($FAI::configs{$config}{disklabel} eq "gpt") {
+    (0 == ($current_disk->{partitions}{$part_id}{end_byte} + 1)
+        % $current_disk->{sector_size})
+      or die "Preserved partition $part_id does not end at a sector boundary\n";
+  }
+
+  return ($next_start, $min_req_total_space);
+}
+
+################################################################################
+#
+# @brief Handle extended partitions while computing the size of partitions
+#
+# @param $part_id Partition id within $config
+# @param $config Disk config
+# @param $current_disk Current config of this disk
+#
+################################################################################
+sub do_partition_extended {
+
+  my ($part_id, $config, $current_disk) = @_;
+      
+  # reference to the current partition
+  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
+
+  ($FAI::configs{$config}{disklabel} eq "msdos")
+    or die "found an extended partition on a non-msdos disklabel\n";
+
+  # ensure that it is a primary partition
+  ($part_id <= 4) or
+    &FAI::internal_error("Extended partition wouldn't be a primary one");
+
+  my $epbr_size = $current_disk->{bios_sectors_per_track} *
+    $current_disk->{sector_size};
+
+  # initialise the size and the start byte
+  $part->{size}->{eff_size} = 0;
+  $part->{start_byte} = -1;
+
+  foreach my $p (&numsort(keys %{ $FAI::configs{$config}{partitions} })) {
+    next if ($p < 5);
+
+    $part->{start_byte} = $FAI::configs{$config}{partitions}{$p}{start_byte} -
+      $epbr_size if (-1 == $part->{start_byte});
+
+    $part->{size}->{eff_size} += $FAI::configs{$config}{partitions}{$p}{size}{eff_size} +
+      $epbr_size;
+
+    $part->{end_byte} = $FAI::configs{$config}{partitions}{$p}{end_byte};
+  }
+
+  ($part->{size}->{eff_size} > 0)
+    or die "Extended partition has a size of 0\n";
+}
+
+################################################################################
+#
+# @brief Handle all other partitions while computing the size of partitions
+#
+# @param $part_id Partition id within $config
+# @param $config Disk config
+# @param $current_disk Current config of this disk
+# @param $next_start Start of the next partition
+# @param $min_req_total_space Minimum space required on disk
+# @param $worklist Reference to the remaining partitions
+#
+# @return Updated values of ($next_start, $min_req_total_space)
+#
+################################################################################
+sub do_partition_real {
+
+  my ($part_id, $config, $current_disk, $next_start, $min_req_total_space,
+    $worklist) = @_;
+      
+  # reference to the current partition
+  my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
+        
+  my ($start, $end) = &FAI::make_range($part->{size}->{range},
+    $current_disk->{size} . "B");
+
+  # check, whether the size is fixed
+  if ($end != $start) {
+
+    # the end of the current range (may be the end of the disk or some
+    # preserved partition or an ntfs volume to be resized)
+    my $end_of_range = -1;
+
+   # minimum space required by all partitions, i.e., the lower ends of the
+   # ranges
+   # $min_req_space counts up to the next preserved partition or the
+   # end of the disk
+    my $min_req_space = 0;
+
+    # maximum useful space
+    my $max_space = 0;
+
+    # inspect all remaining entries in the worklist
+    foreach my $p (@{$worklist}) {
+
+      # we have found the delimiter
+      if ($FAI::configs{$config}{partitions}{$p}{size}{preserve} ||
+        ($FAI::configs{$config}{partitions}{$p}{size}{resize} &&
+          ($current_disk->{partitions}->{$p}->{filesystem} eq "ntfs"))) {
+        $end_of_range = $current_disk->{partitions}->{$p}->{begin_byte};
+
+        # logical partitions require the space for the EPBR to be left
+        # out
+        if (($FAI::configs{$config}{disklabel} eq "msdos")
+          && ($p > 4)) {
+          $end_of_range -= $current_disk->{bios_sectors_per_track} *
+            $current_disk->{sector_size};
+        }
+        last;
+      } elsif ($FAI::configs{$config}{partitions}{$p}{size}{extended}) {
+        next;
+      } else {
+        my ($min_size, $max_size) = &FAI::make_range(
+          $FAI::configs{$config}{partitions}{$p}{size}{range},
+          $current_disk->{size} . "B");
+
+        # logical partitions require the space for the EPBR to be left
+        # out
+        if (($FAI::configs{$config}{disklabel} eq "msdos")
+          && ($p > 4)) {
+          $min_size += $current_disk->{bios_sectors_per_track} *
+            $current_disk->{sector_size};
+          $max_size += $current_disk->{bios_sectors_per_track} *
+            $current_disk->{sector_size};
+        }
+
+        $min_req_space += $min_size;
+        $max_space     += $max_size;
+      }
+    }
+
+    # set the end if we have reached the end of the disk
+    $end_of_range = $current_disk->{end_byte} if (-1 == $end_of_range);
+
+    my $available_space = $end_of_range - $next_start + 1;
+
+    # the next boundary is closer than the minimal space that we need
+    ($available_space < $min_req_space)
+      and die "Insufficient space available for partition $part_id\n";
+
+    # the new size
+    my $scaled_size = $end;
+    $scaled_size = POSIX::floor(($end - $start) * 
+      (($available_space - $min_req_space) /
+          ($max_space - $min_req_space))) + $start
+      if ($max_space > $available_space);
+
+    ($scaled_size >= $start)
+      or &FAI::internal_error("scaled size is smaller than the desired minimum");
+
+    $start = $scaled_size;
+    $end   = $start;
+  }
+
+  # now we compute the effective locations on the disk
+  # msdos specific offset for logical partitions
+  if (($FAI::configs{$config}{disklabel} eq "msdos")
+    && ($part_id > 4)) {
+
+    # add one head of disk usage if this is a logical partition
+    $min_req_total_space += $current_disk->{bios_sectors_per_track} *
+      $current_disk->{sector_size};
+
+    # move the start byte as well
+    $next_start += $current_disk->{bios_sectors_per_track} *
+      $current_disk->{sector_size};
+  }
+
+  # partition starts at where we currently are, or remains fixed in case of
+  # resized ntfs
+  if ($FAI::configs{$config}{partitions}{$part_id}{size}{resize} &&
+    ($current_disk->{partitions}->{$part_id}->{filesystem} eq "ntfs")) {
+    ($next_start <= $current_disk->{partitions}->{$part_id}->{begin_byte}) 
+      or die "Cannot preserve start byte of ntfs volume on partition $part_id, space before it is too small\n";
+    $next_start = $current_disk->{partitions}->{$part_id}->{begin_byte};
+  }
+  $FAI::configs{$config}{partitions}{$part_id}{start_byte} =
+    $next_start;
+
+  # the end may need some alignment, depending on the disk label
+  my $end_byte = $next_start + $start - 1;
+
+  # on msdos, ensure that the partition ends at a cylinder boundary
+  if ($FAI::configs{$config}{disklabel} eq "msdos") {
+    $end_byte -=
+      ($end_byte + 1) % ($current_disk->{sector_size} *
+        $current_disk->{bios_sectors_per_track} *
+        $current_disk->{bios_heads});
+  }
+
+  # on gpt, ensure that the partition ends at a sector boundary
+  if ($FAI::configs{$config}{disklabel} eq "gpt") {
+    $end_byte -=
+      ($end_byte + 1) % $current_disk->{sector_size};
+  }
+
+  # set $start and $end to the effective values
+  $start = $end_byte - $next_start + 1;
+  $end   = $start;
+
+  # write back the size spec in bytes
+  $part->{size}->{range} = $start . "-" . $end;
+
+  # then set eff_size to a proper value
+  $part->{size}->{eff_size} = $start;
+
+  # write the end byte to the configuration
+  $part->{end_byte} = $end_byte;
+
+  # and add it to the total disk space required by this config
+  $min_req_total_space += $part->{size}->{eff_size};
+
+  # set the next start
+  $next_start = $part->{end_byte} + 1;
+
+  return ($next_start, $min_req_total_space);
+}
+
+################################################################################
+#
+# @brief Compute the desired sizes of the partitions and test feasibility
+# thereof.
+#
+################################################################################
+sub compute_partition_sizes
+{
+
+  # loop through all device configurations
+  foreach my $config (keys %FAI::configs) {
+
+    # for RAID or LVM, there is nothing to be done here
+    next if ($config eq "RAID" || $config =~ /^VG_./);
+    ($config =~ /^PHY_(.+)$/) or &FAI::internal_error("invalid config entry $config");
+    # nothing to be done, if this is a configuration for a virtual disk
+    next if $FAI::configs{$config}{virtual};
+    my $disk = $1; # the device name of the disk
+    # test, whether $disk is a block special device
+    (-b $disk) or die "$disk is not a valid device name\n";
+    # reference to the current disk config
+    my $current_disk = $FAI::current_config{$disk};
+
+    # at various points the following code highly depends on the desired disk label!
+    # initialise variables
+    # the id of the extended partition to be created, if required
+    my $extended = -1;
+
+    # the id of the current extended partition, if any; this setup only caters
+    # for a single existing extended partition!
+    my $current_extended = -1;
+
+    # find the first existing extended partition
+    foreach my $part_id (&numsort(keys %{ $current_disk->{partitions} })) {
+      if ($current_disk->{partitions}->{$part_id}->{is_extended}) {
+        $current_extended = $part_id;
+        last;
+      }
+    }
+
+    # the space required on the disk
+    my $min_req_total_space = 0;
+
+    # the start byte for the next partition
+    my $next_start = 0;
+
+    # on msdos disk labels, the first partitions starts at head #1
+    if ($FAI::configs{$config}{disklabel} eq "msdos") {
+      $next_start = $current_disk->{bios_sectors_per_track} *
+        $current_disk->{sector_size};
+
+      # the MBR requires space, too
+      $min_req_total_space += $current_disk->{bios_sectors_per_track} *
+        $current_disk->{sector_size};
+    }
+
+    # on GPT disk labels the first 34 and last 34 sectors must be left alone
+    if ($FAI::configs{$config}{disklabel} eq "gpt") {
+      $next_start = 34 * $current_disk->{sector_size};
+
+      # modify the disk to claim the space for the second partition table
+      $current_disk->{end_byte} -= 34 * $current_disk->{sector_size};
+
+      # the space required by the GPTs
+      $min_req_total_space += 2 * 34 * $current_disk->{sector_size};
+    }
+
+    # the list of partitions that we need to find start and end bytes for
+    my @worklist = (&numsort(keys %{ $FAI::configs{$config}{partitions} }));
+
+    while (scalar (@worklist))
+    {
+
+      # work on the first entry of the list
+      my $part_id = $worklist[0];
+      # reference to the current partition
+      my $part = (\%FAI::configs)->{$config}->{partitions}->{$part_id};
+
+      # the partition $part_id must be preserved
+      if ($part->{size}->{preserve}) {
+        ($next_start, $min_req_total_space) = &FAI::do_partition_preserve($part_id, 
+          $config, $current_disk, $next_start, $min_req_total_space);
+
+        # partition done
+        shift @worklist;
+      }
+
+      # msdos specific: deal with extended partitions
+      elsif ($part->{size}->{extended}) {
+        # make sure that there is only one extended partition
+        ($extended == -1 || 1 == scalar (@worklist))
+          or &FAI::internal_error("More than 1 extended partition");
+
+        # set the local variable to this id
+        $extended = $part_id;
+
+        # the size cannot be determined now, push it to the end of the
+        # worklist; the check against $extended being == -1 ensures that
+        # there is no indefinite loop
+        if (scalar (@worklist) > 1) {
+          push @worklist, shift @worklist;
+          next;
+        }
+
+        # determine the size of the extended partition
+        &FAI::do_partition_extended($part_id, $config, $current_disk);
+
+        # partition done
+        shift @worklist;
+      } else {
+        ($next_start, $min_req_total_space) = &FAI::do_partition_real($part_id, 
+          $config, $current_disk, $next_start, $min_req_total_space, \@worklist);
+
+        # partition done
+        shift @worklist;
+      }
+    }
+
+    # check, whether there is sufficient space on the disk
+    ($min_req_total_space > $current_disk->{size})
+      and die "Disk $disk is too small - at least $min_req_total_space bytes are required\n";
+
+    # make sure, extended partitions are only created on msdos disklabels
+    ($FAI::configs{$config}{disklabel} ne "msdos" && $extended > -1)
+      and &FAI::internal_error("extended partitions are not supported by this disklabel");
+
+    # ensure that we have done our work
+    (defined ($FAI::configs{$config}{partitions}{$_}{start_byte})
+        && defined ($FAI::configs{$config}{partitions}{$_}{end_byte}))
+      or &FAI::internal_error("start or end of partition $_ not set")
+        foreach (&numsort(keys %{ $FAI::configs{$config}{partitions} }));
+  }
+}
+
+1;
+




More information about the Fai-commit mailing list