#!/bin/sh MY_VERSION="1.40" # ---------------------------------------------------------------------------------------------------------------------- # Linux MD (Soft)RAID Add Script - Add a (new) harddisk to another multi MD-array harddisk # Last update: July 15, 2008 # (C) Copyright 2005-2008 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 dd 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 3 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 3;; esac fi done if [ -z "$SOURCE" ] || [ -z "$TARGET" ]; then echo "ERROR: Bad or missing argument(s)" show_help; exit 4 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 5 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 6 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 7 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 8 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 9 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 10 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 11 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 mdadm --detail --scan --verbose >/tmp/mdadm-detail-scan.txt retval=$? if [ "$retval" != "0" ]; then printf "\033[40m\033[1;31mERROR: MDADM returned an error($retval) while determining detail information!\n\033[0m" exit 12 fi # Copy/build all md devices that exist on the source drive: BOOT=0 NO_ADD=1 while read STRING; do if echo "$STRING" |grep -q "^ARRAY "; then MD_DEV=$(echo "$STRING" |awk '{ print $2 }') fi if echo "$STRING" |grep -q "devices=.*$SOURCE"; then NO_ADD=0 PARTITION_NR="$(echo "$STRING" |sed -e s:".*devices=.*$SOURCE":"": -e s:",.*":"":)" if [ -z "$PARTITION_NR" ]; then printf "\033[40m\033[1;31mERROR: Unable to retrieve detail information for $SOURCE from $MD_DEV!\n\033[0m" exit 13 fi if grep -q -e "^$MD_DEV.*/boot" -e "^$MD_DEV.*/.*1$" /etc/fstab; then BOOT=1 fi echo "" echo "--> Adding $TARGET$PARTITION_NR to RAID array $MD_DEV:" printf "\033[40m\033[1;31m" mdadm --add "$MD_DEV" "$TARGET""$PARTITION_NR" printf "\033[0m" fi done < /tmp/mdadm-detail-scan.txt 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 [ "$NO_ADD" = "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.\n You *MAY* need to reinstall your boot loader (ie. GRUB) on this device!\n\033[0m" fi # TODO?: # sanity check nopt (check if target device has a partition table)? # detect if device has superblock (mdadm --examine /dev/sda1; echo $?)? # continue ask (show what will be done):?