FreeBSD manual multipath script

I recently ran into an issue installing FreeBSD on a system that already had some disks & zpools. Because the disks were partitioned previously, automatic multipath was not an option as the last sector of all hard drives isn’t available to store an ID. The remaining option is to do manual multipath, and it needs to be done every time the system boots.

Here’s an rc script that will run early in the sequence and create a multipath “link” between drives based on their serial number.

/etc/rc.d/manual_multipath

#!/bin/sh

# PROVIDES: manual_multipath
# REQUIRE: sysctl
# BEFORE: hostid

. /etc/rc.subr

name="manual_multipath"
start_cmd="${name}_start"
stop_cmd=":"

manual_multipath_start()
{
        echo "> manual_multipath script started"
        echo "> linking drives with the same serial number with gmultipath"
        counter=0
        serials=""
        devices=`/usr/bin/find /dev -maxdepth 1 -regex '.*da[0-9]*' | /usr/bin/cut -d '/' -f 3`
        for device in $devices
        do
                echo $device
                serial=`camcontrol inquiry $device -S`
                substring=`echo "$serials" | /usr/bin/sed -n "s/|$serial|.*//p" | /usr/bin/wc -c`
                if [ $substring -eq 0 ]
                then
                        found_multi=0
                        arg1="$device"
                        arg2="$device"
                        for newdevice in $devices
                        do
                                newserial=`camcontrol inquiry $newdevice -S`
                                if [ "$device" != "$newdevice" -a "$serial" == "$newserial" ]
                                then
                                        echo "  same as $newdevice!"
                                        counter=`expr $counter + 1`
                                        found_multi=1
                                        arg1=$arg1"$newdevice"
                                        arg2=$arg2" $newdevice"
                                fi
                        done
                        if [ $found_multi -eq 1 ]
                        then
                                gmultipath create $arg1 $arg2
                        fi
                fi
                serials=$serials"|$serial|"
        done
        echo "> manual_multipath script finished, found $counter matches"
}

load_rc_config $name
run_rc_command "$1"

Don’t forget to “chmod 555 /etc/rc.d/manual_multipath”.

Lastly, when importing a zpool from the drives you just multipathed, make sure to specify where to look for devices or you might end up importing a mix of multipath and regular devices. Make sure to “zpool import -d /dev/multipath”.

I’m delving pretty deep into FreeBSD, time to grow an epic beard.

ZFS send/receive accross different transport mechanisms

Sending ZFS snapshots across the wires can be done via multiple mechanisms. Here are examples of how you can go about it and what the strengths and weaknesses are for each approach.

SSH

strengths: encryption / 1 command on the sender

weaknesses: slowest

command:

zfs send tank/volume@snapshot | ssh user@receiver.domain.com zfs receive tank/new_volume

NetCat

strengths: pretty fast

weaknesses: no encryption / 2 commands on each side that need to happen in sync

command:

on the receiver

netcat -w 30 -l -p 1337 | zfs receive tank/new_volume

on the sender

zfs send tank/volume@snapshot | nc receiver.domain.com 1337

(make sure that port 1337 is open)

MBuffer

strengths: fastest

weaknesses: no encryption / 2 commands on each side that need to happen in sync

command:

on the receiver

mbuffer -s 128k -m 1G-I 1337 | zfs receive tank/new_volume

on the sender

zfs send tank/volume@snapshot | mbuffer -s 128k -m 1G -O receiver.domain.com:1337

(make sure that port 1337 is open)

SSH + Mbuffer

strengths: 1 command / encryption

weaknesses: seems CPU bound by SSH encryption, may be a viable option in the future?

command:

zfs send tank/volume@snapshot | mbuffer -q -v 0 -s 128k -m 1G | ssh root@receiver.domain.com 'mbuffer -s 128k -m 1G | zfs receive tank/new_volume'

Finally, here is a pretty graph of the relative time each approach takes:

SSH + MBuffer would seem like the best of both worlds (speed & encryption), unfortunately it seems as though CPU becomes a bottleneck when doing SSH encryption.

MDNS/Bonjour printer discovery script

Here’s a script I wrote whose purpose is to discover the printers that are currently being advertised by Bonjour on the network. The reason I wrote it was for a Nagios check that would in term verify that our printers were present. Writing it took me through the meanders of MDNS in Python & on Linux with multiple vlans. Let’s just say non-trivial.

Download

find_mdns_printers_1.0.tar.gz

Sample output