venerdì 24 aprile 2009

OpenSolaris snv_111a

E questa mattina siamo arrivati alla build 111a di OpenSolaris! Si tratta di un "affinamento" della già conosciuta build 111 e che porterà nel giro di poco tempo (speriamo) alla release 2009.06, prevista come dice il nome per giugno.

Ovviamente questa build appartiene ancora al branch developer, quindi ancora non è garantita una piena stabilità (in poche parole... aggiornate a vostro rischio e pericolo!!!); per aggiornare potete usare Update Manager (dal menu System - Administration) oppure da linea di comando con il solito:
$ pfexec pkg image-update --be-name opensolaris-111a

noterete che ho aggiunto l'opzione --be-name utile per scegliere il nome da assegnare al nuovo boot environment che pkg andrà a creare.
Terminato l'aggiornamento possiamo riavviare e cominciare a testare!

[caption id="attachment_270" align="aligncenter" width="150" caption="OpenSolaris 2009.06"]OpenSolaris 2009.06[/caption]

giovedì 23 aprile 2009

Aggiungere dischi ai mirror di ZFS

Come già detto nei precedenti post inerenti ZFS è un filesystem "nato sicuro", ovvero per sua natura abbiamo la massima garanzia di affidabilità per quello che riguarda le memorizzazioni su disco; tuttavia se veramente vogliamo dormire sonni tranquilli e sfruttare tutte le features di sicurezza di ZFS è consigliabile fornire più di un disco al sistema in modo che si possa quantomeno implementare un mirroring dei dati (sistema minimo di ridondanza).

Se al momento dell'installazione di OpenSolaris (o dell'ultima release di Solaris 10) avevate a disposizione un solo disco ZFS creerà in automatico un mirror "zoppo", finchè non gli fornirete il secondo disco, se avete un disco nuovo nuovo basterà digitare:
# zpool attach -f rpool c0t0d0s0 c0t1d0s0

dove rpool è il nome del vostro pool, seguito dal device del vecchio disco e da quello del nuovo. Se invece il disco che andate ad aggiungere non è nuovo (magari proviene da una vecchia macchina o contiene una versione di Solaris che andate ad aggiornare) riceverete un bel messaggio di errore:
# zpool attach -f rpool c0t0d0s0 c0t1d0s0
cannot attach c0t1d0s0 to c0t0d0s0: device is too small

questo perchè con molta probabilità il vostro disco contiene già una label in formato EFI e questo tipo di label non "copre" totalmente la dimensione del disco, quindi occorrerà passare al formato SMI, per fare questo useremo il comando format (ho evidenziato in grassetto le scelte effettuate):
# format -e
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0. c0t0d0 <DEFAULT cyl 8921 alt 2 hd 255 sec 63>
          /pci@0,0/pci8086,25f8@4/pci1000,3150@0/sd@0,0
       1. c0t1d0 <DEFAULT cyl 8915 alt 2 hd 255 sec 63>
          /pci@0,0/pci8086,25f8@4/pci1000,3150@0/sd@1,0
Specify disk (enter its number): 1
selecting c0t1d0
[disk formatted]

FORMAT MENU:
        disk       - select a disk
        type       - select (define) a disk type
        partition  - select (define) a partition table
        current    - describe the current disk
        format     - format and analyze the disk
        fdisk      - run the fdisk program
        repair     - repair a defective sector
        label      - write label to the disk
        analyze    - surface analysis
        defect     - defect list management
        backup     - search for backup labels
        verify     - read and display labels
        save       - save new disk/partition definitions
        inquiry    - show vendor, product and revision
        scsi       - independent SCSI mode selects
        cache      - enable, disable or query SCSI disk cache
        volname    - set 8-character volume name
        !<cmd>     - execute <cmd>, then return
        quit
format> label
[0] SMI Label
[1] EFI Label
Specify Label type[0]: 0
Ready to label disk, continue? y

format> quit
#

fatto questo potremo ripetere il comando di attach e in automatico ZFS comincerà il resilvering del disco in modo da sincronizzare i dati.
# zpool status
pool: rpool
state: ONLINE
scrub: resilver completed after 0h11m with 0 errors on Thu Apr 23 15:09:22 2009
config:

NAME          STATE     READ WRITE CKSUM
rpool         ONLINE       0     0     0
mirror      ONLINE       0     0     0
c0t0d0s0  ONLINE       0     0     0
c0t1d0s0  ONLINE       0     0     0

errors: No known data errors

C'è da aggiungere una piccola nota, alcune volte è necessario cancellare tutte le vecchie partizioni presenti sul disco prima di cambiare il formato delle label, basta entrare nel sottomenu fdisk e rimuovere tutte le partizioni e poi ripetere le operazioni viste prima.

I servizi di OpenSolaris (SMF) parte #2

Nella precedente puntata abbiamo visto rapidamente come creare un nuovo SMF, oggi cercheremo di approfondire alcuni aspetti riprendendo sempre il manifesto creato come esempio.

Per quello che riguarda il prologo del nostro manifesto è possibile andare a definire alcune tipologie differenti rispetto a quelle utilizzate; per il tag service_bundle è possibile indicare:

  • type='manifest' (il nostro caso) indichiamo che stiamo descrivendo un servizio vero e proprio

  • type='profile' indica che stiamo descrivendo un profilo (simile ad una collezione di servizi)


per il tag service possiamo avere tre tipologie differenti:

  • type='service' indica un servizio vero e proprio

  • type='restarter' definisce un servizio "speciale" che si occupa di controllare lo status (partenza/arresto e riavvio) di una sottocategoria di servizi, di default viene usato svc.startd ma ad esempio per i servizi di rete viene usato come restarter inetd

  • type='milestone' rappresenta un servizio che in realtà aggrega più servizi e proprietà, sono a tutti gli effetti paragonabili con i "vecchi" runlevel (ad esempio in runlevel 3 corrisponde alla milestone milestone/multi-user-server:default)


Passando invece alle dipendenze (tag dependency) possiamo innanzi tutto definire la tipologia di dipendenze:

  • type='service' in questo caso andremo a descrivere una o più dipendenze da altri servizi

  • type='path' così indicheremo la dipendenza da uno o più file presenti nel sistema, attualmente viene controllata solo l'esistenza del file ma non vengono monitorati eventuali cambiamenti o cancellazioni


successivamente possiamo indicare il grado di dipendenza dai servizi (o dai file) con la proprietà grouping:

  • grouping='require_any' occorre che almeno un servizio tra quelli elencati sia online per far partire il nostro (oppure deve essere presente almeno un file)

  • grouping='require_all' tutti i servizi indicati devono essere online prima che possa partire il nostro (oppure tutti i file devono essere presenti)

  • grouping='optional_all' tutti i servizi devono essere online oppure possono essere anche in offline purchè questa disabilitazione non sia stata espressamente settata dall'operatore

  • grouping='exclude_all' tutti i servizi elencati devono essere offline (oppure i file indicati non devono esistere)


Infine possiamo decidere il legame tra il nostro servizio e le sue dipendenze nel caso in cui queste ultime subiscano delle variazioni, in particolare:

  • restart_on='none' ignora errori o cambiamenti di stato della dipendenza

  • restart_on='restart' il nostro servizio viene riavviato al riavviarsi della dipendenza

  • restart_on='refresh' se il servizio da cui dipendiamo subisce un refresh

  • restart_on='error' in caso errore di una (o più dipendenze) il nostro servizio verrà riavviato.


Termina qui questa seconda parte di approfondimento, la prossima volta analizzeremo nel dettaglio le proprietà e i metodi di esecuzione dei nostri servizi.

sabato 18 aprile 2009

I servizi di OpenSolaris (SMF) parte #1

Era da tempo che volevo parlare di questa interessantissima caratteristica di OpenSolaris (ma presente anche in Solaris 10): i Service Management Facility. Grazie agli SMF il sistema è in grado di gestire l'avvio di tutti i servizi al momento del boot, il loro corretto arresto in fase di shutdown ed anche la loro ripartenza in caso di problemi.
Quest'ultima caratteristica rende gli SMF unici ma non è la sola a rappresentare un punto di vantaggio al sistema, infatti nel descrittore dei servizi è possibile definire una serie di dipendenze che legano tra di loro i servizi stessi. Indicheremo ad esempio da quali servizi dipende un nostro servizio, quindi essi precederanno il nostro nella fase di avvio, oppure il nostro servizio non potrà essere avviato se prima non verranno fatte partire le sue dipendenze.

Visto che in questi giorni mi sono cimentato nella realizzazione di un SMF per gestire il Sun Java System Web Server 7 che usiamo qui in azienda vorrei condividere con coi questa esperienza, analizzando passo passo le varie sezioni che costituiscono il servizio.

Il servizio SMF viene descritto tramite un file XML (il manifesto), come punto di partenza potete analizzare e prendere spunto da quelli forniti di base con OpenSolaris, memorizzati in /var/svc/manifest/, ecco come è composto il mio:
<?xml version="1.0"?>
<!DOCTYPE service_bundle
SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='webserver7'>
<service
name='network/webserver7'
type='service'
version='1'>
<single_instance />

questa prima parte è puramente descrittiva, dove scegliamo un nome per il nostro "manifesto" (io ho scelto webserver7) e il nome che andrà ad identificare in maniera univoca il nostro servizio nel sistema (il nome "parziale" sarà svc:/network/webserver7 a cui successivamente aggiungeremo le varie istanze), questo identificatore univoco lo troverete spesso indicato nella documentazione e nelle man pages con la sigla FMRI (ovvero Fault Management Resource Identifier).
<dependency
name='multi-user-server'
grouping='optional_all'
type='service'
restart_on='none'>
<service_fmri value='svc:/milestone/multi-user-server' />
</dependency>

questa seconda sezione troviamo l'unica dipendenza che ho definito, ovvero che il sistema sia stato avviato in modalità multi-user-server. In realtà è possibile definire meglio le dipendenze, ad esempio avrei potuto mettere due dipendenze di base: il "montaggio" dei dischi locali e la partenza dei servizi di rete, dichiarando inoltre che se quest'ultima venisse riavviata anche il mio servizio doveva essere riavviato.
<exec_method
type='method'
name='start'
exec='/lib/svc/method/webserver %m %i %{webserver/home} %{webserver/user}'
timeout_seconds='60'>
</exec_method>

<exec_method
type='method'
name='restart'
exec='/lib/svc/method/webserver %m %i %{webserver/home} %{webserver/user}'
timeout_seconds='60'>
</exec_method>

<exec_method
type='method'
name='stop'
exec='/lib/svc/method/webserver %m %i %{webserver/home} %{webserver/user}'
timeout_seconds='60'>
</exec_method>

queste tre direttive rapprensentano il cuore del servizio SMF in fase di realizzazione, infatti descrivono come far partire, arrestare o riavviare la nostra applicazione; tutti e tre richiamano lo stesso script di shell (sempre da me sviluppato) passando tre paramenti: il primo (%m) rapprensenta il metodo che si sta eseguendo (start, stop o restart), seguito da %i che rappresenta il nome dell'istanza (che vedremo successivamente) e per concludere due proprietà del servizio webserver/home e webserver/user.
<property_group name="webserver" type="application">
<propval name="home" type="astring" value="/sun/webserver7" override="true"/>
<propval name="user" type="astring" value="webservd" override="true"/>
</property_group>

come anticipato il nostro servizio fa uso di due proprietà passandole allo script di gestione visto prima, grazie ad esse l'utilizzatore potrà personalizzarle secondo la sua specifica installazione (essendo state dichiarate tutte e due con la proprietà ovverride settata su true), comunque vedremo come impostare dei valori differenti successivamente.
<instance name='https-myhost' enabled='false'>
<property_group name="instance" type="application">
<propval name="name" type="astring" value="https-myhost" override="false"/>
</property_group>
</instance>

<instance name='admin-server' enabled='false'>
<property_group name="instance" type="application">
<propval name="name" type="astring" value="admin-server" override="false"/>
</property_group>
</instance>

queste due sezioni praticamente identiche vanno a definire due istanze del nostro servizio, identificandone ognuna con un nome. Grazie a questa caratteristica risulta molto semplice gestire istanze multiple di uno stesso servizio, con la possibilità ad esempio di definire delle proprietà specifiche per ognuna di esse.
  <template>
<common_name>
<loctext xml:lang='C'>WebServer 7</loctext>
</common_name>
</template>
</service>
</service_bundle>

infine indichiamo una breve descrizione del servizio, qui potremmo inserire anche una serie di link o riferimenti a specifiche man page utili per gestire/utilizzare l'applicazione gestita dal servizio.

Conclusa la fase di creazione del nostro file non resta altro da fare che controllare la sua correttezza con il comando:
# svccfg validate webserver.xml

in caso di presenza di errori ci verranno segnalate le linee non corrette, in caso contrario possiamo passare alla fase di importazione del nostro manifesto con il comando:
# svccfg import webserver.xml

quindi controlliamo la presenza nella lista dei servizi del nostro appena creato:
# svcs webserver7
STATE          STIME    FMRI
disabled       Apr_16   svc:/network/webserver7:admin-server
disabled       Apr_16   svc:/network/webserver7:https-myhost

come vedete tutte e due le istanze sono disabilitate in quanto tutte e due, al momento della loro dichiarazione, avevano l'attributo enabled='false', prima di abilitarle controlliamo le loro proprietà con il comando:
# svcprop webserver7:admin-server
instance/name astring admin-server
general/enabled boolean false
general/single_instance boolean true
webserver/home astring /export/home/www/webserver7
webserver/user astring www
multi-user-server/entities fmri svc:/milestone/multi-user-server
multi-user-server/grouping astring optional_all
multi-user-server/restart_on astring none
multi-user-server/type astring service
startd/duration astring transient
start/exec astring /lib/svc/method/webserver\ %m\ %i\ %{webserver/home}\ %{webserver/user}
start/timeout_seconds count 60
start/type astring method
restart/exec astring /lib/svc/method/webserver\ %m\ %i\ %{webserver/home}\ %{webserver/user}
restart/timeout_seconds count 60
restart/type astring method
stop/exec astring /lib/svc/method/webserver\ %m\ %i\ %{webserver/home}\ %{webserver/user}
stop/timeout_seconds count 60
stop/type astring method
tm_common_name/C ustring WebServer\ 7
restarter/start_pid count 11703
restarter/start_method_timestamp time 1239890611.150876000
restarter/start_method_waitstatus integer 0
restarter/logfile astring /var/svc/log/network-webserver7:admin-server.log
restarter/transient_contract count
restarter/auxiliary_state astring none
restarter/next_state astring none
restarter/state astring disabled
restarter/state_timestamp time 1239890652.156404000
restarter_actions/refresh integer
general_ovr/enabled boolean false

noterete che sono presenti anche numerose altre proprietà di default dei servizi (come ad esempio il file di log utilizzato per memorizzare i messaggi generati durante le operazioni di start/stop), in più ho provveduto a personalizzare le due proprietà webserver/home e webserver/user per rispondere alle specifiche della mia installazione, per fare questo basta digitare:
# svccfg -s webserver7 setprop webserver/home=/export/home/www/webserver7
# svccfg -s webserver7 setprop webserver/user=luca

noterete che ho settato le proprietà omettendo volontatiamente la parte di istanza, essendo queste proprietà definite a livello di servizio (quindi hanno valore per tutte le istanze del webserver), a questo punto possiamo far partire la nostra istanza (e rimarrà attiva fino al prossimo reboot):
# svcadm enable -t webserver7:admin-server

mentre per per farla ripartire anche in caso di reboot della macchina basterà digitare:
# svcadm enable webserver7:admin-server

Appuntamento al prossimo post per l'analisi dello script usato dal servizio.