[Fai-commit] r3666 - people/michael/features/setup_harddisks_2/implementation

fai-commit at lists.alioth.debian.org fai-commit at lists.alioth.debian.org
Sun Jul 23 19:40:37 UTC 2006


Author: michael-guest
Date: 2006-07-23 19:40:32 +0000 (Sun, 23 Jul 2006)
New Revision: 3666

Added:
   people/michael/features/setup_harddisks_2/implementation/document_template
Modified:
   people/michael/features/setup_harddisks_2/implementation/NOTES
   people/michael/features/setup_harddisks_2/implementation/shdd2
   people/michael/features/setup_harddisks_2/implementation/shdd2-commands
   people/michael/features/setup_harddisks_2/implementation/shdd2-exec
   people/michael/features/setup_harddisks_2/implementation/shdd2-fstab
   people/michael/features/setup_harddisks_2/implementation/shdd2-init
   people/michael/features/setup_harddisks_2/implementation/shdd2-lib
   people/michael/features/setup_harddisks_2/implementation/shdd2-parser
   people/michael/features/setup_harddisks_2/implementation/shdd2-sizes
Log:
lots of cleanup, some of the code is more perlish (and thus less readable) - and
quite of lot of comments were added


Modified: people/michael/features/setup_harddisks_2/implementation/NOTES
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/NOTES	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/NOTES	2006-07-23 19:40:32 UTC (rev 3666)
@@ -4,5 +4,9 @@
 
 query commands
 
+allow for some arbitrary predefined list instead of $ENV{disklist}
+
 split into functions, size computation must be fixed
 
+getopt processing
+

Added: people/michael/features/setup_harddisks_2/implementation/document_template
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/document_template	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/document_template	2006-07-23 19:40:32 UTC (rev 3666)
@@ -0,0 +1,12 @@
+################################################################################
+#
+# @brief SHORT DESC
+#
+# @param a
+# @param b
+#
+# @pointen
+#
+# @return 0
+#
+################################################################################

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,35 +2,61 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2
+#
+# @brief The main function of setup harddisks 2 - the tool to configure the
+# partitioning from within FAI. 
+# 
+# This is an implementation from scratch to properly support LVM and RAID. The
+# input format is documented in @ref shdd2-parser
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 package FAI;
 
+# include all subparts
+require "shdd2-init";
 require "shdd2-lib";
-require "shdd2-init";
 require "shdd2-parser";
 require "shdd2-sizes";
 require "shdd2-commands";
 require "shdd2-fstab";
 require "shdd2-exec";
 
+# start the parsing - thereby $FAI::configs is filled
 &FAI::run_parser;
 
+# read the sizes and partition tables of all disks listed in $FAI::disks
 &FAI::get_current_disks;
 
+# compute the new partition sizes
 &FAI::compute_sizes;
 
+# TODO - debugging only: print the current contents of $FAI::configs
 &FAI::print_hash( \%FAI::configs );
 
+# generate the command script
 &FAI::build_commands;
 
+# TODO - debugging only: print the command script
 foreach my $cmd (@FAI::commands)
 {
   print $cmd . "\n";
   # &FAI::execute_command($cmd);
 }
 
+# generate the proposed fstab contents
 my @fstab = &FAI::generate_fstab( \%FAI::configs );
+# TODO - debugging only; print fstab
 foreach my $line (@fstab)
 {
-  printf $line. "\n";
+  printf "$line\n";
 }
 

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-commands
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-commands	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-commands	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,6 +2,19 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2-commands
+#
+# @brief TODO
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 package FAI;
 
 sub build_commands
@@ -77,7 +90,7 @@
         else
         {
           push @FAI::commands,
-            "$FAI::parted_binary $disk mklabel $target_label";
+            "$FAI::bash_commands{'parted'} $disk mklabel $target_label";
         }
       }
       else
@@ -90,7 +103,8 @@
             shift @to_preserve;
             next;
           }
-          push @FAI::commands, "$FAI::parted_binary $disk rm $part_id";
+          push @FAI::commands,
+            "$FAI::bash_commands{'parted'} $disk rm $part_id";
         }
       }
 
@@ -134,7 +148,8 @@
             $FAI::configs{$config}{"partitions"}{"size"}{"eff_size"} +
             $next_start - 1;
           push @FAI::commands,
-            "$FAI::parted_binary $disk resize $part_id $next_start" . "B "
+            "$FAI::bash_commands{'parted'} $disk resize $part_id $next_start"
+            . "B "
             . $part_size . "B";
           unless ( $FAI::configs{$config}{"disklabel"} eq "msdos"
             && $FAI::configs{$config}{"partitions"}{$part_id}{"size"}
@@ -162,7 +177,8 @@
             $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} +
             $next_start - 1;
           push @FAI::commands,
-            "$FAI::parted_binary $disk mkpart $part_type $next_start" . "B "
+            "$FAI::bash_commands{'parted'} $disk mkpart $part_type $next_start"
+            . "B "
             . $part_size . "B";
           unless ( $FAI::configs{$config}{"disklabel"} eq "msdos"
             && $FAI::configs{$config}{"partitions"}{$part_id}{"size"}

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-exec
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-exec	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-exec	2006-07-23 19:40:32 UTC (rev 3666)
@@ -1,10 +1,36 @@
 #!/usr/bin/perl -w
 
 use strict;
+
+################################################################################
+#
+# @file shdd2-exec
+#
+# @brief functions to execute bash commands
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 use File::Temp;
 
 package FAI;
 
+################################################################################
+#
+# @brief hash, defined: errors, descriptions, actions on error
+#
+# @scalar error error
+# @scalar message our errormessage
+# @scalar stderr_regex regex to recognize the error message on stderr output of the bash
+# @scalar stdout_regex regex to recognize the error message on stdout output of the bash
+# @scalar program the program this error message can come from
+# @scalar response default action on this error.
+#
+################################################################################
 $FAI::error_codes = [
   {
     error        => "parted_1",
@@ -42,6 +68,15 @@
   },
 ];
 
+################################################################################
+#
+# @brief returns the error message associated with an error
+#
+# @param error identifier of an error
+#
+# @return our interpretation of the error as string
+#
+################################################################################
 sub get_error_message
 {
   my ($error) = @_;
@@ -52,6 +87,16 @@
   }
 }
 
+################################################################################
+#
+# @brief gets any part of the error struct associated with an error
+#
+# @param error identifier of an error
+# @param field field of the error struct as string, example: "stderr_regex"
+#
+# @return the associated value
+#
+################################################################################
 sub get_error
 {
   my ( $error, $field ) = @_;
@@ -61,8 +106,24 @@
     return "$m->{$field}";
   }
 }
-
-sub execute_command_std       #execute command with standard error handling
+################################################################################
+#
+# @brief execute a /bin/bash command, given as string. also catch stderr and
+# stdout, to be passed to the caller function, and also used for error
+# recognition. This execute function does execute the in the error struct
+# defined action, when an error occurs.
+#
+# @param command bash command to be executed as string
+# @reference stdout_ref reference to a list, that should contain the standard
+# output of the bash command
+#
+# @reference stderr_ref reference to a list, that should contain the standard
+# errer output of the bash command
+#
+# @return the identifier of the error
+#
+################################################################################
+sub execute_command_std    #execute command with standard error handling
 {
   my ( $command, $stdout_ref, $stderr_ref ) = @_;
   my $err = &execute_command( $command, $stdout_ref, $stderr_ref );
@@ -86,6 +147,22 @@
   return "";
 }
 
+################################################################################
+#
+# @brief execute a /bin/bash command, given as string. also catch stderr and
+# stdout, to be passed to the caller function, and also used for error
+# recognition. This caller function must handle the error.
+#
+# @param command bash command to be executed as string
+# @reference stdout_ref reference to a list, that should contain the standard
+# output of the bash command
+#
+# @reference stderr_ref reference to a list, that should contain the standard
+# errer output of the bash command
+#
+# @return the identifier of the error
+#
+################################################################################
 sub execute_command
 {
   my ( $command, $stdout_ref, $stderr_ref ) = @_;
@@ -100,11 +177,15 @@
     $run = 1;
   }
 
+  #make tempfile, get perl filehandle and filename of the file
   ( my $stderr_fh, my $stderr_filename ) = File::Temp::tempfile();
   ( my $stdout_fh, my $stdout_filename ) = File::Temp::tempfile();
 
+  # do only execute the given command, when in no_dry_mode
   if ( $run == 1 )
   {
+
+    # execute the bash command, write stderr and stdout into the testfiles
     `$command 1> $stdout_filename 2> $stderr_filename`;
   }
   else
@@ -113,32 +194,39 @@
 "would run command $command, to run in NO_DRY_MODE, please set environment variable NO_DRY_RUN to 1 \n";
   }
 
+  # read the tempfile into lists, each element of the list one line
   @stderr = <$stderr_fh>;
   @stdout = <$stdout_fh>;
 
+  #when closing the files, the tempfiles are removed too
   close($stderr_fh);
   close($stdout_fh);
 
+  #if the stderr contains information, get the first line for error recognition
   if ( scalar(@stderr) > 0 )
   {
     $stderr_line = $stderr[0];
   }
 
+  #see last comment
   if ( scalar(@stdout) > 0 )
   {
     $stdout_line = $stdout[0];
   }
 
+  #if an array is passed to the function, it is filled with the stdout
   if ( 'ARRAY' eq ref($stdout_ref) )
   {
     @$stdout_ref = @stdout;
   }
 
+  #see above
   if ( 'ARRAY' eq ref($stderr_ref) )
   {
     @$stderr_ref = @stderr;
   }
 
+  #get the error, eventually happened
   foreach my $err (@$FAI::error_codes)
   {
     if (

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-fstab
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-fstab	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-fstab	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,40 +2,81 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2-fstab
+#
+# @brief TODO
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 package FAI;
 
-#call this function only with one parameter (generate_fstab($hash_ref)). The rest is used for recursion
+################################################################################
+#
+# @brief this function generates the fstab file from our representation of the
+# partitions to be created. Call this function only with one parameter,
+# the rest is used for recursion.
+#
+# @reference hash_ref to our representation of the partitions to be created
+# @param modus help variable for the recursion. holds the value wheter we are
+# opertationing in physical partition, lvm or raid mode
+#
+# @param device help variable, holds the actual device
+#
+# @reference listref help variable, holding the reference to the list which
+# contains the lines of the fstab file to be generated
+#
+# @param call_count holds the actual recursion depth
+#
+# @return 0
+#
+################################################################################
 sub generate_fstab
 {
   my ( $hash_ref, $modus, $device, $listref, $call_count ) = @_;
 
+  #first check if we have already a list, when not, create one
   if ( !$listref )
   {
     my @newlist = ();
     $listref = \@newlist;
   }
 
+#check if call_count is set, if not, the function is called the first time, set it
   if ( !$call_count )
   {
     $call_count = 1;
   }
   else
   {
+
+    #if we go deaper, increment it
     $call_count++;
   }
 
+  # go through all drives, lvms, raids
   foreach my $key ( keys %$hash_ref )
   {
 
     if ( ref( $hash_ref->{$key} ) && $key =~ /^PHY_(.*)$/ )
     {
+
+      #set the modus to physical drive partition
       $modus  = "PHY";
       $device = $1;
     }
 
+    # check if we are at the important place for the fstab file
     if ( ref( $hash_ref->{$key} ) && $key eq "partitions" )
     {
 
+# every partition means one line in fstab, let's get the information about each one
       foreach my $partition ( keys %{ $hash_ref->{$key} } )
       {
         my $p_ref = $hash_ref->{$key}->{$partition};
@@ -55,6 +96,8 @@
           {
             push @fstab_line, 2;
           }
+
+#lets join the columns of one line with tabs, and the push it to our fstab line array
           push @$listref, join( "\t", @fstab_line );
         }
 
@@ -70,6 +113,8 @@
   }
   if ( $call_count eq 1 )
   {
+
+    #if we are at highes level, lets return the listref
     return @$listref;
   }
 }

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-init
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-init	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-init	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,29 +2,84 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2-init
+#
+# @brief Initialize all variables and acquire the set of disks of the system.
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 package FAI;
 
+################################################################################
+#
+# @brief Enable debugging by setting $FAI::debug to a value greater than 0
+#
+################################################################################
 $FAI::debug = 1;
 
-# getopt processing
-
-#REMOVE THIS
-# use a predefined list?
-
+# TODO - REMOVE THIS
 $ENV{disklist} = "hda
 ";
-################
+
+################################################################################
 #
-
+# @brief The lists of disks of the system
+#
+################################################################################
 @FAI::disks = split( /\n/, $ENV{disklist} );
 
+################################################################################
+#the hash, where we write the disc config we want to have
+#
+# @brief The hash of all configurations specified in the disk_config file
+#
+# The structure is as follows:
+# VG_<NAME>
+#   TODO
+# PHY_<DEVICE>
+#   TODO
+# RAID
+#   TODO
+#
+################################################################################
 %FAI::configs = ();
 
+################################################################################
+#the hash, with information about the actual disc config
+#
+# @brief The current disk configuration
+#
+# The structure is as follows:
+# <DEVICE>
+#   TODO
+#
+################################################################################
 %FAI::current_config = ();
 
+################################################################################
+#list of commands
+#
+# @brief The list of commands to be executed
+#
+################################################################################
 @FAI::commands = ();
 
+################################################################################
+#
+# @brief The parted command to be run
+#
+################################################################################
 $FAI::parted_binary = "/sbin/parted -s";
 
+#list of bash commands
+%FAI::bash_commands = ( parted => "/sbin/parted -s", );
+
 1;
 

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-lib
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-lib	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-lib	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,30 +2,85 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2-lib
+#
+# @brief A small library of utility functions possibly useful in various places
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 package FAI;
 
+################################################################################
+#
+# @brief Test, whether @ref $cmd is available on the system using $PATH
+#
+# @param $cmd Command that is to be found in $PATH
+#
+# @return 1, if the command is found, else 0
+#
+################################################################################
 sub in_path
 {
-  my ($filesystem) = @_;
 
+  # initialize the parameter
+  my ($cmd) = @_;
+
+  # split $PATH into its components
   my @path_list = split( ":", $ENV{"PATH"} );
 
+  # search all components of $PATH
   foreach my $p (@path_list)
   {
-    ( -x "$p/mkfs.$filesystem" ) and return 0;
+
+    # and test for $cmd being executable
+    ( -x "$p/$cmd" ) and return 1;
   }
-  return 1;
+  return 0;
 }
 
+################################################################################
+#
+# @brief our structure, in which we hold informations about existing partitions
+# and partitions we wan't to create a hold in hash of hashes. This debug function
+# allows to recursivly print such a hash with all keys und subhashes
+# @brief Recursively explore the hash
+#
+# @param hash_ref the reference to the hash, where we want to start printing
+# the hash recursively
+# @param $cmd Command that is to be found in $PATH
+#
+# @param k help variable, is only to be used for the recursion. caller function
+# shoudn't set this one
+#
+# @return returns nothing, is a void function
+# @return 1, if the command is found, else 0
+#
+################################################################################
 sub print_hash
 {
+
+  # This function is for debugging purposes only
+  # only be used in debugging mode, otherwise return silently
   ( $FAI::debug > 0 ) or return 0;
 
+  # get the function parameters
   my ( $hash_ref, $k ) = @_;
+
+  # append a > for showing the depth in the hash of hashes
   $k = "$k>";
 
+  # print all keys
   foreach my $key ( keys %$hash_ref )
   {
+
+    # if there is another hash, recursively call the function with this hash
     if ( ref( $hash_ref->{$key} ) )
     {
       print "$k KEY: $key VAL: hash\n";

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-parser
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-parser	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-parser	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,7 +2,13 @@
 
 use strict;
 
+################################################################################
 #
+# @file shdd2-parser
+#
+# @brief A parser for the disk_config files within FAI, based on the EBNF
+# listed below. The implementation makes use of the RecDescent package.
+#
 # file ::= <lines> EOF
 #
 # lines ::= EOL
@@ -77,43 +83,73 @@
 # fs_options ::= .*
 #                /* options appended to mkfs.xxx call */
 #
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig, Sam Vilain
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
 
 use Parse::RecDescent;
 
 package FAI;
 
-$FAI::device                    = "";
-$FAI::partition_primary_counter = 0;
-$FAI::partition_logical_counter = 0;
+################################################################################
+#
+# @brief the name of the device currently being configured, including a prefix
+# such as PHY_ or VG_ to indicate physical devices or LVM volume groups. For
+# RAID, the entry is only "RAID"
+#
+################################################################################
+$FAI::device = "";
 
+################################################################################
+#
+# @brief Initialise a new entry in @ref $FAI::configs for a physical disk.
+#
+# Besides creating the entry in the hash, the fully path of the device is
+# computed (see @ref $disk) and it is tested, whether this is a block device.
+# The device name is then used to define @ref $FAI::device.
+#
+# @param $disk Either an integer, occurring in the context of, e.g., disk2, or
+# a device name. The latter may be fully qualified, such as /dev/hda, or a short
+# name, such as sdb, in which case /dev/ is prepended.
+#
+################################################################################
 sub init_disk_config
 {
+
+  # Initialise $disk
   my ($disk) = @_;
 
+  # test $disk for being numeric
   if ( $disk =~ /^\d+$/ )
   {
-    if ( $FAI::disks >= $disk )
-    {
-      $disk = $FAI::disks[ $disk - 1 ];
-    }
-    else
-    {
-      die "this system does not have a physical disk $disk\n";
-    }
+
+    # $disk-1 must not be valid index in the map of all disks in the system
+    ( $FAI::disks < $disk )
+      or die "this system does not have a physical disk $disk\n";
+
+    # fetch the (short) device name
+    $disk = $FAI::disks[ $disk - 1 ];
   }
 
-  unless ( $disk =~ m{^/} )
-  {
-    $disk = "/dev/" . $disk;
-  }
+  # test, whether the device name starts with a / and prepend /dev/, if
+  # appropriate
+  ( $disk =~ m{^/} ) or $disk = "/dev/$disk";
+
+  # test, whether $disk is a block special device
   ( -b $disk ) or die "$disk is not a valid device name\n";
 
-  $FAI::device = "PHY_" . $disk;
+  # prepend PHY_
+  $FAI::device = "PHY_$disk";
 
-  if ( defined( $FAI::configs{$FAI::device} ) )
-  {
-    die "Duplicate configuration for disk $FAI::disks[ $1-1 ]\n";
-  }
+  # test, whether this is the first disk_config stanza to configure $disk
+  defined( $FAI::configs{$FAI::device} )
+    and die "Duplicate configuration for disk $FAI::disks[ $1-1 ]\n";
+
+  # Initialise the entry in $FAI::configs
   $FAI::configs{$FAI::device} = {
     "virtual"    => 0,
     "disklabel"  => "msdos",
@@ -122,98 +158,174 @@
   };
 }
 
+################################################################################
+#
+# @brief Initialise the entry of a partition in @ref $FAI::configs
+#
+# @param $type The type of the partition. It must be either primary or logical.
+#
+################################################################################
 sub init_part_config
 {
+
+  # the type of the partition to be created
   my ($type) = @_;
 
+  ( $type eq "primary" || $type eq "logical" ) or die "INTERNAL PARSER ERROR\n";
+
+  # check that a physical device is being configured; logical partitions are
+  # only supported on msdos disk labels.
+  (
+    $FAI::device =~ /^PHY_/ && ( $type ne "logical"
+      || $FAI::configs{$FAI::device}{"disklabel"} eq "msdos" )
+  ) or die "Syntax error: invalid partition type";
+
+  # the index of the new partition
+  my $part_number = 0;
+
+  # create a primary partition
   if ( $type eq "primary" )
   {
-    ( $FAI::device =~ /^PHY_/ ) or die "wrong partition type";
-    (      $FAI::partition_primary_counter < 4
-        || $FAI::configs{$FAI::device}{"disklabel"} ne "msdos" )
-      or die "Too many primary partitions\n";
-    $FAI::partition_primary_counter++;
-    unless (
-      defined(
-        $FAI::configs{$FAI::device}{"partitions"}
-          {$FAI::partition_primary_counter}
-      )
-      )
+
+    # find all previously defined primary partitions
+    foreach
+      my $part_id ( sort keys %{ $FAI::configs{$FAI::device}{"partitions"} } )
     {
-      $FAI::configs{$FAI::device}{"partitions"}
-        {$FAI::partition_primary_counter} = {};
+
+      # break, if the partition has not been created by init_part_config
+      defined( $FAI::configs{$FAI::device}{"partitions"}{$part_id}{"size"}
+          {"extended"} )
+        or last;
+
+      # on msdos disklabels we cannot have more than 4 primary partitions
+      last
+        if ( $part_id > 4
+        && $FAI::configs{$FAI::device}{"disklabel"} eq "msdos" );
+
+      # store the latest index found
+      $part_number = $part_id;
     }
-    $FAI::partition_pointer =
-      ( \%FAI::configs )->{$FAI::device}->{"partitions"}
-      ->{$FAI::partition_primary_counter};
-    $FAI::partition_pointer->{"number"} = $FAI::partition_primary_counter;
+
+    # the next index available - note that $part_number might have been 0
+    $part_number++;
+
+    # msdos disk labels don't allow for more than 4 primary partitions
+    ( $part_number < 5 || $FAI::configs{$FAI::device}{"disklabel"} ne "msdos" )
+      or die "$part_number are too many primary partitions\n";
   }
-  elsif ( $type eq "logical" )
+  else
   {
-    (      $FAI::device =~ /^PHY_/
-        && $FAI::configs{$FAI::device}{"disklabel"} eq "msdos" )
-      or die "wrong partition type";
+
+    # no further checks for the disk label being msdos have to be performed in
+    # this branch, it has been ensured above
+
+# find the index of the new partition, initialise it to the highest current index
+    foreach
+      my $part_id ( sort keys %{ $FAI::configs{$FAI::device}{"partitions"} } )
     {
-      if ( $FAI::partition_logical_counter == 0 )
+
+      # skip primary partitions
+      next if ( $part_id < 5 );
+
+      # break, if the partition has not been created by init_part_config
+      defined( $FAI::configs{$FAI::device}{"partitions"}{$part_id}{"size"}
+          {"extended"} )
+        or last;
+
+      # store the latest index found
+      $part_number = $part_id;
+    }
+
+    # and use the next one available
+    $part_number++;
+
+    # if this is the first logical partition, the index must be set to 5 and an
+    # extended partition  must be created
+    if ( $part_number <= 5 )
+    {
+      $part_number = 5;
+
+      # the proposed index of the extended partition
+      my $extended = 0;
+
+      # find all previously defined primary partitions
+      foreach
+        my $part_id ( sort keys %{ $FAI::configs{$FAI::device}{"partitions"} } )
       {
-        ( $FAI::partition_primary_counter < 4 )
-          or die "Too many primary partitions\n";
-        $FAI::partition_primary_counter++;
-        $FAI::configs{$FAI::device}{"partitions"}
-          {$FAI::partition_primary_counter}{"size"}{"extended"} = 1;
-        unless (
-          defined(
-            $FAI::configs{$FAI::device}{"partitions"}
-              {$FAI::partition_primary_counter}{"size"}{"preserve"}
-          )
-          )
-        {
-          $FAI::configs{$FAI::device}{"partitions"}
-            {$FAI::partition_primary_counter}{"size"}{"preserve"} = 0;
-        }
-        unless (
-          defined(
-            $FAI::configs{$FAI::device}{"partitions"}
-              {$FAI::partition_primary_counter}{"size"}{"resize"}
-          )
-          )
-        {
-          $FAI::configs{$FAI::device}{"partitions"}
-            {$FAI::partition_primary_counter}{"size"}{"resize"} = 0;
-        }
+
+        # break, if the partition has not been created by init_part_config
+        defined( $FAI::configs{$FAI::device}{"partitions"}{$part_id}{"size"}
+            {"extended"} )
+          or last;
+
+        # we cannot have more than 4 primary partitions
+        last if ( $part_id > 4 );
+
+        # store the latest index found
+        $extended = $part_id;
       }
-      $FAI::partition_logical_counter++;
-      unless (
-        defined(
-          $FAI::configs{$FAI::device}{"partitions"}
-            { $FAI::partition_logical_counter + 4 }
-        )
-        )
-      {
-        $FAI::configs{$FAI::device}{"partitions"}
-          { $FAI::partition_logical_counter + 4 } = {};
-      }
-      $FAI::partition_pointer =
-        ( \%FAI::configs )->{$FAI::device}->{"partitions"}
-        ->{ $FAI::partition_logical_counter + 4 };
-      $FAI::partition_pointer->{"number"} = $FAI::partition_logical_counter + 4;
+
+      # the next index available
+      $extended++;
+
+      # msdos disk labels don't allow for more than 4 primary partitions
+      ( $extended < 5 )
+        or die "Too many primary partitions while creating extended\n";
+
+      # mark the entry as an extended partition
+      $FAI::configs{$FAI::device}{"partitions"}{$extended}{"size"}{"extended"} =
+        1;
+
+      # add the preserve = 0 flag, if it doesn't exist already
+      defined( $FAI::configs{$FAI::device}{"partitions"}{$extended}{"size"}
+          {"preserve"} )
+        or $FAI::configs{$FAI::device}{"partitions"}{$extended}{"size"}
+        {"preserve"} = 0;
+
+      # add the resize = 0 flag, if it doesn't exist already
+      defined(
+        $FAI::configs{$FAI::device}{"partitions"}{$extended}{"size"}{"resize"} )
+        or
+        $FAI::configs{$FAI::device}{"partitions"}{$extended}{"size"}{"resize"} =
+        0;
     }
   }
-  else
-  {
-    die "internal parser error\n";
-  }
+
+  # initialise the hash for the partitions, if it doesn't exist already
+  # note that it might exists due to options, such as preserve:x,y
+  # the initialisation is required for the reference defined next
+  defined( $FAI::configs{$FAI::device}{"partitions"}{$part_number} )
+    or $FAI::configs{$FAI::device}{"partitions"}{$part_number} = {};
+
+  # set the reference to the current partition
+  # the reference is used by all further processing of this config line
+  $FAI::partition_pointer =
+    ( \%FAI::configs )->{$FAI::device}->{"partitions"}->{$part_number};
+
+  # as we can't compute the index from the reference, we need to store the
+  # $part_number explicitly
+  $FAI::partition_pointer->{"number"} = $part_number;
+
+  # the partition is not an extended one
   $FAI::partition_pointer->{"size"}->{"extended"} = 0;
-  unless ( defined( $FAI::partition_pointer->{"size"}->{"preserve"} ) )
-  {
-    $FAI::partition_pointer->{"size"}->{"preserve"} = 0;
-  }
-  unless ( defined( $FAI::partition_pointer->{"size"}->{"resize"} ) )
-  {
-    $FAI::partition_pointer->{"size"}->{"resize"} = 0;
-  }
+
+  # add the preserve = 0 flag, if it doesn't exist already
+  defined( $FAI::partition_pointer->{"size"}->{"preserve"} )
+    or $FAI::partition_pointer->{"size"}->{"preserve"} = 0;
+
+  # add the resize = 0 flag, if it doesn't exist already
+  defined( $FAI::partition_pointer->{"size"}->{"resize"} )
+    or $FAI::partition_pointer->{"size"}->{"resize"} = 0;
 }
 
+# have RecDescent do proper error reporting
+$::RD_HINT = 1;
+
+################################################################################
+#
+# @brief The effective implementation of the parser is instantiated here
+#
+################################################################################
 $FAI::Parser = Parse::RecDescent->new(
   q{
     file: line(s?) /\Z/
@@ -226,124 +338,175 @@
         | volume
     disk_config_arg: 'raid'
         {
-          #TODO: check, whether raid tools are available
+          # check, whether raid tools are available
+          ( &FAI::in_path( "mdadm" ) == 1 ) or 
+            die "mdadm not found in PATH\n";
           $FAI::device = "RAID";
         }
         | 'lvm'
         {
-          #TODO: check, whether lvm tools are available
+          # check, whether lvm tools are available
+          ( &FAI::in_path( "lvcreate" ) == 1 ) or 
+            die "LVM tools not found in PATH\n";
+          # initialise $FAI::device to inform the following lines about the LVM
+          # being configured
           $FAI::device = "VG_";
         }
         | 'end'
         {
+          # exit config mode
           $FAI::device = "";
         }
         | /^disk(\d+)/
         {
+          # initialise the entry of the hash corresponding to disk$1
           &FAI::init_disk_config( $1 );
         }
         option(s?)
         | /^\S+/
         {
+          # initialise the entry of the hash corresponding to $item[1]
           &FAI::init_disk_config( $item[ 1 ] );
         }
         option(s?)
     option: /^preserve:(\d+(,\d+)*)/
         {
-          my @ids = split( ",", $1 );
-          foreach my $id ( @ids )
+          # set the preserve flag for all ids
+          foreach my $id ( split( ",", $1 ) )
           {
             $FAI::configs{ $FAI::device }{ "partitions" }{ $id }{ "size" }{ "preserve" } = 1;
           }
         }
         | /^resize:(\d+(,\d+)*)/
         {
-          my @ids = split( ",", $1 );
-          foreach my $id ( @ids )
+          # set the resize flag for all ids
+          foreach my $id ( split( ",", $1 ) )
           {
             $FAI::configs{ $FAI::device }{ "partitions" }{ $id }{ "size" }{ "resize" } = 1;
           }
         }
         | /^disklabel:(msdos|sun|gpt|mac)/
         {
+          # set the disk label - actually not only the above, but all types 
+          # supported by parted could be allowed
           $FAI::configs{ $FAI::device }{ "disklabel" } = $1;
         }
         | /^bootable:(\d+)/
         {
+          # specify a partition that should get the bootable flag set
           $FAI::configs{ $FAI::device }{ "bootable" } = $1;
         }
         | 'virtual'
         {
+          # this is a configuration for a virtual disk
+          # TODO not yet implemented
           $FAI::configs{ $FAI::device }{ "virtual" } = 1;
         }
-    volume: type mountpoint size filesystem mount_options fs_options
-        | 'vg' name size
+    volume: 'vg' name devices
+        | /^raid([0156])\s+/
+        {
+          # make sure that this is a RAID configuration
+          ( $FAI::device eq "RAID" ) or die "RAID entry invalid in this context\n";
+          # initialise RAID entry, if it doesn't exist already
+          defined( $FAI::configs{"RAID"} ) or $FAI::configs{"RAID"}{"volumes"} = {};
+          # compute the next available index - the size of the entry
+          my $vol_id = scalar( keys %{ $FAI::configs{"RAID"}{"volumes"} } );
+          # set the RAID type of this volume
+          $FAI::configs{"RAID"}{"volumes"}{$vol_id}{"mode"} = $1;
+          # initialise the hash of devices
+          $FAI::configs{"RAID"}{"volumes"}{$vol_id}{"devices"} = {};
+          # set the reference to the current volume
+          # the reference is used by all further processing of this config line
+          $FAI::partition_pointer = ( \%FAI::configs )->{"RAID"}->{"volumes"}->{$vol_id};
+        }
+        mountpoint devices filesystem mount_options fs_options
+        | type mountpoint size filesystem mount_options fs_options
     type: 'primary'
         {
+          # initialise a primary partition
           &FAI::init_part_config( $item[ 1 ] );
         }
         | 'logical'
         {
+          # initialise a logical partition
           &FAI::init_part_config( $item[ 1 ] );
         }
-        | /^raid[0156]/
+        | m{^([^/\s\-]+)-([^/\s\-]+)\s+}
         {
-          # TODO
+          # set $FAI::device to VG_$1
+          $FAI::device = "VG_$1";
+          # make sure, the volume group $1 has been defined before
+          defined( $FAI::configs{$FAI::device} ) or 
+            die "Volume group $1 has not been declared yet.\n";
+          # make sure, $2 has not been defined already
+          defined( $FAI::configs{$FAI::device}{"volumes"}{$2} ) and 
+            die "Logical volume $2 has been defined already.\n";
+          # initialise the new hash
+          $FAI::configs{$FAI::device}{"volumes"}{$2} = {};
+          # set the reference to the current volume
+          # the reference is used by all further processing of this config line
+          $FAI::partition_pointer = ( \%FAI::configs )->{$FAI::device}->{"volumes"}->{$2};
         }
-        | m{^[^/\s]+-[^/\s]+}
-        {
-          # TODO
-        }
     mountpoint: '-'
         {
+          # this partition should not be mounted
           $FAI::partition_pointer->{ "mountpoint" } = "-";
         }
         | 'swap'
         {
+          # this partition is swap space, not mounted
           $FAI::partition_pointer->{ "mountpoint" } = "swap";
         }
         | m{^/\S*}
         {
+          # set the mount point
           $FAI::partition_pointer->{ "mountpoint" } = $item[ 1 ];
         }
-    name: /^\S+/
+    name: m{^([^/\s\-]+)\s+}
         {
-          if( ! $FAI::device =~ /^VG_/ )
-          {
+          # make sure this line is part of an LVM configuration
+          ( $FAI::device =~ /^VG_/ ) or
             die "vg is invalid in a non LVM-context.\n";
-          }
-          $FAI::device = "VG_" . $item[ 1 ];
-          $FAI::partition_pointer = (\%FAI::configs)->{ $FAI::device };
+          # set the device name to VG_ and the name of the volume group
+          $FAI::device = "VG_$1";
+          # make sure, the volume group $1 not has been defined already
+          defined( $FAI::configs{$FAI::device} ) and
+            die "Volume group $1 has been defined already.\n";
+          # initialise the new hash
+          $FAI::configs{$FAI::device}{"volumes"} = {};
+          # initialise the list of physical devices
+          $FAI::configs{$FAI::device}{"devices"} = ();
         }
     size: /^(\d+%?(-(\d+%?)?)?)(:resize)?\s+/
         {
+          # complete the size specification to be a range in all cases
           my $range = $1;
+          # the size is fixed
           if( ! defined( $2 ) )
           {
-            $range = $range . "-" . $1;
+            # make it a range of the form x-x
+            $range = "$range-$1";
           }
           elsif( ! defined( $3 ) )
           {
+            # range has no upper limit, assume the whole disk
             $range = $range . "100%";
           }
+          # enter the range into the hash
           $FAI::partition_pointer->{ "size" }->{ "range" } = $range;
-          if( defined( $4 ) )
-          {
-            $FAI::partition_pointer->{ "size" }->{ "resize" } = 1;
-          }
+          # set the resize flag, if required
+          defined( $4 ) and $FAI::partition_pointer->{ "size" }->{ "resize" } = 1;
         }
         | /^(-\d+%?)(:resize)?\s+/
         {
-          $FAI::partition_pointer->{ "size" } = {
-            "range" => "0" . $1
-          };
-          if( defined( $2 ) ) 
-          {
-            $FAI::partition_pointer->{ "size" }->{ "resize" } = 1;
-          }
+          # complete the range by assuming 0 as the lower limit 
+          $FAI::partition_pointer->{ "size" }{ "range" } = "0$1";
+          # set the resize flag, if required
+          defined( $2 ) and $FAI::partition_pointer->{ "size" }->{ "resize" } = 1;
         }
         | /^preserve(\d+)\s+/
         {
+          # set the preserve flag, if the index of the partition hasn't changed
           if( $1 == $FAI::partition_pointer->{ "number" } )
           {
             $FAI::partition_pointer->{ "size" }->{ "preserve" } = 1;
@@ -353,19 +516,47 @@
             die "partition number of to-be-preserved partition $1 changed to $FAI::partition_pointer->{number}\n";
           }
         }
-        | /^[^\d,:\s\-][^,:\s]*(:(spare|missing))*(,[^,:\s]+(:(spare|missing))*)*\s+/
+        | <error: invalid partition size near "$text">
+    devices: /^([^\d,:\s\-][^,:\s]*(:(spare|missing))*(,[^,:\s]+(:(spare|missing))*)*)\s+/
         {
-          if( $FAI::device ne "RAID" || ! ( $FAI::device =~ /^VG_/ ) )
+          # split the device list by ,
+          foreach my $dev ( split( ",", $1 ) )
           {
-            die "invalid within this context\n";
+            # match the substrings
+            ( $dev =~ /^([^\d,:\s\-][^,:\s]*)(:(spare|missing))*$/ ) or die "INTERNAL PARSER ERROR\n";
+            # redefine the device string
+            $dev = $1;
+            # make $dev a full path name; can't validate device name yet as it
+            # might be created later on
+            ( $dev =~ m{^/} ) or $dev = "/dev/$dev";
+            # options are only valid for RAID
+            defined( $2 ) and ( $FAI::device ne "RAID" ) and die "Option $2 invalid in a non-RAID context\n";
+            if( $FAI::device eq "RAID" )
+            {
+              # parse all options
+              my $spare = 0;
+              my $missing = 0;
+              if( defined( $2 ) )
+              {
+                ( $2 =~ /spare/ ) and $spare = 1;
+                ( $2 =~ /missing/ ) and $missing = 1;
+              }
+              # each device may only appear once
+              defined( $FAI::partition_pointer->{"devices"}->{$dev} ) and 
+                die "$dev is already part of the RAID volume\n";
+              # set the options
+              $FAI::partition_pointer->{"devices"}->{$dev}->{"options"} = {
+                "spare" => $spare,
+                "missing" => $missing
+              };
+            }
+            else
+            {
+              push @{ $FAI::configs{$FAI::device}{"devices"} }, $dev;
+            }
           }
-          else
-          {
-            $FAI::partition_pointer->{ "devices" } = $item[ 0 ];
-            # TODO parse and check for validity
-          }
         }
-        | <error: invalid partition size near "$text">
+        | <error: invalid device spec "$text">
     mount_options: /\S+/
         {
           $FAI::partition_pointer->{ "mount_options" } = $item[ 1 ];
@@ -380,10 +571,7 @@
         }
         | /^\S+/
         {
-          unless ( &FAI::in_path("$item[1]") == 0 ) 
-          {
-             die "unknown/invalid filesystem type $item[1]";
-          }
+          ( &FAI::in_path("mkfs.$item[1]") == 1 ) or die "unknown/invalid filesystem type $item[1]";
           $FAI::partition_pointer->{ "filesystem" } = $item[ 1 ];
         }
     fs_options: /.*/

Modified: people/michael/features/setup_harddisks_2/implementation/shdd2-sizes
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/shdd2-sizes	2006-07-23 14:01:42 UTC (rev 3665)
+++ people/michael/features/setup_harddisks_2/implementation/shdd2-sizes	2006-07-23 19:40:32 UTC (rev 3666)
@@ -2,6 +2,19 @@
 
 use strict;
 
+################################################################################
+#
+# @file shdd2-sizes
+#
+# @brief TODO
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
 use POSIX qw(ceil floor);
 
 package FAI;
@@ -22,7 +35,8 @@
     {
       $ENV{"NO_DRY_RUN"} = "1";
       my $error =
-        &FAI::execute_command( "$FAI::parted_binary $disk unit TiB print",
+        &FAI::execute_command(
+        "$FAI::bash_commands{'parted'}} $disk unit TiB print",
         \@parted_print, 0 );
       $ENV{"NO_DRY_RUN"} = "";
 
@@ -30,7 +44,8 @@
         ) #this error happens when the disk has no disk label. then, parted provides no information about the disk
       {
         $error =
-          &FAI::execute_command("$FAI::parted_binary $disk mklabel msdos");
+          &FAI::execute_command(
+          "$FAI::bash_commands{'parted'}} $disk mklabel msdos");
         next;
       }
 
@@ -100,7 +115,8 @@
 
     $ENV{"NO_DRY_RUN"} = "1";
     @parted_print = ();
-    &FAI::execute_command_std( "$FAI::parted_binary $disk unit B print",
+    &FAI::execute_command_std(
+      "$FAI::bash_commands{'parted'}} $disk unit B print",
       \@parted_print, 0 );
     $ENV{"NO_DRY_RUN"} = "";
 
@@ -147,7 +163,8 @@
 
     $ENV{"NO_DRY_RUN"} = "1";
     @parted_print = ();
-    &FAI::execute_command_std( "$FAI::parted_binary $disk unit chs print",
+    &FAI::execute_command_std(
+      "$FAI::bash_commands{'parted'}} $disk unit chs print",
       \@parted_print, 0 );
     $ENV{"NO_DRY_RUN"} = "";
 




More information about the Fai-commit mailing list