[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