On my third day at XTIVIA, it was recommended I tinker with Oracle’s free VirtualBox. The following week, I was hooked! A Unix guy at heart, I can launch whichever flavor of Linux desktop I’m in the mood for, while Windows keeps running and all the tools there remain available. But, if you intend to do any serious testing between virtual machines, you cannot rely on the default networking configurations.

Out of the box

The default VirtualBox networking for a Linux virtual machine (or VM) is adequate for testing self-contained programs and configurations within the VM. It’s also great for surfing the web, getting email, and ssh’ing to external servers. But if you want to have several virtual machines interacting with each other, say for validating Liferay clustering architectures, you’ll probably end up pulling out your hair. This is because by default VirtualBox uses NAT and serves as a DHCP server. Don’t bother trying to set your hosts file to something like:

     10.0.3.102     dbserver
     10.0.3.103     cluster-node01
     10.0.3.104     cluster-node02

…and expect  it to stay that way.

DHCP Roulette

It seems the DHCP server doesn’t put any effort into preserving, preferring, or reserving IPs for prior clients; it is very simple. This could work for a while, but if you save or power-off any VM, you’re hosed. You must start all the VMs you had running when you created your hosts file, and in the same order, or your little network layout will fall apart! The hosts file example above implies we need to start one unrelated VM to take 10.0.3.101, then ‘dbserver’ followed by node01 then node02.

Hope lay in Host-only Adapters

The first thing I did to fix this was add a network adapter to each VM within VirtualBox, and assign it to the “Host-only” network. You will want to take a look under “File->Preferences->Networks->Host-Only-Network->DHCP” to confirm or set the IP range the DHCP server will manage.

This picture shows the DHCP configuration window in VirtualBox.

Static IP Addresses

At that point, you might want to create a hosts file with your desired IPs and hostnames and save it in your VirtualBox shared folder. You’ll need to use addresses outside of the DHCP range but obviously within the same subnet. Then start each VM, log into them one by one and set the static IP for the adapter which has an address assigned by the Host-Only DHCP. For example, the NAT adapter will probably be using a 10.0.x.x address, and your host-only adapter will likely have 192.168.x.10x (whatever range DHCP is managing; 192.168.56.101-254 in the screen-grab). If you like using NetworkManager, just edit the connection and set it to “Manual” then insert your desired IP. Be forewarned, however, that NetworkManager and VirtualBox seem to work against one another in various ways. At one point, I had to enable all 4 adapters in VirtualBox so that I could find one that was listed in both ifconfig(8) and NetworkManager. I even had four interfaces numbered randomly between “eth0” and “eth9”. In other words, it’s probably better to use your Linux-fu in order to set up the static IPs outside of NetworkManager.

The next step is to update your /etc/hosts — either edit it manually or copy the one you created in the shared folder. Although it’s not strictly necessary (unless an app needs to know the hostname of the machine it’s running on), you can set the machine’s hostname in whatever fashion your Linux flavor requires.

Who doesn’t need DNS resolution?

You’re almost finished. Don’t bother trying to muck about in /etc/resolv.conf in order to resolve external names. A better answer is to use the “VBoxManage” utility on the host. There are two methods that could help you here: “natdnsproxy1” or “natdnshostresolver1”. I found the latter works great in my LAN. At the command line on your VirtualBox host, run the following command for each VM, and every subsequent VM you create:

VBoxManage modifyvm "VM name or UUID" --natdnshostresolver1 on

Having to setup VirtualBox on several hosts with numerous VMs, I threw together a quick & dirty script to do this for every VM.

#!/bin/sh
# Help Chapter: 9.11.6. Using the host's resolver as a DNS proxy in NAT mode
##### Set your specific path to the executable 
VBM="/cygdrive/c/Program Files/Oracle/VirtualBox/VBoxManage.exe" 
for VMUUID in `"$VBM" list vms | cut -f2 -d{ | cut -f1 -d}` ; do
 "$VBM" modifyvm $VMUUID --natdnshostresolver1 on && echo "$VMUUID done"
done

Finally, halt and “power cycle” each VM just to make sure everything loads correctly. Now you’re finished. Try SSH’ing (or whatever) from your host to one of the static IPs and you should connect. You’ll find that your virtual machines can reliably use hostnames and reach the one(s) with the required resource you’re trying to access. As such:

cluster-node01 % ping -c3 dbmaster
PING dbmaster (192.168.56.66) 56(84) bytes of data.
64 bytes from dbmaster (192.168.56.66): icmp_seq=1 ttl=64 time=0.344 ms
64 bytes from dbmaster (192.168.56.66): icmp_seq=2 ttl=64 time=6.31 ms
64 bytes from dbmaster (192.168.56.66): icmp_seq=3 ttl=64 time=0.277 ms

--- dbmaster ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.277/2.312/6.316/2.831 ms
cluster-node01 %

Next steps

I have a feeling that somewhere along the line I’ll put BIND on my host machine and convert my /etc/hosts to a DNS zone file. There are better ways to spend your time than toting /etc/hosts files all over the place. But if you only have to manage a handful, it’ll work just fine.