Package: mdadm
Version: 2.5.6-9
I wrote a script (see attachement) to automatically add a new harddrive
to a system which already has a harddrive with multiple RAID1
partitions. Now one has manually create a partition table on the new
drive, copy the MBR (if bootable), create SWAP (if used) and do a mdadm
--add for each partition. My script automates this process. This is
especially handy when a harddisk containing multiple RAID1 partitions
fails and is replaced by a new empty one.
Example:
When the system has 2 harddives, sda & sdb and looks like this:
- sda1/sdb1 (type fd) part of /dev/md0 (RAID1)
- sda2/sdb2 (type 82) swap
- sda5/sdb5 (type fd) part of /dev/md1 (RAID1)
When sdb fails and is replaced with a new (empty) harddrive. A single
command like: "mdadd.sh /dev/sda /dev/sdb" is sufficient. This will
completely restore the array and even the swap is recreated on the sdb.
I hope it's usefull.
--
Ing. A.C.J. van Amersfoort (Arno)
Department Of Electronics (ELD, k1007)
Huygens Laboratory
Leiden University
P.O. Box 9504
Niels Bohrweg 2
2333 CA Leiden
The Netherlands
----------------------------------------------------------------
Phone : +31-(0)71-527.1894 Fax: +31-(0)71-527.5819
E-mail: [EMAIL PROTECTED]
----------------------------------------------------------------
Arno's (Linux firewall) homepage: http://rocky.eld.leidenuniv.nl
#!/bin/sh
MY_VERSION="1.33-WIP"
#
----------------------------------------------------------------------------------------------------------------------
# Linux MD (Soft)RAID Add Script - Add a (new) harddisk to another multi
MD-array harddisk
# Last update: May 4, 2007
# (C) Copyright 2005-2007 by Arno van Amersfoort
# Homepage : http://rocky.eld.leidenuniv.nl/
# Email : a r n o v a AT r o c k y DOT e l d DOT l e i d e n u
n i v DOT n l
# (note: you must remove all spaces and substitute the
@ and the . at the proper locations!)
#
----------------------------------------------------------------------------------------------------------------------
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# 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.
#
----------------------------------------------------------------------------------------------------------------------
show_help()
{
echo "Bad or missing parameter(s)"
echo "Usage: `basename $0` [ source_disk ] [ target_disk ] [ options ]"
echo "Options:"
echo "--force = Even proceed if target device does not appear empty"
echo "--noptupdate = Do NOT update the partition table on the target device
(EXPERT!)"
echo "--nombrupdate = Do NOT update the MBR boot-loader on the target device
(EXPERT!)"
}
echo "MDadd for SoftRAID-MDADM v$MY_VERSION"
echo "Written by Arno van Amersfoort"
echo "--------------------------------"
if [ "$UID" != "0" ]; then
printf "\033[40m\033[1;31mERROR: Root check FAILED (you MUST be root to use
this script)! Quitting...\n\033[0m"
exit 1
fi
if ! which mdadm 2>&1 >/dev/null; then
printf "\033[40m\033[1;31mERROR: Unable to find mdadm-binary!
Quitting...\n\033[0m"
exit 2
fi
if ! which sfdisk 2>&1 >/dev/null; then
printf "\033[40m\033[1;31mERROR: Unable to find sfdisk-binary!
Quitting...\n\033[0m"
exit 2
fi
if ! which sfdisk 2>&1 >/dev/null; then
printf "\033[40m\033[1;31mERROR: Unable to find dd-binary!
Quitting...\n\033[0m"
exit 2
fi
# Set environment variables to default
FORCE=0
NOPTUPDATE=0
NOMBRUPDATE=0
SOURCE=""
TARGET=""
# Check arguments
for arg in $*; do
ARGNAME=`echo "$arg" |cut -d= -f1`
ARGVAL=`echo "$arg" |cut -d= -f2`
if ! echo "$ARGNAME" |grep -q "^-"; then
if [ -z "$SOURCE" ]; then
SOURCE="$ARGVAL"
else
if [ -z "$TARGET" ]; then
TARGET="$ARGVAL"
else
show_help;
exit 2
fi
fi
else
case "$ARGNAME" in
--force|-force|-f) FORCE=1;;
--noptupdate|-noptupdate|--noptu|-noptu) NOPTUPDATE=1;;
--nombrupdate|-nombrupdate|--nombru|nombru) NOMBRUPDATE=1;;
--help) show_help;
exit 0;;
*) echo "ERROR: Bad argument: $ARGNAME";
show_help;
exit 4;;
esac
fi
done
if [ -z "$SOURCE" ] || [ -z "$TARGET" ]; then
echo "ERROR: Bad or missing argument(s)"
show_help;
exit 2
fi
if ! echo "$SOURCE" |grep -q '^/dev/'; then
printf "\033[40m\033[1;31mERROR: Source device $SOURCE does not start with
/dev/! Quitting...\n\033[0m"
exit 6
fi
if ! echo "$TARGET" |grep -q '^/dev/'; then
printf "\033[40m\033[1;31mERROR: Target device $TARGET does not start with
/dev/! Quitting...\n\033[0m"
exit 7
fi
if echo "$SOURCE" |grep -q 'md'; then
printf "\033[40m\033[1;31mERROR: The source device specified is an md-device!
Quitting...\n\033[0m"
echo "A physical drive (part of the md-array('s)) is required as source
device (ie. /dev/hda)!"
exit 8
fi
# We also want variables without /dev/ :
SOURCE_NODEV="$(echo "$SOURCE" |sed s,'^/dev/',,)"
TARGET_NODEV="$(echo "$TARGET" |sed s,'^/dev/',,)"
if ! grep -q -e " $TARGET_NODEV " -e " $TARGET_NODEV$" /proc/partitions; then
printf "\033[40m\033[1;31mERROR: Target device $TARGET is NOT a valid target
drive! Quitting...\n\033[0m"
exit 9
fi
if ! grep -q -e " $SOURCE_NODEV " -e " $SOURCE_NODEV$" /proc/partitions; then
printf "\033[40m\033[1;31mERROR: Source device $SOURCE is NOT a valid source
drive! Quitting...\n\033[0m"
exit 10
fi
if ! grep -q -e " $SOURCE_NODEV[p,1..9]" /proc/partitions; then
printf "\033[40m\033[1;31mERROR: Source device $SOURCE does not contain any
partitions!? Quitting...\n\033[0m"
exit 11
fi
if grep -q -e " $TARGET_NODEV[p,1..9]" /proc/partitions && [ "$FORCE" != "1" ];
then
printf "\033[40m\033[1;31mERROR: Target device $TARGET is NOT empty! Use
--force to override. Quitting...\n\033[0m"
exit 13
fi
if grep -q -e " $TARGET_NODEV" /proc/mdstat; then
grep " $TARGET_NODEV" /proc/mdstat
printf "\033[40m\033[1;31mWARNING: Target device is already in use by an MD
RAID array!\nPress any key to continue or CTRL-C to abort...\n\033[0m"
read -n 1
fi
# Create backup of partition table:
echo "--> Backing up partition table of target device $TARGET to
/tmp/partitions.$TARGET_NODEV..."
sfdisk -d "$TARGET" >"/tmp/partitions.$TARGET_NODEV"
# Disable all swaps on this disk
echo "--> Disabling any swap partitions on target device $TARGET"
grep "^$TARGET" /proc/swaps |awk '{ print $1 }' |while read SWAP; do
swapoff $SWAP 2>&1 >/dev/null
done
#echo "--> Copying source device $SOURCE to target device $TARGET:"
if [ "$NOMBRUPDATE" != "1" ]; then
echo "--> Copying track0(containing MBR)..."
dd if="$SOURCE" of="$TARGET" bs=65536 count=1
fi
if [ "$NOPTUPDATE" != "1" ]; then
echo "--> Copying partition table from $SOURCE to $TARGET..."
sfdisk -d "$SOURCE" |sfdisk --force "$TARGET"
else
echo "--> Restoring partition table from /tmp/partitions.$TARGET_NODEV to
$TARGET..."
sfdisk -d "$SOURCE" |sfdisk --force "$TARGET"
fi
# Copy/build all md devices that exist on the source drive:
BOOT=0
NOTHING=1
while read STRING; do
if echo "$STRING" |grep -q -e " $SOURCE_NODEV"; then
NOTHING=0
MD_DEV=$(echo "$STRING" |awk '{ print $1 }')
# PARTITION=$(echo "$STRING" |awk '{ print $5 }' |sed s,'\[.\]',, |sed
s,'^...',,)
PARTITION_NR="$(mdadm --detail "/dev/$MD_DEV" |grep "active sync" |awk '{
print $NF }' |grep "^$SOURCE" |head -n1 |sed s,"^$SOURCE",,)"
retval=$?
if [ "$retval" != "0" ]; then
printf "\033[40m\033[1;31mERROR: MDADM returned an error($retval) while
determining detail information for $SOURCE from /dev/$MD_DEV!\n\033[0m"
exit 14
fi
if [ -z "$PARTITION_NR" ]; then
printf "\033[40m\033[1;31mERROR: Unable to retrieve detail information
for $SOURCE from /dev/$MD_DEV!\n\033[0m"
exit 15
fi
if grep -q -e "^/dev/$MD_DEV.*/boot" -e "^/dev/$MD_DEV.*/.*1$" /etc/fstab;
then
BOOT=1
fi
echo ""
echo "--> Adding $TARGET$PARTITION_NR to RAID array /dev/$MD_DEV:"
printf "\033[40m\033[1;31m"
mdadm --add "/dev/$MD_DEV" "$TARGET""$PARTITION_NR"
printf "\033[0m"
fi
done < /proc/mdstat
echo ""
# Create swapspace on partitions with ID=82
echo "--> Creating swapspace on target device (if any swap partitions exist):"
sfdisk -d "$TARGET" |grep -i "Id=82" |awk '{ print $1 }' |while read
SWAP_DEVICE; do
mkswap "$SWAP_DEVICE"
swapon "$SWAP_DEVICE"
if ! grep -q "$SWAP_DEVICE.*none.*swap" /etc/fstab; then
printf "\033[40m\033[1;31mWARNING: /etc/fstab does NOT contain a (valid)
swap entry for $SWAP_DEVICE\n\033[0m"
fi
done
#echo "--> Showing current mdadm detail-scan (you may need to update your
mdadm.conf (manually):"
#mdadm --detail --scan
echo "--> Showing current /proc/mdstat (you may need to update your mdadm.conf
(manually):"
cat /proc/mdstat
echo ""
if [ "$NOTHING" = "1" ]; then
printf "\033[40m\033[1;31mWARNING: No mdadm --add actions were performed,
please investigate!\n\033[0m"
fi
if [ "$BOOT" = "1" ]; then
printf "\033[40m\033[1;31mNOTE: Boot and/or root partition detected. Although
the MBR was copied,\n you *MAY* need to reinstall your boot loader (ie.
GRUB) on this device!\n\033[0m"
fi