20141231-181722.jpg

Salvataggio e ripristino di una VM libvirt (parte I)

Con l’adozione definitiva da parte di Red Hat e altri vendor di kvm/qemu quale piattaforma di virtualizzazione con hypervisor l’evoluzione software a contorno di questa tecnologia ha fatto grandi passi, consentendo ad oggi di ottenere una perfetta architettura di virtualizzazione di livello enterprise anche a casa vostra gratuitamente (mediante distro quali Ubuntu, Fedora, ecc).
La scalabilità dell’architettura viene garantita dalla infrastruttura costruita a partire dalla libvirt: un demone per il controllo anche remoto dell’hypervisor, una interfaccia amministrativa grafica e una testuale e altro a corollario.

20141231-181855.jpg

Da questa complessa architettura risulta ancora assente uno strumento integrato e completo per il salvataggio e ripristino delle VM.

Assenza però non significa impossibilità: con strumenti disponibili e standard si può realizzare un semplice ma efficace e sicuro software per la realizzazione di procedure di salvataggio e ripristino automatico di VM gestite da libvirt.

Questo sarà oggetto di questa serie di articoli.

Gli strumenti disponibili
La console amministrativa virsh ha i comandi dumpxml e define atti a salvare e ripristinare la definizione di una VM (un dominio, nella nomenclatura libvirt). Questo è un buon punto di partenza.
Quello che manca è il salvataggio della componente storage della VM. Questa è descritta nel file XML di definizione, ed in ogni caso è uno o più file collocati nel percorso /var/lib/libvirt/images/.
Questo percorso è accessibile solo da utente amministratore (l’hypervisor che ne gestisce l’accesso è un servizio di sistema), e questo diviene un requisito per una costruenda procedura automatica.

Il salvataggio di una VM è dunque la copia della sua definizione e dei file delle immagini disco.
Per realizzarlo è sufficiente dunque copiare questi files in un archivio (magari compresso) su un supporto esterno.

Vedremo della prossima puntata il codice (script shell) con cui realizzare questo compito.

Defrag_icon

Deframmentare Linux ?

Non vogliamo tirarla lunga con un articolo accademico sulla frammentazione e sulle tecniche implementate per minimizzarla sui filesystem della famiglia ext*.

Vogliamo solo farvi giocare concretamente con questo concetto/problema che sfugge all’attenzione degli utenti (e sistemisti Linux) per un assunto ben poco esatto ma comunque in concreto valido: “Linux non soffre di problemi di frammentazione”.

In realtà questo, come abbiamo detto, non è “esattamente” vero (e non vogliamo tediarvi con questioni tecniche), ma è altrettanto vero che il filesystem ext2 (e successori) ha dei buoni anticorpi per risolvere l’influenza della deframmentazione.

Il primo giocattolo per poter cominciare a saggiare con mano l’esistenza di questa realtà è il comando filefrag. Questo è disponibile nel pacchetto e2fsprogs (disponibile sia su distribuzioni RedHat like che Debian like).

Questo comando è capace di rilevare la frammentazione di un file indicato, in numero e identità dei blocchi di indirezione (extents).

A partire da questo e considerando che tra gli artifici del filesystem ext2 (e successori) per evitare la framentazione vi è la tecnica di allocare sequenzialmente i blocchi di un file in fase di creazione, possiamo porre le basi per un nuovo giocattolo.

Prendiamo ora il seguente nuovo assunto: “per deframmentare un file basta copiarlo”.
La nuova copia (per via del modo di allocazione blocchi) sarà “probabilmente” deframmentato. Il “probabilmente” è dovuto al fatto che i blocchi contigui devono essere disponibili. Ecco perché nell’implementazione provvediamo a copiare il file su un filesystem di appoggio (di base /tmp), liberiamo spazio sul filesystem sorgente (per aumentare la probabilità di trovare blocchi consecutivi) e ricopiamo nuovamente il file.

Dato che “repetita iuvant”, ripetere questa operazione quando la deframmentazione non è stata pienamente possibile potrà renderla possibile (a patto che il filesystem sia nel frattempo mutato rendendo disponibile nuove sequenze di blocchi contigui).

Ed ecco il nostro defrag per Linux:

#!/bin/bash
#
#
[ "$USER" != "root" ] && echo Must be root && exit 1

TEMPFILE=`mktemp`
trap 'rm -f $TEMPFILE' EXIT 1 15

echo -n "Raccolgo elenco file(s) ... "
find ${1:-.} -type f 2>/dev/null | grep -v $TEMPFILE >$TEMPFILE
echo fatto
NFILES=`cat $TEMPFILE | wc -l`
echo "Trovati $NFILES file(s)"

exec 3<> $TEMPFILE
declare -i i
declare -i defrag

i=0
defrag=0
read <&3
while [ -n "$REPLY" ]
do
EXTENTS=`filefrag "$REPLY" | cut -d: -f2 | awk '{ print $1 }'`
if [ ${EXTENTS:-0} -gt 2 ] 2>/dev/null; then
# Usare mktemp -p /altrodisco (se server più spazio)
TEMP=`mktemp`
cp -dp $REPLY $TEMP
rm -f $REPLY
cp $TEMP $REPLY
rm -f $TEMP
defrag=$(( defrag + 1 ))
fi
i=$((i + 1))
echo -en "\r$i/$NFILES ($(( 100 * i / NFILES ))%)"
read <&3
done
echo
exec 3>&-
echo "Processati $i file(s)"
echo "Deframmentati $defrag file(s)"
trap '' 1 15
exit 0

Ovviamente, in quanto giocattolo, non possiamo chiedervi di provarlo in ambienti di produzione. Pur essendo (crediamo) esente da problemi, non è consigliato soprattutto per il suo tempo di esecuzione, che è legato proporzionalmente alla dimensione e numero dei files da ottimizzare.

Non è il migliore degli approcci, ma è capace di ottenere il suo scopo. Soprattutto è capace di mostrarci il motivo nascosto del perché in Linux abbiamo pochi problemi di frammentazione (la copia dei file che ogni tanto avviene o la creazione degli stessi sono alla base della deframmentazione che avviene fuori dal nostro sguardo)

A noi bastava fornire una fascinazione riguardo il problema.