As discussed in my previous post, Libvirt is an open source project for managing hypervisors. With the increasing popularity of Openstack, it’s important to get familiar with KVM as an alternative virtualization platform to commercial products like vSphere and Hyper-V.
To use KVM, you don’t have to install Openstack – you can just install KVM as a standalone product as described in my previous post. In that, it’s pretty much like VMware Player or Workstation. In terms of maturity, KVM is pretty solid and way ahead of Openstack which is also improving quickly since last year with many commercial vendors jumping in.
Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.
If you want to automate something, you can use the virsh commands, or use the libvirt API directly. Check this link for the full description of the APIs.
Although the libvirt in C is the original API and other language bindings are built on top of it, it’s pretty low level and procedural. Luckily, language bindings like Java provide more than simple wrapper – it actually build simple object model around it. For this reason, we will introduce the API with Java binding. I think you would agree with me that this javadoc is easier to understand than the previous C API doc.
To understand the libvirt, it’s important to know these types. Their relationship is depicted in this page (http://libvirt.org/api.html#Objects). While reading the diagram, just ignore the vir prefix and ptr suffix.
With the knowledge of the vSphere APIs, you can guess out what these object mean and what they are for, except the Domain which is really just another name for VirtualMachine in libvirt world. I will blog about the terminology difference in another post later.
In some ways, these five types are similar to the managed object types in vSphere APIs. The ESXi implementation of vSphere APIs has a lot more types than here due to richer functionalities exposed.
Like vSphere, libvirt also has data objects, which are really defined as struct in its original form in C. The key difference from managed object types is that they do not have method defined – all they do is to hold information about something.
There is another set of interfaces in libvirt called virErr that is designed for error handling.
Common Flow and Object Navigation
While using the libvirt, the first thing is to connect to a hypervisor. You can achieve this in all the language bindings supported. In my previous post, you can find a sample I wrote in Java. The form and style could be different but the overall picture is the same.
In Java binding, a connection is created through the Connect which is very similar to the ServiceInstance in vijava API. With the Connect instance, you can call into various methods defined on the type, for example, nodeInfo() for the information about the physical server that runs the hypervisor.
From the Connect object, you can also get to other “managed objects” like Domain objects. This could be a little tricky given the fact that there is no direct method to iterate though the Domain object on the hypervisor.
You can, however, achieve this indirectly – first call the list*s() methods to get an array of IDs or names. Then, you can call *LookupByID() or *lookupByName() to get hold of the real * object. In parallel with the list*s() methods are listDefined*s() which return similar info but for inactive * objects. Note: the * is place holder for types like Domain.
Once you can navigate though the object hierarchy and get the object of your interest, you can continue to call corresponding methods on these objects for what you want to achieve.
More on XML
To use libvirt, it’s not required to use XML for most of the part. I do find a good usage of XML, which simplifies the interfaces themselves. The complexity does not go away but goes into the XML itself. If you use virsh commands, you also find XML as input and output as well.
Let me pick up domain as an example as shown below. There are more on other types like Network, Network filter, Storage, Capabilities, Secret, and Snapshot here.
public Domain domainDefineXML(java.lang.String xmlDesc) throws LibvirtException
The interface is very simple with a string as input. What is the schema of the xmlDesc is not quite clear, but you can guess what should be there, like name, memory, storage, device, etc, as would you do to create a new virtual machine in vSphere. There is actually a pretty long page () to describe the metadata for the XML relating to a domain. Somehow I could not find a XML schema file for this.
Documentation is great but I think XML schema is equally important especially coming to coding. There are some XML samples you may find useful. It seems the format is different from fully virtualized to para-virtualized domain. I think this is really a loose end for the libvirt APIs – it does not bind, and any tiny typo in the API input could fail the runtime and only in runtime, a huge challenge for testing especially your code needs to support multiple types of hypervisors. More than that is you cannot automatically generate code from XML schema. In my opinion, XML is for machine not for human being.
Anyway, the other direction is to get XML from the API. It’s not going to risk failing the libvirtd server, but it remains a challenge on how to parse out the information of your interest.
Having said all these, it may not too bad because the common use cases are limited. If you are not sure, you can try it out with virsh first, and you can convert the command line options to XML and vice-versa.
If you are interested to explore more about libvirt API, you would find the following resources very helpful.
Application Development Guide (PDF)
Libvirt API spec
Javadoc for Libvirt Java Binding