List forwarding rules in VirtualBox running headless (even with older VBoxManage versions)

The VBoxManage command is very handy for managing virtual machines in servers running headless. Adding and removing forwarding rules is super simple, you just call for example

# adding "rule1" for "vm_1" mapping TCP host_port to guest_port
VBoxManage modifyvm vm_1 --natpf1 "rule1,tcp,,host_port,,guest_port"

# deleting that same rule
VBoxManage modifyvm vm_1 --natpf1 delete rule1

I created two simple scripts so that I don’t have to remember the exact syntax every time: vm_forward_add and vm_forward_delete. You run the commands with no arguments, and they tell you what you need to add.

Listing the existing rules is a bit more complex, as VBoxManage has no option for that (not the version that I use, at least).

This is where xmlstarlet comes to the rescue. Xmlstarlet is a command-line tool for parsing XML that comes pre-installed in most UNIX systems.

Since forwarding rules are stored in VirtualBox .vbox files, which are just big XML files storing all properties for a VM, we can grab the information we want from there.

This is the script that I use to list all forwarding rules. I can’t guarantee that it works with any version of VirtualBox, but it works with any version <=4.3 (the one I use).

Feel free to use the script, the worst that it can do is… not work 🙂

About things that weren't too obvious: you need to include the XML schema not only in the XPath of the XML node you're interested in, but in all definitions (!).

So, say you have a node with this path and these attributes (xmlstarlet el -a lists all XPaths available in the XML file):

me@server:~ xmlstarlet el -a my_vm.vbox | grep Forwarding
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@name
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@proto
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@hostport
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@guestport

To query those four attributes you need to specify the XML schema using the -N option (easy to find in xmlstarlet‘s docs), but you also need to set that schema for every single attribute name!

So, this will fail:

xmlstarlet sel -N x="http://www.innotek.de/VirtualBox-settings" -t \
-m "//x:Machine/Hardware/Network/Adapter/NAT/Forwarding" -v @name \
-o " " -v @hostport -o " " -v @guestport -n my_vm.vbox

but this will work (note the repeated x:):

xmlstarlet sel -N x="http://www.innotek.de/VirtualBox-settings" -t \
-m "//x:Machine/x:Hardware/x:Network/x:Adapter/x:NAT/x:Forwarding" \
-v "concat(@name, ' - host:', @hostport, ' guest:', @guestport)" \
-n my_vm.vbox

I wish this was more explicit in xmlstarlet documentation!

Advertisements

2 thoughts on “List forwarding rules in VirtualBox running headless (even with older VBoxManage versions)

  1. Hi, I know this post is not so old, but I can’t get it work:
    – the URL “http://www.innotek.de/VirtualBox-settings” leads to an empty page. Was it the XSD ?
    – I use a VirtualBox configuration file which has defined port forwarding but they are not found.

    Here is the code I used:

    list_vbox_nat_fwding_rules() {
    local VMName=”$1″

    echo “INFO: Running $FUNCNAME”

    if [[ -z $VMName ]] ; then
    echo “ERROR: No name provided for source virtual machine”
    return 1
    fi

    VMcfg=$(get_vbox_vminfo “$VMName” “CfgFile”)

    if [ ! -f “$VMcfg” ]; then
    echo “ERROR: Source Config File \”$VMcfg\” doesn’t Exist”
    return 2
    fi

    echo “DEBUG: Configuration file for VM is: $VMcfg”

    #xmlstarlet el -a “$VMcfg” | grep Forwarding
    xmlstarlet select -N x=”https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Main/xml/VirtualBox-settings.xsd” \
    -t –match “//x:Machine/x:Hardware/x:Network/x:Adapter/x:NAT/x:Forwarding” -v “concat(@name, ‘ – host:’, @hostport, ‘ guest:’, @guestport)” \
    “$VMcfg”
    }

    Could you help me ?

    Like

    • Hi there, the URL was pointing to the namespace definition for the XML file (which is shown at the very top of the .vbox file. For my latest VMs, it is now simply http://www.virtualbox.org). However, they say that recent versions of xmlstarlet should supposedly do that for you automatically (without having to specify the whole ‘x:‘ thing for every node).

      Anyway, there’s another thing you can do, which is to strip out the namespace altogether, and feed that to xmlstarlet. Try this:

      cat "$VMcfg" | sed -e 's/ xmlns.*=".*"//g' | xmlstarlet sel -t -m "//VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding" -v "concat(@name, ' - host: ', @hostport, ' guest: ', @guestport)"

      If it doesn’t work, double check the path in your .vbox file, when I tried it I saw that on my machine was inside (because I’m not using NAT anymore on my VMs, I switched to bridged mode — no pun intended).

      Good luck! 🙂

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s