Cuando se trata de computación de escalabilidad horizontal (como por ejemplo cloud computing), libvirt puede ser una de las bibliotecas más importantes de las que haya oído hablar. Libvirt brinda una API agnóstica a hipervisores para administrar de manera segura sistemas operativos huéspedes que se ejecutan en un host. Libvirt no es una herramienta propiamente dicha sino una API para construir herramientas a fin de administrar sistemas operativos huéspedes. La misma libvirt está construida sobre la idea de abstracción. Ofrece una API común para la funcionalidad común que implementan los hipervisores soportados. Libvirt sediseñó originalmente como una API de gestión para Xen, pero desde entonces se ha ampliado para soportar una cantidad de hipervisores.
Comencemos nuestra discusión de libvirt con una vista del modelo de uso, luego nos meteremos en su arquitectura y su uso. Libvirt existe como un conjunto de interfaces de programación de aplicaciones diseñado para ser utilizado por una aplicación de gestión (ver Figura 1). Libvirt, a través de un mecanismo específico en hipervisores, se comunica con cada hipervisor disponible para realizar solicitudes de API. Explico cómo se hace con QEMU más adelante en el artículo.
Figura 1. Comparación y modelo de uso de libvirt
También se muestra una comparación de la terminología que utiliza libvirt. Esta terminología es importante, ya que estos términos se utilizan en el nombrado de la API. Las dos diferencias fundamentales son que libvirt denomina al host físico nodo, y el sistema operativo huésped se denomina dominio. Nótese que libvirt (y su aplicación) se ejecuta en el dominio del sistema operativo Linux anfitrión (dominio 0).
Con libvirt se tienen dos medios de control distintos. El primero se demuestra en la Figura 1, donde la aplicación de gestión y los dominios existen en el mismo nodo. En este caso, la aplicación de gestión funciona a través de libvirt para controlar los dominios locales. Los otros medios de control existen cuando la aplicación de gestión y los dominios son nodos individuales. En este caso, se requiere comunicación remota (ver Figura 2). Este modo utiliza un daemon especial llamado libvirtd que se ejecuta en nodos remotos. Este daemon se inicia automáticamente cuando libvirt se instala en un nodo nuevo y puede determinar automáticamente los hipervisores locales y establecer drivers para ellos (se tratará a la brevedad). La aplicación de gestión se comunica a través de la libvirt local con la libvirtd remota a través de un protocolo personalizado. Para QEMU, el protocolo termina en el monitor QEMU. QEMU incluye una consola de monitoreo que le permite inspeccionar un sistema operativo en ejecución y también controlar aspectos de la máquina virtual (VM).
Figura 2. Control de hipervisores remotos con libvirtd
Para soportar extensibilidad sobre una amplia variedad de hipervisores, libvirt implementa una arquitectura basada en drivers, lo que permite que una API común preste servicio a una gran cantidad de hipervisores subyacentes de modo común. Esto significa que cierta funcionalidad especializada de algunos hipervisores no es visible a través de la API. Además, puede que algunos hipervisores no implementen todas las funciones API, lo que luego se define como no compatible dentro del driver específico. La figura 3 Ejemplifica la separación en niveles de la API libvirt y los drivers relacionados. Observe también aquí que libvirtd brinda los medios de acceder a los dominios locales desde aplicaciones remotas.
Figura 3. Arquitectura de libvirt basada en drivers
Al momento de la redacción de este artículo, libvirt implementa drivers para los hipervisores indicados en la Tabla 1. Sin duda habrá otros drivers disponibles a medida que surjan nuevos hipervisores de las comunidades de fuente abierta.
Tabla 1. Hipervisores que soporta libvirt
| Hipervisor | Descripción |
|---|---|
| Xen | Hipervisor para arquitecturas IA-32, IA-64 y PowerPC 970 |
| QEMU | Emulador de plataforma para diversas arquitecturas |
| Máquina virtual basada en el kernel (KVM) | Emulador de plataforma Linux |
| Contenedores de Linux (LXC) | Contenedores de Linux (ligeros) para la virtualización del sistema operativo |
| OpenVZ | Virtualización a nivel sistema operativo basado en el kernel Linux |
| VirtualBox | Hipervisor para virtualización de x86 |
| User Mode Linux | Emulador de plataforma Linux para diversas arquitecturas |
| Prueba | Driver de prueba para un hipervisor falso |
| Almacenamiento | Drivers de bloque de almacenamiento (disco local, disco de red, volumen iSCSI) |
Libvirt y el shell de virtualización
Ahora que he cubierto parte de la arquitectura de libvirt, veamos algunos ejemplos del uso de la API de virtualización libvirt. Comienzo utilizando una aplicación llamada virsh (shell de virtualización), que se construye sobre libvirt. Este shell permite usar gran parte de la funcionalidad de libvirt y aunque de un modo interactivo (basado en shell). En esta sección, demuestro algunos de los aspectos de la manipulación de la VM usando virsh.
El primer paso es definir el archivo de configuración del domino (mostrado en el Listado 1, a continuación). Este código especifica todas las opciones necesarias para definir un dominio — desde el hipervisor (emulador) a los recursos que usa el dominio y la configuración periférica (como por ejemplo la red). Observe que esta es una configuración muy simple: los verdaderos atributos que soporta libvirt son mucho más diversos. Por ejemplo, puede especificar una BIOS y un cargador de arranque host, recursos a ser utilizados por el dominio, y dispositivos a ser utilizados — desde discos flexibles y CD-ROMs a USB y dispositivos PCI.
El archivo de configuración de dominio define algunos de los metadatos básicos a utilizar para este dominio QEMU, inclusive el nombre del dominio, la memoria máxima, e inicialmente la memoria disponible (actual) así como también la cantidad de procesadores virtuales que se pondrán a disposición de este dominio. No debe asignar un Identificador Único Universal (UUID); en cambio, se permite que libvirt asigne uno. Usted define el tipo de máquina a emular para esta plataforma—en este caso, un procesador 686 que está completamente virtualizado (hvm). Usted define la ubicación del emulador (si necesita soportar múltiples del mismo tipo) y el disco virtual para el dominio. Observe que usted indica la VM, que es un sistema operativo ReactOS en formato Disco Virtual (VMDK). Finalmente, se especifica la configuración de red predeterminada, y usted usa Computación de Red Virtual (VNC) para los gráficos.
Listado 1. Archivo de configuración de dominio
<xml version="1.0"?> <domain type='qemu'> <name>ReactOS-on-QEMU<name> <uuid<uuid> <memory>131072<memory> <currentMemory>131072<currentMemory> <vcpu>1<vcpu> <os> <type arch='i686' machine='pc'>hvm<type> <os> <devices> <emulator>usr/bin/qemu<emulator> <disk type='file' device='disk'> <source file='/home/mtj/libvtest/ReactOS.vmdk'/> <target dev='hda'/> <disk> <interface type='network'> <source network='default'/> <interface> <graphics type='vnc' port='-1'/> <devices> <domain> |
Ahora, una vez completado el archivo de configuración de dominio, iniciemos un
dominio con la herramienta virsh. La herramienta virsh toma un argumento de comando
para la acción particular a tomar. En caso de iniciar un dominio nuevo, usted
utiliza el comando create y el archivo de configuración de
dominio:
Listado 2. Iniciar un nuevo dominio
mtj@mtj-desktop:~/libvtest$ virsh create react-qemu.xml Connecting to uri: qemu:///system Domain ReactOS-on-QEMU created from react-qemu.xml mtj@mtj-desktop:~/libvtest$ |
Observe que el Indicador de Recursos Universal (URI) usado para adjuntar al dominio
(qemu:///system). Este URI local se adjunta al daemon
de modo del sistema para el driver QEMU local. Para adjuntar un hipervisor QEMU
remoto sobre el protocolo de Shell Seguro (SSH) al host shinchan, podría utilizar el
URI qemu+ssh://shinchan/.
Luego puede listar los dominios activos en un host determinado utilizando el
comando list dentro de virsh. Al hacerlo se listan los
dominios activos, sus ID de dominio y su estado, como se muestra a continuación:
Listado 3. Listar dominios activos
mtj@mtj-desktop:~/libvtest$ virsh list Connecting to uri: qemu:///system Id Name State ---------------------------------- 1 ReactOS-on-QEMU running mtj@mtj-desktop:~/libvtest$ |
Observe que el nombre que se define aquí es el nombre que usted definió en los metadatos del archivo de configuración de dominio. Puede ver que este dominio tiene una ID de dominio de 1 y actualmente se está ejecutando.
También puede suspender un dominio con el comando suspend.
Este comando hace que el dominio deje de ser planificado, pero el dominio sigue
residiendo en la memoria y puede hacerse recomenzar rápidamente. El siguiente
ejemplo muestra cómo suspender el dominio, como realizar un listado para ver el
estado y luego reiniciar el dominio:
Listado 4. Suspender un dominio, verificar el estado y reiniciar
mtj@mtj-desktop:~/libvtest$ virsh suspend 1 Connecting to uri: qemu:///system Domain 1 suspended mtj@mtj-desktop:~/libvtest$ virsh list Connecting to uri: qemu:///system Id Name State ---------------------------------- 1 ReactOS-on-QEMU paused mtj@mtj-desktop:~/libvtest$ virsh resume 1 Connecting to uri: qemu:///system Domain 1 resumed mtj@mtj-desktop:~/libvtest$ |
La utilidad virsh también soporta una cantidad de otros comandos, como por ejemplo
guardar un dominio (save), restaurar un dominio guardado
(restore), reiniciar un dominio (reboot), y muchos otros. También puede crear un archivo de configuración
de dominio desde un dominio en ejecución (dumpxml).
Hasta ahora, ha iniciado y manipulado un dominio. Ahora adjuntemos a él para ver el dominio en acción. Puede hacerlo utilizando VNC. Para crear una ventana que represente el escritorio gráfico del dominio particular, puede utilizar VNC como:
Listado 5. Adjuntar a un dominio
mtj@mtj-desktop:~/libvtest$xvnc4viewer 127.0.0.1
0 |
El ejemplo anterior mostró el control de dominios utilizando la línea de comandos de la utilidad virsh. Ahora veamos un ejemplo de control de dominio usando Python. Python era el lenguaje de scripting soportado por libvirt y brinda a la API libvirt una interfaz limpia, orientada a los objetos.
En este ejemplo exploro algunas de las mismas operaciones que demostré con la
utilidad virsh (list, suspend, resume, etc.). El script Python de
muestra se observa en el Listado 6. En este ejemplo, usted
comienza importando el módulo libvirt. Luego se conecta al hipervisor QEMU local.
Desde aquí, recorre en iteración los ID de dominio disponibles; para cada uno crea
un objeto de domino, y luego suspende, recomienza y finalmente destruye el
dominio.
Listado 6. Script Python de muestra para el control de dominio (libvtest.py)
import libvirt conn =
libvirt.open('qemu:///system') for id in conn.listDomainsID(): dom =
conn.lookupByID(id) print "Dom %s State %s" % ( dom.name(), dom.info()[0] )
dom.suspend() print "Dom %s State %s (after suspend)" % ( dom.name(), dom.info()[0]
) dom.resume() print "Dom %s State %s (after resume)" % ( dom.name(), dom.info()[0]
) dom.destroy() |
Aunque este es un ejemplo simple, puede usar el poder que le ofrece libvirt a través de Python. Mediante un script simple puede recorrer en iteración todos los dominios QEMU locales, emitir información sobre el dominio, y luego controlar el dominio. Los datos de salida de este script se muestran en el Listado 7.
Listado7. Datos de salida del script Python en el Listado 6
mtj@mtj-desktop:~/libvtest$ python libvtest.py Dom ReactOS-on-QEMU State 1 Dom ReactOS-on-QEMU State 3 (after suspend) Dom ReactOS-on-QEMU State 1 (after resume) mtj@mtj-desktop:~/libvtest$ |
A un nivel elevado, la API libvirt se puede dividir en cinco secciones API: la API de conexión al hipervisor, la API de dominio, la API de red, la API de volumen de almacenamiento y finalmente la API del bloque de almacenamiento.
Toda la comunicación de libvirt ocurre luego de la creación de una conexión para un
determinado hipervisor (por ejemplo, como se muestra con open en el Listado 6). La conexión brinda una ruta de
acceso para todas las demás API. En la API C, esta
conducta se brinda a través de la llamada virConnectOpen (así como también otras para autenticación). La respuesta de
estas funciones es un objeto virConnectPtr, que representa
una conexión a un hipervisor. Este objeto sirve como base para toda otra
funcionalidad de gestión y por ende es un argumento requerido para posteriores
llamadas API a un determinado hipervisor. Llamadas importantes posteriores son virConnectGetCapabilities, que devuelve las capacidades del
hipervisor y el driver, yvirNodeGetInfo, que recupera
información sobre el nodo. Esta información se devuelve como documento XML que se
puede analizar para comprender qué conductas son posibles.
Ahora, teniendo acceso a un hipervisor, usted puede recorrer en iteración los
diversos recursos sobre ese hipervisor con un conjunto de llamadas API. La llamada
API virConnectListDomains devuelve una lista de
identificadores de dominio que representan los dominios activos en ese
hipervisor.
La API implementa una gran cantidad de funciones destinadas a los dominios. Para
explorar o administrar un dominio, primero necesita un objeto virDomainPtr. Puede obtener este controlador en una cantidad de maneras
(usando la ID, UUID, o el nombre de dominio). Siguiendo con el ejemplo del recorrido
en iteración de dominios, puede utilizar la lista de índices que devuelve esta
función y realizar la llamada virDomainLookupByID para
obtener el controlador del dominio. Con el controlador del dominio ahora puede
realizar una gran cantidad de operaciones, desde explorar el dominio (virDomainGetUUID, virDomainGetInfo, virDomainGetXMLDesc, virDomainMemoryPeek) a controlar el dominio (virDomainCreate, virDomainSuspend, virDomainResume, virDomainDestroy, y virDomainMigrate).
También puede utilizar la API para administrar e inspeccionar redes virtuales y
recursos de almacenamiento. Siguiendo el modelo de la API, se necesita un
objeto virNetworkPtr para administrar e inspeccionar
redes virtuales, y se necesita un objeto virStoragePoolPtr (bloqueo almacenamiento) o se necesita un objeto
(volumen) virStorageVolPtr para administrar estos
recursos.
La API también soporta un mecanismo de evento con el cual se puede registrar para ser notificado de eventos particulares (como por ejemplo cuando se arranca, suspende, reinicia o detiene un dominio).
La biblioteca libvirt se implementó en C (que soporta C++) e incluye soporte directo para Python. Pero también da
soporte a una cantidad de enlaces de lenguaje. Se han implementado enlaces para
Ruby, el lenguaje™ Java, Perl y OCaml. Se ha trabajado para llamar a libvirt
desdeC#. Libvirt soporta los lenguajes de
programación de sistemas más populares (C y C++), una variedad de lenguajes de scripting, e incluso un
lenguaje funcional unificado (Objective caml). Así que cualquiera sea su lenguaje,
libvirt le brinda una ruta para controlar sus dominios.
Con la pequeña cantidad de capacidades que he demostrado en este artículo, puede ver el poder que ofrece libvirt. Y como se puede esperar, hay una cantidad de aplicaciones que se están construyendo exitosamente sobre libvirt. Una de las aplicaciones interesantes es virsh (aquí demostrada), que es un shell de virtualización. También está virt-install, que se puede utilizar para aprovisionar nuevos demonios desde distribuciones de sistemas operativos. La utilidad virt-clone se puede utilizar para clonar una VM de otra VM (cubriendo ambos el sistema operativo y la replicación de disco). Algunas de las aplicaciones de nivel superior incluyen virt-manager, que es una herramienta de administración de escritorio de uso general, y virt-viewer, que es una herramienta ligera para adjuntar de manera segura a la consola gráfica de las VM.
Una de las herramientas más importantes construidas sobre libvirt se llama oVirt. La aplicación de administración de VM oVirt se diseñó para administrar una VM individual en un nodo individual o miles de VM en cientos de hosts. Además de simplificar la administración de grandes cantidades de hosts y VM, se puede utilizar para automatizar clustering y equilibrio de carga y funciona en varias plataformas y arquitecturas.
Como puede ver en este artículo breve, libvirt es una biblioteca genial para construir aplicaciones que administran dominios en muchos entornos diferentes de hipervisores sobre grandes redes de sistemas. Debido a la cada vez mayor popularidad de cloud computing, sin duda libvirt crecerá junto a ella, encontrando nuevos usuarios y aplicaciones. Al momento de la redacción de este artículo, libvirt tiene solo cuatro años, así que es relativamente nuevo en el espacio de de la computación escalable masiva. Ciertamente oiremos más sobre ella.
Aprender
- Vea el sitio web de
libvirt para obtener las noticias más recientes sobre libvirt y para
descargar la última versión. También encontrará un manual de referencia de
API completo que cubre las interfaces principales y las interfaces de control de
errores.
- Libvirt soporta una gran cantidad de hipervisores,
que incluyen:
- En "VirtualLinux: An overview of virtualization
methods, architectures, and implementations" (developerWorks, diciembre de
2006), obtenga más información sobre los diversos tipos de virtualización. Cloud
computing depende de la virtualización para el uso óptimo de los recursos
disponibles en el servidor. Con la virtualización, los servidores se pueden utilizar
para alojar múltiples sistemas operativos y conjuntos de aplicaciones.
- En "LXC:Linux Container Tools"
(developerWorks, febrero de 2009), usted puede obtener más información sobre las
herramientas de gestión construidas específicamente para LXC. Aquí notará algunos
paralelos con los métodos de administración para libvirt.
- Computación de Red Virtual, o VNC, es un método para compartir escritorios
gráficos sobre una red. Esta abstracción es ideal para la computación de
escalabilidad horizontal, ya que significa que una estación individual puede
administrar varios clientes distribuidos.
- El subsistema Linux para administrar sistemas de
archivos es grande y complejo. Puede obtener más información sobre el subsistema de
sistema de archivo más grande en "Anatomy of the Linux file system"
(developerWorks, octubre de 2007).
- En la zona Linux developerWorks Linux,
encuentre más recursos para desarrolladores de Linux, y lea nuestros artículos y tutoriales más
populares.
- Vea todos los artículos de Linux y tutoriales de Linux sobre
developerWorks.
- Siga actualizado con eventos técnicos y transmisiones por
Internet de developerWorks.
Obtener los productos y tecnologías
- La plataforma de
administración de VM abierta de Red Hat oVirt es
usuaria de libvirt y demuestra qué clase de aplicaciones se pueden construir.. Puede
usar oVirt para administrar grandes cantidades de hosts, y la plataforma se escala
fácilmente para soportar miles de máquinas virtuales.
- En este artículo, usted
usó ReactOS como medio para
demostrar un dominio en QEMU. Este artículo ofrece más información sobre ReactOS (un
clon gratuito de Windows®), que se ejecuta fácilmente en la
plataforma QEMU.
- Con el Software de prueba de IBM, que puede
descargar directamente de developerWorks, construya su próximo proyecto de
desarrollo sobre Linux.
Comentar
- Involúcrese en la comunidad My developerWorks. Conéctese
con otros usuarios de developerWorks mientras explora los blogs, foros, grupos y
wikis basados creados por desarrolladores.

M. Tim Jones es arquitecto de firmware incrustado y es autor de Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (actualmente en su segunda edición), AI Application Programming (en su segunda edición) y BSD Sockets Programming from a Multilanguage Perspective. Sus antecedentes en la ingeniería abarcan desde el desarrollo de kernels para naves espaciales geosincrónicas hasta la arquitectura de sistemas incrustados y el desarrollo de protocolos de redes. Tim es Consultant Engineer de Emulex Corp. en Longmont, Colorado.