initial commit of file from CVS for e-smith-base on Thu 26 Oct 11:24:52 BST 2023
This commit is contained in:
126
root/sbin/e-smith/add_drive_to_raid
Normal file
126
root/sbin/e-smith/add_drive_to_raid
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/perl -w
|
||||
#----------------------------------------------------------------------
|
||||
# add_drive_to_raid: Add spare disk to existing raid arrays
|
||||
#----------------------------------------------------------------------
|
||||
# Copyright (C) 2005 Gordon Rowell <gordonr@gormand.com.au>
|
||||
# Copyright (C) 2006 Shad L. Lords <slords@mail.com>
|
||||
#
|
||||
# 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Getopt::Long;
|
||||
use Data::Dumper;
|
||||
|
||||
my %options = ();
|
||||
|
||||
GetOptions(\%options, 'f', 'force');
|
||||
|
||||
my $force = $options{f} || $options{force};
|
||||
my $newdev = $ARGV[0] || die "usage:\n\n\tadd_drive_to_raid [-f] dev\n\n";
|
||||
my $target_drive = "/dev/$newdev";
|
||||
my $raid = require "/sbin/e-smith/console-menu-items/manageRAID.pl";
|
||||
|
||||
# Log STDOUT from this point on and return STDERR back to the console
|
||||
my $pid = open(STDOUT, "|-");
|
||||
die gettext("Can't fork"), ": $!\n" unless defined $pid;
|
||||
|
||||
unless ($pid)
|
||||
{
|
||||
exec qw(/usr/bin/logger -p local1.info -t add_drive_to_raid);
|
||||
}
|
||||
|
||||
# Get dictionary of active md devices and sort by size
|
||||
my %devices = $raid->get_raid_details();
|
||||
my @devices = sort { $devices{$a}{DeviceSize} <=> $devices{$b}{DeviceSize} } keys %devices;
|
||||
|
||||
die "There are no RAID devices configured\n" unless $#devices >= 0;
|
||||
|
||||
# Get dictionary of all partitions from /proc/partitions
|
||||
my %partitions = $raid->get_partitions();
|
||||
my @partitions;
|
||||
|
||||
die "$target_drive is not a block special device\n" unless -b $target_drive;
|
||||
|
||||
# Calculate min size of new disk to accomodate active md devices
|
||||
my $minsize = 0;
|
||||
for my $dev (@devices)
|
||||
{
|
||||
die "$target_drive is already in use\n" if grep m#^$newdev$#, @{$devices{$dev}{UsedDisks}};
|
||||
$minsize += $devices{$dev}{DeviceSize} + 65;
|
||||
}
|
||||
|
||||
die "$target_drive is not large enough\n" unless $partitions{$newdev}{blocks} >= $minsize;
|
||||
die "$target_drive already contains partitions\n" unless $force or ! grep m#^$newdev.+$#, keys %partitions;
|
||||
|
||||
# Find a healthy drive hosting our /boot partition to use as our template
|
||||
my @srcdrives = qx(df /boot --output=source | grep /dev/ | xargs -r lsblk -lnsp | grep disk);
|
||||
die "Unable to identify existing boot device - manual intervention required\n" unless (scalar @srcdrives) >= 1;
|
||||
my ($source_drive) = $srcdrives[0] =~ /(\S+)/;
|
||||
print "Using $source_drive as source partition template.\n";
|
||||
|
||||
# Check if it's MBR or GPT
|
||||
my $pttype = qx(blkid -o value -s PTTYPE $source_drive);
|
||||
chomp $pttype;
|
||||
die "Unable to identify source partition table type for $source_drive\n" unless $pttype;
|
||||
print "$source_drive partition table type is $pttype\n";
|
||||
|
||||
# Clear disk in preparation
|
||||
print "Wiping $target_drive...\n";
|
||||
system("wipefs", "-a", $target_drive) == 0
|
||||
or die "Error clearing existing partition table on $target_drive\n";
|
||||
|
||||
# Copy new partition layout
|
||||
print "Copying partition table from $source_drive to $target_drive...\n";
|
||||
if ($pttype eq 'dos') {
|
||||
system("sfdisk -d $source_drive | sfdisk -qf --no-reread $target_drive") == 0
|
||||
or die "Error copying MBR partition table to $target_drive\n";
|
||||
} elsif ($pttype eq 'gpt') {
|
||||
system("sgdisk", "-R", $target_drive, $source_drive) == 0
|
||||
or die "Error copying GPT partition table to $target_drive\n";
|
||||
system("sgdisk", "-G", $target_drive) == 0
|
||||
or die "Error randomising GUID on $target_drive\n";
|
||||
} else {
|
||||
die "Couldn't interpret partition table type '$pttype' on $source_drive\n";
|
||||
}
|
||||
|
||||
# Pause to sync
|
||||
sleep(3);
|
||||
|
||||
# Install GRUB
|
||||
print "Installing GRUB on $target_drive...\n";
|
||||
system("grub2-install", "--recheck", $target_drive) == 0
|
||||
or warn "Warning - error installing GRUB to $target_drive\n";
|
||||
|
||||
# Loop through RAID devices and add the corresponding new partitions
|
||||
my @srcparts;
|
||||
my $srcpart;
|
||||
my $tgtpart;
|
||||
foreach my $part (0..$#devices)
|
||||
{
|
||||
# Find the matching source drive partition and substitute the name
|
||||
@srcparts = qx(mdadm -v --detail --scan $devices[$part]);
|
||||
foreach my $s (@srcparts) {($srcpart) = $s =~ /devices=(\Q$source_drive\E\d+)/};
|
||||
$tgtpart = $srcpart =~ s/\Q$source_drive/$target_drive/r;
|
||||
|
||||
print "Adding $tgtpart to $devices[$part]\n";
|
||||
system("/sbin/mdadm", $devices[$part], "--add", $tgtpart) == 0
|
||||
or die "Error adding $tgtpart to $devices[$part]";
|
||||
}
|
||||
|
||||
# Finished
|
||||
print "Successfully added $target_drive to RAID!\n";
|
Reference in New Issue
Block a user