Source:SwRaid
From FAIWiki
Source code of the hook script for software raid support. Store this code in the $FAI/hooks/mountdisks.SW_RAID file.
#!/usr/bin/perl
# BEGIN LICENCE BLOCK
#
# Copyright (C) 2005 Michal Svamberg <svamberg@civ.zcu.cz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#
# END LICENCE BLOCK
# Usage:
# SW_RAID_CONFIG=mdX[
# raid_level[,mdadm_option[,mdadm_option]
# ]=deviceA[,deviceB][;spareX[,spareY]]
# :mountpoint:[filesystem[,mkfs_options]:mount_options]:[boot]
#
# Now supported this raids:
# linear, raid0, stripe, raid1, mirror, raid5
# This filesystems are supported:
# ext2, ext3, reiserfs, xfs, swap
#
# Example:
# SW_RAID_CONFIG="md0[mirror,--chunk=16]=/dev/sda1,/dev/sdb1;/dev/sdc1:/:ext3,-T news:rw,errors=remount-ro:boot
# md1[raid0]=/dev/sda2,/dev/sdb2:/var:ext3:rw:"
#
# Records in configuration string are breaking by new line.
#
# Version: 0.0.8 (4.10.2007)
#
# ChangeLog:
# 0.0.8: fix mistake in name of disk_var.sh
# 0.0.7: fix missing diskvar variable in environment
# 0.0.6: fix error messages (__FILE__ and __LINE__ variables)
# 0.0.5: remove previously disabled wait_to_init()
# 0.0.4: mkfs.xfs is now called with -f option.
# You can now give mkfs options in SW_RAID_CONFIG, thanks Jonathon Blumenthal <jonblumenthal[at]gmail[dot]com>
# Fix hash referencies, thanks Radoslav Bodo <bodik[at]civ[dot]zcu[dot]cz>
# 0.0.3: disabled wait_to_init(), thanks Rene Cunningham <rene[at]compounddata[dot]com>
# set_partition_type() before create_md(), thanks Sebastien Estienne <sebastien[dot]estienne[at]gmail[dot]com>
# 0.0.2: add xfs support
use strict;
use Data::Dumper;
my %config = ();
my $swaplist = "$ENV{SWAPLIST}";
# ------------------------------------------------------------------------
sub parse_config {
my $var = shift;
my $line;
my $md;
my $rest;
my @opt;
foreach $line (split /\n/, $var) {
chomp $line;
next if $line =~ /^\s*$/;
next if $line =~ /^\s*#/;
# md device, type
$line =~ m#^(md[\d+])\[(linear|raid0|stripe|raid1|mirror|raid5),?(.*?)\]=(.*)$#
|| die __FILE__,"[",__LINE__,"]: Error in SW_RAID_CONFIG at line: \n$line\n";
$md = $1;
$config{$md}{level} = $2;
$config{$md}{options} = $3;
$rest = $4;
# options: --chunk=435,--verbose -> --chunk=435 --verbose
if ($config{$md}{options}) {
$config{$md}{options} =~ s/,/ /g;
}
# rest (partitions, mount options)
@opt = split /:/, $rest;
# $opt[0]: devices (data & spare)
($config{$md}{devices}, $config{$md}{spares}) = split /;/, $opt[0], 2;
$config{$md}{devices} =~ s/,/ /g;
$config{$md}{num_devices} = split / /, $config{$md}{devices};
if ($config{$md}{spares}) {
$config{$md}{spares} =~ s/,/ /g;
$config{$md}{num_spare} = split / /, $config{$md}{spares};
}
# $opt[1]: mountpoint
$config{$md}{mountpoint} = $opt[1];
# $opt[2]: filesystem
if ($opt[2] !~ /^(ext2|ext3|reiserfs|swap|xfs),?(.*?)$/) {
die __FILE__,"[",__LINE__,"]: Error in SW_RAID_CONFIG at line:\n$line\n in filesystem: $opt[2]\n";
}
$config{$md}{filesystem} = $1;
$config{$md}{filesystem_opt} = $2;
# $opt[3]: mount options
$config{$md}{mountoptions} = $opt[3] || 'defaults';
# $opt[4]: boot
$config{$md}{boot} = $opt[4];
# changes for swap
if ($config{$md}{filesystem} eq 'swap') {
$config{$md}{mountoptions} = 'sw';
$config{$md}{mountpoint} = 'none';
$swaplist .= "/dev/$md ";
}
}
}
# ----------------------------------------------------------------------
sub do_command {
my $command = shift;
my $result;
print "$command\n";
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$result = `sh -c '$command'`;
(($? >> 8) == 0) || (die "\nERROR:\n $result\n");
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
print $result;
}
# ----------------------------------------------------------------------
sub create_md {
my $md;
my $cmnd;
foreach $md (sort keys %config) {
$cmnd = "echo 'y' | mdadm --create $config{$md}{options} --verbose /dev/$md --level=$config{$md}{level} --raid-devices=$config{$md}{num_devices} $config{$md}{devices}";
if ($config{$md}{spares}) {
$cmnd .= " --spare-devices=$config{$md}{num_spare} $config{$md}{spares}";
}
do_command($cmnd);
}
}
# -----------------------------------------------------------------------
sub set_partition_type {
my $md;
my $cmnd;
my $dev;
my $devnum;
foreach $md (sort keys %config) {
foreach $dev (split / /, $config{$md}{devices}) {
$dev =~ /^(.*?)(\d+)$/;
$cmnd = "sfdisk --change-id $1 $2 fd";
do_command($cmnd);
}
foreach $dev (split / /, $config{$md}{spares}) {
$dev =~ /^(.*?)(\d+)$/;
$cmnd = "sfdisk --change-id $1 $2 fd";
do_command($cmnd);
}
}
}
# ------------------------------------------------------------------------
sub mkfs {
my $md;
my %trans = (
'reiserfs' => 'mkfs.reiserfs -q',
'ext3' => 'mkfs.ext3 -q',
'ext2' => 'mkfs.ext2 -q',
'swap' => 'mkswap',
'xfs' => 'mkfs.xfs -q -f'
);
foreach $md (sort keys %config) {
do_command("$trans{$config{$md}{filesystem}} $config{$md}{filesystem_opt} /dev/$md");
}
}
# ----------------------------------------------------------------------
sub update_fstab() {
my @lines = ();
my $i;
my $md;
my $nums;
my $filename = "$ENV{LOGDIR}/fstab";
my $comments = "";
# read $target/etc/fstab
open FILE, $filename || die __FILE__,"[",__LINE__,"]: Can't open $filename for read\n";
@lines = <FILE>;
close FILE;
# remove comments
$i = 0;
while (($lines[$i] =~ /^#/) && ($i <= $#lines)) {
$comments .= splice (@lines, $i, 1);
next;
$i++;
}
# remove old records
print Data::Dumper->Dump([\@lines],['lines']);
foreach $md (sort keys %config) {
LINE: for ($i = 0; $i <= $#lines; $i++) {
# remove mountpoint
if (($lines[$i] =~ /\s+$config{$md}{mountpoint}\s+/) && ($lines[$i] !~ /swap/)) {
print "remove lines (mountpoints):\n '$config{$md}{mountpoint}' \n $lines[$i]\n";
splice (@lines, $i, 1);
redo LINE;
}
# remove all devices in raid
foreach (split / /, $config{$md}{devices}) {
if ($lines[$i] =~ /$_/) {
print "remove lines (devices):\n '$_' \n $lines[$i]\n";
splice (@lines, $i, 1);
redo LINE;
}
}
# remove all devices as spare
foreach (split / /, $config{$md}{spares}) {
if ($lines[$i] =~ /$_/) {
print "remove lines (spares):\n '$_' \n $lines[$i]\n";
splice (@lines, $i, 1);
redo LINE;
}
}
}
}
# append new records
foreach $md (sort keys %config) {
$nums = ($config{$md}{mountpoint} eq 'none')?'0 0':'0 2';
if ($config{$md}{mountpoint} eq '/') {
$nums = '0 1';
unshift @lines, "/dev/$md\t$config{$md}{mountpoint}\t$config{$md}{filesystem}\t$config{$md}{mountoptions}\t$nums\n";
}
else {
push @lines, "/dev/$md\t$config{$md}{mountpoint}\t$config{$md}{filesystem}\t$config{$md}{mountoptions}\t$nums\n";
}
}
# save fstab
open FILE, ">$filename" || die __FILE__,"[",__LINE__,"]: Can't open $filename for write\n";
print FILE $comments;
print FILE @lines;
close FILE;
}
# -------------------------------------------------------------------------
sub update_diskvar {
my $filename = "$ENV{LOGDIR}/disk_var.sh";
my $lines = "";
my $md;
open FILE, $filename || die __FILE__,"[",__LINE__,"]: Can't open $filename for read\n";
while ($_ = <FILE>){
$lines .= $_;
}
close FILE;
foreach $md (sort keys %config) {
# ROOT_PARTITION
if ($config{$md}{mountpoint} eq '/') {
$lines =~ s#^(.*)ROOT_PARTITION=\S+(.*)$#$1ROOT_PARTITION="/dev/$md"$2#s;
}
}
# SWAPLIST
$swaplist =~ s/^\s*(.*?)\s*$/$1/;
# $lines =~ s#^(.*)SWAPLIST=\S+(.*)$#$1SWAPLIST="$swaplist"$2#s;
$lines =~ s#^(.*)SWAPLIST=\".*?\"(.*)$#$1SWAPLIST="$swaplist"$2#s;
open FILE, ">$filename" || die __FILE__,"[",__LINE__,"]: Can't open $filename for write\n";
print FILE $lines;
close FILE;
}
# ======================================================================
$ENV{SW_RAID_CONFIG} || die "Variable SW_RAID_CONFIG non exists.\n";
print "Configuration of SW_RAID:\n$ENV{SW_RAID_CONFIG}\n";
parse_config($ENV{SW_RAID_CONFIG});
print Data::Dumper->Dump([\%config],['config']);
set_partition_type();
create_md();
mkfs();
update_fstab();
update_diskvar();
exit 0;
