Automatic gmirror script on FreeBSD9 with gpart

This is far from perfect, but it seems to work for my purposes. Input & improvements greatly welcomed. Licensed BSD or whatever, since most of it’s just modification & gluing of Ralf S. Engelschall and Christian Laursen code & smarts.

There’s no error checking/handling/trapping, so if things go wrong, you don’t even really get to keep both pieces. I will say it’s worked fine for me, but I’ve only tested this in my staging environment, never on a running machine with actual, real, live, important data.

The next things I’d like to do are:

  • add are checking (via mount and swapinfo) that the first stage has worked properly before blindly adding the first drive to the mirror.
  • make the whole thing stop cold if something goes wrong (I think this is quite easy but I forget how)
  • remove the extraneous logger in stage II, since it doesn’t actually log anything
  • figure out what’s up with boot.config and how to not hard-code it (though I know extremely little about FreeBSD’s boot/loader/etc…)

I appreciate input & improvements, please leave them in the comments below!

#!/bin/sh
# Full disk mirroring for FreeBSD 9 by Myke
# (assuming automatic & stock install, this has not been tested with
# more than just boot,root & swap)
#
# 20120502 - First version
#
# Based on the directions and scripts from both
# http://people.freebsd.org/~rse/mirror/
# and
# http://borderworlds.dk/notes/gmirror.html
#
# Assumes an already installed FreeBSD 9 system living on ada0:
# Creates a mirror on ada1 and then migrates
# the system onto that, reboots, then adds ada0 to the mirror
# (blindly, doesn't check if the first step was successful)

# A suggestion for $mir is # echo `hostname -s` `date +%Y` | sed -e "s/ /-/g"

### EDIT THIS ### EDIT THIS ### EDIT THIS ###
### EDIT THIS ### EDIT THIS ### EDIT THIS ###
### EDIT THIS ### EDIT THIS ### EDIT THIS ###
d0=ada0; d1=ada1; mir=Mirror0;
### EDIT THIS ### EDIT THIS ### EDIT THIS ###
### EDIT THIS ### EDIT THIS ### EDIT THIS ###
### EDIT THIS ### EDIT THIS ### EDIT THIS ###


echo ; echo Creating half-mirror $mir on $d1 from $d0
echo ; echo

kldload geom_mirror

echo ; echo Labelling drive...
gmirror label ${mir} $d1
gmirror status

echo ; echo Copying partitions
gpart backup $d0 > /tmp/part.txt
gpart restore mirror/${mir} < /tmp/part.txt

echo ; echo Installing bootcode...
gpart bootcode -b /boot/pmbr mirror/${mir}
gpart bootcode -p /boot/gptboot -i 1 mirror/${mir}

echo ; echo Formatting filesystem...
newfs -U /dev/mirror/${mir}p2

echo ; echo Mounting on /mnt
mount /dev/mirror/${mir}p2 /mnt

echo ; echo Dumping to mirror...
dump -L -0 -f- / | (cd /mnt/ && restore -r -v -f-);

echo ; echo Updating fstab, loader.conf and boot.config...
cp -v /etc/fstab /mnt/etc/fstab.orig
sed -e "s/${d0}/mirror/${mir}/" < /etc/fstab > /mnt/etc/fstab
echo 'geom_mirror_load="YES"' >> /mnt/boot/loader.conf

# I do not like hardcoding this next bit!!!
# I do not like hardcoding this next bit!!!
# I do not like hardcoding this next bit!!!

# Tell the bootloader on the first drive to use the second (now mirrored) drive:

# This very well may not work with SCSI drives or something
# but the boot.config(5) manpage doesn't explain what this means
# nor are is it up to date/unambiguous for ATA_CAM
# (ie: 'ad', not 'ada', but '0p2' rather than '1,a' (or b))
# Also, the boot(8) and loader(8) manpages don't help either.
echo "1:ad(0p2)/boot/loader" > /boot.config

### That really needs to be smarter.


echo ; echo "Creating restart script..."
#echo "#!/bin/sh" > /mnt/root/raid-stage-II.sh
#echo "d0="$d0 "; d1="$d1 "; mir="$mir >> /mnt/root/raid-stage-II.sh
cat << EOT >> /mnt/root/raid-stage-II.sh
#!/bin/sh
echo "Adding first drive to mirror" | logger
gmirror insert ${mir} $d0

cp /etc/rc.local /etc/rc.local.temp
grep -v "/root/raid-stage-II.sh > /var/log/RAID-STAGE-II.log #KAZBLAT" < /etc/rc.local.temp > /etc/rc.local && rm /etc/rc.local.temp

EOT
chmod +x /mnt/root/raid-stage-II.sh
echo "/root/raid-stage-II.sh > /var/log/RAID-STAGE-II.log #KAZBLAT" >> /mnt/etc/rc.local

umount /mnt
shutdown -r now
Posted in Uncategorized