Vim, GNU Screen et souris

Peut-être avez-vous activé le support de la souris dans Vim avec un petit set mouse=a dans votre ~/.vimrc. Ce support ne fonctionne qu’avec certains émulateurs de terminaux (Xterm, RXVT, etc) mais pas avec GNU Screen où l’utilisation de la souris sélectionne simplement le texte dans le terminal, bof.

Vous pouvez régler le problème rapidement en précisant à Vim la manière de gérer la souris pour le terminal en question. Il suffit d’un set ttymouse=xterm2 et le tour est joué. Et hop, un GNU Screen avec une session sur /dev/ttyUSB0, une pour le code dans Vim et une pour make et compagnie… Total bonheur.

KVM dans un screen (encore) avec le monitor kvm

Comme dit dans les précédents billets kvm ne dispose pas de de manager comme Xen (xm toussa). Après avoir réussi à obtenir le système guest dans un screen il restait à garder une main sur le monitor (contrôle de kvm, screenshot, dump, gdb, load/save, etc) sans l’interface graphique (ctrl+alt+2). Comme en plus je suis exigeant, avoir le monitor dans une fenêtre screen à côté du système dans la kvm était un minimum.

Bon, pour le kvm dans un screen pas de problème. C’est du déjà vu (option -nographic et console série sur le guest). Voyons ce que nous dit kvm -h pour le reste :
Debug/Expert options:
-monitor dev redirect the monitor to char device ‘dev’
[…]
Après des heures à chercher comment récupérer cela dans un screen, un cu ou un minicom à grand coup de bidouilles autour de pts, ptmx, et autre… j’ai bêtement tenté un :
% tty
/dev/pts/7
% kvm [truc option bla bla] -monitor /dev/pts/7
(qemu)
Oh ! Le prompt du monitor kvm ! Restait à l’intégrer dans une fenêtre dans la même session de screen que la sortie série du système guest. Voici la recette :

Le but du jeu est de lancer un screen et de récupérer dans la première fenêtre le TTY, on ouvre alors une seconde fenêtre pour y lancer kvm. La méthode la plus simple est de faire un script shell lancé dans screen invoquant lui-même un screen :
#!/bin/sh
echo Running kvm with monitor send to `tty` : $STY
screen -t KVM kvm -hda debian.cow -m 512 -net nic
-net tap,ifname=tap10,script=no -nographic -localtime -monitor `tty`
for ((;;))
do
sleep 10000
done
La boucle for est nécessaire sinon la fenêtre ne reste pas ouverte. Reste plus qu’à lancer ça avec :
% screen -S rototo -t monitor ./script.sh
Le -S pour nommer la session et le -t pour nommer la première fenêtre. L’invocation de screen depuis le script créé un nouvelle fenêtre appelée KVM avec le guest dedans.

Comme je ne voulais pas m’arrêté en si bon chemin, j’ai écris un petit quelque chose pour simplifier encore plus le tout en utilisant un script façon init. Le truc s’appel kvmmanage.

Ce script supporte le lancement, le listage et l’accès aux guests kvm. Accessoirement il permet aussi de stopper le guest (en attachant le screen et en vous laissant faire) ou salement avec un gros SIGKILL.

Le script utilise un autre script (launcher.sh) permettant de lancer les guests dans les screen avec le monitor comme présenté plus haut :
#!/bin/sh
echo Running kvm with monitor send to `tty` : $STY
touch /var/run/kvmmanage/$STY
. $1
screen -t KVM ${KVMCMD}
for ((;;))
do
sleep 10000
done
Il suffit ensuite de créé des profiles sous la forme de fichiers .prf :
KVMCMD= »kvm -hda debian.cow -m 512 -net nic -net tap,ifname=tap10,script=no -nographic -localtime -monitor `tty` »
Un kvmmanage start nom lance launcher.sh avec en argument nom.prf, le screen apparaît à l’écran et un fichier dans /var/run/kvmmanage est créé avec l’identifiant de session screen. Lister les guests est simple, il suffit de lister ce répertoire. C’est ce que fait kvmmanage list. Pour réattacher la console on check le fichier, s’il existe on utilise l’identifiant de session pour attacher le screen.

Ce script est du vite-fait et vous devrez modifier certains chemins comme KVMDIR et LAUNCHSCRIPT. Il est également possible de lancer plusieurs fois le même guest (comme en vrai avec kvm) ce qui est passablement dangeureux. Enfin, je n’ai pas trouvé de moyen propre de stopper un guest sauf en s’y attachant et en le stoppant par halt, init 0, etc…

KVM, console série et GNU screen

Le gros avantage cosmétique de Xen est son manager. Il permet de créer des machines virtuelles et d’attacher et détacher une console. KVM/QEMU utilise SDL pour créer une fenêtre présentant la console graphique. Il est également possible d’utiliser une connexion VNC. Mais tout cela n’est pas suffisant pour obtenir quelque chose de souple comme la commande xm de Xen.

Voici comment palier à cela avec un peu de configuration de base et GNU Screen…

La commande kvm dispose d’une option -nographic permettant de désactiver l’affichage graphique et de rediriger la console série du système guest (pas vraiment guest puisque c’est KVM) sur la console d’où à été lancé la commande. Côté kvm c’est donc tout simple. Reste à dire au système guest d’utiliser la console série exactement comme pour une configuration classique utilisant un TTY série.

Dans le système guest on commence par configurer Grub en ajoutant en début du fichier menu.lst :
serial –unit=0 –speed=9600 –word=8 –parity =no –stop=1
terminal –timeout=10 –dumb serial console
Bref, on utilise la console série en 9600 8N1. Toujours dans ce fichier, on ajoute les arguments pour le noyau sur la ligne kernel qui va bien :
console=tty0 console=ttyS0,9600n8
Grub, au prochain boot affichera ses informations sur la console série (attention, c’est moche, pas de beau menu coloré). Idem pour le noyau. Maintenant configurons le système lui-même pour permettre l’utilisation d’une console. Ceci est l’affaire de getty et se configure naturellement dans /etc/inittab :
T0:123:respawn:/sbin/getty -L ttyS0 9600 vt100
Cette ligne est normalement commentée et utilisée pour les runlevel 2 et 3 (second champ). On décommente et on précise un runlevel en plus (123 donc).

Dernier point, on s’assure que ttyS0 est bien un terminal considéré comme sûr :
% cat /etc/securetty | grep ttyS0
ttyS0
Parfait. Il ne reste plus qu’à stop le système guest et le relancer dans un screen :
% screen kvm -hda disk.cow -m 512 -net nic -net tap,ifname=tap10 -nographic
Et voilà. Total bonheur.

PS : Attention ! Configurer screen ou votre PS1 de manière à clairement différencier le guest de l’hôte. Lacher un reboot ou un init 0 dans la mauvaise console arrive très très facilement.