Recently one of my fellow Consulting colleagues asked around whether anybody knew of a script to export all VM names and the MAC addresses of their virtual interfaces. A list like this could be useful not only for tracking and network management purposes (think of NAC) but also to create DHCP reservations (For Linux geeks, you can probably stop reading here because I don’t want to bore you :) , but if you are like me and don’t work with Linux every day, this might be interesting).

Not having touched XenServer scripting for some time, it took me a little more time than expected to get back into it but I must say: You should try it, it’s great fun and using the XenAPI is not only very straightforward but also extremely flexible, so it gives you a lot of possibilities the built-in management tools like XenCenter do not provide out of the box.

The reason you need a script to complete this seemingly small task is that MAC addresses are not a direct attribute of a VM but of a virtual interface (VIF). VMs can have a one to many relationship to a VIF. To find these relations, multiple XenAPI queries are necessary.

So here we go, I’ll get to the point and tell you what the script does:

  • query all VMs in a pool/host and obtain their unique UUID (we don’t necessarily need the UUID, however the name-label attribute is not a unique identifier so we better be on the safe side. Also, this way we are prepared to extend the script easily.)
  • using the UUID, get the name label (so the VM name as you would see it in XenCenter)
  • obtain the list of virtual network interfaces that are mapped to the VM and count them
  • read the MAC addresses of each VIF
  • write “vm-name”,”MAC1″,”MAC2″,….”MACn” into a txt file called “output.csv”

Some basic error catching functionality:

  • the user running the script must be root
  • the output.txt file is being created if it doesn’t exist; if it does exist, it will be emptied
  • the VM “Control domain on host: %hostname%” which is the Dom0 and does not have any virtual interfaces and hence MAC addresses will not be processed
  • if you happen to have a single VIF with the device id “1″ (or anything higher for that matter) mapped to a VM (you would expect “0″ as the first device, however when you have two VIFs and delete the first, you will be left with one VIF with the ID “1″), the script will detect this and not query an interface with the device id “0″.

That’s it. Once you’ve run the script, you will only need to copy the file off of the host you have run it on using SCP for example and import it into the tool of your choice. Speaking of which, if I ever find some more time (not exclusively a Consulting destiny I hear) I might wrap this into PowerShell, because then you could directly import the MACs into a Windows DHCP server.

Long story short, here’s the code (WordPress destroys the formatting, download the script here:


if [ $(whoami) != 'root' ];
echo “Must be root to run $0″
exit 1;

if [[ ! -e output.csv ]];
touch output.csv
> output.csv

for vmuuid in `xe vm-list | awk -F’: ‘ ‘/^uuid/ {print $2}’` ;
namelabel=`xe vm-param-get uuid=$vmuuid param-name=name-label`
case $namelabel in
*”Control domain”* ) continue ;;
i=`xe vif-list vm-name-label=”$namelabel” | grep device | wc -l`
for ((j=0;j<$i;j++))
mac=`xe vif-list vm-name-label=”$namelabel” params=MAC device=$j | awk -F’: ‘ ‘/^MAC/ {print $2}’`
if [ -z "$mac" ]
i=`expr $i + 1`
if [ $j -lt `expr $i - 1` ]
echo “$writeline” >> output.csv
echo “VMs and their respective MAC addresses have been written to output.csv in the current directory.”
exit 0

Make sure you make it executable using “chmod +x %filename%” and then run it either using bash (./scriptname) or the bourne shell (sh scriptname). The result will be the same as we don’t use any advanced shell features.

Last but not least, obviously this is a custom solution and will not be supported by Citrix Support, however you are very welcome to comment and let me know of any problems you’re having with the script.