9.2.2.1.2.1.2. Ejecución de máquinas¶
QEmu no es un programa especialmente amigable para la ejecución de máquinas. No hay más que leer la presentación La jungla de los parámetros de QEmu. De hecho, no está pensado para el uso habitual de un usuario normal y ni siquiera pueden crearse máquinas virtuales, sino que al utilizar uno o varios discos se declaran cuáles son las características de la máquina virtual que los usará.
Nota
QEmu no distingue el guión del doble guión. Por tanto, -hda equivale a --hda.
9.2.2.1.2.1.2.1. Básica¶
La ejecución más básica que podemos hacer es la siguiente:
$ qemu-system-x86_64 -machine accel=kvm -m 512 -hda disco.qcw
que, habilitando la aceleración por hardware[1], levantará una máquina:
Con 512MiB de memoria RAM gracias a la opción -m. Es necesario incluirla, porque la memoria predeterminada son 128 MiB, muy escasa para practicamente cualquier sistema operativo moderno. Puede incluirse G para significar GiB. Por ejemplo,
-m 1G
.Con firmware BIOS.
Con un procesador.
Dispone de un disco duro representado por el archivo
disco.qcw
.Con una tarjeta de red configurada como NAT (según la terminología de Virtualbox)[2].
Con una salida de vídeo compatible con VGA.
Muestra el huésped (una opción -display gtk implícita) en una ventana del anfitrión.
Nota
En cualquier caso, esta forma de lanzar es un poco peligrosa, puesto que la ventana se cerrará sin confirmación (y con ello la máquina virtual se abortará) con tan sólo pulsar el aspa que proporciona el gestor de ventanas. Es recomendable evitarlo añadiendo:
-display gtk,window-close=off
.
Sin embargo, si el disco está vacío, de poco servirá porque la máquina no encontrará sistema operativo que arrancar. Así que podemos añadir un cedé y arrancar por él:
$ qemu-system-x86_64 -machine accel=kvm -m 512 -hda disco.qcw -cdrom gparted.iso -boot d
donde hemos tenido que añadir la opción -boot para poder arrancar desde el cedé en vez de el disco duro, que es el comportamiento predeterminado, ya que «d» significa CDRom, como «c» disco duro, y «n» red. En realidad es una simplificación (obsoleta, según su página de manual qemu-system-x86_64) de:
-boot order=d
Pueden indicarse varias letras para definir una secuencia de arranque. Por ejemplo:
-boot order=ndc
intenta primero un arranque por red, si éste falla, un arranque por la unidad óptica y, por último, un arranque por el disco duro. También podemos optar por presentar un menú de selección:
-boot menu=on
Nota
-boot sólo tiene efecto con firmware BIOS.
En cualquier caso, y antes de empezar a profundizar en la virtualización de algunos dispositivos, es recomendable introducir los siguientes alias:
$ alias qemu-system='qemu-system-x86_64 -nodefaults -display none -m 512 -machine accel=kvm'
$ alias qemu-system-vga='qemu-system -device virtio-vga -display gtk -monitor vc'
El primero elimina cualquier dispositivo predeterminado (p.e. ya no habrá ninguna interfaz de red ni ninguna salida de vídeo) gracias a la opción -nodefaults, mientras que el segundo añadirá una salida de vídeo VGA. Este segundo alias hace algo más: hace accesible el monitor de QEmu para manipular la máquina virtual en la ventana gráfica en que se ve el huésped. Si nos resulta un problema crear máquinas sin interfaz de red (el estudio de ellas lo posponemos al siguiente epígrafe), podemos redefinir el primer alias para que añada una interfaz dispuesta en NAT:
$ alias qemu-system='qemu-system-x86_64 -nodefaults -display none -m 512 -machine accel=kvm -netdev user,id=nic -device virtio-net,netdev=nic'
Sobre esta base podremos probar las opciones que se proponen a continuación.
9.2.2.1.2.1.2.2. Discos¶
QEmu provee un mecanismo simplificado para indicar qué discos duros (o unidad óptica) pretenden incorporarse a la máquina virtual, y que es el que hemos utilizado bajo el epígrafe anterior: las opciones -hda, -hdb, -hdc -hdd, y -cdrom, la cual convierte el disco situado en hdc en un medio óptico, por lo que es incompatible con la opción -hdc. Para estos cinco argumentos el parámetro es un archivo regular: una imagen de disco (p.e. en formato QCOW2) para los cuatro primeros, y una imagen ISO para el último.
Nota
Como estará sospechando por estar reducido a la declaración de cuatro discos, QEmu emula, mediante esta forma simplificada, una controladora IDE.
Normalmente, bastará con expresar mediante estas opciones los medios de almacenamiento, pero podemos encontrarnos casos en que tengamos que conocer con mayor profundidad cómo se refieren éstos. Hay dos opciones que deberemos usar conjuntamente:
- -blockdev
que define en sí el dispositivo de bloques que se utilizará como backend. Por ejemplo, lo siguiente define un dispositivo que es un archivo de nombre
disco.qcw
en formato QCOW2.-blockdev "driver=file,node-name=f1,filename=disco.qcw" -blockdev "driver=qcow2,node-name=hdd,file=f1"
Y, esto esto, un archivo en formato crudo:
-blockdev "driver=file,node-name=iso,filename=gparted.iso" -blockdev "driver=raw,node-name=cdrom,file=iso"
que, obviamente, es la imagen de un cedé. Ahora bien, como raw es el formato predeterminado podríamos habernos ahorrado el segundo -blockdev:
-blockdev "driver=file,node-name=cdrom,filename=gparted.iso"
Si, en cambio, quisiéramos usar directamente el lector óptico (
/dev/sr0
):-blockdev "drive=host_device,node-name=cdrom,filename=/dev/sr0"
Sea como sea, esta opción solamente declara dispositivos de bloques sin especificar qué se quiere hacer con ellos. Para que una máquina virtual los use, es necesario añadir una opción más.
- -device
que define cómo se usara el dispositivo. Por ejemplo, esto nos conectaría el disco definido anteriormente (recordemos node-name=hdd) a la controladora IDE:
-device "ide-hd,drive=hdd,bootindex=1"
y, si queremos conectar también el cedé (al que nombramos con node-name=cdrom):
-device "ide-cd,drive=cdrom,bootindex=0"
Obsérvese que hemos referido el orden de arranque para que arranque primero el cedé. Sin embargo, por rendimiento es mejor usar virtio-blk para los discos duros en vez de emular la controladora IDE. En consecuencia:
-device "virtio-blk,drive=hdd,bootindex=1" -device "ide-cd,drive=cdrom,bootindex=0"
Poniendo todo junto podríamos arrancar una máquina con un disco del siguiente modo:
$ qemu-system-vga -blockdev "driver=file,node-name=f1,filename=disco.qcw" \
-blockdev "driver=qcow2,node-name=hdd,file=f1" -device "ide-hd,drive=hdd"
y si queremos añadir un lector óptico con una imagen de disco incluida y que arranque primero:
$ qemu-system-vga -blockdev "driver=file,node-name=f1,filename=disco.qcw" \
-blockdev "driver=qcow2,node-name=hdd,file=f1" -device "virtio-blk,drive=hdd,bootindex=1" \
-blockdev "driver=file,node-name=cdrom,filename=gparted.iso" -device "ide-cd,drive=cdrom,bootindex=0"
Evidentemente las formas simplificadas con que comenzamos el epígrafe son bastante más sencillas.
Nota
virtio-blk tiene el inconveniente de que en un huésped Linux los
discos no serán los dispositivos de bloques /dev/sdX
, sino
/dev/vdX
. Una buenaalternativa que mantiene los nombres habituales y
que permite también emular dispositivos ópticos, aunque con algo menos de
rendimiento, es virtio-scsi.
9.2.2.1.2.1.2.3. Salida de vídeo¶
Por defecto, o sea, en ausencia de la opción -nodefaults, QEmu la define así[3]:
-device VGA -display gtk
en que hay dos opciones: -device, que hace referencia a un hardware virtualizado por la aplicación (ya vimos que también se usaba para virtualizar discos) y -display que refiere la forma en que el vídeo se presentará al anfitrión. En este caso, para el huésped se virtualiza una tarjeta de vídeo con compatibilidad absoluta con el estándar VGA y en el anfitrión se muestra éste mediante una ventana que que presenta un menú superior con algunas opciones de manipulación de la máquina. En principio, podemos sustituir VGA por virtio-vga, que debería ser más eficiente y, de hecho, es lo que se ha hecho al crear el alias qemu-system-vga.
Ver también
Puede echarle un ojo a otras virtualizaciones del hardware de vídeo.
- Ventana gráfica
Si no manipulamos -display, el anfitrión se muestra dentro de la ventana gráfica y hay algunas combinaciones de teclas que nos conviene saber:
Ctrl+Alt+q, que cancela inmediatamente la ejecución de la máquina.
Ctrl+Alt+f, que pone la ventana gráfica a pantalla completa (y revierte el efecto si vuelve a pulsarse).
Ctrl+Alt+g, que recupera para el anfitrión el ratón si el huésped lo capturó.
Ctrl+Alt+1, Ctrl+Alt+2, Ctrl+Alt+3, que cambian de consola virtual. En la 1 está el anfitrión; el la 2, el monitor (si definimos la salida del monitor como vc); y en 3, el puerto serie.
Además, dado que el anfitrión aparece en una ventana aparte, la terminal donde estemos ejecutado QEmu quedará inútilmente ocupada hasta que apaguemos la máquina. Por tanto, nos convendrá normalmente añadir la opción
-daemonize
, que la liberará para que podamos utilizarla entretanto:$ qemu-system-vga -hda caca.qcw -daemonize
- VNC
Una posibilidad es sustituir la ventana por un servidor VNC, de modo que para observar e interactuar con el huéspedes utilicemos un cliente VNC en el anfitrión:
$ qemu-system-vga -hda disco.qcw -display "vnc=localhost:0" -daemonize
lo cual creará un servidor VNC que escuchará en el puerto 5900/TCP de la interfaz de loopback. Podemos ir sustituyendo el número (0, 1, etc.) si arrancamos varias máquinas a la vez, para que cada una se ponga a eschar en un puerto distinto (5900, 5901, etc.). Como en el caso de la ventana gráfica, hemos añadido -daemonize para liberar la terminal del anfitrión.
Aunque lo anterior basta, es conveniente añadir estos parámetros:
-device qemu-xhci -device usb-tablet -k es
que habilitan el USB y definen la configuración del teclado (es recomendación de la propia página de manual).
Advertencia
Ejecutado así, la comunicación con la máquina virtual no será cifrada ni tendrá contraseña, aunque hemos paliado el problema permitiendo la conexión únicamente desde el propio cliente. Pueden usarse contraseñas o certificados para cifrar la conexión. Échele un vistazo a:
$ qemu-system-x86_64 -display vnc=help
- Texto
Si nuestro huésped es un servidor sin entorno gráfico, no necesitamos en realidad una ventana gráfica en la que ni siquiera podemos copiar y pegar (y esto incluye el acceso VNC que acabamos de ver)[4]. Una buena alternativa es sustituir dicha ventana por la salida y entrada estándares de la propia terminal del anfitrión. Tendremos, no obstante, dos desventajas:
Sólo podremos tener una sesión abierta (a menos que habilitemos accesos adicionales por SSH) a diferencia de la ventana gráfica o VNC, en los que podemos abrir las seudoterminales típicas a través de Alt+F1, Alt+F2, etc.
Tendremos que modificar el huésped para que se muestre a través del puerto serie. En un huésped Linux que arranque con GRUB esto se logra editando
/etc/default/grub
de modo que incluya estas tres líneas:#GRUB_CMDLINE_LINUX_DEFAULT="quiet" GRUB_CMDLINE_LINUX="console=ttyS0" GRUB_TERMINAL="console serial" GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1" GRUB_GFXPAYLOAD_LINUX="text"
La primera línea suele encontrarse descomentada y, simplemente, evita que el núcleo informe demasiado durante el arranque. Como yo prefiero verlos, he comentado la línea. La segunda añade un parámetro al arranque del núcleo y puede ya encontrarse en el archivo con algún otro valor. Si es así, no habrá más que añadir el nuevo (console=ttyS0). Las dos siguientes líneas provocan que el propio GRUB también se muestre por el puerto serie. La última línea le indica al núcleo que arranque en modo texto. Finalmente, habrá que regenerar la configuración:
# update-grub
Nota
Como alternativa a añadir console=ttyS0 a GRUB_CMDLINE_LINUX, puede habilitarse el siguiente servicio:
# systemctl enable --now serial-getty@ttyS0.service
Sin embargo, esto no permitirá ver los mensajes del núcleo durante el arranque, por lo que, dado que de todos modos hay que editar
/etc/default/grub
para lograr que grub se vea por el puerto serie, es preferible la primera opción
Una primera forma es usar la opción
-nographic
:$ qemu-system-x86_64 -machine accel=kvm -m 512 -hda disco.qcw -nographic
que requiere los dispositivos predeterminados por lo que no usamos los alias creados anteriormente, que hacen uso de -nodefaults.
Una alternativa mejor es, simplemente, redirigir el puerto serie del huésped a la salida y entrada estándares del anfitrión:
$ qemu-system -hda disco.qcw -serial stdio
Nota
Obsérvese que no hemos usado el alias qemu-system-vga. En este caso, no queremos ninguna salida de vídeo.
El problema de esta comunicación con el anfitrión es que habremos perdido el monitor. Para paliarlo, QEmu permite multiplexar con el monitor simplemente añadiendo el prefijo mon: al valor de -serial:
$ qemu-system -hda disco.qcw -serial mon:stdio
Hay alternativas a mostrar directamente una terminal del huésped en la terminal del anfitrión. Por ejemplo, redirigir a un servidor telnet situado en un determinado puerto (p.e. el 12345):
$ qemu-system -hda disco.qcw -serial mon:telnet:localhost:12345,server=on,wait=off -daemonize`
al cual podremos conectarnos desde el anfitrión con telnet:
$ telnet localhost 12345
Nota
Si añadimos a la línea el dispositivo gráfico
-device sga
, que es precisamente lo que hace la opción -nographic, veremos también los mensajes de arranque de la BIOS, pero no es recomendable porque afecta a toda la salida posterior.- Tubería
Una variante para la interfaz CLI anterior, es manipular la salida para poder manipular la máquina de forma no interactiva. Exige también que el huésped presente una consola en el puerto serie, pero en este caso tal puerto se redirige a una tubería del anfitrión:
$ mkfifo /tmp/huesped.{in,out}
arrancando la máquina con la opción:
$ qemu-system -hda disco.qcw -serial pipe:/tmp/huesped
En estas condiciones,
huesped.out
mostrará la salida de la máquina:$ cat /tmp/huesped.out
y a través de
huesped.in
podremos introducir datos. Por tanto, cuando aparezca el login, podremos ingresar del siguiente modo:$ cat > /tmp/huesped.in root contraseñaderoot whoami
Advertencia
Cada instrucción puede requerir un tiempo de procesamiento, por lo que en ocasiones será necesario que exista una pausa entre instrucciones. El caso de justamente arriba funciona porque se supone que se está escribiendo interactivamente la orden y entre la primera línea (root) y la segunda (su contraseña) pasará un tiempo. En cambio, si las tres líneas estuvieran previamente escritas en un archivo y se redirigiera éste a la tubería, no lograríamos ingresar.
- Spice
Cuando el huésped dispone de entorno gráfico esta salida es la más adecuada, ya que ofrece varias ventajas y, entre ellas, la posibilidad de copiar y pegar con el ratón entre anfitrión y huésped.
La máquina debe arrancarse del siguiente modo:
$ qemu-system -spice unix=on,addr=/var/run/vm_spice.socket,disable-ticketing=on -device qxl-vga -display spice-app \ -device virtio-serial -chardev spicevmc,id=vdagent,debug=0,name=vdagent \ -device virtserialport,chardev=vdagent,name=com.redhat.spice.0
donde la primera línea es la estrictamente necesaria para usar spice utilizando como comunicación con el anfitrión un socket, y las dos siguientes permiten que funcione el cortapega entre anfitrión y huesped.
Lo necesario, no obstante, no acaba aquí. En el anfitrión necesitamos un cliente spice (p.e. spice-client-gtk o virt-viewer) para acceder al huésped.
-display spice-app
intenta lanzar automáticamente uno al arrancar la máquina, pero requiere que tal cliente esté asociado al tipo MIME x-scheme-handler/spice+unix. spicy (el cliente que incluye el paquete spice-client-gtk) tiene la ventaja de que no incluye ninguna dependencia de libvirt, pero al menos hasta Bullseye no tiene ningún archivo .desktop que permita establecer la asociación[5]. La solución es sencilla si se repasa el epígrafe sobre aplicaciones predeterminadas en entorno GUI y se siguen sus instrucciones, para la cual necesitaremos crear primero un archivospicy.desktop
en~/.local/share/applications
con este contenido:[Desktop Entry] Comment=Cliente spice Type=Application Exec=spicy --uri=%u Name=spicy MimeType=x-scheme-handler/spice+unix
En el huésped, por su parte, hay también tareas que hacer:
El entorno gráfico del cliente debe usar el driver QXL (si el cliente es un sistema Debian, tendrá que estár instalado el paquete xserver-xorg-video-qxl)[6].
Para compartir el portapapeles es necesario instalar:
# apt install spice-vdagent
y comprobar que el servicio homónimo se encuentra en funcionamiento:
$ systemctl status spice-vdagent
Notas al pie