Creiamo una VM Ubuntu su un server Xen CentOS

In questi giorni ho avuto la necessità di installare una DomU Ubuntu avendo a disposizione un server Xen Dom0 su CentOS.

Non è una delle operazioni più immediate, pertanto vi spiego la procedura che ho utilizzato.

Innanzi tutto ho creato una immagine per la root del sistema operativo della dimensione di 4 GB usando il comando dd:

dd if=/dev/zero of=ubuntu.img bs=1024 count=4096

Quindi formattiamo l’immagine con il filesystem ext3:

mke2fs -j ubuntu.img

Ora scarichiamo il cd di installazione di Ubuntu: in questo caso utilizzo Ubuntu 10.10, ma vale per qualsiasi versione:

wget http://archive.ubuntu.com/ubuntu/dists/maverick/main/installer-amd64/current/images/netboot/mini.iso

Creiamo il file di configurazione di xen per eseguire il boot dall’immagine CD:

<strong>/etc/xen/ubuntu</strong>
name="ubuntu"
memory=512
vif=['bridge=xenbr0']
disk = ['file:/home/user/mini.iso,xvdc:cdrom,r', 'file:/home/user/ubuntu.img,xvda,w']
bootloader="/usr/bin/pygrub"
on_reboot='restart'
on_crash='restart'

e avviamo la nuova vm con

xm create /etc/xen/ubuntu -c

Ora seguiamo i passi di installazione standard, con due sole eccezioni:

  1. quando l’installer chiederà di partizionare il disco, prestate molta attenzione a NON ripartizionare il disco, dicendogli di montare l’unica partizione rilevata in / senza formattarla nuovamente.

  2. quando, al termine dell’installazione, chiederà di installare il bootloader grub, saltate questo passaggio

Al termine dell’installazione l’immagine si riavvierà, ma dato che non avete “espulso” il CD ripartirà il processo di installazione. Lanciate il seguente comando per spegnere la VM:

xm destroy ubuntu

Ora arriva la parte divertente: il comando pygrub di centos non è in grado di avviare correttamente le immagini di Ubuntu, pertanto utilizzeremo in vecchio e caro metodo di Xen andando a specificare quale kernel utilizzare.
Montiamo provvisoriamente l’immagine di Ubuntu:

mkdir /mnt/tmp
mount -o loop /home/user/ubuntu.img /tmp/mnt
cp /tmp/mnt/boot/vmlinuz* /tmp/mnt/boot/initrd* /home/user

Andiamo a modificare il file di configurazione di Xen per avviare correttamente la nostra immagine:

<strong>/etc/xen/ubuntu</strong>
name="ubuntu"
memory=512
vif=['bridge=xenbr0']
disk = ['file:/home/user/ubuntu.img,xvda,w']
kernel = "/srv/vms/kernel/ubuntu/vmlinuz-2.6.35-30-generic"
ramdisk = "/srv/vms/kernel/ubuntu/initrd.img-2.6.35-30-generic"
root = '/dev/sda'
on_reboot='restart'
on_crash='restart'

e avviamo nuovamente la vm con:

xm create /etc/xen/ubuntu -c

Scusate ma non resisto…/2

Da un colloquio tra me e un tecnico dell’help desk di un ISP del quale non faccio il nome per decenza:

A: Salve, la chiamavo in quanto ho qualche problema ad usare il Vostro servizio di TSA per apporre la marca temporale a dei file

T: Che problema rileva?

A: Sostanzialmente mi sembra che manchino dei gli elementi: mi avete dato una URL di configurazione e un programma per Windows da scaricare, però io avrei bisogno del certificato pubblico e dei dati relativi alla URL della TSA per utilizzare il servizio secondo lo standard RFC 3161

T: Non è che mi può inviare lo snapshot della schermata di errore?

A: Guardi, forse mi sono espresso male: io non ho intenzione di usare il Vostro client per Windows, perchè ho bisogno di far marcare dei file in maniera automatica da un server attraverso uno script che lavora in automatico secondo lo standard RFC 3161

T: Ah, ok, è una cosa particolare: mi prendo nota e la faccio contattare dai tecnici di secondo livello. A proposito di quel programma che usa… ha detto R di Roma, poi…

A: R di Roma, F di Firenze e C di Como: stà per Request for Comments ed è il sistema con cui vengono identificati gli standard in Internet. Poi c’è un numero che identifica quello che a noi interessa, è 3161.

T: Capisco però non so dirle se è possibile usare il servizio senza il nostro client per Windows

A: Senta, mi levi una curiosità: ma voi avete realizzato un Vostro client per windows anche per spedire messaggi attraverso il protocollo RFC 821?

T: Mi scusi?

Ok, quest’ultima me la sarei potuta risparmiare vista la levatura intellettuale del personaggio con cui stavo parlando…

La nuova politica di aggiornamento di Firefox

E’ senza dubbio il leitmotiv di questi giorni: Firefox ha appena rilasciato la versione 5 del suo browser, quando era solo da circa un mese che era “sul mercato” la versione 4 e buona parte degli utenti non ha ancora provveduto all’aggiornamento dalla ormai datata 3.6.
Ma non solo: è di oggi l’annuncio che la versione 4 non sarà più aggiornata e che entro l’anno sarà rilasciata sia la versione 6 che la versione 7!

Ma come mai tutta questa fretta? Gli sviluppatori sono presi da un “delirius coding”? Quali sono i pro e i contro di questa politica accelerata?

Partiamo dall’inizio e facciamo un po’ di chiarezza.

Innanzi tutto è bene precisare che Firefox è tuttora il browser più utilizzato: all’inizio c’era Netscape (il cui nome in codice era Mozilla) che una volta reso OpenSource e abbandonato da America on Line a fine anni ‘90, è stato mantenuto dalla neonata Mozilla Foundation che ha creato il “Mozilla Suite”, cioè un insieme di programmi per il web tra cui il browser Mozilla Firefox.
Netscape è stato per molto tempo l’unica alternativa gratuita (ma terribilmente pesante) ad Internet Explorer. Quando è nato Mozilla Firefox, il “pubblico” si è innamorato di questo browser sia perchè è stata migliorata di molto la velocità rispetto a Netscape, sia per il rispetto degli standard HTML e W3C, sia perchè l’architettura totalemente aperta ha favorito quello che secondo me è il reale punto di forza di questo browser: i plugin esterni. Tutto questo, come già detto, ha reso Firefox il browser attualmente più utilizzato al mondo.

Negli ultimi anni si sono affacciati molti altri concorrenti OpenSource: uno di questi è Google Crome, che si è dimostrato particolarmente valido grazie alla sua velocità “turbo”, insidiando la supremazia di Firefox. Molti utenti, difatti, iniziano a preferire Chrome a Firefox, per cui alla Mozilla Foundation si è deciso di correre ai ripari.

Inutile nascondersi dietro ad un dito, quindi: il reale motivo di questa accelerazione nel rilascio di nuove versioni di Firefox è proprio dovuto alla necessità di dover competere con Chrome in termini di velocità, nel tentativo di arginare la migrazione di utenti verso il browser concorrente.

Ma questo servirà realmente a tenersi stretti gli utenti?

La mia opinione è no, proprio perchè a causa di questo velocissimo piano di sviluppo, anche gli sviluppatori di plugin esterni devono essere altrettanto veloci nel rilascio degli aggiornamenti. Ovviamente non si può pretendere che gli sviluppatori esterni, che spesso non hanno alle spalle colossi come la Mozilla Foundation, riescano a tenere il passo dei velocissimi ritmi della casa madre, cosa che porterà inevitabilmente ad avere plugin incompatibili ed inutilizzabili, perdendo quello che è, a mio avviso, il reale motivo di successo, da sempre, di Firefox cioè la possibilità di espansione grazie ad elementi esterni.

Poi solo il tempo decreterà se ho ragione io oppure la Mozilla Foundation…

Cos’è Google Web Toolkit

Come spiegato precedentemente, con Google App Engine abbiamo a disposizione un framework server-side per creare applicazioni web che risiedono sul Cloud di Google. Questo è un bel passo in avanti per il programmatore, in quanto ha a disposizione un sistema per creare la propria applicazione senza dover pensare a tutte le problematiche di scalabilità e di storage distribuito proprie di un sistema in cloud: è sufficiente utilizzare le API di Google per gestire queste operazioni ed ecco che la vostra applicazione gestirà automaticamente tutte le peculiarità del Cloud.

Bene, ma lato client?

La nostra Web Application potrà fare cose davvero interessanti, ma se vengono presentate in una maniera poco accattivante l’applicazione non riscuoterà il successo sperato. Come già accennato precedentemente, è possibile utilizzare una versione appositamente creata di django o fare i salti mortali per usare Scala/Lift, però esite un altro sistema messo a disposizione direttamente da Google: il Web Toolkit.

Giusto per capire, mentre Google App Engine si occupa della parte server, Google Web Toolkit si occupa della parte client: questo SDK permette di avere delle primitive in Java per creare l’interfaccia utente in Web 2.0 della nostra applicazione, quindi la possibilità di creare pulsanti, finestre flottanti, ecc.

Mentre con Google App Engine si ha la libertà di scegliere il linguaggio da utilizzare, con il Google Web Toolkit si è legati a Java: in pratica l’interfaccia web viene scritta in Java e poi il compilatore crea il codice Javascript ottimizzato che sarà inviato al browser. Ecco perchè, a mio avviso, per avere una migliore “development experience” con i Tools di Google è opportuno scegliere Java come linguaggio di programmazione.

Configurazione AWstat per webserver in load balancing

In questo articolo affrontiamo un problemino che si incontra utilizzando più web server dietro ad un load balancer: la generazione delle statistiche.

Ammettiamo una situazione in cui abbiamo quattro web server apache con indirizzo IP 192.168.20.101-102-103-104 dietro ad un load balancer con indirizzo IP pubblico che rigira ai 4 server le richieste HTTP provenienti dalla rete internet. I quattro server leggono il contenuto dei siti web (pagine html, php, immagini…) da un disco condiviso comune con una qualsiasi tecnica (NFS, GlusterFS, MooseFS, iSCSI/OCFS2, ecc.). In questo caso ciascun server genererà i propri log di accesso indipendentemente: come fare per far si che un programma che genera statistiche (in questo caso AWstats) faccia il suo compito a dovere?

Le soluzioni sono principalmente due: la più immediata è condividere la directory con i log di Apache tra i quattro server in modo che tutti scrivano su un unico file di log. Questo, però, può generare facilemente problemi in quanto la situazione più complessa da gestire per un disco condiviso sono le scritture multiple contemporanee su uno stesso file.

La seconda soluzione, quella che adotteremo in questo articolo, è di far salvare i log a ciascun server in una sua directory e creare una nuova macchina che periodicamente copierà i file di log da ciascun server, li aggregherà e genererà le statistiche con awstat per ciascun website.

Partiamo quindi da una nuova installazione linux su cui installeremo AWstats. Su Debian/Ubuntu:

apt-get install awstats

Ora montiamo la directory condivisa con i siti web come fosse un comune web server: questo ci servirà per far si che awstats scriva le pagine con le statistiche all’interno della directory “web/stats” di ciascun virtualhost. Nella mia configurazione (ISPConfig) all’interno della directory /var/www c’è una directory per ogni sito web al cui interno c’è, appunto, una sottodirectory web con le pagine del sito e, ad un livello ancora inferiore, la sottodirectory stats che conterrà le statistiche.
Nel mio caso si tratta di un filesystem di rete NFS (/mnt/www sul server 192.168.20.253), per cui mi è sufficiente aggiungere la seguente riga nel file hosts del server AWstats:

<strong>/etc/fstab</strong>
192.168.20.253:/mnt/www                /var/www                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

Quindi lancio i seguenti comandi per montare il filesystem:

mkdir /var/www
apt-get install nfs-kernel-server nfs-client
mount /var/www

Ora creo una directory per ciascun server in cui salvare i log:

mkdir -p /var/log/httpd-1
mkdir -p /var/log/httpd-2
mkdir -p /var/log/httpd-3
mkdir -p /var/log/httpd-4

A questo punto possibile creare uno script che tramite scp copi i file in locale periodicamente, però l’utilizzo della rete sarebbe molto significativo per cui preferisco usare NFS ed esportare le 4 nuove directory verso i webserver. Per lo stesso motivo evito di esportare la directory con i log dei 4 webserver con NFS: meglio che awstats lavori con i file in locale.
Quindi modifico il file /etc/exports per esportare le quattro directory:

<strong>/etc/exports</strong>
/var/log/httpd-1        192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-2      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-3      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-4      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)

e lancio il comando per avviare l’esportazione:

exportfs -a

Ora, su ciascun server web, monto la directory esportata dal server AWstats. Modifico il file /etc/fstab:

<strong>/etc/fstab</strong>
192.168.20.44:/var/log/httpd-1                /var/log/httpd                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

In questo caso sono sul server “1” e quindi monto la directory /var/log/httpd-1; bisogna agire di conseguenza sugli altri server.

mount /var/log/httpd

Ora, sui nostri quattro web server andiamo a modificare la configurazione di apache.
Innanzi tutto creaiamo un alias per la directory awstats-icon aggiungendo le seguenti righe:

<strong>/etc/httpd/httpd.conf</strong>
Alias /awstats-icon/ "/usr/share/awstats/awstats-icon/"

    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all

E copiamo su ciascun webserver la directory con le icone di awstats in /usr/share/awstats/awstats-icon.
Inoltre dobbiamo modificare la configurazione dei Virtualhost in modo che i log vengano salvati in una diversa directory per ciascun sito. Questa configurazione rispecchia il comportamento di default di ISPConfig.

Ora veniamo allo script che farà il lavoro vero e proprio. I commenti sono autoesplicativi, in qualsiasi caso lo script prende in esame tutte le directory presenti in /var/www assumendo che ciascuna di queste contenga un virtualhost.
La riga di configurazione più importante è echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile: in questa riga si indica dove sono i file di log relativi al virtualhost. Si usa lo script di awstats “logresolvemerge.pl” per fare il merge di tutti i file di log relativi al giorno precedente: tale script viene lanciato “al volo” e genera il file che sarà utilizzato da awstats in ram.

<strong>/usr/local/bin/crea-statistiche.sh</strong>
#!/bin/bash

# Variabili da configurare
# ---------------------------
# Directory con i siti web
webdir="/var/www"
# Sottodirectory per l'output dei file di report
reportdir="web/stats"
# Directory con i log
logdir="/var/log/httpd-*"
# Directory con le configurazioni di awstats
awstatsdir="/etc/awstats"
# Path allo script per realizzare il merge dei log
mergepath="/usr/share/doc/awstats/examples/logresolvemerge.pl"
# ---------------------------
# Elaboro il nome del file sul quale generare i log
data=`date +%Y%m%d`
filelog="$(($data - 1))-access.log.gz"

# Eseguo il ciclo per tutte le directory in "webdir"
j="${webdir}/*"
for directory in $j
do
    # Nel caso in cui si tratti effettivamente di una directory
    if [ -d ${direcroty} ]
    then
    # Estraggo il nome dominio dalla path
    dominio=${directory##*/}

    # Genero i file di configurazioni di AWStats
    configfile="${awstatsdir}/awstats.${dominio}.conf"
    echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile
    echo "SiteDomain=${dominio}" >> $configfile
    echo "LogFormat=1" >> $configfile
    echo "DirIcons=\"/awstats-icon\"" >> $configfile
    fi

    # Eseguo AWStats
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -update
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -output -staticlinks > ${webdir}/${dominio}/${reportdir}/awstats.html
done