pfSense On Citrix XenServer

Mon 07 July 2014 by feld

pfSense 2.2 snapshots are now based on FreeBSD 10 which means that support for Xen is built into the GENERIC kernel. This means virtualizing pfSense is very easy. If you install pfSense on Citrix XenServer it will not let you live migrate the VM to another host unless the Xen Tools are installed. Fortunately, there's an easy fix for that!

Step 1: Install the tools. If you haven't installed the pkg utility yet it will automatically fetch that first.

# pkg install xe-guest-utilities

Step 2: Enable it to start on boot.

Unfortunately pfSense has largely diverged from FreeBSD and won't run the rc scripts unless they end in .sh. We can fix this with a symlink. These two commands will enable it to run on boot.

# echo "xenguest_enable=\"YES\"" >> /etc/rc.conf.local
# ln -s /usr/local/etc/rc.d/xenguest /usr/local/etc/rc.d/xenguest.sh

Step 3: Start the service manually or reboot.

# service xenguest start

Ta-da! Fully functional Xen Tools on your virtualized pfSense firewall.

Note: If you happen to read this the day I wrote this you may find the memory reporting is broken and every few minutes some errors scroll on the console:

bc: cannot find dc: No such file or directory
bc: cannot find dc: No such file or directory
bc: cannot find dc: No such file or directory
bc: cannot find dc: No such file or directory
bc: cannot find dc: No such file or directory

You can hand-patch or just wait a week until the FreeBSD repo has xe-guest-utilties 6.0.2_3 or later.

diff --git a/src/sbin/xe-update-guest-attrs b/src/sbin/xe-update-guest-attrs
index 981f62f..44a0c63 100755
--- a/src/sbin/xe-update-guest-attrs
+++ b/src/sbin/xe-update-guest-attrs
@@ -129,11 +129,11 @@ done
 if [ $MEMORY_MODE -eq 1 ] ; then
        # calc memory... used http://www.cyberciti.biz/files/scripts/freebsd-memory.pl.txt as guide
        pagesize=$(sysctl hw.pagesize | cut -d ':' -f2)
-       memtotal=$(echo "$(sysctl hw.physmem | cut -d ':' -f2) / 1024" | bc)
-       meminactive=$(echo "$(sysctl vm.stats.vm.v_inactive_count | cut -d ':' -f2) * $pagesize / 1024" | bc)
-       memcache=$(echo "$(sysctl vm.stats.vm.v_cache_count | cut -d ':' -f2) * $pagesize / 1024" | bc)
-       memfree=$(echo "$(sysctl vm.stats.vm.v_free_count | cut -d ':' -f2) * $pagesize / 1024" | bc)
-       memavail=$(echo "$meminactive + $memcache + $memfree" | bc)
+       memtotal=$(let "$(sysctl hw.physmem | cut -d ':' -f2) / 1024")
+       meminactive=$(let "$(sysctl vm.stats.vm.v_inactive_count | cut -d ':' -f2) * $pagesize / 1024")
+       memcache=$(let "$(sysctl vm.stats.vm.v_cache_count | cut -d ':' -f2) * $pagesize / 1024")
+       memfree=$(let "$(sysctl vm.stats.vm.v_free_count | cut -d ':' -f2) * $pagesize / 1024")
+       memavail=$(let "$meminactive + $memcache + $memfree")

        # we're using memavail as "free" for now
        xenstore_write_cached "data/meminfo_total" "$memtotal"

It's really just changing the echo through bc into a POSIX sh let.