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