Raid, reiserfs, and FAI

Devlin devlin at softhome.net
Mon Aug 5 22:24:11 CEST 2002


Here is the unfinished RAID hook, that I described in that last mail.  
It doesn't work yet.  It requires the e2labels patches, and only works 
with ext2 and ext3 right now.

The problem now is that problem 3 from my last post.  That is, 
setup_harddisks does both partitioning and mkfs, without room between 
those for my script to do anything.

#! /usr/bin/perl

#
# Configuration files for this hook are named <classname>.raid .
# The file first matching an entry in $classes is used.
#
# In the configuration file:
#  spaces and tabs are folded, characters on a line after # are ignored
#
# Every entry thereafter is a raid device description:
#  <mountpoint> <label>
# Entries with mountpoints / and /boot are required.
#
# Example:
#  /            slash
#  /usr         user
#  /boot        shoe
#

#
# The associated disk_config must use the same label for each device in a
#  RAID array.  One and only one device from each array must be mounted 
on
#  the proper point; the others must not be mounted (by using - as the 
mount
#  point).
#
# Associated example:
#
# disk_config hda
# primary       /       50      rw,errors=remount-ro    ;-c -L slash
# primary       swap    200     rw
# primary       /usr    200     rw                      ;-L user
# primary       /boot   16      rw                      ;-L shoe
#
# disk_config hdb
# primary       -       50      rw,errors=remount-ro    ;-c -L slash
# primary       swap    200     rw
# primary       -       200     rw                      ;-L user
# primary       -       16      rw                      ;-L shoe
#

# # # # # # # #
# DEFINITIONS #
# # # # # # # #

$RAIDTAB = "/tmp/fai/raidtab";
$FSTAB = "/tmp/fai/fstab";

$CONFPATH = "/fai/hooks";

$PROCPART = "/proc/partitions";

$DD     = "/bin/dd";
$SYNC      = "/bin/sync";
$SFDISK    = "/sbin/sfdisk";
$SETUPHDDS = "/sbin/setup_harddisks";
$E2LABEL   = "/sbin/e2label";
$HDPARM    = "/sbin/hdparm";
$MKRAID    = "/sbin/mkraid";

sub fold
{
         s/\s+/ /g;
         s/#.*$//;
         s/^ //;
         s/ $//;
}

$SCRIPT = $0;
$SCRIPT =~ s%^.*/([^/]+)$%$1%;

# # # # # # # # # # # #
# PARSE CONFIGURATION #
# # # # # # # # # # # #

for ( split( " ", $ENV{ classes } ) )
         { open( CONF, "$CONFPATH/$_.raid" ) && last; }

scalar stat( CONF ) != 0 || die "did not open configuration file";

# Each of these uses mount points as keys.
%RAIDLABELS = ();
%RAIDNUMS = ();

$INCR = 0;
while ( <CONF> )
{
         fold();
         if ( /^(\S+) (\S+)$/ )
         {
                 (length( $RAIDLABELS{ $1 } ) > 0 && $RAIDLABELS{ $1 } != 
$2)
                         && die "conflicting labels for mount point $1";

                 for ( keys %RAIDLABELS )
                 {
                         ($RAIDLABELS{ $_ } == $2 && $_ != $1)
                                 && die "conflicting mount points for 
label $2";
                 }
                 $RAIDLABELS{ $1 } = $2;
                 $RAIDNUMS{ $1 } = $INCR++;
         }
         elsif ( /^$/ ) {}
         else
                 { die "did not recognize configuration line"; }
}
close( CONF );

scalar grep( /^\/$/, keys %RAIDLABELS ) == 1
         || die "configuration did not describe root";
scalar grep( /^\/boot$/, keys %RAIDLABELS ) == 1
         || die "configuration did not describe boot";

# # # # # # # # # #
# PARTITION DISKS #
# # # # # # # # # #

print "$SCRIPT: Calling setup_harddisks\n";
system( "$SETUPHDDS -X" ) / 256 == 0 || die "did not set disks up";

# # # # # # # # # # # # #
# GET  PARTITION LABELS #
# # # # # # # # # # # # #

# This uses labels as keys.
%LABELDEVS = ();

print "$SCRIPT: Calling e2label to find labels\n";
open( PROCPART, $PROCPART ) || die "did not open partition description";
<PROCPART>; <PROCPART>;
while ( <PROCPART> )
{
         /\s*(\S*)$/;
         $DEVICE = $1;
         if ( $1 =~ /[hs]d[a-z][0-9]{1,2}/ )
         {
                 $DEVICE = "/dev/$DEVICE";
                 $ERR = system( "$E2LABEL $DEVICE > /dev/null" ) / 256;
                 $ERR != -1 || die "did not execute e2label";

                 if ( $ERR == 0 )
                 {
                         $LABEL = `$E2LABEL $DEVICE 2> /dev/null`;
                         $LABEL =~ s/\s//g;
                         if ( length( $LABEL ) > 0 )
                         {
                                 if ( length( $LABELDEVS{ $LABEL } ) > 0 )
                                         { $LABELDEVS{ $LABEL } .= " "; }
                                 $LABELDEVS{ $LABEL } .= "$DEVICE";
                         }
                 }
         }
}
close( PROCPART );

# # # # # # # # # # # # # #
# CHANGE  PARTITION TYPES #
# # # # # # # # # # # # # #

for ( keys %RAIDLABELS )
{
         for ( split( " ", $LABELDEVS{ $RAIDLABELS{ $_ } } ) )
         {
                 $DEVICE = $_;
                 $DEVICE =~ s/\d+$//;
                 $NUMBER = $_;
                 $NUMBER =~ s/^.*(\d+)$/$1/;
                 `$SFDISK --print-id $DEVICE $NUMBER 2> /dev/null` == 83
                         || die "did not find proper partition id on $_";

                 print "$SCRIPT: Calling sfdisk to change partition id on 
$_\n";
                 system( "$SFDISK --change-id $DEVICE $NUMBER fd" ) / 
256 == 0
                         || die "did not change $_ to RAID auto-detect";
         }
}

# # # # # # # # # #
# CREATE  RAIDTAB #
# # # # # # # # # #

open( RAIDTAB, "> $RAIDTAB" ) || die "did not open raidtab";
for ( keys %RAIDLABELS )
{
         $NUMDISKS = scalar split( " ", $LABELDEVS{ $RAIDLABELS{ $_ } } );
         $NUMDISKS != 0 || die "did not find complete entry for $_";

         print RAIDTAB <<EOF;

# $_ ($RAIDLABELS{ $_ })
raiddev                 /dev/md$RAIDNUMS{ $_ }
raid-level              1
nr-raid-disks           $NUMDISKS
nr-spare-disks          0
chunk-size              4
EOF

         $INCR = 0;
         for ( split( " ", $LABELDEVS{ $RAIDLABELS{ $_ } } ) )
         {
                 print RAIDTAB <<EOF;

device                  $_
raid-disk               $INCR
EOF
                 $INCR++;
         }
}
print RAIDTAB "\n";
close( RAIDTAB );

# # # # # # # # # # #
# MAKE RAID DEVICES #
# # # # # # # # # # #

for ( keys %RAIDNUMS )
{
         print "$SCRIPT: Calling mkraid on md$RAIDNUMS{ $_ }\n";
         system( "$MKRAID --really-force -c $RAIDTAB 
/dev/md$RAIDNUMS{ $_ }" ) / 256 == 0
                 || die "did not make raid device";
}

# # # # # # # # #
# MODIFY  FSTAB #
# # # # # # # # #

open( FSTAB, "$FSTAB" ) || die "did not open fstab";
$OUT = "";
while ( <FSTAB> )
{
         /^(\S*)\s*(\S*)/;
         $POINT = $2;
         if ( length( $RAIDLABELS{ $POINT } ) > 0 )
         {
                 scalar grep( /^$1$/, split( " ", $LABELDEVS{ $RAIDLABELS
{ $POINT } } ) ) > 0
                         || die "found unlisted device for label in 
fstab";
                 s/^$1/LABEL=$RAIDLABELS{ $POINT }/;
         }
         $OUT .= $_;
}
close( FSTAB );
open( FSTAB, "> $FSTAB" ) || die "did not open fstab";
print FSTAB $OUT;
close( FSTAB );

# # # # # # # # # #
# MODIFY  DISKVAR #
# # # # # # # # # #

open( DISKVAR, "$ENV{ diskvar }" ) || die "did not open diskvar";
$OUT = "";
while( <DISKVAR> )
{
         /([^=]+)=([^=]+)/ || die "did not recognize line in $ENV
{ diskvar }";

         if ( "$1" =~ /^ROOT_PARTITION$/ )
         {
                 scalar grep( /\b$2\b/, split( " ", $LABELDEVS
{ $RAIDLABELS{ "/" } } ) ) > 0
                         || die "did not match root partition in $ENV
{ diskvar }";
                 s%=[^=]+$%=/dev/md$RAIDNUMS{ "/" }%;
         }
         elsif ( "$1" =~ /^BOOT_PARTITION$/ )
         {
                 scalar grep( /\b$2\b/, split( " ", $LABELDEVS
{ $RAIDLABELS{ "/boot" } } ) ) > 0
                         || die "did not match boot partition in $ENV
{ diskvar }";
                 s%=[^=]+$%=/dev/md$RAIDNUMS{ "/boot" }%;
         }
         $OUT .= "$_\n";
}
close( DISKVAR );

$_ = $LABELDEVS{ $RAIDLABELS{ "/" } };
s/ /,/g;

open( DISKVAR, "> $ENV{ diskvar }" ) || die "did not open diskvar";
print DISKVAR $OUT;
close( DISKVAR );



More information about the linux-fai mailing list