- Preparing Your System for Virtualization
- Installing KVM
- libvirt: A Virtualization API
- Other VM Workflows
- Command-Line Access to libvirt with virsh / Running the Code
libvirt: A Virtualization API
libvirt provides an API that allows software access to VM facilities. Some of the key items to note in the libvirt lexicon are the following:
- Node - A single physical machine.
- Hypervisor - A layer of software that allows the virtualization of a node in a set of VMs.
- Domain - An instance of an operating system running on a VM provided by the hypervisor.
Let's try to make this all a bit more concrete by actually running some code. Listing 1 illustrates the program output from a simple libvirt client when no VMs are running on the host Ubuntu system.
Listing 1Enumerating QEMU Domains with libvirt
Hello World! Hypervisor version 8003 Type QEMU NumOfDefinedDomains 2 URI qemu:///system Domain:MyKVMVirtualMachine id -1 running OS hvm host name stephen-Latitude-E5400 hypervisor version 8003 Domain state: VIR_DOMAIN_SHUTOFF
Listing 1 illustrates what is essentially an empty virtual environmenti.e., no VMs are running. Notice however, that libvirt has identified that two domains have been created but that the domain state is VIR_DOMAIN_SHUTOFFi.e., no VMs are running.
How do I acquire the information in Listing 1? It's not too difficult; in Listing 2, you see the Java code that produces the output in Listing 1.
Listing 2The libvirt API in Action
Connect conn = new Connect("qemu:///system", true); System.out.println(" Hypervisor version " + conn.getHypervisorVersion(null)); System.out.println(" Type " + conn.getType()); System.out.println(" NumOfDefinedDomains " + conn.numOfDefinedDomains()); System.out.println(" URI " + conn.getURI()); Domain testDomain = conn.domainLookupByName("MyKVMVirtualMachine"); System.out.println("Domain:" + testDomain.getName() + " id " + testDomain.getID() + " running OS " + testDomain.getOSType() + " host name " + conn.getHostName() + " hypervisor version " + conn.getHypervisorVersion(null)); System.out.println("Domain state: " + testDomain.getInfo().state.name());
The first action in Listing 2 is to instantiate a Connect instance. This object is then used to communicate with the hypervisor; in this case, the hypervisor is QEMU/KVM. I enumerate the version of the hypervisor before reading the number of domains associated with that hypervisor. I then do a domain lookup of one of the VMs by name. Finally, the details of the underlying VM are enumerated.
Let's now build on the output from Listing 1 by interacting with the QEMU/KVM hypervisor and by running one of its defined VMs. On Ubuntu, I do this by running the abovementioned program Virtual Machine Manager from the Applications > System Tools menu. This results in the display illustrated in Figure 1.
Comparing Figure 1 with Listing 1, you can see that there are indeed two QEMU/KVM VMs defined and that both of them are in the “not running” or “shutoff” state. Let's now run one of the VMs. You do this by selecting one of the VMs in Figure 1 and clicking the green start button, which results in the contents displayed in Figure 2.
Figure 2 Running one of the virtual machines on the Ubuntu host
In passing, notice in Figure 2 the CPU usage graphic starts to indicate activity in the VM. This is a nice way of showing you that the VM is beginning to consume resources in the underlying platform. Also, note that the state of the VM changes to “Running”.
I've always felt that graphical tools are invaluable for giving rapid insight into the operation of even the most complex software systems!
So, what effect does this newly running VM in Figure 2 have on the Listing 2 libvirt Java code? Let's run it again to see, with the result displayed in Listing 3.
Listing 3One VM Running
Hello World! Hypervisor version 8003 Type QEMU NumOfDefinedDomains 1 URI qemu:///system Domain:MyKVMVirtualMachine id 2 running OS hvm host name stephen-Latitude-E5400 hypervisor version 8003 Domain state: VIR_DOMAIN_RUNNING
In Listing 3, you can see the domain state is now VIR_DOMAIN_RUNNING. The Java code in Listing 2 is now mirroring the (now running) VM state. Notice also that the domain name 'stephen-Latitude-E5400' has been displayed in Listing 3.
Clearly, if we're using virtualization in a commercial or corporate context, we'll need to run many VMs. Indeed, in large corporate data centers, it's commonplace to have many thousands of VMs running constantly. How do we modify the Listing 2 Java code to see more than one VM?
Well, because we're now going to address two VMs, a small modification to the code is required, as illustrated in Listing 4. The change I made is to extract (or refactor) the displaying of the domain details into a separate method called displayDomainDetails(). This method is then called for each of the two domains.
Listing 4Minor libvirt Code Change
private static void displayDomainDetails(Connect conn, Domain testDomain) throws LibvirtException { System.out.println("Domain:" + testDomain.getName() + " id " + testDomain.getID() + " running OS " + testDomain.getOSType() + " host name " + conn.getHostName() + " hypervisor version " + conn.getHypervisorVersion(null)); System.out.println("Domain state: " + testDomain.getInfo().state.name()); } public static void main(String[] args) { System.out.println("Hello World!"); Connect conn = null; try { conn = new Connect("qemu:///system", true); System.out.println(" Hypervisor version " + conn.getHypervisorVersion(null)); System.out.println(" Type " + conn.getType()); System.out.println(" NumOfDefinedDomains " + conn.numOfDefinedDomains()); System.out.println(" URI " + conn.getURI()); Domain testDomain1 = conn.domainLookupByName("MyKVMVirtualMachine"); Domain testDomain2 = conn.domainLookupByName("MyKVMVirtualMachine-clone"); displayDomainDetails(conn, testDomain1); displayDomainDetails(conn, testDomain2);
With the Java code changed, let's now run the second VM, and again review the program output as illustrated in Listing 5.
Listing 5Two VMs Running
Hello World! Hypervisor version 8003 Type QEMU NumOfDefinedDomains 0 URI qemu:///system Domain:MyKVMVirtualMachine id 2 running OS hvm host name stephen-Latitude-E5400 hypervisor version 8003 Domain state: VIR_DOMAIN_RUNNING Domain:MyKVMVirtualMachine-clone id 3 running OS hvm host name stephen-Latitude-E5400 hypervisor version 8003 Domain state: VIR_DOMAIN_RUNNING
So, from Listing 5, you can see the way libvirt allows us to programmatically view the contents of the host VMs running inside the QEMU/KVM hypervisor. What else can we do with the Virtual Machine Manager program?