Seguramente más de uno se ha preguntado alguna vez "¿cómo conecto un dispositivo USB físico a una máquina virtual?". Las tecnologías de virtualización actuales permiten pasar (pass through) dispositivos de hardware físicos directamente desde el host al guest (máquina virtual) para que puedan ser accedidos desde el guest como si estuvieran conectados en el mismo. KVM no es la excepción, por ello en este artículo presento tres alternativas diferentes para pasar un dispositivo USB conectado a un host de máquinas virtuales KVM, en una máquina virtual. Es decir, cómo conectar un dispositivo de hardware USB físico (por ejemplo un pendrive, modem GSM o cualquier otro dongle USB) directamente a una máquina virtual en GNU/Linux utilizando virt-manager, libvirt o qemu.



Durante el proceso de consolidación de servidores (conversión de un servidor físico a virtual) podemos toparnos con el inconveniente de que un servidor que ha sido seleccionado para ser virtualizado dependa de un dispositivo de hardware específico, por ejemplo un módem 3G, una clave de seguridad o licencia de software por hardware USB, un dispositivo de cinta específico, etc. Por lo tanto será necesario mapear el dispositivo USB a la máquina virtual para que sea accedido de forma directa por el guest, como si se tratase de hardware virtual.

Antes de comenzar es necesario conectar el dispositivo USB en el host. A modo de ejemplo utilizo un módem 3G Huawei:

$ lsusb | grep Huawei
Bus 002 Device 004: ID 12d1:1c05 Huawei Technologies Co., Ltd. E173s 3G broadband stick (modem on)

virt-manager

La forma más sencilla de conectar un dispositivo USB a una máquina virtual es utilizando la herramienta gráfica de gestión de hosts y máquinas virtuales virt-manager. Ya que muy posiblemente el servidor host de máquinas virtuales no posee entorno gráfico, es necesario instalar virt-manager en una workstation cliente y conectarse al hipervisor qemu-kvm de forma remota, tal como explica el artículo Administrar máquinas virtuales KVM de forma remota.

En la captura se observa la salida del comando lsusb (utilidad para mostrar información acerca de los buses USB del sistema y los dispositivos conectados a ellos) en una máquina virtual KVM, la cual corre Mageia 2.

Acceder a la configuración de hardware de la máquina virtual y presionar el botón "Add Hardware" para agregar un nuevo dispositivo:

Seleccionar "USB Host Device", y luego seleccionar el dispositivo deseado:

Presionar "Finish". El dispositivo USB queda inmediatamente conectado, sin necesidad de reiniciar el sistema operativo guest:

Al ejecutar lsusb nuevamente se observa el dispositivo listado. Desde este momento es posible comenzar a utilizarlo normalmente en la máquina virtual:

libvirt

Por supuesto en GNU/Linux no existe tarea realizada por una herramienta gráfica que no pueda ser realizada desde la línea de comandos. Si no disponemos de virt-manager, podemos realizar el mismo trabajo utilizando virsh. El artículo Cómo crear y administrar máquinas virtuales KVM desde línea de comandos explica de forma detallada el funcionamiento de los comandos básicos de las herramientas virt-install y virsh.

Antes de comenzar es necesario identificar el vendor ID y product ID asociado al dispositivo USB en el host, utilizando nuevamente lsusb:

$ lsusb | grep Huawei
Bus 002 Device 004: ID 12d1:1c05 Huawei Technologies Co., Ltd. E173s 3G broadband stick (modem on)

Tal como se observa, el módem Huawei se identifica como el dispositivo 004 en el bus 002. Los dos octetos separados con dos puntos indican el vendor ID y product ID respectivamente. Por lo tanto el vendor ID es 12d1 y el product ID es 1c05.

Una vez determinado el vendor ID y product ID es posible definir el dispositivo en el archivo de configuración XML del guest. Para editar directamente el archivo de configuración de una máquina virtual en ejecución se debe utilizar el comando virsh edit. El nombre de dominio del guest en el ejemplo es "mageia":

# virsh edit mageia

Por defecto, virsh utiliza el editor vi. El dispositivo USB debe ser definido dentro de la sección <devices> utilizando el tag <hostdev>:

<devices>

  [configuración de otros dispositivos...]

  <hostdev mode='subsystem' type='usb' managed='yes'>
    <source>
      <vendor id='0x12d1'/>
      <product id='0x1c05'/>
    </source>
  </hostdev>
</devices>

Al guardar y cerrar, virsh informa que la configuración de la máquina virtual ha sido actualizada:

# virsh edit mageia
Domain mageia XML configuration edited.

Debe notarse que se ha agregado el prefijo "0x" para identificar que se trata de valores hexadecimales. Finalmente es necesario reiniciar el guest para reflejar los cambios en la configuración de hardware.

Si no se desea (o no es posible por razones de servicio) reiniciar el guest, es posible agregar el dispositivo "en caliente" a partir de un archivo XML de configuración de dispositivo utilizando el comando virsh attach-device.

Crear el archivo huawei.xml con el siguiente contenido:

<hostdev mode='subsystem' type='usb' managed='yes'>
  <source>
    <vendor id='0x12d1'/>
    <product id='0x1c05'/>
  </source>
</hostdev>

Luego ejecutar:

# virsh attach-device mageia huawei.xml
Device attached successfully

Si al mismo tiempo mantenemos abierto el log de sistema (tail -f /var/log/syslog) en el guest, es posible ver "en vivo" como se agrega a la máquina virtual y el kernel Linux reconoce el nuevo dispositivo USB:

QEMU

Finalmente, ¿cómo paso un dispositivo USB a una máquina virtual creada directamente desde la línea de comandos del emulador QEMU?

El artículo Emular Raspberry Pi con QEMU y KVM en CentOS 6 explica cómo crear una máquina virtual con procesador ARM para emular Raspberry Pi. Para crear la máquina virtual usaba directamente el emulador qemu-system-arm. En tales casos (cuando se inician máquinas virtuales ejecutando manualmente el emulador QEMU) para agregar un dispositivo USB se debe utilizar el parámetro -usbdevice en la línea de comando junto con el vendor ID y product ID:

-usbdevice host:12d1:1c05

Por supuesto, sólo es posible en el momento de creación de la máquina virtual, por ejemplo:

$ qemu-system-arm -kernel kernel-qemu -cpu arm11mpcore -m 128 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1" -hda raspi.img -vnc 127.0.0.1:55 -usbdevice host:12d1:1c05

Fin.


Tal vez pueda interesarte


Compartí este artículo