Transfer VMs between Xenserver pools

When Xenserver 7 came out I found myself unable to easily upgrade to it thanks to my custom RAID 1 build.  If I wanted Xenserver 7 I would have to blow the whole instance away and start from scratch. This posed a problem because I have a pool of 2 xenserver hosts. You cannot add a server with a higher xenserver version to a lower versioned pool; the pool master must always have the highest version of Xenserver installed. My decision to have an mdadm RAID 1 setup on my pool master ultimately turned into forced VM downtime for an upgrade despite having a pool of other xenserver hosts.

After transferring VMs to my secondary host and promoting it to pool master, I wiped my primary xenserver and installed 7. When it was up and running I essentially had two separate pools running. To transfer my VMs back to my primary server I had to resort to the command line.

Offline VM transfer

The xe vm-export and vm-import commands work with stdin/out and piping. This is how I accomplished transferring my VMs directly between two pools. Simply pipe xe vm-export commands with an ssh xe vm-import command like so:

xe vm-export uuid=<VM_UUID> filename= | ssh <other_server> xe vm-import filename=/dev/stdin

Note the lack of a filename – this instructs xenserver to pipe to standard output instead. Also note that transferring the VM scrambles the MAC addresses of its interfaces. If you want to keep the MAC address you’ll have to manually re-assign it after the copy is complete.

Minimal downtime

For the method above you will have to turn the VM off in order to transfer it.  I had some VMs that I didn’t want to stay down for the entire transfer. A way around this is to take a snapshot of the VM and then copy the snapshot to the other pool. Note that this method does not retain any changes made inside the VM that occurred after you took the snapshot. You will have to manually transfer any file changes that took place during the VM transfer (or be fine with losing them.)

In order to export a snapshot you must first convert it to a VM from a template (thanks to this site for outlining how.) The full procedure is as follows:

  1. Take a snapshot of the VM you want to move
    xe vm-snapshot uuid=<VM_UUID> new-name-label=<snapshotname>
  2. Convert the snashot template to a VM (the command xe snapshot-list is a handy way to obtain UUIDs of your snapshots)
    xe template-param-set is-a-template=false ha-always-run=false uuid=<UUID of snapshot>
  3. Transfer the template to the new pool
    xe vm-export uuid=<UUID of snapshot> filename= | ssh <other_server> xe vm-import filename=/dev/stdin
  4. Rename VM and/or modify interface MAC addresses as needed on the new host. Stop the VM on the old host and start it on the new one.

I used both methods above to successfully move my VMs from my older 6.5 pool to the newer 7 pool. Success.

8 thoughts on “Transfer VMs between Xenserver pools”

  1. This saved me a lot of time, thanks! One note, there is a typo in the Offline VM Transfer command… fiename should be filename.

  2. First off really interesting use of pipes. I am pretty newb at this so please help me out here.

    What is /dev/stdin?
    Don’t I need to name the vm i am exporting and importing?

    1. /dev/stdin is a special device that means “whatever is coming down the pipe at me.” It’s there to instruct programs that normally look for a file to look for information coming down the pipe instead.

      The VM you are exporting / importing is named at the xenserver level. When you use xe vm-export & vm-import with pipes you’re taking the information from one server and transporting it directly to the other without the need of saving anything to a file.

  3. I don’t have success with this… I waited a lot of time, but nothing happened. I’m using booth xenserver 6.2. Any Idea?

  4. xe vm-export uuid=4859c988-786c-290d-7553-a9afd9a2af28 filename= | ssh xe vm-import filename=/dev/stdin

    im use that and freez ….0 % network trafic

  5. Hi All,
    It is not working because you have to give sr-uuid too at the import command.
    So before the on-the-fly export-import at the destination you should query the storage possibilities with the xe sr-list command. Then you should use the uuid of the local storage with the import command.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.