XenAPI vs. libvirt (and why libvirt is winning)

XenAPI vs. libvirt (and why libvirt is winning)

I think this post is a little on the late side, since I have a feeling that libvirt already won, but I just spent two days learning libvirt, as opposed to the weeks I spent trying to get XenAPI to act in a predictable manner. So here are some thoughts...

Libvirt is a superset of XenAPI

Yep. Libvirt can do everything (important) that XenAPI can do. The funny thing is that it is effectively using XenAPI/XenD to do it, since libvirt just connects to the xend socket to get work done. It is just that libvirt does it in a predictable, and well documented way.

Libvirt is more stable than XenAPI

Libvirt has a well defined and stable implementation. In fact, libvirt's python bindings return useful documentation, whereas the XenAPI being an abstraction of an XMLRPC interface, has no easily usable docs (yes I know there is a PDF file, but compare the methods to the actual XMLRPC stuff, and it is not always obvious how they work). Worse, XenAPI is guaranteed to break in the near future, so you are building on shifting sands.

Libvirt supports more than one virtualization platform

I develop against Xen on a lot of different boxen, and interoperability is one of my worst problems. PV vs HVM is one issue that particularly bothers me. It is impossible for me to test hardware virtualization on my older (but still hella fast) Xeon servers. Libvirt with it's qemu support (which uses the same method calls exactly as the Xen PV and HVM support) gives me the ability to seamlessly use my VM images across different hardware. Better, since there is (as yet untested by me) KVM support, I can develop against whatever platform eventually "wins".

Libvirt is used in production

... by Redhat no less (among a lot of others). That equals a LOT of testing, and smoothing out the messy stuff. XenAPI is basically beta, and nobody is using it. I am sure that XenAPI will mature a lot over the next few months. The Xensource team are VERY smart folks, but libvirt has a large head start, and will probably mature just as much in the same time. Closing the gap will not happen until there isn't much left to fix in libvirt, and their progress slows.

Libvirt is easy to use

So, let's pretend we want to get data about the VM. I already showed how in XenAPI here: XenAPI example... Here are the actual transactions I used to learn the first few things in libvirt that I wanted to do...

import libvirt
conn=libvirt.open('xen:///')
dir(conn)
['__del__', '__doc__', '__init__', '__module__', '_o', 'createLinux', 'createXML', 'defineXML', 
 'getCapabilities', 'getHostname', 'getInfo', 'getMaxVcpus', 'getType', 'getURI', 'listDefinedDomains', 
 'listDefinedNetworks', 'listDomainsID', 'listNetworks', 'lookupByID', 'lookupByName', 'lookupByUUID', 
 'lookupByUUIDString', 'networkDefineXML', 'networkLookupByName', 'networkLookupByUUIDString', 
 'numOfDefinedDomains', 'numOfDefinedNetworks', 'numOfDomains', 'numOfNetworks', 'restore', 'virConnGetLastError', 
 'virConnResetLastError']
#Wow... That was reasonably self explanatory...
foo=conn.lookupByUUIDString('aa753a14-5116-6734-8f0e-475e65db0206') #Yes, I knew the UUID already.
dir(foo)
['ID', 'OSType', 'UUID', 'UUIDString', 'XMLDesc', '__del__', '__doc__', '__init__', '__module__', 
 '_conn', '_o', 'attachDevice', 'autostart', 'connect', 'coreDump', 'create', 'destroy', 'detachDevice', 
 'info', 'maxMemory', 'maxVcpus', 'name', 'pinVcpu', 'reboot', 'resume', 'save', 'setAutostart', 
 'setMaxMemory', 'setMemory', 'setVcpus', 'shutdown', 'suspend', 'undefine']
#Wow. Nice and clean set of obvious API calls. Kind of like feedparser, or boto, or any other well written interface.
#So... how does this work?
help(foo.attachDevice)
 Help on method attachDevice in module libvirt:

 attachDevice(self, xml) method of libvirt.virDomain instance
     Create a virtual device attachment to backend.
#Neat. How about some commands...
foo.info()
 [2, 131072L, 131072L, 1, 3679113315L]
foo.suspend()
 0
foo.info()
 [3, 131072L, 131072L, 1, 3682550185L]
foo.resume()
 0
foo.info()
 [2, 131072L, 131072L, 1, 3682727196L]
#Well that was surprisingly easy...

Home Home
http://www.reaysmoving.com/