Waking up and shutting down FreeNAS „on demand”
What I wanted is simple. I wanted my FreeNAS box (a HP ProLiant N54L MicroServer) to be available when one of our PCs/Laptops in the household was online, but to shut it down, when no one was home (save energy, …). Also giving SWMBO some sort of „remote” to manually turn on the server was out of the question.
What I came up with as a solution was to utilize the always running TP-LINK TL-WDR4300 N750 (with OpenWrt 12.09) as a „watchdog”. If one of the „main” PCs comes online, it checks if the FreeNAS is running and if not, sends a WoL package to it, starting it.
The idea was simple, the execution not so much, especially in the case of the FreeNAS …
(Scroll past the N54L part, if you are not using that piece of Hardware)
HP Proliant N54L
The built in NIC for the HP ProLiant N54L (at least in my box) is a ‘NetXtreme BCM5723 Gigabit Ethernet PCIe’ which utilizes, in FreeNAS 22.214.171.124, the if_cxgbe.ko driver, which does NOT support Wake On Lan (wol):
bge0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=c0099<:RXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,VLAN_HWTSO,LINKSTATE>
The Linux drivers support it and in apparently worked with FreeNAS 9.1, so it seems to be a FreeBSD driver issue, as far as I was able to trace the issue. The „fix” is a rather ugly hack.
- Download the NAS4Free ISO version 126.96.36.199.847x64 (current version in August 2014)
- Mount that iso and extract the file boot/kernel/if_bge.ko.gz
- Unpack that file so you have a „if_bge.ko” file (the driver)
- Mount the root file system on the FreeNAS box as writeable mount / -rw
- Copy that file to the FreeNAS box and into the „/boot/kernel” directory
- Make the driver load upon boot up, by placing „if_bge_load="YES"” at the bottom of the „/boot/loader.conf” file
- Remount „/” as read-only on the FreeNAS box
- Reboot the FreeNAS box
After that, the NIC shows up as WOL capable (notice the „WOL_MAGIC”?):
bge0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=c2099<RXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,VLAN_HWTSO,LINKSTATE>
I am not really sure, why that helps, as FreeNAS was using if_cxgbe and we added if_bge, but I am not complaining. ;) If someone more knowledgeable of FreeBSD could point me in the right direction, I would be happy to open a bug report on that.
So now that the NIC of the N54L as well as the BIOS and the OS supports WOL and the box reacts to the right packet, let’s look at the other components.
OpenWrtWhat we need on the WiFI Router is a cron job to check every minute, if the FreeNAS box is down (not pingable). If so, it should check, whether at least one of the „important” PCs is online. If so, the script should wake up the FreeNAS box via a WOL broadcast.
Preparations on the OpenWrt box:
- Start and enable cron:
- Install wol: „opkg install wol
#!/bin/ash FREENAS_MAC="38:ea:a7:xx:xx:xx" FREENAS_MASK="192.168.1.255" FREENAS_IP="192.168.1.24" NASPING=`ping -c 1 -q $FREENAS_IP | grep -c '1 packets received'` if [ $NASPING -eq 0 ]; then while IFS= read -r MAC <&3; do echo "Working on $MAC ..." if [ -z "$MAC" ]; then # skip empty lines continue fi VAR=`grep $MAC /proc/net/arp` if [ -z "$VAR" ]; then : else IP=`echo "$VAR" | cut -d ' ' -f1` PING=`ping -c 1 -q $IP | grep -c '1 packets received'` if [ $PING -eq 0 ]; then printf "%s\tPC down\n" $MAC : else echo "$MAC PC online, FreeNAS offline. Therefore waking up FreeNAS." /usr/bin/wol -h $FREENAS_MASK $FREENAS_MAC 1</dev/null break fi fi done 3> "/etc/pcs.txt" else echo "NAS already running" : fi
The file „/etc/pcs.txt” just contains a list of MAC addresses, one per line, denoting the „important” PCs. You will have to add all the MACs of all the NICs (wired and wireless) of the PCs/Laptops you want to check for.
Now just add the script call to cron via „crontab -e”:
*/1 * * * * /etc/wakeUpNAS.sh
And we are all done on the OpenWrt side. Now within one minute of a PC being online, the FreeNAS gets woken up via Wake On LAN.
FreeNASNow all that is left is to shut down FreeNAS once no „important” PC is online anymore. As you probably have guessed by now, this calls for another script, which I put at „/mnt/raid_name/scripts/shutdown4wol.sh”:
#!/bin/bash SUBNET=192.168.1. SHUTDOWN=true # Fill ARP cache export COUNTER=1 while [ $COUNTER -lt 255 ] do ping -c 1 -t 1 $SUBNET$COUNTER 1</dev/null & COUNTER=$(( $COUNTER + 1 )) done #wait for pings to finish sleep 3 while IFS= read -r MAC <&3; do # skip empty lines in file if [ -z "$MAC" ]; then continue fi # Let's see, if we find a IP for the current MAC VAR=`arp -a | grep $MAC` if [ -z "$VAR" ]; then : else # We have an IP for the MAC, so the PC might still be on. Check with ping IP=`echo "$VAR" | cut -d ' ' -f1` PING=`ping -c 1 -q $IP | grep -c '1 packets received'` if [ $PING -eq 0 ]; then printf "%s\tPC down\n" $MAC : else echo "$MAC PC online" # Abort shutdown SHUTDOWN=false # One PC running is enough to keep the server running break fi fi done 3> "./pcs.txt" if [ "$SHUTDOWN" = true ] ; then echo "Shutdown this server" /sbin/shutdown -p now else echo "Do nothing, keep server running" fi
The file „/mnt/raid_name/scripts/pcs.txt” again contains a list of MAC addresses, one per line, denoting the „important” PCs. You will have to add all the MACs of all the NICs (wired and wireless) of the PCs/Laptops you want to check for. Also make sure, that this list equals the list on the OpenWrt router.
Add the script to FreeNAS’ cron via the GUI, as described in the FreeNAS documentation.
FinaleAnd that’s it. Just make sure, that the cron jobs do not end in an endless shutdown/restart circle and you are good to go.
Further reading, ThanksAs usual, „The Internet” was a big help in setting this up. The solution was heavily „influenced”, by the following blogposts/forum postings:
- [HowTo] have OpenWrt auto detect MAC address and start NAS with wol
- Automatic Shutdown/Wake Up on FreeNAS by Hoong Ern Ng.
- How to patch ‘if_bge.c’ - FreeBSD 9.2