GOLEM Dolly 2014

Da GolemWiki.

All'Officina Informatica capita spesso di rimanere in arretrato con la preparazione di nuove macchine semplicemente a causa di un sistema che non vuole installarsi: CD/DVD d'installazione danneggiati, prestati oppure utilizzati contemporaneamente da qualcun altro, hardware che non piace alle versioni live, localizzazione italiana che non funziona, ecc... Inoltre, è frequente che una stessa associazione richieda più computer, che, per omogeneità, devono montare la stessa distribuzione e devono avere gli stessi software. Come soluzione a questi problemi, è stato concepito e realizzato il GOLEM Dolly, una macchina che si occupa di clonare una distribuzione personalizzata su un hard disk, che verrà poi semplicemente montato nella macchina da donare.

Funzionamento della macchina clonatrice

Configurazione hardware

  • AMD Duron 1500+ 1400MHz
  • 512M RAM
  • 40GB HDD
  • Cassetto per dischi IDE

Funzionamento

GOLEM Dolly monta due sistemi operativi sul suo disco fisso: il primo è la distribuzione Linux personalizzata dal GOLEM che si desidera replicare sulle macchine donate, mentre il secondo è un sistema minimale che, tramite uno script con una comoda interfaccia grafica, permette di clonare agevolmente il sistema personalizzato su un secondo hard disk, che va inserito nel cassetto IDE. Quando avremo sistemato i cassetti SATA, si potrà clonare anche su dischi SATA.

La distribuzione GOLEM Dolly

Questa sezione descrive il sistema che viene clonato e che viene installato sulle macchine donate.

Configurazione software della distribuzione GOLEM Dolly

Poiché, facendo trashware, non abbiamo a che fare con macchine di ultima generazione, abbiamo optato per una configurazione software che potesse essere parsimoniosa nell'uso delle risorse hardware e allo stesso tempo completa.

  • Sistema operativo: Debian 8 Jessie. Attualmente è la versione testing, quindi contiene le ultime versioni stabili dei vari software già pacchettizzate. Come sistema d'avvio, abbiamo scelto systemd (in genere è più veloce di init).
  • Ambiente desktop: XFCE 4.10. Adatto alle macchine che utilizziamo, unisce la leggerezza con la praticità e la completezza.
  • Software d'utilizzo comune: browser Iceweasel (Firefox), con Flash Player e Java (IcedTea); client di posta Icedove (Thunderbird); suite d'ufficio LibreOffice 4; editor Geany; applicazioni multimediali: riproduzione: VLC, mplayer; registrazione: Audacity, Cheese; chat Pidgin, Skype; torrent Deluge; programmi grafici: fotoritocco GIMP, scanner XSane; gestore grafico pacchetti: Synaptic; codec e encoder/decoder vari (ffmpeg, gstreamer1.0); strumenti vari (catfish, gucharmap, file-roller, youtube-dl, screen, zsh).

Come si può notare, un paio tra software e codec non sono liberi: purtroppo, a causa del vendor lock-in, attualmente risulta estremamente sconveniente non includere codec come MP3 o software come Skype e Adobe Flash. Ci auguriamo di poter risolvere questo bug.

Adobe Flash Player

Alcuni anni fa, i geni della Adobe hanno deciso che il loro Flash Player poteva funzionare solamente utilizzando il set di istruzioni SSE2 della Intel, pertanto alcuni processori AMD un po' più datati (come ad esempio il sopracitato AMD Duron 1500+) non sono fisicamente in grado di eseguire i binari del Flash Player. Poiché Flash è una tecnologia proprietaria mangiarisorse e non è poi così essenziale per navigare su Internet (i video di YouTube oggi possono essere visti in HTML5), abbiamo deciso di installare una versione un po' più vecchia di Flash piuttosto che sostituire il processore. Di seguito, la procedura:

Scaricare l'ultima versione 10.3.* di Flash Player da questa pagina: http://helpx.adobe.com/flash-player/kb/archived-flash-player-versions.html#flash_player_archives

per esempio

$ wget http://download.macromedia.com/pub/flashplayer/installers/archive/fp_10.3.183.86_archive.zip

estrarre il binario libflashplayer.so e posizionarlo in /opt/flashplugin-nonfree/v10.3.183.86

$ unzip fp_10.3.183.86_archive.zip && cd fp_10.3.r183.86_archive/10_3_r183_86/
$ tar -xvzf flashplayer_10_3r183_86_linux.tar.gz && cd flashplayer_10_3r183_86_linux
# mkdir -p /opt/flashplugin-nonfree/v10.3.183.86
# cp libflashplayer.so /opt/flashplugin-nonfree/v10.3.183.86/

infine, utilizzare update-alternatives per installare manualmente quella versione di Flash Player:

# update-alternatives --install /usr/lib/mozilla/plugins/flash-mozilla.so \
flash-mozilla.so /opt/flashplugin-nonfree/v10.3.183.86/libflashplayer.so 10

Questa procedura è anche descritta, in maniera più dettagliata, in questo topic in lingua inglese sul forum Debian: http://forums.debian.net/viewtopic.php?f=6&t=89675

Help

Quando un computer donato dovesse presentare dei manfunzionamenti dovuti al software (per esempio, GRUB2 si è danneggiato dopo un aggiornamento, ecc...), è bene tener presente che nella cartella /root del sistema sono presenti dei pratici .txt che riassumono in poche righe alcune procedure utili, tra cui:

  • comandi comuni per BTRFS
  • come effettuare chroot d'emergenza
  • ripristinare password dimenticata
  • ripristinare GRUB2
  • ...

Partizioni Hard Disk

+-GRUB BOOT-+-SWAP-+--GOLEM Dolly BTRFS-----+   +-GOLEM Installer-+
|           |      |                        |   |                 |
|           |      | +--btrfs subvolumes--+ |   |    installer    |
| bios_grub | swap | |   slash   |   home | |   |                 |
|           |      | +--------------------+ |   |                 |
+-----------+------+------------------------+   +-----------------+

Questo è uno schema delle partizioni del disco di GOLEM Dolly; naturalmente, il sistema minimale con gli script di installazione è presente solo sulla macchina clonatrice. Utilizzando la modalità manuale dello script, è possibile partizionare il disco come si preferisce (ad esempio, quando è necessario un dual boot con altri sistemi operativi).

Per approfondire, vedere GPT con sistemi BIOS e BTRFS.

Script di installazione

Lo script di installazione è scritto in bash e si appoggia a zenity per poter interagire graficamente con il socio GOLEM che sta installando. Questa sezione spiega nel dettaglio cosa fa lo script, e non è necessario leggerla per l'utilizzo di GOLEM Dolly (anche perché credo che sia abbastanza noiosa).

Intestazione di rito, con spiegazione sul funzionamento e codici di uscita per arresti anomali (utili per capire cosa è successo quando si verifica un errore):

#!/bin/bash
# -- GOLEM Dolly Installation script
# Released under GNU GPL3+
# Date: September 2014
# Exit codes:
# 1    must be root
# 2    stopped by user
# 3    mount error
# 4    data error (mainly rsync copy, or btrfs subvolumes editing)
# 5    GRUB2 error
# 6    can't execute more than one istance
# 100  manual stop

>&2 echo "GOLEM Dolly Installer -- clona il sistema
 In questo terminale saranno mostrate alcune informazioni utili
 circa lo svolgimento del processo, e in particolare si potranno
 leggere i messaggi di errore nel dettaglio.
 Durante l'installazione, non chiudere questo terminale per nessuna ragione;
 anche se l'installazione fallisce, prima di chiudere, annotarsi il
 messaggio di errore."

Per eseguire lo script bisogna essere root, altrimenti non si possono modificare i dischi e/o copiare i dati e i permessi.

if [ $(whoami) != "root" ]; then
 zenity --error --text="Per eseguire questo script devi essere root"
 exit 1
fi

Lockfile: lo script controlla se esiste un determinato file di blocco in /tmp: se non esiste, lo crea; altrimenti, significa che un'altra istanza dello script è in esecuzione, quindi esce (è impossibile accedere contemporaneamente al disco per clonare il sistema)

# Evita di avviare più istanze di questo script
LOCKFILE="/tmp/golem-dolly-installer-lock"
if [ -f "$LOCKFILE" ]; then
 zenity --error --text="Un'altra istanza di questo script è già in esecuzione;
 se si è sicuri che questo problema sia dovuto a un crash inaspettato dello script,
 rimuovere manualmente il filo di blocco '$LOCKFILE'"
 exit 6
else
 touch "$LOCKFILE"
fi

CURRENTDISK è il disco su cui è installato attualmente questo sistema, cioè la distribuzione personalizzata e il sistema minimale col relativo script di installazione. Il disco viene individuato ricercando la / nel file /etc/mtab, ma potrebbe fallire! In tal caso, commentare la riga automatica e modificare manualmente la variabile CURRENTDISK per impostare questo disco.

Se la ricerca fallisce, spesso, è colpa di GRUB2, che, per identificare e montare i dischi all'avvio, utilizza gli UUID al posto dei classici /dev/sd*: nel sistema minimale d'installazione, è essenziale utilizzare i device node classici, mentre nel nuovo sistema clonato devono essere utilizzati gli UUID, in modo da poter individuare i dischi anche quando vengono spostati sulla nuova macchina.

CURRENTDISK=$(cat /etc/mtab | grep /dev/sd | grep -w / | awk '{print $1}' | sed 's/[0-9]*//g' )
# CURRENTDISK="/dev/sde"

zenity --info --text="*** Benvenuto nel GOLEM DOLLY Installer ***
 Adesso lo script effettuerà alcuni controlli e farà alcune domande,
 dopodiché sarà possibile entrare nella modalità automatica.
 Lo script ha assunto che questo sistema (Installer) si trovi sul disco
 $CURRENTDISK. Se così non fosse, interrompere immediatamente la clonazione
 e modificare manualmente la variabile CURRENTDISK dello script."
if [ "$?" != 0 ]; then exit 2; fi

Scelta del disco di installazione del nuovo sistema; viene automaticamente escluso dalle proposte il disco CURRENTDISK su cui è installato il sistema minimale d'installazione e la distribuzione personalizzata (vorrei anche vedere che, dopo tutto il tempo che ho impiegato, qualcuno cancelli tutto per sbaglio!):

INSTALLDISK=$(zenity --list --text="In quale disco di desidera installare il sistema?" \
 --column="Device" $(ls -1 /dev/sd? | grep -v "$CURRENTDISK"))
if [[ "$?" != 0 || -z "$INSTALLDISK" ]]; then exit 2; fi

zenity --text="Il sistema verrà installato in $INSTALLDISK.
 Vuoi utilizzare la modalità automatica?" --question
AUTO="$?"

Nella modalità manuale, lo script avvia GParted e chiede di creare manualmente le partizioni (questa operazione è utile quando si deve installare la distribuzione su un disco che contiene già un altro sistema operativo). Naturalmente bisogna prestare attenzione a creare le giuste partizioni (ad esempio, nelle macchine BIOS che utilizzano uno schema di partizionamento GPT, è necessario creare la corrispondente partizione con flag 0xEF02 o bios_grub).

Nella modalità manuale è comunque sempre necessario creare e scegliere almeno due partizioni, una per / e una per swap.

if [ "$AUTO" != 0 ]; then
 zenity --info --text="Adesso verrà avviato GParted sul disco $INSTALLDISK.
   È possibile partizionare manualmente a proprio piacimento il disco.
   Al termine del partizionamento, è sufficiente chiudere GParted per
   proseguire con l'installazione."
 gparted "$INSTALLDISK"

 while [ true ]; do # finché non si selezionano due partizioni diverse per / e swap
   INSTALLROOT=$(zenity --list --text="Scegliere la partizione / del nuovo sistema:" \
   --column="Partizione" $(ls -1 $INSTALLDISK*))
   if [ "$?" != 0 ]; then exit 2; fi

   INSTALLSWAP=$(zenity --list --text="Scegliere la partizione swap del nuovo sistema:" \
   --column="Partizione" $(ls -1 $INSTALLDISK*))
   if [ "$?" != 0 ]; then exit 2; fi

   if [ "$INSTALLROOT" != "$INSTALLSWAP" ]; then
     break;
   else
     zenity --error --text="Non è possibile selezionare la stessa partizione per / e swap!"
     if [ "$?" != 0 ]; then exit 2; fi
   fi
 done

Se invece si sta utilizzando la modalità automatica, tutti i dati verranno cancellati dal disco $INSTALLDISK, sarà creata una nuova tabella partizioni GPT, una partizione per swap e una partizione BTRFS con due sottovolumi, uno per / e uno per /home. Per una rappresentazione grafica d'effetto, vedere lo schema sopra.

else
 # Cancella la tabella partizioni; al primo passaggio azzera tutto,
 # epuò fallire se la tabella è corrotta o il disco è vuoto
 sgdisk -Z "$INSTALLDISK" 2> /dev/null; sgdisk -o "$INSTALLDISK"
 # Crea le nuove partizioni
 sgdisk -n 1:1M:199M "$INSTALLDISK"    # bios_grub (compatibilità GPT per sistemi BIOS)
 sgdisk -t 1:EF02 "$INSTALLDISK"       # imposta tipo di partizione
 sgdisk -n 2:200M:999M "$INSTALLDISK"  # swap
 sgdisk -t 2:8200 "$INSTALLDISK"       # imposta tipo di partizione
 sgdisk -n 3:1000M:-0M "$INSTALLDISK"  # btrfs filesystem
 sgdisk -t 3:8300 "$INSTALLDISK"       # imposta tipo di partizione
 INSTALLSWAP="$INSTALLDISK""2"
 INSTALLROOT="$INSTALLDISK""3"
fi

Formattazione delle partizioni:

>&2 echo " Swap: $INSTALLSWAP - Creazione swap con mkswap"
mkswap "$INSTALLSWAP"

>&2 echo " Root: $INSTALLROOT - Creazione filesystem BTRFS con mkfs.btrfs"
mkfs.btrfs "$INSTALLROOT"

Creazione dei sottovolumi BTRFS:

if [ -n "$(cat /etc/mtab | grep /target)" ]; then  # prima di pulire, controlla che non vi sia montato niente
 zenity --error --text="'/target' is a busy mount point"
 exit 3
fi
rm -rf /target   # pulisce eventuali residui di installazioni non completate
mkdir -p /target
mount "$INSTALLROOT" /target
if [ "$?" != 0 ]; then
 zenity --error --text="Impossibile montare $INSTALLROOT sul punto di mount '/target'"
 exit 3
fi
cd /target
btrfs subvolume create slash
btrfs subvolume create home
cd
umount /target


Installazione del sistema: qui vengono montate le partizioni al giusto posto:

# Montaggio di GOLEM Dolly originale
mkdir -p /dolly/slash  # creazione mountpoint
mkdir -p /dolly/home
mount -o subvol=slash "$CURRENTDISK""3" /dolly/slash
mount -o subvol=home "$CURRENTDISK""3" /dolly/home
if [ "$?" != 0 ]; then zenity --error --text="Impossibile montare il sottovolume BTRFS di $CURRENTDISK""3"" sul punto di mount '/dolly'"; exit 3; fi

# Montaggio del disco target su cui clonare il sistema
mkdir -p /target/slash
mkdir -p /target/home
mount -o subvol=slash "$INSTALLROOT" /target/slash
if [ "$?" != 0 ]; then zenity --error --text="Impossibile montare il sottovolume BTRFS slash di $INSTALLROOT sul punto di mount '/target'"; exit 3; fi
mount -o subvol=home "$INSTALLROOT" /target/home
if [ "$?" != 0 ]; then zenity --error --text="Impossibile montare il sottovolume BTRFS home di $INSTALLROOT sul punto di mount '/target'"; exit 3; fi

Installazione del sistema vera e propria, tramite rsync: l'opzione -a significa archiviazione e conserva permessi, date, gruppi ecc...

Dalla copia vengono escluse tutte quelle cartelle temporanee o create live dal sistema (come proc che contiene informazioni sui processi in esecuzione, dev che contiene la configurazione hardware, ecc...)

>&2 echo " => Root..."
rsync -va --exclude /dev/ --exclude /proc/ --exclude /sys/ --exclude /tmp/  /dolly/slash/ /target/slash/
if [ "$?" != 0 ]; then zenity --error --text="rsync ha fallito!"; exit 4; fi
# Creazione delle cartelle temporanee che non sono state copiate
mkdir -p /target/slash/tmp; chmod 777 /target/slash/tmp
mkdir -p /target/slash/proc
mkdir -p /target/slash/sys
mkdir -p /target/slash/dev

>&2 echo " => Home..."
rsync -va /dolly/home/ /target/home/
if [ "$?" != 0 ]; then zenity --error --text="rsync ha fallito!"; exit 4; fi

>&2 echo "==> Termine dell'installazione..."

Generazione automatica del nuovo /etc/fstab:

# Ricerca dell'UUID del filesystem delle partizioni coinvolte
INSTALLROOTUUID=$(blkid "$INSTALLROOT" | cut -d' ' -f2 | cut -d'"' -f2)
INSTALLSWAPUUID=$(blkid "$INSTALLSWAP" | cut -d' ' -f2 | cut -d'"' -f2)

echo "
# This fstab was dinamically generated by the GOLEM Dolly installation script
UUID=$INSTALLROOTUUID  /   btrfs noatime,relatime,subvol=slash 0 1
UUID=$INSTALLROOTUUID  /home btrfs noatime,relatime,subvol=home  0 0
# systemd should automatically detect the swap device; if it does not happen,
# then uncomment the following line:
#UUID=$INSTALLSWAPUUID swap  swap  defaults  0 0
/dev/sr0        /media/cdrom0   udf,iso9660  user,noauto     0       0
/dev/fd0        /media/floppy0  auto     rw,user,noauto    0       0" | tee /target/slash/etc/fstab

Installazione del bootloader GRUB2:

# preparazione dell'ambiente chroot
mount -o bind /dev /target/slash/dev
if [ "$?" != 0 ]; then zenity --error --text="chroot error!"; exit 3; fi
mount -t proc /proc /target/slash/proc
if [ "$?" != 0 ]; then zenity --error --text="chroot error!"; exit 3; fi
mount -t sysfs /sys /target/slash/sys
if [ "$?" != 0 ]; then zenity --error --text="chroot error!"; exit 3; fi
# installazione vera e propria
chroot /target/slash /usr/sbin/grub-install "$INSTALLDISK"
if [ "$?" != 0 ]; then zenity --error --text="Error: grub-install in chroot!"; exit 5; fi
chroot /target/slash /usr/sbin/update-grub2
if [ "$?" != 0 ]; then zenity --error --text="Error: update-grub2 in chroot!"; exit 5; fi

Attende il termine dei processi di scrittura, poi smonta i dischi:

>&2 echo " => Termine di scrittura su disco (sync)..."
cd
sync
sleep 2

>&2 echo "==> Smontaggio dischi..."
umount /target/home
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile smontare!"; exit 3; fi
umount /dolly/home
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile smontare!"; exit 3; fi
umount -l /target/slash
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile smontare!"; exit 3; fi
umount /dolly/slash
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile smontare!"; exit 3; fi
>&2 echo "<==- FINE -==>"

Grazie alle potenzialità del BTRFS, viene creata una snapshot per poter ripristinare il sistema alle condizioni originarie in caso di malfunzionamenti o danni:

# Creazione della snapshot finale funzionante
mount "$INSTALLROOT" /target
if [ "$?" != 0 ]; then
 zenity --error --text="Impossibile montare $INSTALLROOT sul punto di mount '/target'"
 exit 3
fi
cd /target
date > golem-release.date
btrfs subvolume snapshot slash slashbak
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile creare snapshot BTRFS di ripristino!"; exit 4; fi
cd
umount /target
if [ "$?" != 0 ]; then zenity --error --text="Errore: impossibile smontare!"; exit 3; fi

Rimozione del lockfile:

# Pulizia dello script e termine
rm -rf "$LOCKFILE"

Termine dell'installazione:

zenity --info --text="Se il terminale non ha dato errori,
 sembra che l'installazione sia andata a buon fine.
 Accendere un cero votivo a Stallman,
 dopodiché spegnere questa macchina e collegare il disco alla nuova macchina"

exit 0