Permalink
Browse files

Add bunch of new functionality to lpreserver

Replace "mirror" with "zpool" sub-cmd, which will allow you to
attach / detach / online / offline / list various zpool drives

* Important notes *

When attaching a new disk to a zpool, the drive will
be wiped and re-formatted with a 'freebsd-zfs' file-system of the same
size as the first-disk in th zpool array.

If the first disk has a swap partition it will be created also,
but not activated, since advanced users can handle that as the see fit.

Last but not least, GRUB will be stamped on the new disk, making it
bootable should another drive in the array go bad.
  • Loading branch information...
1 parent 26599e2 commit 59f367e1dbcbd089fdacd6506c51f2c699a48949 @kmoore134 kmoore134 committed Sep 9, 2013
Showing with 162 additions and 67 deletions.
  1. +114 −30 src-sh/lpreserver/backend/functions.sh
  2. +48 −37 src-sh/lpreserver/lpreserver
View
144 src-sh/lpreserver/backend/functions.sh
@@ -375,9 +375,10 @@ listStatus() {
done
}
-add_mirror_disk() {
+add_zpool_disk() {
pool="$1"
disk="$2"
+ disk="`echo $disk | sed 's|/dev/||g'`"
if [ -z "$pool" ] ; then
exit_err "No pool specified"
@@ -389,28 +390,84 @@ add_mirror_disk() {
exit 0
fi
+ if [ ! -e "/dev/$disk" ] ; then
+ exit_err "No such device: $disk"
+ exit 0
+ fi
+
# Check if pool exists
zpool status $pool >/dev/null 2>/dev/null
if [ $? -ne 0 ] ; then exit_err "Invalid pool: $pool"; fi
- # Make sure zpool isn't raid
- zpool list -H -v ${pool} | grep -q "raid"
- if [ $? -eq 0 ] ; then exit_err "Cannot mirror a raidz pool!" ; fi
+ # Cleanup the target disk
+ echo "Deleting all partitions on: $disk"
+ rc_nohalt "gpart destroy -F $disk" >/dev/null 2>/dev/null
+ rc_nohalt "dd if=/dev/zero of=/dev/${disk} bs=1m count=1" >/dev/null 2>/dev/null
+ rc_nohalt "dd if=/dev/zero of=/dev/${disk} bs=1m oseek=`diskinfo /dev/${disk} | awk '{print int($3 / (1024*1024)) - 4;}'`" >/dev/null 2>/dev/null
# Grab the first disk in the pool
- mDisk=`zpool list -H -v | grep -v "^$pool" | awk '{print $1}' | grep -v "^mirror" | head -n 1`
+ mDisk=`zpool list -H -v | grep -v "^$pool" | awk '{print $1}' | grep -v "^mirror" | grep -v "^raidz" | head -n 1`
+
+ # Is this MBR or GPT?
+ echo $mDisk | grep -q 's[0-4][a-z]$'
+ if [ $? -eq 0 ] ; then
+ # MBR
+ type="MBR"
+ # Strip off the "a-z"
+ rDiskDev=`echo $mDisk | rev | cut -c 2- | rev`
+ else
+ # GPT
+ type="GPT"
+ # Strip off the "p[1-9]"
+ rDiskDev=`echo $mDisk | rev | cut -c 3- | rev`
+ fi
- # Now we can insert the target disk
- zpool attach $pool $mDisk $disk
- if [ $? -ne 0 ] ; then
- exit_err "Failed attaching $disk"
+ # Make sure this disk has a layout we can read
+ gpart show $rDiskDev >/dev/null 2>/dev/null
+ if [ $? -ne 0 ] ; then
+ exit_err "failed to get disk device layout $rDiskDev"
+ fi
+
+ # Get the size of "freebsd-zfs & freebsd-swap"
+ sSize=`gpart show ${rDiskDev} | grep freebsd-swap | cut -d "(" -f 2 | cut -d ")" -f 1`
+ zSize=`gpart show ${rDiskDev} | grep freebsd-zfs | cut -d "(" -f 2 | cut -d ")" -f 1`
+
+ echo "Creating new partitions on $disk"
+ if [ "$type" = "MBR" ] ; then
+ # Create the new MBR layout
+ rc_halt_s "gpart create -s MBR -f active $disk"
+ rc_halt_s "gpart add -a 4k -t freebsd $disk"
+ rc_halt_s "gpart set -a active -i 1 $disk"
+ rc_halt_s "gpart create -s BSD ${disk}s1"
+ rc_halt_s "gpart add -t freebsd-zfs -s $zSize ${disk}s1"
+ if [ -n "$sSize" ] ; then
+ rc_halt_s "gpart add -t freebsd-swap -s $sSize ${disk}s1"
+ fi
+ aDev="${disk}s1a"
+ else
+ # Creating a GPT disk
+ rc_halt_s "gpart create -s GPT $disk"
+ rc_halt_s "gpart add -b 34 -s 1M -t bios-boot $disk"
+ rc_halt_s "gpart add -t freebsd-zfs -s $zSize ${disk}"
+ if [ -n "$sSize" ] ; then
+ rc_halt_s "gpart add -t freebsd-swap -s $sSize ${disk}"
+ fi
+ aDev="${disk}p2"
fi
- echo "Added $disk to zpool $pool. Resilver will begin automatically."
+ # Now we can insert the target disk
+ echo "Attaching to zpool: $aDev"
+ rc_halt_s "zpool attach $pool $mDisk $aDev"
+
+ # Lastly we need to stamp GRUB
+ echo "Stamping GRUB on: $disk"
+ rc_halt_s "grub-install --force /dev/${disk}"
+
+ echo "Added $disk ($aDev) to zpool $pool. Resilver will begin automatically."
exit 0
}
-list_mirror_disks() {
+list_zpool_disks() {
pool="$1"
if [ -z "$pool" ] ; then
@@ -422,23 +479,10 @@ list_mirror_disks() {
zpool status $pool >/dev/null 2>/dev/null
if [ $? -ne 0 ] ; then exit_err "Invalid pool: $pool"; fi
- # Make sure zpool isn't raid
- zpool list -H -v ${pool} | grep -q "raid"
- if [ $? -eq 0 ] ; then exit_err "Pool: $pool is raidz!" ; fi
-
- zpool list -H -v | grep -v "^$pool" | awk '{print $1}' | grep -v "^mirror" | tail +2 > /tmp/.mList.$$
-
- while read line
- do
- echo "$line" | grep -q -e "spare" -e "log" -e "cache"
- if [ $? -eq 0 ] ; then break ; fi
-
- echo "$line"
- done < /tmp/.mList.$$
- rm /tmp/.mList.$$
+ zpool list -H -v $pool
}
-rem_mirror_disk() {
+rem_zpool_disk() {
pool="$1"
disk="$2"
@@ -456,14 +500,54 @@ rem_mirror_disk() {
zpool status $pool >/dev/null 2>/dev/null
if [ $? -ne 0 ] ; then exit_err "Invalid pool: $pool"; fi
- # Make sure zpool isn't raid
- zpool list -H -v ${pool} | grep -q "raid"
- if [ $? -eq 0 ] ; then exit_err "Cannot remove disks from a raidz pool!" ; fi
-
zpool detach $pool $disk
if [ $? -ne 0 ] ; then
exit_err "Failed detaching $disk"
fi
echo "$disk was detached successfully!"
exit 0
}
+
+offline_zpool_disk() {
+ pool="$1"
+ disk="$2"
+
+ if [ -z "$pool" ] ; then
+ exit_err "No pool specified"
+ exit 0
+ fi
+
+ if [ -z "$disk" ] ; then
+ exit_err "No disk specified"
+ exit 0
+ fi
+
+ # Check if pool exists
+ zpool status $pool >/dev/null 2>/dev/null
+ if [ $? -ne 0 ] ; then exit_err "Invalid pool: $pool"; fi
+
+ zpool offline $pool $disk
+ exit $?
+}
+
+online_zpool_disk() {
+ pool="$1"
+ disk="$2"
+
+ if [ -z "$pool" ] ; then
+ exit_err "No pool specified"
+ exit 0
+ fi
+
+ if [ -z "$disk" ] ; then
+ exit_err "No disk specified"
+ exit 0
+ fi
+
+ # Check if pool exists
+ zpool status $pool >/dev/null 2>/dev/null
+ if [ $? -ne 0 ] ; then exit_err "Invalid pool: $pool"; fi
+
+ zpool online $pool $disk
+ exit $?
+}
View
85 src-sh/lpreserver/lpreserver
@@ -46,74 +46,83 @@ Type in help <command> for information and usage about that command
listcron - Listing of scheduled snapshots
listsnap - List snapshots of a zpool/dataset
mksnap - Create a ZFS snapshot of a zpool/dataset
- mirror - Enable / Disable ZFS mirroring to a local drive
replicate - Enable / Disable ZFS replication to a remote system
revertsnap - Revert zpool/dataset to a snapshot
rmsnap - Remove a snapshot
set - Set lpreserver options
status - List datasets, along with last snapshot / replication date
+ zpool - Mange a zpool by attaching / detaching disks
__EOF__
};
-help_mirror()
+help_zpool()
{
title
- echo "Help mirror
+ echo "Help zpool
-Life-Preserver mirror sub-system
+Life-Preserver zpool sub-system
-Mirroring uses ZFS to create a exact copy of your target disk to a new drive,
-such as an external USB disk. When first started the mirror will take a while
-to sync or "resilver". Once this is finished your new disk will be kept in sync
-with the target disk automatically, and can be used as a fall-back disk if the
-primary begins to fail.
+The 'zpool' sub-command allows you to attach / detach drives to a zpool,
+as well as get status and more.
-Should your primary disk fail the mirrored disk can then be used to restore
-the system via the restore option of the PC-BSD installation media.
+When a drive is first attached to a zpool, it will be re-formatted with
+a new gpart layout and made bootable with GRUB. For this reason the disk
+must be the same size, or larger, than the first array disk SWAP + ZFS
+partition size.
-*NOTES*
+Available Flags:
+ list - List zpool disks
+ attach - Attach a new zpool disk
+ detach - Remove a zpool disk
+ offline - Mark a disk as offline
+ online - Mark a disk as being online again
-* Mirroring will only work with a non-raidz ZFS pool. If you are using
-raidz you will need to manage disks through the "zpool" command.
+Attach Options:
-* The mirror disk must be the same size or larger than the target disk
+ attach <zpool> <new disk>
-Available Flags:
- list - List mirror disks
- add - Add a new mirror disk
- remove - Remove a mirror disk
+ Example 1:
-Add Options:
+ attach tank1 /dev/da0
- add <zpool> <new disk>
+ Attach the disk /dev/da0 to tank1 pool. The disk will be
+ auto-partioned with a SWAP / ZFS partition and made bootable.
- Example 1:
+Detach Options:
- add tank1 /dev/da0
+ detach <zpool> <disk>
+
+ Detach a disk from the zpool
- Will enable mirroring of the tank1 pool to /dev/da0
+ Use 'zpool list' for a list of available disks
-Remove Options:
+Offline Options:
- remove <zpool> <disk>
+ offline <zpool> <disk>
- Remove a mirrored disk from the zpool
+ Mark a disk in the zpool array as 'offline', should be when you
+ want to unplug a device, and anticipate plugging it back in later.
- Use 'mirror list' for a list of available disks
+Online Options:
+
+ online <zpool> <disk>
+
+ Mark an offline disk in the array as online again. The disk will begin
+ to resilver again automatically.
List Options:
list <zpool>
- Lists mirrored disks of a zpool
+ Lists the connected disks of a zpool
Usage:
- lpreserver mirror <subcmd> <flags>
+ lpreserver zpool <subcmd> <flags>
Example:
- lpreserver mirror list tank1
+ lpreserver zpool list tank1
"
};
@@ -387,7 +396,7 @@ case "$1" in
listcron) help_listcron ;;
listsnap) help_listsnap ;;
revertsnap) help_revertsnap ;;
- mirror) help_mirror ;;
+ zpool) help_zpol ;;
replicate) help_replicate ;;
cronsnap) help_cronsnap ;;
rmsnap) help_rmsnap ;;
@@ -488,13 +497,15 @@ revertsnap) require_root
*) help_replicate ;;
esac
;;
- mirror) require_root
+ zpool) require_root
shift
case ${1} in
- add) add_mirror_disk "$2" "$3" ;;
- list) list_mirror_disks "$2" ;;
- remove) rem_mirror_disk "$2" "$3" ;;
- *) help_mirror ;;
+ attach) add_zpool_disk "$2" "$3" ;;
+ detach) rem_zpool_disk "$2" "$3" ;;
+ online) online_zpool_disk "$2" "$3" ;;
+ offline) offline_zpool_disk "$2" "$3" ;;
+ list) list_zpool_disks "$2" ;;
+ *) help_zpool ;;
esac
;;
*) help_main ;;

0 comments on commit 59f367e

Please sign in to comment.