Xen : nettoyer la TDB

 

La TDB (Tree Database) de Xen est une sorte de base de registre ou de pseudo filesystem référençant des informations sur les machines virtuelles en fonctionnement. Pour plus d'informations sur la TDB vous pouvez lire cet article. Ce pseudo filesystem se trouve dans un fichier /var/lib/xenstored/tdb. On peut rencontrer régulièrement des problème au démarrage de nouvelles machines virtuelles à cause d'une limite de taille de ce fichier.

Les erreurs ressemblent à ceci :

Error: (28, 'No space left on device, while writing /vm/58c0159f-19c9-5e94-1ae7-eebd4205d520/image/cmdline : ')

La plupart des réponses sur les listes de diffusion sont basées sur le fait qu'il faut :

  1. éteindre toutes les machines virtuelles
  2. effacer le fichier tdb
  3. redémarrer le serveur
  4. redémarrer les vms

Sur un serveur en prod cela peut-être assez délicat. Le problème est que quand une vm est éteinte, souvent dans le cas d'une coupure électrique, mais aussi lors de xm destroy. Des informations concernant cette machine sont toujours référencées dans le fichier et au bout d'un moment on va retrouver des dizaines de lignes de données concernant des machines virtuelles éteintes ou supprimées. Après pas mal de test j'ai réussi à trouver une procédure qui permet de nettoyer la tdb et donc de pouvoir de nouveau démarrer une vm sans avoir à rebooter le serveur.   Il nous faut d'abord le script permettant de dumper le contenu de la tdb :

vi /var/lib/xenstore/dump_xenstore

#!/bin/sh

function dumpkey() {
local param=${1}
local key
local result
result=$(xenstore-list ${param})
if [ "${result}" != "" ] ; then
for key in ${result} ; do dumpkey ${param}/${key} ; done
else
echo -n ${param}'='
xenstore-read ${param}
fi
}

for key in /vm /local/domain /tool ; do dumpkey ${key} ; done

  La première étape consiste à lister les uuid des vms en fonctionnement :

for i in `xm list | awk '{ print $1 }' | grep -v Name | grep -v Domain-0`; do xm list $i --long | grep -m1 uuid | tr -s [' '] [':'] | cut -d : -f 3 | cut -d')' -f1; done | xargs | tr '[ ]' '|'

On obtiens donc une liste d'uuid séparés par des '|'. Pour effacer les informations non nécessaires du fichier :

for i in `/var/lib/xenstore/dump_xenstore  | grep ^/vm | egrep -v '(resultat_de_la_commande_precedente)' | cut -d'/' -f 3 | uniq`; do  xenstore-rm /vm/$i; done

Remplacez resultat_de_la_commande_precedente par la liste des uid récupérée plus haut.