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

Reply via email to