« Qemu » : différence entre les versions
(Ajout de l'affichage GTK avec gestion OpenGL + Ajout d'une section sur la gestion de la RAM à chaud.) |
(→Sources de la section : Ajout d'une source.) |
||
Ligne 254 : | Ligne 254 : | ||
* https://askubuntu.com/questions/978552/how-to-make-libusb-work-as-non-root | * https://askubuntu.com/questions/978552/how-to-make-libusb-work-as-non-root | ||
* https://unix.stackexchange.com/questions/39370/how-to-reload-udev-rules-without-reboot | * https://unix.stackexchange.com/questions/39370/how-to-reload-udev-rules-without-reboot | ||
* http://www.linux-kvm.org/page/USB_Host_Device_Assigned_to_Guest | |||
==Passer un USB à une machine== | ==Passer un USB à une machine== |
Version du 27 décembre 2018 à 18:56
Prérequis
- L'installation d'Open vSwitch et création d'un commutateur virtuel
- Vérifier que les instructions de virtualisations sont supportés et activés :
egrep '^flags.*(vmx|svm)' /proc/cpuinfo
. Si un résultat s'affiche, c'est que c'est bon.
Installation
Qemu est disponible dans les dépôts Debian
apt install qemu-system-x86-64 openvswitch-switch
Création de l’arborescence de travail (c'est un choix personnel, l’intérêt de cette solution est justement qu'elle n'impose rien)
mkdir -p /etc/qemu/{iso,disques,machines}
Script réseau
Pour que la machine virtuelle puise se connecter sur Open vSwitch, des scripts sont a créer.
INFORMATION
Ce script met dynamiquement les interfaces réseaux dans le VLAN indiqué dans la variableifname
de la commande de démarrage d'une machine virtuelle. Il suffit de mettre l'id du VLAN après un trait de soulignement pour que le script puisse le gérer. Dans l'exemple, ma machine sera dans le VLAN 180.ASTUCE
Les scripts peuvent être dans l'arborescence que vous voulez puisque vous spécifiez leur chemin dans la commande de démarrage de la machine virtuelle.Script de démarrage de l’interface
vim /etc/qemu/qemu-ifup
#!/bin/sh
#Séparation du nom de l'interface de l'id du VLAN utilisé
#nomIface=`echo $1 | cut -f 1 -d '_'`
idVlan=`echo $1 | cut -f 2 -d '_'`
OVSCOMMUT=br0
OVSTAG=$idVlan
echo "Execution de /etc/qemu/qemu-ifup"
echo "Allumage de $1 pour l'ajout au pont OVS..."
ip link set $1 up promisc on
echo "Ajout de $1 à ${OVSCOMMUT}..."
ovs-vsctl --may-exist add-br ${OVSCOMMUT}
ovs-vsctl --if-exists del-port ${OVSCOMMUT} $1
ovs-vsctl --may-exist add-port ${OVSCOMMUT} $1
ovs-vsctl --if-exists set port $1 tag=${OVSTAG}
sleep 2
Variables:
- OVSCOMMUT : interface de votre commutateur virtuel
- OVSTAG : numéro du Vlan
Script de d'arrêt de l’interface
vim /etc/qemu/qemu-ifdown
#!/bin/sh
OVSCOMMUT=br0
echo "Execution de /etc/qemu/qemu-ifdown"
echo "Arrêt de $1 pour la suppression au pont OVS..."
ip link set $1 down
echo "Suppression de $1 à ${OVSCOMMUT}..."
ovs-vsctl --if-exists del-port ${OVSCOMMUT} $1
echo "Suppression de $1..."
ip link delete dev $1
Variable:
- OVSCOMMUT : interface de votre commutateur virtuel
Modifier les droits
Ajouter les droits d’exécutions aux scripts
chmod +x /etc/qemu/qemu-if*
Création d'une machine virtuelle
Création d'un disque virtuel
qemu-img create -f qcow2 /etc/qemu/disques/hdd.qcow2 10G
Paramètres:
- -f qcow2 : type du disque vituel
- hdd.qcow2 : nom de l'image disque
- 10G : taille attribué au disque
Démarrage de la machine virtuelle
Démarrage classique
qemu-system-x86_64 -m 1024 -name host1 -vnc :6 --enable-kvm -cpu host -smp cores=2,threads=1,sockets=1 -net nic,macaddr=52:54:00:12:34:56 -net tap,ifname=host1_180,script=/etc/qemu/qemu-ifup,downscript=/etc/qemu/qemu-ifdown -boot c --cdrom /etc/qemu/iso/debian-live-8.7.1-amd64-lxde-bureau.iso -hda /etc/qemu/disques/hdd.qcow2
Paramètres:
- -m 1024 : mémoire attribué a la machine virtuelle (en octets)
- -name : nom de la machine virtuelle
- -vnc :6 : Utilisation de VNC sur le port 5906
- --enable-kvm : Permet la prise en charge des instructions de virtualisation du processeur
- -cpu host : Émule un processeur KVM avec théoriquement les mêmes fonctionnalités que l'hôte (ne fonctionne qu'avec le paramètre --enable-kvm). Voir le paramètre -cpu help pour la liste des possibilités
- -smp cores=2,threads=1,sockets=1 : Émule un multiprocesseur symétrique à mémoire partagée (on peut mettre plusieurs cœurs et plusieurs processeurs sur une machine)
- -net nic,macaddr=52:54:00:12:34:57 : l'adresse MAC de la machine virtuelle (voir)
- -net tap,ifname=host1_180,script=/etc/qemu/qemu-ifup,downscript=/etc/qemu/qemu-ifdown : nom de l'interface réseau sur la machine maître (limité à 15 caractères) suivie des scripts précédemment créés. Le _180 permet de remplir la variable $idVlan du script de démarrage de l'interface réseau
- -boot c : Démarre sur le disque dur. Le disque étant vierge, il démarre le cdrom pour l'installation et redémarrera sur le disque dur la prochaine fois (valeurs possible : c|d|n - disque principal|cdrom|réseau)
- --cdrom /srv/iso/debian-live-8.7.1-amd64-lxde-bureau.iso : lien vers l'ISO du CD-ROM
- -hda /root/hdd.qcow2 : lien vers le disque virtuel précédant créé
Démarrage sur squashfs
En lecture seule
qemu-system-x86_64 -m 1024 -name pxe-doc -vnc :3 --enable-kvm -cpu host -smp cores=1,threads=1,sockets=1 -net nic,macaddr=52:54:00:12:34:53 -net tap,ifname=pxe-doc_182,script=/etc/qemu/qemu-ifup,downscript=/etc/qemu/qemu-ifdown -boot c -append 'root=/dev/sda net.ifnames=0' -kernel /var/lib/lxc/lxc-pxe/rootfs/srv/tftp/noyaux/stretch/vmlinuz-4.13.0-custom -initrd /var/lib/lxc/lxc-pxe/rootfs/srv/tftp/noyaux/stretch/initrd.img-4.13.0-custom -hda /var/lib/lxc/lxc-pxe/rootfs/srv/tftp/images/stretch-pxe.squashfs
Les 3 éléments importants sont:
- -append: définit les paramètres du noyau. Le pré-requis indispensable est la valeur root=/dev/sda qui va indiquer au noyau d'utiliser ce périphérique comme / (il est émulé. Il n'existe pas réellement).
- -kernel: Indique le chemin du noyau
- -initrd: Indique le chemin de l'image initrd
En lecture/écriture
La lecture seule ne convient qu'à certains cas et devient vite limitante. Pour passer en lecture/écriture, il faut préciser le paramètre boot=live
au noyau et ajouter un périphérique bloc contenant /live/<IMAGE_SQUASHFS>
.
INFORMATION
Pour utiliser le paramètreboot=live
, un module "live" doit être présent dans l'initrd. Ce module est installé par le paquet live-boot sous Debian et casper sous Ubuntu. C'est lui qui scanne les périphériques au démarrage pour trouver un /live contenant le /.Vous pouvez soit utiliser un vrai périphérique soit utiliser losetup afin d'en faire un virtuel. J'ai fait le test en le formatant en vFAT avec un mkfs.vfat /dev/loop0
.
Il convient après de préciser un second disque à votre machine virtuelle. Voici la ligne que j'ai utilisé et qui fonctionne:
qemu-system-x86_64 -m 1024 -name pxe-doc --enable-kvm -vnc :3 -cpu host -smp cores=1,threads=1,sockets=1 -net nic,macaddr=52:5e:0a:12:34:53 -boot c -append 'root=/dev/sda net.ifnames=0 boot=live' -kernel vmlinuz-2 -initrd live/initrd.img-2 -hda stretch-pxe.squashfs -hdb /tmp/disque.dd
ASTUCE
À la place de -hdb il est également simuler une clé USB en utilisant la méthode décrite plus bas.J'ai constaté que certains mettaient le paramètre union=aufs
. Cela peut peut-être utile pour les vieux systèmes si la méthode d'union n'est pas automatique (Aufs a été remplacé par Overlayfs dans Linux 3.18).
Source de la section
Arrêt de la machine virtuelle
L’arrêt s'effectue via la fonction dédiée à chaque système émulé. Pour forcer l’extinction, effectuer un CTRL+C
.
Modes d'affichage
Qemu supporte divers modes d'affichage. En l'absence de précisions, il utilisera le gestionnaire de fenêtre de l'interface graphique si présente, sinon, il se terminera en erreur. Il est également possible d'exécuter une machine virtuelle sans affichage ou via le réseau.
Affichage classique
Comme précisé, l'affichage classique s'effectuera en l'absence de paramètre d'affichage. Dans ce mode, une fenêtre Xorg s'ouvrira et le fait de la fermer, terminera le processus de la machine virtuelle (extinction électrique).
qemu-system-x86_64 -m 512 --boot n --enable-kvm
Ceci équivaut à utiliser le paramètre -display gtk
. Pour utiliser OpenGL en complément, utiliser l'argument suivant:
-display gtk,gl=on
Source de la section
Affichage par telnet via liaison série
Cette configuration peut s'avérer utile lorsque vous désirez administrer une machine virtuelle qui est isolé dans un VLAN ou simplement inaccessible depuis votre machine d'administration. Il suffit d'initier une connexion telnet à l'hyperviseur qui va renvoyer le retour du TTY de l'invité via une liaison série (configuré via un paramètre passé au noyau de l'invité). On a ainsi un contrôle textuel (copier/coller possible) de la MV sans pour autant avoir un accès réseau à celle-ci.
qemu-system-x86_64 -m 1024 -name vpn1 --enable-kvm -cpu host -smp cores=2,threads=1,sockets=1 -net nic,macaddr=52:54:00:12:34:61 -net tap,ifname=vpn1_180,script=/etc/qemu/qemu-ifup,downscript=/etc/qemu/qemu-ifdown -boot n -nographic -serial telnet:0.0.0.0:5001,server,nowait -monitor none
Les 3 éléments importants sont:
- -nographic: permet l'utilisation de l'affichage telnet en désactivant tout les autres types d'affichage
- -serial: définit le port d'écoute du serveur telnet de l'hyperviseur
- -monitor none: désactive la console qemu. Si vous la voulez, vous pouvez soit supprimer ce paramètre pour entrer directement dedans à l'exécution de la commande, soit la faire écouter sur un socket réseau avec les options suivantes: -monitor tcp:127.0.0.1:41127,server,nowait
Une fois exécuté, la MV est accessible via la traditionnelle commande telnet
en pointant vers l'adresse IP de votre hyperviseur suivi du port d'écoute définit dans la commande.
Affichage réseau
Via VNC
C'est l'affichage que j'ai utilisé pour mon exemple dans le démarrage d'une machine virtuelle. Il est possible de sécuriser l'accès à cet affichage via mot de passe et TLS.
qemu-system-x86_64 -m 512 --boot n --enable-kvm -vnc :0
Le :0 est en fait le numéro de port en omettant le début qui est standard à VNC. Lire 5900. Si cela avais été :6, le port aurai été 5906.
Pour la partie cliente, on peut utiliser Vinagre ou gvncviewer
gvncviewer 127.0.0.1:0
Accès par mot de passe
J'ai testé mais n'ai été convaincu par cette possibilité. D'apprès la documentation, l'ajout du paramètre password aurai pour effet de demandé un mot de passe (limité à 8 caractères maximums) à l'exécution de la machine (ce qui n'arrive pas). Donc j'en déduis que ça ne fonctionne pas et de toute façon la sécurité est jugé merdique par les dévelopeurs eux même donc aucun intéret. Si vous voulez de la sécurité, utilisez SPICE ou passé par de la tunnellisation (SSH ou VPN) qui elle est sécurisé.
Pour la partie cliente, on peut utiliser Vinagre ou spice-client-gtk (qui s'utilise via la commande spicy).
Accès via TLS
Usant de VNC uniquement dans mon réseau local ou via un VPN, je n'ai pas besoin de cette fonctionnalité et je ne l'ai pas testé. Si le cœur vous en dit, vous trouverez les explications ici.
Via SPICE
SPICE est le protocole d'affichage historique de KVM. Il a été développé par la société Qumranet (qui a également créé KVM) et libéré par Red Hat qui a racheté l'entreprise le 4 septembre 2008.
Accès sans mot de passe
Partie serveur
qemu-system-x86_64 -m 512 --boot n --enable-kvm -spice port=5905,addr=0.0.0.0,disable-ticketing
Avec addr=0.0.0.0, on autorise les connexions de n'importe quelle adresse cliente.
Partie cliente
spicy -h 127.0.0.1 -p 5905
Accès par mot de passe
Partie serveur
qemu-system-x86_64 -m 512 --boot n --enable-kvm -spice port=5905,addr=0.0.0.0,password=secret123
Partie cliente
spicy -h 127.0.0.1 -p 5905 -w secret123
Accès via TLS
Non testé mais peut être intéressante.
Source de la section
Passer un périphérique à une machine
Passer un périphérique bloc
Dans le cas d'une installation sans réseau ou d'une machine Windows (ce qui revient un peu au même...), pouvoir transférer des fichiers via un périphérique bloc branché à la machine invité peut s’avérer intéressant.
-drive if=none,id=stick,file=/dev/sda \
-device nec-usb-xhci,id=xhci \
-device usb-storage,bus=xhci.0,drive=stick
Source de la section
Passer un clavier et une souris
Avec certains systèmes, la gestion de la souris au survole de Qemu est catastrophique. Il est donc utile de pouvoir donner des périphériques d'entrés/sorties directement à l'invité.
Il existe deux méthodes:
- Avec l'identifiant du bus (simple mais variable à chaque branchement - pratique pour faire un test)
- Avec l'identifiant du vendeur/produit (un peu plus chiant à écrire mais invariable)
Les périphériques s'identifient avec la commande:
lsusb
qui donne comme résultat (j'ai branché un clavier Dell RT7D50 et une souris Logitech M115 USB sur un PC portable):
Bus 002 Device 003: ID 0bda:8153 Realtek Semiconductor Corp.
Bus 002 Device 002: ID 2109:0813 VIA Labs, Inc.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 04f3:21d5 Elan Microelectronics Corp.
Bus 001 Device 003: ID 0cf3:e300 Atheros Communications, Inc.
Bus 001 Device 009: ID 413c:2005 Dell Computer Corp. RT7D50 Keyboard
Bus 001 Device 002: ID 2109:2813 VIA Labs, Inc.
Bus 001 Device 005: ID 1bcf:2b95 Sunplus Innovation Technology Inc.
Bus 001 Device 008: ID 046d:c058 Logitech, Inc. M115 Mouse
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Il est à noter que l'adresse du bus n'a aucun rapport avec tel ou tel port USB physique du PC. Après un débranchement/rebranchement, les valeurs changent...
Pour un usage avec un utilisateur standard, il faut donner les droits au périphérique. Ceci peut ce faire soit via un:
chmod 666 /dev/bus/usb/001/08
soit via une règle Udev:
vim /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c058", MODE="0666" SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="2005", MODE="0666"
Il faut ensuite recharger les règles udev (sinon un redémarrage s'en chargera)
udevadm control --reload-rules && udevadm trigger
Avec l'identifiant du bus
-usb -device usb-host,hostbus=1,hostaddr=8 \ -usb -device usb-host,hostbus=1,hostaddr=9
Avec l'identifiant du produit
-usb -device usb-host,vendorid=0x046d,productid=0xc058 \ -usb -device usb-host,vendorid=0x413c,productid=0x2005
Sources de la section
- https://qemu.weilnetz.de/doc/qemu-doc.html#usb_005fdevices
- https://askubuntu.com/questions/15570/configure-udev-to-change-permissions-on-usb-hid-device
- https://askubuntu.com/questions/978552/how-to-make-libusb-work-as-non-root
- https://unix.stackexchange.com/questions/39370/how-to-reload-udev-rules-without-reboot
- http://www.linux-kvm.org/page/USB_Host_Device_Assigned_to_Guest
Passer un USB à une machine
ATTENTION
Méthode à peaufiner...Il peut être utile d'envoyer un périphérique USB dans une machine virtuelle (une caméra dans mon exemple). Pour ce faire, il faut identifier le numéro du bus sur lequel est branché l'équipement avec un
lsusb
Ce qui dans mon cas, me donne: Bus 003 Device 005: ID 0bda:58b0 Realtek Semiconductor Corp.
Il suffit ensuite de passer les paramètres suivants à Qemu
-device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x0bda,productid=0x58b0
Je retrouve bien un /dev/video0
dans ma machine virtuelle.
Source de la section
- Commentaire numéro 5: https://bugs.launchpad.net/qemu/+bug/1385934
RAM à chaud
Il est possible d'ajouter et de retirer de la RAM à chaud dans une machine virtuelle. Cette fonction s'appelle virtio-balloon et un pilote doit être installé sur les machines invitées (avec Windows, ce pilote est accessible dans cet ISO - je n'ai pas réussi à le faire fonctionner). Sous Linux, ce pilote est intégré au noyau (comme d'habitude j'ai envi de dire). Il suffi donc de passer l'argument suivant à Qemu:
-device virtio-balloon
La machine va démarrer avec la quantité de RAM définie avec l'argument -m
et il sera possible de changer cette valeur dynamiquement via la console Qemu en y tapant la commande suivante:
balloon 2048
pour passer la machine à 2 Go de RAM.
On peut voir la RAM allouée via la commande suivante:
info balloon
Source de la section
Convertir une image disque
INFORMATION
La conversion semble impossible d'un disque à l'autre. Il faut être sur le même système de fichier pour la totalité de l'opération.Image OVA
Une image OVA est une exportation de machine virtuelle VMWare. Elle se présente sous la forme d'une archive tar avec comme extension .ova contenant un descriptif de la machine virtuelle (RAM, CPU, emplacement disque...) au format XML avec une extension .ovf, un disque virtuel en .vmdk et une empreinte SHA1 des deux fichiers mentionnés dans un document texte en .mf.
Bien que Qemu sache gérer les VMDK, il est conseillé de travailler avec du Qcow2.
Désarchivage du .ova
tar xvf archive.ova
Conversion du VMDK en Qcow2
qemu-img convert -O qcow2 image_source.vmdk image_destination.qcow2
Source
Réduire une image Qcow2
Un disque virtuel Qcow2 étant un fichier creux, il se rempli au fur et à mesure de son utilisation jusqu'à atteindre la limite fixée lors de sa création (même après suppression des fichiers de l'invité, ces derniers sont remplacés par des zéros). Les zéros qui remplissent ses espaces sont alors ré-écrits à mesures des modifications du système de fichier invité. Afin de les purger, il faut reconvertir l'image dans son même format. Il est également possible d'appliquer une compression aux données déjà existantes (cette compression ne s'applique pas aux nouvelles données ajoutées après la conversion). Il est à noter que la conversion n'alter en rien les données. Si vous convertissez deux fois de suite une image et que vous faites un hash du résultat vous vous apercevrez qu'il est identique.
ATTENTION
Faites bien attention à ne pas donner la même destination+nom au fichier de sorti, sinon vous allez écraser le disque virtuel que vous tentez de réduire et donc tout niquer !Récupérer les zéros
qemu-img convert -f qcow2 /tmp/image-src.qcow2 -O qcow2 /tmp/image-dst.qcow2
Compresser l'image
qemu-img convert -c -f qcow2 /tmp/image-src.qcow2 -O qcow2 /tmp/image-dst.qcow2
Note: Ajout du paramètre -c
.
Source
Émuler un Raspberry Pi
Dans cette section, nous allons utiliser un autre aspect de Qemu: l'émulation, pour créer un Raspberry Pi virtuel, ce qui peut être pratique pour faire des simulations en s'affranchissant de la lourdeur du monde physique ou pour lancer des compilations sur une machine distante.
Le système utilisé dans cette procédure est un Raspian stretch version 2017-11-29-lite.
Pour ma part, j'ajoute un répertoire dans mon arborescence afin d'accueillir le noyau que nous téléchargerons plus loin.
mkdir -p /etc/qemu/noyaux/rpi/
Installation de Qemu ARM
Le Raspberry Pi utilisant un processeur ARM, il nous faut une autre version de Qemu pour l'émuler.
apt install qemu-system-arm
Téléchargement du noyau
Il va nous falloir un noyau adapté à Qemu, à ce stade on peut soit le compiler nous même en allant chercher ses sources et en suivant cette procédure (je documenterai ça si je le fait un jour), soit télécharger directement un noyau pré-compilé.
wget https://github.com/dhruvvyas90/qemu-rpi-kernel/raw/master/kernel-qemu-4.4.34-jessie -P /etc/qemu/noyaux/rpi/
J'ai mis ce noyau à l’abri des erreurs 404 ici.
Téléchargement de l'image disque
Pour télécharger Raspbian c'est par ici et comme on ne peut pas télécharger les anciennes images sur ce site, j'ai mis en cache l'image que j'ai utilisé si vous n'avez pas de temps à perdre avec une adaptation sur de nouvelles version futures et qu'il faut un truck qui marche dans le quart d'heure (bon quand vous verrez ma bande passante en téléversement vous allez vous dire que le quart d'heure c'est gentil mais vous pouvez pousser si ça vous fait plaisir).
Décompression de l'image disque
apt install unzip
unzip /tmp/2017-11-29-raspbian-stretch-lite.zip -d /tmp/
Conversion de l'image disque
Afin de ne pas forcer Qemu à passer le montage du disque en mode RAW (ce qui à fortement tendance à foutre la merde de façon générale), on va convertir notre .img.
qemu-img convert -f raw -O qcow2 2017-11-29-raspbian-stretch-lite.img /etc/qemu/disques/raspbian-stretch-lite.qcow
Agrandissement du disque
qemu-img resize /etc/qemu/disques/raspbian-stretch-lite.qcow +6G
On peut vérifier les informations sur le disque (notamment sa taille max puisqu'un qcow est un fichier creux) avec cette commande:
qemu-img info /etc/qemu/disques/raspbian-stretch-lite.qcow
Exécution de la machine virtuelle
qemu-system-arm -kernel /etc/qemu/noyaux/rpi/kernel-qemu-4.4.34-jessie -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda /etc/qemu/disques/raspbian-stretch-lite.qcow -cpu arm1176 -m 256 -machine versatilepb -no-reboot -serial stdio -net nic -net user -net tap,ifname=vnet0,script=no,downscript=no -vnc :0
Note pour plus tard: le réseau ne fonctionne pas mais il me semble que c'est expliqué dans la source. Je n'ai pas le temps de m'en occuper pour l'instant.
Sources de la section
2 autres sources qui ne m'ont pas servis mais m'ont amenés à effectuer des essais avec des éléments intéressants:
- http://www.jdhp.org/docs/tutoriel_rpi_qemu/tutoriel_rpi_qemu.html
- https://azeria-labs.com/emulate-raspberry-pi-with-qemu/ avec une solution au problème lié à l'option -serial stdio avec -nographic