Getting acquainted with libvirt and its implementation
As discussed in a previous chapter, there is an extra management layer called libvirt
which can talk to various hypervisors (for example: KVM/QEMU, LXC, OpenVZ, UML, and so on) underlying it. libvirt is an open source Application Programming Interface (API). At the same time, it is a daemon and a management tool for managing different hypervisors as mentioned. libvirt is in use by various virtualization programs and platforms; for example, graphical user interfaces are provided by GNOME boxes and virt-manager (http://virt-manager.org/). Don't confuse this with virtual machine monitor/VMM which we discussed in Chapter 1, Understanding Linux Virtualization.
The command line client interface of libvirt is the binary called virsh
. libvirt is also used by other higher-level management tools, such as oVirt (www.ovirt.org):
Most people think that libvirt is restricted to a single node or local node where it is running; it's not true. libvirt has remote support built into the library. So, any libvirt tool (for example virt-manager) can remotely connect to a libvirt daemon over the network, just by passing an extra –connect
argument. One of libvirt's clients (the virsh
binary provided by the libvirt-client package) is shipped in most distributions such as Fedora, CentOS, and so on.
As discussed earlier, the goal of the libvirt library is to provide a common and stable layer to manage VMs running on a hypervisor. In short, as a management layer it is responsible for providing the API that does management tasks such as virtual machine provision, creation, modification, monitoring, control, migration, and so on. In Linux, you will have noticed some of the processes are deamonized. The libvirt process is also deamonized, and it is called libvirtd
. As with any other daemon process, the libvirtd provides services to its clients upon request. Let us try to understand what exactly happens when a libvirt client such as virsh or virt-manager requests a service from libvirtd
. Based on the connection URI (discussed in the following section) passed by the client, libvirtd opens a connection to the hypervisor. This is how the clients virsh or virt-manager ask the libvirtd to start talking to the hypervisor. In the scope of this book, we are aiming at KVM virtualization technology. So, it would be better to think about it in terms of a QEMU/KVM hypervisor instead of discussing some other hypervisor communication from libvirtd. You may be a bit confused when you see QEMU/KVM as the underlying hypervisor name instead of either QEMU or KVM. But don't worry, all will become clear in due course. The connection between QEMU and KVM is discussed in the following. For now just know that there is a hypervisor that uses both the QEMU and KVM technologies.
Let us go back to the connection URI we passed with the libvirt client virsh. As we are concentrating on QEMU/KVM virtualization, the connection URI, which has been passed from the client has, strings of "QEMU", or will have the following skeleton when passed to libvirt to open a connection:
qemu://xxxx/system
qemu://xxxx/session
The former (qemu://xxxx/system
) basically requests to connect locally as the 'root' to the daemon supervising QEMU and KVM domains or virtual machines. However, the latter (qemu://xxxx/session
) requests to connect locally as a "normal user" to its own set of QEMU and KVM domains. Previously, I mentioned that libvirt also supports remote connections; luckily, to achieve this functionality, it is only required to have a small change in the connection URI. That said, it can establish a remote connection by changing some strings in the connection URI. For example, the common format for the connection URI is as follows:
driver[+transport]://[username@][hostname][:port]/[path][?extraparameters]
A simple command line example of a virsh
binary for a remote connection would be as follows:
$ virsh --connect qemu+ssh://root@remoteserver.yourdomain.com/system list --all
As shown in the virsh
command example (qemu+ssh://root@remoteserver.yourdomain.com/system
), remote URIs are formed by taking ordinary local URIs and adding a hostname and/or transport name:
The preceding figure shows the remote connection established to talk to the libvirt running on a remote or other system. The details of the driver API or driver implementation follow later. When using a URI scheme of "remote", it will tell the remote libvirtd server to probe for the optimal hypervisor driver. The following sections will provide some details about "remote" drivers. Refer to the following URLs for more details on what options can be given for a remote connection URI:
To understand how libvirt really works, let us look at the code. This section contains some developer-oriented details; if you are not at all keen to know about how libvirt works internally, you can skip this part. If you are in half a mind, go through it!