Created
September 13, 2016 23:47
-
-
Save storbeck/849a9cbe18662914f56a47eb808378a8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# AUTHOR: zoite | |
# DATE: 02.29.2012 | |
# PURPOSE: An automated migration script to do a 1:1 server migration | |
# completey independent of drive size and configuration | |
# Note: Supports software (mdadm) RAID | |
# | |
exec 3> /dev/tty | |
# Adds SSH private key to server | |
function add_key() { | |
echo "StrictHostKeyChecking no" >> ~/.ssh/config | |
cat > ~/.ssh/id_rsa <<KEYEND | |
################################# | |
# ADD SSH PRIVATE KEY HERE # | |
################################# | |
KEYEND | |
chmod 0600 ~/.ssh/id_rsa | |
} | |
# Function to display a sane progress bar for rsync | |
rsync_progress() { | |
cat >> rsync.awk << EOF | |
{ | |
if (index($0, "to-check=") > 0) | |
{ | |
split($0, pieces, "to-check=") | |
split(pieces[2], term, ")"); | |
split(term[1], division, "/"); | |
print (1-(division[1]/division[2]))*100"%" | |
} | |
else | |
{ | |
print "#"$0; | |
} | |
fflush(); | |
} | |
EOF | |
} | |
# Various dialog boxes for configuration | |
function discover_info() { | |
rm -f *.in *.ans | |
# Set network info for server you're migrating from | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Networking" --form "Networking setup" 15 50 0 \ | |
"(old) IP:" 1 1 "" 1 10 30 0 \ | |
"(new) Subnet: " 2 1 "" 2 15 25 0 \ | |
2>&1 1>&3) | |
echo "$VALUES" > net.ans | |
# Set number of drives that will be used | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Drives" --radiolist "Number of drives" 15 50 0 \ | |
"1" "Drive" on \ | |
"2" "Drives" off \ | |
"3" "Drives" off \ | |
"4" "Drives" off \ | |
2>&1 1>&3) | |
NODRIVES=$(echo $VALUES) | |
# Set number of partitions per drive | |
i=0 | |
while [[ $NODRIVES -ne $i ]]; do | |
let i=$i+1 | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Partitions" --radiolist "Number of partitions on [drive $i]" 15 50 0 \ | |
"1" "Partition" off \ | |
"2" "Partitions" off \ | |
"3" "Partitions" on \ | |
"4" "Partitions" off \ | |
2>&1 1>&3) | |
NOPARTITIONS=$(echo $VALUES) | |
echo "drive$i $NOPARTITIONS" > drive$i.ans | |
done | |
# set partitions details | |
for LOOP in drive*.ans; do | |
DRIVE=$(echo $LOOP | cut -f1 -d.) | |
if [[ $DRIVE == "drive1" ]]; then DRIVE="sda"; fi | |
if [[ $DRIVE == "drive2" ]]; then DRIVE="sdb"; fi | |
if [[ $DRIVE == "drive3" ]]; then DRIVE="sdc"; fi | |
if [[ $DRIVE == "drive4" ]]; then DRIVE="sdd"; fi | |
NOPARTITIONS=$(cat $LOOP | awk '{print $2}') | |
i=0 | |
while [[ $i -ne $NOPARTITIONS ]]; do | |
let i=$i+1 | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Partitions" --form "Partition setup: $DRIVE$i" 15 50 0 \ | |
"Partiton" 1 1 "$DRIVE$i" 1 10 30 0 \ | |
"Size: " 2 1 "" 2 10 30 0 \ | |
"Type: " 3 1 "" 3 10 30 0 \ | |
"Mount: " 4 1 "" 4 10 30 0 \ | |
"Label: " 5 1 "" 5 10 30 0 \ | |
"Bootable: " 6 1 "" 6 10 30 0 \ | |
2>&1 1>&3) | |
echo $VALUES >> $DRIVE-partitions.ans | |
done | |
done | |
# does it need raid? | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Raid" --radiolist "Does raid need to be setup?" 15 50 0 \ | |
"1" "No" on \ | |
"2" "Yes" off \ | |
2>&1 1>&3) | |
echo "$VALUES" > needraid.ans | |
# Set it up if selected yes | |
NEEDRAID=$(cat needraid.ans) | |
if [[ $NEEDRAID == "2" ]]; then | |
# how many arrays? | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Raid" --radiolist "How many arrays need to be created?" 15 50 0 \ | |
"1" "Array" on \ | |
"2" "Arrays" off \ | |
"3" "Arrays" off \ | |
"4" "Arrays" off \ | |
2>&1 1>&3) | |
NOARRAYS=$(echo $VALUES) | |
# set details for each array | |
i=0 | |
while [[ $i -ne $NOARRAYS ]]; do | |
let i=$i+1 | |
VALUES=$(dialog --backtitle "EasyMigrate" --title "Raid" --form "Details for array $i" 15 50 0 \ | |
"Partition 1: " 1 1 "" 1 10 30 0 \ | |
"Partition 2: " 2 1 "" 2 10 30 0 \ | |
"Level: " 3 1 "" 3 10 30 0 \ | |
"Device: " 4 1 "" 4 10 30 0 \ | |
"Mount: " 5 1 "" 5 10 30 0 \ | |
2>&1 1>&3) | |
echo $VALUES >> raid.ans | |
done | |
fi | |
} | |
# Auto-partition the drives based on value entered | |
function run_partitions() { | |
for DRIVES in *-partitions.ans; do | |
DRIVE=$(echo $DRIVES | cut -f1 -d-) | |
i=0; | |
cat $DRIVES | while read PARTITIONS SIZE TYPE MOUNT LABEL BOOT; do | |
let i=i+1 | |
echo "n" >> $DRIVE-fdisk.in # new partitions | |
echo "p" >> $DRIVE-fdisk.in # primary | |
echo "$i" >> $DRIVE-fdisk.in # partition $i | |
echo "" >> $DRIVE-fdisk.in # default | |
if [[ $SIZE =~ "all" ]]; then | |
echo "" >> $DRIVE-fdisk.in # use rest of disk | |
else | |
echo "+$SIZE" >> $DRIVE-fdisk.in # size | |
fi | |
echo "t" >> $DRIVE-fdisk.in # type | |
if [[ ! $i == 1 ]]; then | |
echo "$i" >> $DRIVE-fdisk.in # type on partition $i | |
fi | |
echo "$TYPE" >> $DRIVE-fdisk.in # set partition type | |
if [[ $BOOT =~ "y" ]]; then | |
echo "a" >> $DRIVE-fdisk.in # set flag | |
echo "1" >> $DRIVE-fdisk.in # bootable | |
fi | |
done | |
echo "w" >> $DRIVE-fdisk.in | |
done | |
echo "" | |
for P1 in *-fdisk.in; do | |
DRIVE=$(echo "$P1" | cut -f1 -d-); | |
fdisk /dev/$DRIVE < $P1 | |
sleep 5 | |
fdisk /dev/$DRIVE << EOF | |
p | |
w | |
EOF | |
sleep 5 | |
done | |
} | |
# Mounts the necessary system points and creates the filesystem | |
function build_fs_and_mount() { | |
mkdir /mnt/chroot | |
mkdir /mnt/chroot/{proc,dev,sys} | |
mount -t proc none /mnt/chroot/proc | |
mount -o bind /dev /mnt/chroot/dev | |
mount -o bind /sys /mnt/chroot/sys | |
NEEDRAID=$(cat needraid.ans) | |
if [[ $NEEDRAID == '1' ]]; then | |
for DRIVES in *-partitions.ans; do | |
DRIVE=$(echo $DRIVES | cut -f1 -d-) | |
cat $DRIVES | while read PARTITION SIZE TYPE MOUNT LABEL BOOT; do | |
if [[ $TYPE == "83" ]]; then | |
mkfs.ext3 /dev/$PARTITION | |
if [[ ! $LABEL =~ "none" ]]; then | |
tune2fs -L /dev/$PARTITION $LABEL | |
fi | |
mkdir -p /mnt/chroot/$MOUNT | |
mount /dev/$PARTITION /mnt/chroot/$MOUNT | |
elif [[ $TYPE == "82" ]]; then | |
mkswap /dev/$PARTITION | |
swapon /dev/$PARTITION | |
else | |
mkfs.ext3 /dev/$PARTITION | |
tune2fs -L /dev/$PARTITION $LABEL | |
fi | |
done | |
done | |
elif [[ $NEEDRAID == '2' ]]; then | |
cat raid.ans | while read PARTITION1 PARTITION2 LEVEL DEVICE MOUNT; do | |
mdadm --create --force --verbose /dev/$DEVICE --level=$LEVEL --metadata=0.90 --raid-devices=2 /dev/$PARTITION1 /dev/$PARTITION2 << EOF | |
y | |
EOF | |
mkfs.ext3 /dev/$DEVICE | |
mkdir -p /mnt/chroot/$MOUNT | |
mount /dev/$DEVICE /mnt/chroot/$MOUNT | |
done | |
fi | |
} | |
# Start the rsync | |
function copy_data() { | |
SERVER=$(awk '{print $1}' net.ans|head -1) | |
rsync --compress --archive --verbose --sparse --numeric-ids -P -t --devices --exclude=/dev --exclude=/lost+found --exclude=/mnt --exclude=/media --exclude=/proc --exclude=/srv --exclude=/sys --progress root@$SERVER:/ /mnt/chroot/ | awk -f rsync.awk | | |
dialog --backtitle "EasyMigrate" --gauge "Copying files" 10 70 0 | |
} | |
# Update the configuration files | |
function update_confs() { | |
SERVER=$(head -1 net.ans) | |
NETMASK=$(tail -1 net.ans) | |
# NOTE: This is configured for a DELL SC1435 | |
# Update modprobe on sc1435 | |
echo "alias eth0 tg3 | |
alias eth1 tg3 | |
alias scsi_hostadapter sata_svw | |
alias usb-controller ehci-hcd | |
alias usb-controller1 ohci-hcd | |
install appletalk /bin/true | |
install ipx /bin/true | |
install irda /bin/true | |
install x25 /bin/true | |
install pppox /bin/true | |
install bluetooth /bin/true | |
install sctp /bin/true | |
install ax25 /bin/true | |
alias CPU0 powernow-k8 | |
install ib_addr /bin/true | |
install ib_cm /bin/true | |
install ib_core /bin/true | |
install ib_mad /bin/true | |
install ib_sa /bin/true | |
install ib_sdp /bin/true | |
install ib_ucm /bin/true | |
install ib_umad /bin/true | |
install ib_uverbs /bin/true | |
install iw_cm /bin/true | |
install ppp_generic /bin/true | |
install rdma_cm /bin/true | |
install slhc /bin/true" > /mnt/chroot/etc/modprobe.conf | |
# create ifcfg-eth0 | |
LASTOCT=$(echo $SERVER|cut -f4 -d.) | |
FIRSTPART=$(echo $SERVER|rev|cut -f2- -d.|rev) | |
let LASTOCT=$LASTOCT-1 | |
GATEWAY="$FIRSTPART.$LASTOCT" | |
echo "DEVICE=eth0 | |
BOOTPROTO=static | |
IPADDR=$SERVER | |
NETMASK=$NETMASK | |
GATEWAY=$GATEWAY | |
ONBOOT=yes | |
TYPE=Ethernet | |
" > /mnt/chroot/etc/sysconfig/network-scripts/ifcfg-eth0 | |
# disable ifcfg-eth1 | |
echo "DEVICE=eth1 | |
ONBOOT=no" > /mnt/chroot/etc/sysconfig/network-scripts/ifcfg-eth1 | |
} | |
# Update network settings - includes auto-update for Plesk and cPanel | |
function update_network() { | |
#IP_MAP=`dialog --stdout --title "Please choose a file" --fselect $HOME/ip_map 14 48` | |
IP_MAP=ip_map | |
if [ -d /mnt/chroot/var/named/run-root/ ]; then | |
NAMEDIR="/var/named/run-root/var/*" | |
else | |
NAMEDIR="/var/named/chroot/var/named/" | |
fi | |
cat $IP_MAP | while read old new | |
do | |
if [[ ! $new == "" ]]; then | |
(grep -Zls $old /mnt/chroot/etc/* /mnt/chroot/var/cpanel/* /mnt/chroot/var/cpanel/users/* /mnt/chroot/${NAMEDIR} /mnt/chroot/var/named/*; | |
grep -rZls $old /mnt/chroot/etc/httpd/conf/* /mnt/chroot/etc/sysconfig/* /mnt/chroot/usr/local/apache/conf/* /mnt/chroot/var/cpanel/userdata/ /mnt/chroot/etc/webmin/*) | xargs -0 sed -i s/$old/$new/g || echo "no matches found" 1>/dev/null 2>/dev/null | |
fi | |
done | |
echo "nameserver 208.67.220.220" > /mnt/chroot/etc/resolv.conf | |
# Plesk reconfigurator | |
if [ -d /mnt/chroot/usr/local/psa ]; then | |
NETMASK=$(tail -1 net.ans) | |
cat ip_map | while read old new; do | |
if [[ ! $new == "" ]]; | |
then echo "eth0:$old $NETMASK -> eth0:$new $NETMASK" >> /mnt/chroot/tmp/PLESKIPMAP | |
fi; | |
done | |
if [ ! -d /mnt/chroot/usr/local/psa/tmp ]; then | |
mkdir /mnt/chroot/usr/local/psa/admin/logs; mkdir /mnt/chroot/usr/local/psa/tmp | |
fi | |
chmod 777 /mnt/chroot/usr/local/psa/admin/logs | |
chmod 777 /mnt/chroot/usr/local/psa/tmp | |
chroot /mnt/chroot /etc/init.d/mysqld start | |
chroot /mnt/chroot /usr/local/psa/bin/reconfigurator.pl /tmp/PLESKIPMAP | |
chroot /mnt/chroot /etc/init.d/mysqld stop | |
chroot /mnt/chroot /usr/local/psa/bin/reconfigurator.pl /tmp/PLESKIPMAP | |
else | |
echo "Plesk not running" | |
fi | |
} | |
# This shouldn't be used. It's for a use-case specific to me | |
function build_kernel() { | |
# install kernel with sata_svw support | |
chroot /mnt/chroot wget http://mirror.centos.org/centos/4/os/i386/CentOS/RPMS/kernel-2.6.9-89.EL.i586.rpm | |
chroot /mnt/chroot wget http://mirror.centos.org/centos/4/os/i386/CentOS/RPMS/kernel-devel-2.6.9-89.EL.i586.rpm | |
chroot /mnt/chroot rpm -ivh --oldpackage kernel*.rpm | |
# build initrd | |
cd /mnt/chroot/boot | |
INITNUM=$(cat /mnt/chroot/boot/grub/menu.lst |grep -v \# |grep default|awk '{print substr($0,length,1)}') | |
INITNUM=$((${INITNUM}+1)) # So it doesn't start at 0 | |
IMGFILE=$(cat /mnt/chroot/boot/grub/menu.lst | grep -v \# | grep initrd | sed -n "${INITNUM}p" | awk -F/ '{print $NF}') | |
KERN=$( echo ${IMGFILE} | sed 's/initrd-//g' | sed 's/\.img//g' ) | |
rm -f /mnt/chroot/boot/${IMGFILE} | |
chroot /mnt/chroot mkinitrd -f -v --preload libata --preload mptsas --preload ata_piix --preload sata_svw --builtin=ata_generic /boot/${IMGFILE} ${KERN} | |
# install grub | |
chroot /mnt/chroot grub-install --recheck /dev/sda | |
CHKGRUB=$(file -s /dev/sda | grep boot ) | |
if [ -z "${CHKGRUB}" ]; then | |
echo "Grub install failed"; exit | |
fi | |
} | |
add_key | |
discover_info | |
run_partitions | |
build_fs_and_mount | |
rsync_progress | |
copy_data | |
update_confs | |
update_network | |
build_kernel |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment