Postazioni diskless usando Gentoo Linux Michael Andrews Kristian Jerpetjoen Sven Vermeulen Xavier Neys Flavio Castelli Questo HOWTO illustra la realizzazione di una rete diskless tramite l'uso di Gentoo Linux 1.22 2006-10-22 Introduzione
Prefazione

Questo HOWTO intende illustrare la creazione di una rete formata da postazioni diskless, basate su Gentoo Linux. Nella rete sono presenti svariate guide che si occupano di questo argomento, purtroppo la maggior parte risultano complicate. Invece questa guida intende essere il più semplice possibile, in modo da aiutare anche le persone che sono alle prime armi con Linux.

Cosa è un PC diskless?

Una postazione diskless è un comune computer sprovvisto delle consuete periferiche di avvio quali: dischi fissi, lettori floppy e lettori di cdrom. La postazione diskless esegue la procedura d'avvio tramite la scheda di rete, pertanto è richiesta la presenza di un server che le fornisca lo spazio fisico su cui salvare i propri dati. D'ora in avanti ci riferiremo al server con il termine di master, mentre con il termine slave si fa riferimento alla postazione diskless. Come detto in precedenza lo slave esegue la procedura d'avvio tramite la propria scheda di rete, per poterlo fare è necessario avere una scheda di rete che supporti i protocolli PXE o Etherboot. Per sapere se la propria scheda di rete sia tra quelle compatibili consultate la lista presente sul sito Etherboot.org. La maggior parte delle schede di rete (comprese quelle integrate sulle schede madri) di recente produzione supporta PXE.

Prima di iniziare

Sul PC master dovrebbe essere installato Gentoo Linux e dovrebbe esserci abbastanza spazio libero per contenere anche l'intero file system degli slave. Inoltre è necessario controllare d'avere due schede di rete sul pc master, una collegata ad internet e l'altra collegata alla rete locale.

Configurazione del master e degli slave
Cosa è il kernel Se si desidera utilizzare le proprie postazioni all'interno di un cluster openMosix è necessario controllare di utilizzare un kernel con applicate le patch necessarie ad openMosix. L'ebuild relativo si può trovare all'interno del portage, nel percorso sys-kernel/openmosix-sources. Per compilare un kernel funzionante con openMosix è consigliata la lettura dell'openMosix HOWTO

Il kernel è il cuore del sistema operativo, è un programma che permette a tutti i programmi presenti di interfacciarsi con l'hardware della propria macchina. Quando un computer è avviato il BIOS legge delle istruzioni presenti in un settore riservato del disco fisso; queste istruzioni non sono altro che il boot loader, il quale si preoccupa di caricare il kernel. In seguito sarà il kernel a gestire tutti i processi in esecuzione.

Per ulteriori informazioni sul kernel e su come configurarlo è consigliata la lettura di questa guida.

Configurazione del kernel della postazione master

Il kernel della postazione master non ha limiti di dimensione, sono solo richieste alcune opzioni. Per attivarle occorre entrare nel menu di configurazione del kernel tramite i seguenti comandi:

# cd /usr/src/linux
# make menuconfig

A questo punto si presenta un'interfaccia grafica: si tratta di un'alternativa più rapida rispetto alla modifica a mano del file /usr/src/linux/.config. Se il proprio attuale kernel è funzionante è consigliabile farne una copia da tenere al sicuro. Per farlo digitare, all'uscita dell'interfaccia grafica, i seguenti comandi:

# cp .config .config_funzionante

Entrare nei seguenti sotto-menu e controllate che le opzioni elencate siano impostate come compilate staticamente (e NON come dei moduli). Le opzioni elencate di seguito sono relative ad un kernel della serie 2.6.10. Nel caso si desideri utilizzare un kernel differente il listato seguente potrebbe variare leggermente. Accertarsi d'avere selezionato le voci indicate di seguito:

Code maturity level options  --->
  [*] Prompt for development and/or incomplete code/drivers
  
  Device Drivers --->
  Networking options --->
  <*> Packet socket
  <*> Unix domain sockets
  [*] TCP/IP networking
  [*]   IP: multicasting
  [ ] Network packet filtering (replaces ipchains)
  
  File systems --->
  Network File Systems  --->
  <*> NFS server support
  [*]   Provide NFSv3 server support


Se si intende accedere a internet tramite il master e avere un firewall sicuro è consigliabile attivare il supporto a iptables.

  [*] Network packet filtering (replaces ipchains)
  IP: Netfilter Configuration  --->
    <*> Connection tracking (required for masq/NAT)
    <*> IP tables support (required for filtering/masq/NAT)

Se si desidera utilizzare il packet filtering è possibile compilare le sue sotto-opzioni modularmente. Per configurare correttamente il proprio firewall è consigliata la lettura del capitolo numero 12 della Guida Gentoo alla sicurezza.

Queste opzioni del kernel sono da intendersi come un'aggiunta alle vostre attuali opzioni, esse non intendono rimpiazzare completamente la propria configurazione del kernel.

Dopo aver riconfigurato il kernel del master è necessario procedere alla sua compilazione:

# make && make modules_install
(Accertarsi che  /boot sia montata prima di copiarvi i file)
# cp arch/i386/boot/bzImage /boot/bzImage-master

Infine aggiungere una nuova voce per il nuovo kernel all'interno di lilo.conf o di grub.conf, a seconda del proprio bootloader. Ora che il nuovo file bzImage è stato copiato nella directory /boot è possibile riavviare il sistema per attivare le nuove modifiche.

Configurare il kernel degli slave

E' consigliabile compilare il kernel degli slave senza moduli, dato che la presenza dei moduli renderebbe la procedura d'avvio remoto difficoltosa. Inoltre il kernel degli slave deve essere il più piccolo e compatto possibile, in modo da essere efficiente al momento dell'avvio. Si compili il kernel degli slave nello stesso percorso in cui abbiamo compilato quello del master.

Per evitare confusione e inutili sprechi di tempo è consigliabile fare una copia della configurazione del kernel del master. Digitare semplicemente:

# cp /usr/src/linux/.config /usr/src/linux/.config_master

Si procede ora alla configurazione del kernel degli slave nello stesso modo con cui è stato configurato quello del master. Se si desidera lavorare su una configurazione "pulita" (ovvero senza avere le opzioni selezionate precedentemente per il master) è possibile recuperare il file /usr/src/linux/.config iniziale digitando:

# cd /usr/src/linux
# cp .config_master .config

Ora è possibile lanciare nuovamente l'interfaccia grafica di configurazione del kernel digitando:

# cd /usr/src/linux
# make menuconfig

Accertarsi d'avere selezionato le seguenti voci come compilate staticamente e NON come moduli:

Code maturity level options  --->
  [*] Prompt for development and/or incomplete code/drivers
  
Device Drivers --->
  [*] Networking support
  Networking options --->
    <*> Packet socket
    <*> Unix domain sockets
    [*] TCP/IP networking
    [*]   IP: multicasting
    [*]   IP: kernel level autoconfiguration
    [*]     IP: DHCP support (NEW)
  
File systems --->
  Network File Systems  --->
    <*> file system support 
    [*]   Provide NFSv3 client support
    [*]   Root file system on NFS
Un'alternativa all'uso di un server dhcp è la creazione di un server BOOTP. E' importante che i driver della scheda di rete siano compilati staticamente (e non come un modulo) all'interno del kernel degli slave. Ad ogni modo l'uso dei moduli generalmente non dovrebbe rappresentare un problema.

Ora non resta altro che compilare il kernel dello slave. In questa fase è opportuno prestare molta attenzione controllando che non siano sovrascritti e/o eliminati i moduli compilati precedentemente per il master (sempre se presenti).

# cd /usr/src/linux
# make

Ora creare una directory sul master per contenere i file si sistema richiesti dallo slave. E' possibile scegliere il percorso che si preferisce, ad esempio questo: /diskless. Ora copiare il file bzImage dello slave all'interno della directory /diskless:

Nel caso in cui si stia lavorando con architetture differenti potrebbe essere utile salvare ogni file di configurazione del kernel come .config_arch. Fare la medesima cosa con le immagini del kernel: salvarle all'interno di /diskless come bzImage_arch.
# mkdir /diskless
# cp /usr/src/linux/arch/i386/boot/bzImage /diskless
Configurare il file system iniziale dello slave

Il file system del master e dello slave possono essere modificati a proprio piacimento, al momento è interessante avere un file system iniziale con le giuste configurazioni ed i punti di mount esatti. Per prima cosa è necessario creare all'interno di /diskless una directory per la prima postazione slave. Ogni slave ha bisogno della sua directory di root (/) riservata, infatti la condivisione di alcuni file di sistema potrebbe causare problemi con i permessi e soprattutto gravi crash. E' possibile chiamare queste directory come si preferisce ma, per motivi pratici, è consigliabile usare l'indirizzo ip dello slave (dato che essi sono unici e non danno luogo a confusioni). Per esempio, nel caso in cui il primo slave avesse il seguente ip 192.168.1.21:

# mkdir /diskless/192.168.1.21

Molti file presenti in /etc devono essere modificati per potere funzionare sullo slave. Copiare la directory /etc del master all'interno della directory di root dello slave:

# cp -r /etc /diskless/192.168.1.21/etc

Il filesystem non è ancora pronto, ci sono ancora da creare diversi punti di mount e directory. Per crearli digitare:

# mkdir /diskless/192.168.1.21/home
# mkdir /diskless/192.168.1.21/dev
# mkdir /diskless/192.168.1.21/proc
# mkdir /diskless/192.168.1.21/tmp
# mkdir /diskless/192.168.1.21/mnt
# chmod a+w /diskless/192.168.1.21/tmp
# mkdir /diskless/192.168.1.21/mnt/.initd
# mkdir /diskless/192.168.1.21/root
# mkdir /diskless/192.168.1.21/sys
# mkdir /diskless/192.168.1.21/var
# mkdir /diskless/192.168.1.21/var/empty
# mkdir /diskless/192.168.1.21/var/lock
# mkdir /diskless/192.168.1.21/var/log
# mkdir /diskless/192.168.1.21/var/run
# mkdir /diskless/192.168.1.21/var/spool
# mkdir /diskless/192.168.1.21/usr
# mkdir /diskless/192.168.1.21/opt
(solo per openMosix)
# mkdir /diskless/192.168.1.21/mfs

La maggior parte delle directory create precedentemente dovrebbero essere familiari. Directory quali /dev o /proc vengono popolate all'avvio dello slave, le restanti sono montate in seguito. E' necessario anche editare il file /diskless/192.168.1.21/etc/conf.d/hostname per riflettere l'hostname dello slave. I file binario, le librerie ed i restanti file vengono inseriti più avanti, prima dell'avvio dello slave.

Anche se la directory /dev sarà popolata successivamente da udev, è comunque necessario creare il device console. Altrimenti si avrà il messaggio d'errore: "unable to open initial console".

  # mknod /diskless/192.168.1.21/dev/console c 5 1
Configurazione del server DHCP
A proposito del server DHCP

La sigla DHCP significa: Dynamic Host Configuration Protocol. Il server DHCP è il primo computer con cui gli slave comunicano all'avvio. Lo scopo principale del server DHCP è l'assegnazione degli indirizzi IP. Volendo, il server DHCP può assegnare gli indirizzi IP in base all'indirizzo MAC della scheda di rete dello slave. Non appena lo slave ottiene un indirizzo IP il server DHCP gli fornisce le indicazioni su dove trovare il suo file system iniziale ed il suo kernel.

Prima di iniziare

Prima di iniziare è meglio controllare il funzionamento di alcune cose. Per prima cosa controlliamo la connessione di rete:

# ifconfig eth0 multicast
# ifconfig -a

E' opportuno controllare che il dispositivo eth0 sia funzionante. Dovrebbe apparire circa così:

eth0      Link encap:Ethernet  HWaddr 00:E0:83:16:2F:D6
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:26460491 errors:0 dropped:0 overruns:2 frame:0
          TX packets:32903198 errors:0 dropped:0 overruns:0 carrier:1
          collisions:0 txqueuelen:100
          RX bytes:2483502568 (2368.4 Mb)  TX bytes:1411984950 (1346.5 Mb)
          Interrupt:18 Base address:0x1800

E' importante che appaia la voce MULTICAST, se non compare è necessario ricompilare il proprio kernel attivando il supporto a multicast.

Installazione del server DHCP

Se la rete non ha ancora un server DHCP è necessario crearne uno:

# emerge dhcp

Invece se la rete ha già un server DHCP non c'è da fare altro che configurarlo in maniera da supportare il protocollo PXE.

Configurazione del server DHCP

Dovrete modificare solamente il file /etc/dhcp/dhcpd.conf prima d'avviare il vostro server. Potete semplicemente copiare il file di configurazione d'esempio, modificandolo in seguito:

# cp /etc/dhcp/dhcpd.conf.sample /etc/dhcp/dhcpd.conf
# nano -w /etc/dhcp/dhcpd.conf

Si tratta di un file indentato che dovrebbe apparire così:

# opzioni globali
ddns-update-style none;
shared-network LOCAL-NET {
# opzioni di rete condivise
subnet 192.168.1.0 netmask 255.255.255.0 {
    # opzioni relative alle varie subnet
    host slave{
        # opzioni relative ad uno specifico host
    }
    group {
        # opzioni relative ad un determinato gruppo
    }
}
}

Il blocco d'opzioni di rete condivise è facoltativo e dovrebbe essere usato per tutti gli IP che si desidera assegnare alla stessa tipologia di rete. Si deve dichiarare almeno una subnet, mentre il blocco d'opzioni relativo al gruppo è opzionale e consente di raggruppare le opzioni tra i vari elementi. Un buon esempio per il file dhcpd.conf è questo:

# DHCP configuration file for DHCP ISC 3.0
 
ddns-update-style none;
 

# Definizione delle opzioni relative a PXE
# Code 1: Indirizzo IP multicast del server di boot
# Code 2: Porta UDP che il client dovrebbe monitorare per le risposte MTFTP
# Code 3: Porta UDP su cui il server MTFTP è in attesa delle richieste MTFTP
# Code 4: Numero di secondi di inattività prima che il client inizi un nuovo trasferimento MTFTP
# Code 5: Numero di secondi di inattività prima che il client provi a riavviare un trasferimento MTFTP
 
option space PXE;
option PXE.mtftp-ip               code 1 = ip-address;
option PXE.mtftp-cport            code 2 = unsigned integer 16;
option PXE.mtftp-sport            code 3 = unsigned integer 16;
option PXE.mtftp-tmout            code 4 = unsigned integer 8;
option PXE.mtftp-delay            code 5 = unsigned integer 8;
option PXE.discovery-control      code 6 = unsigned integer 8;
option PXE.discovery-mcast-addr   code 7 = ip-address;
 
subnet 192.168.1.0 netmask 255.255.255.0 {
 
  
  class "pxeclients" {
    match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
    option vendor-class-identifier "PXEClient";
    vendor-option-space PXE;
 
    # Deve essere indicata almeno una delle opzioni PXE relative alla propria scheda di rete, solo così
    # le schede dei client capiscono che c'è un server compatibile PXE. E' necessario mettere il
    # valore 0.0.0.0 alla variabile MCAST IP, in questo modo i client capiscono che non c'è un
    # server TFPT multicast (il valore 0.0.0.0 indica l'assenza dell'host).
     
    option PXE.mtftp-ip 0.0.0.0;
 
    # Questo è il nome del file che la scheda di rete del client deve scaricare.
    filename "pxelinux.0";
    # Questo è l'indirizzo del server presso il quale è possibile scaricare il file.
    # Utilizzare l'indirizzo IP del master
    next-server 192.168.1.1;
  }

  # Se si sta utilizzando etherboot senza una specifica immagine
  class "etherboot" {
        if substring (option vendor-class-identifier, 0, 9) = "Etherboot" {
        filename "/diskless/vmlinuz";
        }
  }
  
  pool {
    max-lease-time 86400;
    default-lease-time 86400;
    # Questa opzione evita che dei pc non autorizzati ottengano un IP
    deny unknown clients;
  }
 
  host slave21 {
       # Utilizzare l'indirizzo MAC dello slave
       hardware ethernet                00:40:63:C2:CA:C9;
       # Fornire allo slave un indirizzo IP statico
       fixed-address                    192.168.1.21;
       server-name                      "master";
       # Se necessario indicare l'indirizzo IP del vostro gateway
       option routers                   192.168.1.1;
       # Se necessario indicare l'indirizzo IP del vostro server DNS
       option domain-name-servers       192.168.1.1;
       option domain-name               "mydomain.com";
       # Utilizzare l'hostname dello slave
       option host-name                 "slave21";
       
       
       # Etherboot e pxe eseguono l'avvio con una specifica immagine
       option root-path                 "/diskless/192.168.1.21";
       
       if substring (option vendor-class-identifier, 0, 9) = "Etherboot" {
                        filename "/vmlinuz_arch";
        } else if substring (option vendor-class-identifier, 0,9) ="PXEClient" {
                        filename "/pxelinux.0";
        }
                                                               
  }
}
Nulla impedisce di utilizzare insieme l'avvio tramite PXE e quello tramite Etherboot. Il codice illustrato precedentemente è soltanto un esempio. Nel caso incontriate problemi è raccomandata la consultazione della documentazione di DHCPd.

L'indirizzo IP in indicato dopo la voce next-server sarà richiesto nel file indicato alla voce filename Questo indirizzo IP dovrebbe essere quello del server tftp, che solitamente è in esecuzione sul master. Il nome del file indicato nella vece filename ha come percorso relativo /diskless (questo dipende dalle impostazioni relative al server tftp, impostazioni che analizzeremo successivamente). All'interno del blocco di opzioni della voce host alla voce hardware ethernet si specifica un indirizzo MAC, alla voce fixed-address si indica un indirizzo IP da assegnare staticamente all'indirizzo MAC indicato in precedenza. E' consigliabile fare uso anche della voce host-name, la quale non indica altro che l'hostname di un particolare slave. Per ulteriori informazioni è consigliabile la lettura dell'ottima pagina man di dhcpd.conf, ci sono infatti molte altre opzioni che vanno oltre gli scopi di questa guida. E' possibile leggere la pagina man digitando:

# man dhcpd.conf
Avviare il server DHCP

Prima di lanciare lo script d'avvio del server dhcp modificare il file /etc/conf.d/dhcp in maniera che assomigli a questo:

IFACE="eth0"
# inserire altre eventuali opzioni

La variabile IFACE corrisponde al dispositivo di rete su cui il server DHCP resta in ascolto, in questo caso eth0. Nel caso di complesse tipologie di rete, con più dispositivi di rete, potrebbe essere necessario aggiungere più valori alla variabile IFACE. Per avviare il server dhcp digitare:

# /etc/init.d/dhcp start

Per avviare il server dhcp fin dall'avvio del master digitare:

# rc-update add dhcp default
Possibili problemi con il server DHCP

E' possibile verificare l'avvio di una postazione remota leggendo il file /var/log/syslog.log. Se la postazione esegue con successo la procedura di boot, verso la fine del file messages si dovrebbero avere delle linee come queste:

DHCPDISCOVER from 00:00:00:00:00:00 via eth0
DHCPOFFER on 192.168.1.21 to 00:00:00:00:00:00 via eth0
DHCPREQUEST for 192.168.1.21 from 00:00:00:00:00:00 via eth0
DHCPACK on 192.168.1.21 to 00:00:00:00:00:00 via eth0
Da questo file di log è possibile anche scoprire gli indirizzi MAC degli slave.

Nel caso in cui si ottenga il seguente messaggio esistono degli errori all'interno del file di configurazione, ma il server continua comunque a funzionare correttamente in broadcast.

no free leases on subnet LOCAL-NET

Ogni volta che sono fatte delle modifiche alla configurazione è necessario riavviare il server dhcp. Per riavviarlo digitare:

# /etc/init.d/dhcpd restart
Configurare il server TFTP e l'avvio tramite PXE e/o Etherboot
A proposito del server TFTP

La sigla TFTP significa Trivial File Transfer Protocol. Il server TFTP ha la funzione di fornire agli slave il loro kernel ed il loro filesystem iniziale. Tutti i kernel ed i filesystem degli slave saranno conservati sul server TFTP, è quindi una buona idea avviare il server TFTP sul master.

Installare il server TFTP

E' consigliabile utilizzare l'ebuild tftp-hpa. Si tratta di un'implementazione scritta dall'autore di SYSLINUX che funziona molto bene con PXE. Per installarlo digitare:

# emerge tftp-hpa
Configurare il server TFTP

Modificare il file /etc/conf.d/in.tftpd. All'interno si deve specificare, con la variabile INTFTPD_PATH, il percorso della directory di root del server tftp e, nella variabile INTFTPD_OPTS, le opzioni con cui avviare il server tftp. Il file dovrebbe essere simile a quello riportato di seguito:

INTFTPD_PATH="/diskless"
INTFTPD_OPTS="-l -v -s ${INTFTPD_PATH}"

L'opzione -l indica che il server resta in ascolto senza richiedere l'avvio di inetd. L'opzione -v indica che il server scrive nei file di log molte informazioni in più rispetto al solito. L'opzione -s /diskless specifica la directory di root del vostro server tftp.

Avviare il server TFTP

Per avviare il server tftp digitate:

# /etc/init.d/in.tftpd start

In questo modo il server tftp viene avviato usando le opzioni specificate in /etc/conf.d/in.tftpd. Se si desidera avviare il server tftp ad ogni avvio del master digitate:

# rc-update add in.tftpd default
A proposito di PXELINUX

E' possibile saltare questa sezione se si ha intenzione di utilizzare solamente Etherboot. PXELINUX è un bootloader di rete, equivalente a LILO o GRUB, che fa uso di un server TFTP. Sostanzialmente è un insieme di istruzioni che spiegano al pc dove reperire il proprio kernel ed il proprio filesystem. Come tutti i bootloader anche PXELINUX permette il passaggio di parametri all'avvio del kernel.

Prima di iniziare

E' necessario procurarsi il file pxelinux.0 che è contenuto nel pacchetto SYSLINUX (il cui autore è H. Peter Anvin). E' possibile installare questo pacchetto digitando:

# emerge syslinux
Configurare PXELINUX Non è richiesto Etherboot

Prima d'avviare il server tftp si deve configurare pxelinux. Per prima cosa copiare il binario di pxelinux all'interno della directory /diskless:

# cp /usr/lib/syslinux/pxelinux.0 /diskless
# mkdir /diskless/pxelinux.cfg
# touch /diskless/pxelinux.cfg/default

Questo crea una configurazione di default per il bootloader. L'eseguibile pxelinux.0 andrà a cercare, all'interno della directory in cui è contenuto il file pxelinux.cfg, un file il cui nome sia l'equivalente in esadecimale dell'indirizzo IP del client. Nel caso in cui non trovi il file allora ne cerca un altro il cui nome è identico al precedente, senza però l'ultimo gruppo di numeri sulla destra (i numeri sono separati tra di loro da un punto); continua a ripetere questa operazione fino a quando non ci sono più punti all'interno del nome del file da cercare. A partire dalla versione 2.05 syslinux per prima cosa cerca un file il cui nome deriva dall'indirizzo mac. Se non è trovato nessun file allora è eseguita la procedura di scoperta descritta precedentemente. Se non è trovato nessun file allora è usato il file default.

(Lo 01 iniziale indica un'interfaccia Ethernet, i byte successivi coincidono con l'indirizzo MAC dello slave.
01-00-40-63-c2-ca-c9

(IP assegnati in esadecimale)
C0A80115
C0A8011
C0A801
C0A80
C0A8
C0A
C0
C

default
Tutti i caratteri sono minuscoli.

Si analizzi ora il file default:

DEFAULT /bzImage
APPEND ip=dhcp root=/dev/nfs nfsroot=192.168.1.1:/diskless/192.168.1.21

Alla variabile DEFAULT corrisponde il percorso completo dell'immagine del kernel compilata precedentemente per lo slave. Nella variabile APPEND sono specificati gli argomenti da passare al kernel al momento del caricamento. Dato che è stato compilato il kernel dello slave con il supporto a NFS_ROOT_SUPPORT, allora qui si specifica il percorso del file system remoto. Il primo IP è quello del master, mentre il secondo è la directory creata all'interno di /diskless per contenere il file system iniziale dello slave.

A proposito di Etherboot E' possibile evitare l'uso di Etherboot se si ha intenzione di usare PXE.

Etherboot carica l'immagine del kernel da un server TFTP. Così come PXE, anche Etherboot è equivalente a LILO o GRUB. Il programma mknbi permette di creare varie immagini d'avvio.

Prima di iniziare

E' necessario installare il pacchetto mknbi, al suo interno si trova tutto il necessario per creare immagini del kernel utili per il boot da remoto. Questo programma crea un'immagine del kernel preconfigurata a partire dal kernel originale.

# emerge mknbi
Configurare Etherboot

In questa sezione si crea una semplice immagine d'avvio di etherboot. Dato che il server dhcp fornisce ai client il percorso della loro directory di root (è stata specificata all'interno del dhcp.conf con l'opzione option root-path) in questo momento non si deve indicarla. Per ulteriori informazioni è consigliabile la lettura della man page di mknbi:

# man mknbi

Si procede ora alla creazione delle immagini d'avvio. In questa fase si creano delle immagini d'avvio in ELF in grado di fornire al kernel le informazioni relative al dhcp ed al percorso del filesystem remoto; inoltre si forza il kernel a cercare nella rete un server dhcp.

# mkelf-linux -ip=dhcp /diskless/bzImage > /diskless/vmlinuz 
Per le immagini relative ad una determinata architettura è necessario specificare bzImage_arch e vmlinuz_arch.
Problemi comuni con l'avvio tramite rete

Ci sono un paio di modi per individuare gli errori che si verificano durante la fase d'avvio remoto. Per prima cosa è possibile utilizzare un programma chiamato tcpdump. Per installarlo digitare:

# emerge tcpdump

Ora è possibile controllare il traffico della vostra rete, accertandosi che le iterazioni client/server funzionino a dovere. Se non si riesce a vedere il traffico tra i due host dovete controllare un paio di cose. Per primo verificare che i due host siano collegati fisicamente in maniera corretta, e che il cavo di rete non sia danneggiato. Se il client/server non riceve le richieste destinate ad una certa porta allora verificare la presenza di eventuali firewall e la loro configurazione. Per leggere il traffico tra due pc digitare:

# tcpdump host client_ip and server_ip

E' possibile utilizzare tcpdump per visualizzare il traffico relativo ad una particolare porta. Per ascoltare il traffico sulla porta di tftp digitare:

# tcpdump port 69

Un errore molto comune è il seguente: "PXE-E32: TFTP open time-out". Solitamente è dovuto alle regole di alcuni firewall. Se si sta usando TCPwrappers vi consigliamo di controllare i file /etc/hosts.allow e etc/hosts.deny controllando che siano impostati correttamente. Ricordare che al client dove essere consentito di connettersi al server.

Configurare il server NFS
A proposito del server NFS

NFS significa Network File System. Il server NFS viene utilizzato per fornire lo spazio di lavoro agli slave. Il server NFS può essere configurato in vari modi, ma questi esulano dagli intenti di questa guida.

A proposito di Portmapper

Molti servizi dei client e dei server non sono in ascolto su una determinata porta, ma si affidano alle RPCs (Remote Procedure Calls). Quando il servizio è inizializzato si mette in ascolto su una porta a caso e poi registra questa porta tramite l'uso di Portmapper. NFS si affida alle RPCs e pertanto Portmapper deve essere in esecuzione prima del suo avvio.

Prima di iniziare

Il server NFS richiede delle opzioni abilitate all'interno del kernel, nel caso non siano selezionate è necessario ricompilare il kernel del master. Per controllare rapidamente la selezione di queste opzioni digitare:

# grep NFS /usr/src/linux/.config_master

Se il kernel è stato configurato correttamente si dovrebbe avere un risultato simile al seguente:

CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
# CONFIG_NETFILTER is not set
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V4 is not set
# CONFIG_NFSD_TCP is not set
Installare il server NFS

Per installare il pacchetto contenente i programmi di NFS digitare:

# emerge nfs-utils

Questo pacchetto installa i programmi richiesti per un corretto funzionamento di NFS, preoccupandosi di risolvere tutte le loro dipendenze.

Configurare il server NFS

I principali file da configurare sono:

/etc/exports
/diskless/192.168.1.21/etc/fstab
/etc/conf.d/nfs

All'interno del file /etc/exports sono specificate le directory da condividere, come condividerle e a chi condividerle. Il file fstab dello slave viene modificato in maniera tale da montare il filesystem che il master condivide.

Una configurazione tipica del file /etc/exports del master dovrebbe apparire così:

# aggiungete un linea come questa per ogni slave
/diskless/192.168.1.21   192.168.1.21(sync,rw,no_root_squash,no_all_squash)
# comune a tutti gli slave
/opt   192.168.1.0/24(sync,ro,no_root_squash,no_all_squash)
/usr   192.168.1.0/24(sync,ro,no_root_squash,no_all_squash)
/home  192.168.1.0/24(sync,rw,no_root_squash,no_all_squash)
# se si desidera avere dei log comuni
/var/log   192.168.1.21(sync,rw,no_root_squash,no_all_squash)

Il primo campo indica la directory da esportare, quello successivo indica a chi e come condividerla.. Il secondo campo può essere diviso in due parti: nella prima si indica chi può accedere alla condivisione, nel secondo campo si indicano i suoi permessi sulla directory. I permessi possono essere di sola lettura(ro), lettura e scrittura (rw). Gli attributi no_root_squash e no_all_squash sono importanti per le nostre postazioni remote in quanto evitano crash e perdite di dati durante le operazioni di lettura e scrittura. Il file /diskless/192.168.1.21/etc/fstab dello slave dovrebbe essere simile al seguente:

# queste voci sono essenziali
master:/diskless/192.168.1.21   /         nfs     sync,hard,intr,rw,nolock,rsize=8192,wsize=8192    0 0
master:/opt                     /opt      nfs     sync,hard,intr,ro,nolock,rsize=8192,wsize=8192    0 0
master:/usr                     /usr      nfs     sync,hard,intr,ro,nolock,rsize=8192,wsize=8192    0 0
master:/home                    /home     nfs     sync,hard,intr,rw,nolock,rsize=8192,wsize=8192    0 0
none                            /proc     proc    defaults                                     0 0
# voci utili ma opzionali
master:/var/log                 /var/log  nfs     hard,intr,rw                                 0 0

(solo se si sta configurando un cluster openMosix)
none                            /mfs      mfs     dfsa=1                                       0 0

Nell'esempio la variabile master è semplicemente l'hostname del master, oppure il suo indirizzo IP. Il primo campo indica la directory che deve essere montata, il secondo campo indica il punto in cui montarla. Il terzo campo indica il filesystem da utilizzare, questo deve essere NFS per ogni punto di mount NFS. Il quarto campo indica varie opzioni che saranno usate durante il mount (per approfondimenti consultare le pagine man di mount(1)). Molti utenti hanno riscontrato difficoltà usando dei punti di mount soft, pertanto sono stati usati solo punti di mount hard. Per ottimizzare il vostro sistema si consiglia di leggere le varie opzioni applicabili a /etc/fstab.

L'ultimo file da modificare è /etc/conf.d/nfs. In questo file sono specificate alcune opzioni che sono usate all'avvio di nfs. Dovrebbe essere simile al seguente:

# Config file for /etc/init.d/nfs

# Number of servers to be started up by default
RPCNFSDCOUNT=8

# Options to pass to rpc.mountd
RPCMOUNTDOPTS=""

E' necessario cambiare il parametro RPCNFSDCOUNT inserendo il numero di postazioni remote che sono presenti nella propria rete.

Avviare il server NFS

Per avviare il server nfs utilizzare lo script situato in /etc/init.d. Basta digitare:

# /etc/init.d/nfs start

Per avviare il server nfs all'avvio del master digitare:

# rc-update add nfs default
Completare il filesystem dello slave
Copiare i file mancanti

A questo punto è possibile sincronizzare il filesytem dello slave con quello del master fornendo i binari necessari, ma mantendo i file propri dello slave.

# rsync -avz /bin /diskless/192.168.1.21
# rsync -avz /sbin /diskless/192.168.1.21
# rsync -avz /lib /diskless/192.168.1.21
E' stato usato il comando rsync -avz al posto di cp per mantenere i collegamenti simbolici ed i permessi dei file copiati.
Script di inizializzazione

Gli script di base cercano di lanciare checkroot, ciò ovviamente non ha alcun senso per il slave. Per risolvere questo problema è possibile modificare lo script di avvio /diskless/192.168.1.21/sbin/rc, questa però è una soluzione pericolosa e molto difficile; inoltre dopo ogni sincronizzazione del filesystem dello slave sarebbe necessario ripetere questa operazione. Esiste però un trucco: avere un file /fastboot all'avvio del proprio sistema. Questo file indica a checkroot di non compiere alcun controllo all'avvio. Purtroppo checkroot cancella il file /fastboot al termine della procedura d'avvio, si deve quindi ricreare questo file prima dello spegnimento/riavvio dello slave. Basta digitare i seguenti comandi:

(Si crea il file /fastboot per il prossimo avvio)
# touch /diskless/192.168.1.21/fastboot
(Si crea il file /fastboot ad ogni avvio)
# echo "touch /fastboot" >> /diskless/192.168.1.21/etc/conf.d/local.start

Dato che i filesystem remoti devono essere smontati il più tardi possibile bisogna modificare il file /etc/init.d/netmount nel seguente modo:

  depend() {
  before *
La versione 1.11.* e successive di baselayout non necessitano di questa modifica.

Se si sta usando un file system live, non bisogna dimenticarsi di eseguire depscan.sh per risolvere le dipendenze dei servizi. Si possono ignorare tranquillamente gli eventuali messaggi d'avvertimento relativi alle collisioni con /etc/init.d/checkroot. Questo è possibile perchè checkroot è disabilitato dal file fastboot creato nel paragrafo precedente.

A questo punto si è liberi d'aggiungere tutti gli script d'avvio che si desidera all'interno di /diskless/192.168.1.21/etc/runlevels; aggiungere tutti quelli che si desidera che siano avviati sulla propria postazione remota.

NON utilizzare il comando rc-update per rimuovere o aggiungere gli script dal runlevel dello slave mentre si è collegati sul master. Infatti questo provocherebbe un cambiamento al runlevel del master e non dello slave. Si deve creare i collegamenti a mano, oppure collegarsi allo slave fisicamente (tramite tastiera e monitor) oppure da remoto (per esempio tramite ssh).
/diskless/192.168.1.21/etc/runlevels/:
total 16
drwxr-xr-x    2 root     root         4096 2003-11-09 15:27 boot
drwxr-xr-x    2 root     root         4096 2003-10-01 21:10 default
drwxr-xr-x    2 root     root         4096 2003-03-13 19:05 nonetwork
drwxr-xr-x    2 root     root         4096 2003-02-23 12:26 single
 
/diskless/192.168.1.21/etc/runlevels/boot:
total 0
lrwxrwxrwx    1 root     root           20 2003-10-18 17:28 bootmisc -> /etc/init.d/bootmisc
lrwxrwxrwx    1 root     root           19 2003-10-18 17:28 checkfs -> /etc/init.d/checkfs
lrwxrwxrwx    1 root     root           17 2003-10-18 17:28 clock -> /etc/init.d/clock
lrwxrwxrwx    1 root     root           22 2003-10-18 17:28 domainname -> /etc/init.d/domainname
lrwxrwxrwx    1 root     root           20 2003-10-18 17:28 hostname -> /etc/init.d/hostname
lrwxrwxrwx    1 root     root           22 2003-10-18 17:28 localmount -> /etc/init.d/localmount
lrwxrwxrwx    1 root     root           19 2003-10-18 17:28 modules -> /etc/init.d/modules
lrwxrwxrwx    1 root     root           18 2003-10-18 17:28 net.lo -> /etc/init.d/net.lo
lrwxrwxrwx    1 root     root           20 2003-10-18 17:28 netmount -> /etc/init.d/netmount
lrwxrwxrwx    1 root     root           21 2003-10-18 17:28 rmnologin -> /etc/init.d/rmnologin
lrwxrwxrwx    1 root     root           19 2003-10-18 17:28 urandom -> /etc/init.d/urandom
 
/diskless/192.168.1.21/etc/runlevels/default:
total 0
lrwxrwxrwx    1 root     root           23 2003-10-18 17:28 consolefont -> /etc/init.d/consolefont
lrwxrwxrwx    1 root     root           19 2003-10-18 17:28 distccd -> /etc/init.d/distccd
lrwxrwxrwx    1 root     root           19 2003-10-18 17:28 keymaps -> /etc/init.d/keymaps
lrwxrwxrwx    1 root     root           17 2003-10-18 17:28 local -> /etc/init.d/local
lrwxrwxrwx    1 root     root           16 2003-10-18 17:28 sshd -> /etc/init.d/sshd
lrwxrwxrwx    1 root     root           21 2003-10-18 17:28 syslog-ng -> /etc/init.d/syslog-ng
lrwxrwxrwx    1 root     root           17 2003-10-18 17:28 vixie-cron -> /etc/init.d/vixie-cron
 
/diskless/192.168.1.21/etc/runlevels/nonetwork:
total 0
lrwxrwxrwx    1 root     root           17 2003-10-18 17:28 local -> /etc/init.d/local
 
/diskless/192.168.1.21/etc/runlevels/single:
total 0

Questa è la fine, è ora di avviare il proprio slave. In bocca al lupo!