09.01.2015 Views

Prof. Guido Russo - Scope - Università degli Studi di Napoli Federico II

Prof. Guido Russo - Scope - Università degli Studi di Napoli Federico II

Prof. Guido Russo - Scope - Università degli Studi di Napoli Federico II

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Università</strong> <strong>degli</strong> <strong>Stu<strong>di</strong></strong> <strong>di</strong> <strong>Napoli</strong> <strong>Federico</strong> <strong>II</strong><br />

Facoltà <strong>di</strong> Scienze MM.FF.NN.<br />

Corso <strong>di</strong> Laurea in Informatica<br />

Tesi Sperimentale <strong>di</strong> Laurea Triennale<br />

Sviluppo dell'interfaccia utente per la configurazione del<br />

sistema PowerFarm<br />

Relatori Can<strong>di</strong>dato<br />

<strong>Prof</strong>. <strong>Guido</strong> <strong>Russo</strong> Pietro Neroni<br />

Dott.ssa Alessandra Doria (INFN) Matricola: 566/2833<br />

Anno accademico 2008/2009


Ringraziamenti<br />

Al termine <strong>di</strong> questo lavoro <strong>di</strong> tesi, che segna la conclusione del mio percorso <strong>di</strong> stu<strong>di</strong> <strong>di</strong><br />

laurea triennale, mi sento in dovere <strong>di</strong> ringraziare alcune delle persone che hanno con<strong>di</strong>viso<br />

con me tutti i momenti sia felici che <strong>di</strong>fficili vissuti in questi tre anni.<br />

Desidero ringraziare innanzitutto i miei due relatori, il prof. <strong>Guido</strong> <strong>Russo</strong> e la prof.ssa<br />

Alessandra Doria per avermi dato la possibilità <strong>di</strong> realizzare questa tesi e per avermi offerto<br />

tutto il supporto necessario per portare a termine questa esperienza accademica.<br />

Vorrei ringraziare la mia famiglia, mia madre, mio padre e mia sorella, che hanno sempre<br />

creduto nelle mie capacità, regalandomi un grande sostegno morale nonché economico che<br />

mi ha spinto a raggiungere questo importante traguardo.<br />

Ringrazio tutti gli amici del centro S.Co.P.E. per le piacevoli giornate passate insieme, per la<br />

loro simpatia e per essersi <strong>di</strong>mostrate delle persone splen<strong>di</strong>de, sempre pronte ad aiutarti.<br />

Ringrazio i tanti compagni <strong>di</strong> università che vedo tuttora e che non ho più visto per <strong>di</strong>verse<br />

strade intraprese.<br />

Grazie a tutti!


In<strong>di</strong>ce generale<br />

1 INTRODUZIONE.............................................................................................................................1<br />

2 INTRODUZIONE AL CALCOLO IN ATLAS ...............................................................................4<br />

2.1 Il Sito Tier2-<strong>Napoli</strong>...................................................................................................................5<br />

2.1.1 Servizi offerti dal Tier2......................................................................................................6<br />

2.1.2 Collocazione apparati del Tier2 <strong>di</strong> <strong>Napoli</strong>.........................................................................9<br />

3 POWERFARM ...............................................................................................................................14<br />

3.1 Funzionamento Powerfarm.....................................................................................................14<br />

3.2 Architettura Di Powerfarm.......................................................................................................15<br />

3.3 Modulo Principale....................................................................................................................15<br />

3.4 Modulo Per La Gestione Delle Emergenze ...........................................................................16<br />

3.5 Modulo Di Notifica..................................................................................................................17<br />

3.6 Modulo Di Log........................................................................................................................17<br />

3.7 Riga Di Comando E Interfaccia Web.......................................................................................17<br />

3.8 La Gestione Delle Dipendenze ...............................................................................................18<br />

3.9 I Plugin.....................................................................................................................................19<br />

3.9.1 Tecnologie e plugin utilizzati..........................................................................................20<br />

4 I FILE DI CONFIGURAZIONE XML........................................................................................25<br />

5 Gli STRUMENTI UTILIZZATI......................................................................................................30<br />

5.1 JAVA........................................................................................................................................30<br />

5.2 HTML......................................................................................................................................31<br />

5.3 XML.........................................................................................................................................31<br />

5.4 JSP...........................................................................................................................................31<br />

5.5 Javascript.................................................................................................................................32<br />

5.6 Graphviz E Webdot..................................................................................................................32<br />

6 L'OBIETTIVO DELLA TESI: SITO WEBPOWERFARM............................................................35<br />

6.1 Introduzione.............................................................................................................................35<br />

6.2 Diagramma Dei Casi D'uso.....................................................................................................36<br />

6.3 L'architettura ...........................................................................................................................37<br />

6.4 Interfaccia Utente.....................................................................................................................39<br />

6.5 Visualizzazione Del Grafo Delle Dipendenze.........................................................................47<br />

6.6 Inserimento, Mo<strong>di</strong>fica, Eliminazione Di Un Dispositivo........................................................53<br />

6.7 Diagrammi Di Cockburn.........................................................................................................60<br />

6.8 Class Diagram..........................................................................................................................63<br />

6.9 Sequence Diagram...................................................................................................................64<br />

7 VALIDAZIONE E TESTING.........................................................................................................68<br />

8 CONCLUSIONI E SVILUPPI FUTURI.........................................................................................72<br />

9 BIBLIOGRAFIA.............................................................................................................................73<br />

10 APPENDICE.................................................................................................................................74<br />

10.1 L'esperimento ATLAS...........................................................................................................74<br />

10.2 Il Co<strong>di</strong>ce ................................................................................................................................76


1 INTRODUZIONE<br />

Questa tesi si inserisce nello sviluppo del sistema Powerfarm che permette <strong>di</strong> gestire<br />

una o più farm, cioè insiemi <strong>di</strong> <strong>di</strong>spositivi che offrono particolari servizi alla Grid ed<br />

hanno particolari caratteristiche hardware e software.<br />

Il sistema Powerfarm è usato dagli amministatori delle farm per attivare e <strong>di</strong>sattivare<br />

i <strong>di</strong>spositivi, sia attraverso un'interfaccia WEB per le configurazioni e le operazioni<br />

<strong>di</strong> manutenzione, sia automaticamene per la gestione delle emergenze<br />

Dal punto <strong>di</strong> vista logico , ciascun <strong>di</strong>spositivo ha un proprio ruolo nella farm e svolge<br />

compiti specifici, invece dal punto <strong>di</strong> vista fisico ogni <strong>di</strong>spositivo è collegato ad un<br />

alimentatore e risiede all'interno del rack. Quin<strong>di</strong> ogni <strong>di</strong>spositivo ha una serie <strong>di</strong><br />

<strong>di</strong>pendenze logiche e fisiche da rispettare e pertanto prima <strong>di</strong> effettuare un operazione<br />

<strong>di</strong> accensione o spegnimento bisogna creare una vera e propria catena delle<br />

<strong>di</strong>pendenze tra tutti i <strong>di</strong>spositivi presenti nella farm. Per calcolarsi queste <strong>di</strong>pendenze<br />

powerfarm usa un file <strong>di</strong> confgurazione xml dove ci sono sia le <strong>di</strong>pendenze fisiche e<br />

logiche.<br />

La prima parte del mio lavoro <strong>di</strong> tesi è stato quello <strong>di</strong> ottenere informazioni sulle<br />

<strong>di</strong>pendenze logiche analizzando il file xml utilizzando il linguaggio Java, e<br />

rappresentarle tramite un grafo aciclico orientato dove ogni nodo rappresenta un<br />

<strong>di</strong>spositivo o un insieme <strong>di</strong> <strong>di</strong>spositivi, e gli archi rappresentano le <strong>di</strong>pendenze tra i<br />

<strong>di</strong>spositivi.<br />

Ciò consente <strong>di</strong> effettuare un imme<strong>di</strong>ato controllo visivo della configurazione del<br />

sistema.<br />

Questo grafo delle <strong>di</strong>pendenze sarà la home page dell'interfaccia web <strong>di</strong> Powerfarm e<br />

viene creato <strong>di</strong>namicamente ogniqualvolta si accede ed essa, tenendo conto quin<strong>di</strong> <strong>di</strong><br />

eventuali mo<strong>di</strong>fiche dei file <strong>di</strong> configurazione xml. Per visualizzare il grafo delle<br />

<strong>di</strong>pendenze costruito è stato utilizzato uno script lato server ( Webdot) che presa una<br />

descrizione testuale <strong>di</strong> un grafo ne fornisce la sua rappresentazione grafica. Ogni<br />

nodo <strong>di</strong> questo grafo è <strong>di</strong> un colore <strong>di</strong>verso a seconda del tipo <strong>di</strong> <strong>di</strong>spositivo che<br />

rappresenta, e si ha la possibilità <strong>di</strong> raggruppare <strong>di</strong>spositivi che hanno le stesse<br />

<strong>di</strong>pendenze logiche in un unico nodo del grafo. Inoltre per avere maggiori dettagli su<br />

un <strong>di</strong>spositivo o su un gruppo <strong>di</strong> <strong>di</strong>spositivi si può cliccare sul corrispondente nodo e<br />

Pietro Neroni 566/2833 Pagina 4 <strong>di</strong> 117


si viene rein<strong>di</strong>rizzati in una pagina che contiene delle informazioni sul <strong>di</strong>spositivo o<br />

sull'insieme <strong>di</strong> <strong>di</strong>spositivi scelto quali tipo, in<strong>di</strong>rizzo IP, dei link alle pagine <strong>di</strong><br />

monitoraggio, lo stato del <strong>di</strong>spositivo (online, offline), ed un link alla pagina <strong>di</strong><br />

configurazione del <strong>di</strong>spositivo.<br />

Proprio la pagina <strong>di</strong> configurazione <strong>di</strong> un <strong>di</strong>spositivo rappresenta la seconda parte del<br />

mio lavoro <strong>di</strong> tesi. Infatti mi è stato chiesto <strong>di</strong> riscriverla per offrire nuove<br />

funzionalità che migliorino la qualità interna ed esterna , in particolare robustezza e<br />

usabilità.<br />

Innanzitutto si è introdotto nell'interfaccia un meccanismo che associa<br />

automaticamente il tipo del <strong>di</strong>spositivo introdotto con i plugin necessari per la sua<br />

gestione. In questo modo si facilita il compito dell'amministratore che deve<br />

configurare nuovi <strong>di</strong>spositivi del sistema e si evitano gli errori dovuti all'aggiunta<br />

manuale dei plugin .<br />

Inoltre si può avere la possibilità <strong>di</strong> associare dei plugin ad un nuovo tipo <strong>di</strong><br />

<strong>di</strong>spositivo. Infatti quando viene creato un nuovo tipo <strong>di</strong> <strong>di</strong>spositivo si possono<br />

assegnare dei plugin che grazie a questo script vengono inseriti automaticamente<br />

ogniqualvolta si provi ad aggiungere un <strong>di</strong>spositivo dello stesso tipo.<br />

Sempre nell'ottica <strong>di</strong> semplificare il lavoro <strong>degli</strong> amministratori <strong>di</strong> sistema ed evitare<br />

possibile cause <strong>di</strong> errore, sono stati introdotti altri controlli relativi alla<br />

configurazione <strong>di</strong> altri <strong>di</strong>spositivi.<br />

Lato client sono state realizzate delle funzioni in javascript che effettuano i controlli<br />

sui campi obbligatori durante l'inserimento <strong>di</strong> un <strong>di</strong>spositivo, e sull'in<strong>di</strong>rizzo IP che<br />

deve essere del tipo previsto dallo standard IP<br />

Per evitare <strong>di</strong> assegnare al <strong>di</strong>spositivo <strong>di</strong>pendenze non volute, dalla pagina <strong>di</strong><br />

configurazione si può aprire una finestra <strong>di</strong> pop-up che visualizza il grafo delle<br />

<strong>di</strong>pendenze considerando il nuovo <strong>di</strong>spositivo e le sue <strong>di</strong>pendenze in quel momento<br />

assegnate.<br />

Infine, poiché nel grafo orientato aciclico costruito sulla base delle <strong>di</strong>pendenze<br />

logiche dei <strong>di</strong>spositivi , non ci possono essere cicli, prima che le <strong>di</strong>pendenze relative<br />

al nuovo <strong>di</strong>spositivo vengono registrate sui file <strong>di</strong> configurazione , viene verificato<br />

lato server che il loro inserimento non provochi dei cicli nel grafo, e in caso<br />

contrario queste non vengono registrate e viene visualizzata una pagina con la lista<br />

Pietro Neroni 566/2833 Pagina 5 <strong>di</strong> 117


delle <strong>di</strong>pendenze che causano cicli .<br />

Il sistema sviluppato è stato applicato e validato nel sito Grid dell'esperimento ATLS<br />

presente presso il Dipartimento <strong>di</strong> Fisica dell'<strong>Università</strong> <strong>Federico</strong> <strong>II</strong> <strong>di</strong> <strong>Napoli</strong>.<br />

Pietro Neroni 566/2833 Pagina 6 <strong>di</strong> 117


2 INTRODUZIONE AL CALCOLO IN ATLAS<br />

Il modello generale <strong>di</strong> calcolo per l'offline e l'analisi dell'esperimento ATLAS è un<br />

modello gerarchico, i cui livelli sono detti Tier,utilizzato per tutti gli esperimenti<br />

operanti presso l'acceleratore i particelle LHC del CERN <strong>di</strong> Ginevra .<br />

Nel sistema online <strong>di</strong> Acquisizione Dati c'è l'Event Filter Farm, che organizza i dati<br />

grezzi in output dall'esperimento in uno stream da passare al Tier0.<br />

-Il Tier0 è situato al CERN, qui avviene la produzione dei dati da inviare ai Tiers <strong>di</strong><br />

livello inferiore. Dopo una fase <strong>di</strong> calibrazione ed allineamento dei dati <strong>di</strong> output <strong>di</strong><br />

LHC , il Tier0 invia ai Tier1 l'output costruito<br />

-Il Tier1 conserva a tempo indeterminato una porzione dei dati grezzi, sui quali esegue<br />

procedure <strong>di</strong> calibrazione, allineamento e ricostruzione dei dati e li <strong>di</strong>stribuisce al<br />

Tier2.<br />

-Il Tier2 esegue produzione <strong>di</strong> dati simulati e job <strong>di</strong> analisi sui dati reali, passando<br />

l'output ai Tier3 se richiesto.<br />

-Nei Tier3 i fisici compiono localmente ulteriori analisi dei dati.<br />

Ogni Tier mantiene una copia dei dati che ha elaborato per usarli come esempio per le<br />

successive elaborazioni e permettere al livello successivo <strong>di</strong> recuperarli se<br />

necessario[1].<br />

Pietro Neroni 566/2833 Pagina 7 <strong>di</strong> 117


Figura 1: struttura a Tiers <strong>di</strong> ATLAS<br />

2.1 Il Sito Tier2-<strong>Napoli</strong><br />

Nel modello <strong>di</strong> calcolo <strong>di</strong> ATLAS i Tier2 hanno un ruolo molto importante per quel<br />

che riguarda le calibrazioni del rivelatore, la simulazione dati e l'analisi secondo gli<br />

interessi e le attività delle comunità locali ed in base alle caratteristiche tecniche del<br />

singolo sito, intese come risorse, connessioni <strong>di</strong> rete ed affidabilità.<br />

Un Tier2 fornisce capacità <strong>di</strong> analisi per i gruppi e sottogruppi <strong>di</strong> fisica: quin<strong>di</strong> deve<br />

fornire un infrastruttura <strong>di</strong> calcolo che possa sostenere una attività multi-utente, dove<br />

ci sono utenti che eseguono operazioni computazionalmente impegnative e necessitano<br />

<strong>di</strong> tempi <strong>di</strong> risposta ragionevoli.<br />

Oltre a ciò un Tier2 deve farsi carico <strong>di</strong> tutte le capacità <strong>di</strong> simulazione richieste<br />

all'esperimento ed i dati simulati prodotti sono inviati al Tier1 <strong>di</strong> riferimento dove<br />

saranno <strong>di</strong>sponibili per tutti gli altri siti che fanno capo ad esso.<br />

E' necessario quin<strong>di</strong>, che il Tier2 sia pienamente accessibile tramite gli strumenti Grid<br />

standard.<br />

Le risorse del Tier2-<strong>Napoli</strong> sono <strong>di</strong>sponibili 24 ore al giorno, 7 giorni alla settimana.<br />

Il centro è assistito 8-10 ore al giorno per 5 giorni alla settimana e le operazioni <strong>di</strong><br />

Pietro Neroni 566/2833 Pagina 8 <strong>di</strong> 117


manutenzione sono programmate in modo da sospendere il servizio per il minor tempo<br />

possibile.<br />

Il Tier2-<strong>Napoli</strong> è localizzato nel Complesso Universitario <strong>di</strong> Monte Sant'Angelo,<br />

<strong>di</strong>stribuito su due locali :<br />

• Il Capannone SCoPE, che contiene quattro Racks con apparati de<strong>di</strong>cati<br />

esclusivamente al Tier2 Atlas.<br />

• Una sala appositamente de<strong>di</strong>cata nei locali del Servizio <strong>di</strong> Calcolo & Reti (SCR)<br />

della Sezione INFN, del Dipartimento <strong>di</strong> Fisica .<br />

La topologia del Tier2-<strong>Napoli</strong> può essere schematizzata in questo modo :<br />

Figura 2: Topologia del Tier2 <strong>Napoli</strong><br />

L'attività del Tier2 è garantita anche in caso <strong>di</strong> guasti alla rete elettrica grazie alla<br />

presenza <strong>di</strong> cinque gruppi <strong>di</strong> continuità, tre sono utilizzato per alimentare la sala<br />

macchine posta nel <strong>di</strong>partimento <strong>di</strong> fisica, altri due invece garantiscono l'alimentazione<br />

elettrica agli apparati posizionati nel capannone SCoPE. I collegamenti in questione<br />

sono in<strong>di</strong>cati dalla figura 2.<br />

2.1.1 Servizi offerti dal Tier2<br />

Pietro Neroni 566/2833 Pagina 9 <strong>di</strong> 117


Al fine <strong>di</strong> comprendere meglio le attività previste dalla Tier2, è opportuno<br />

illustrare i servizi e gli elementi fondamentali.<br />

Ogni Virtual Organization mette a <strong>di</strong>sposizione delle Grid [2] un insieme <strong>di</strong><br />

risorse interconnesse tramite la rete Internet. In ogni sito sono installate delle<br />

farm composte da macchine <strong>di</strong>stinte a seconda delle funzionalità.; alcune<br />

offrono essenzialmente capacità <strong>di</strong> calcolo, altre <strong>di</strong> storage o implementano<br />

funzionalità <strong>di</strong>verse:<br />

– User Interface (UI) Rappresenta il punto <strong>di</strong> accesso a Grid; è costituita da un<br />

calcolatore dove gli utenti hanno un account personale, dove è installato il loro<br />

certificato e che permette loro <strong>di</strong> interagire con le funzionalità del sistema grid.<br />

Dalla UI, pertanto, un utente può essere autenticato e autorizzato all'utilizzo<br />

delle risorse e può sottomettere le proprie applicazioni (job), gestirne<br />

l'esecuzione e ottenerne i risultati.<br />

Figura 3: Accesso ai servizi Grid tramite UI<br />

– Computing Element(CE) sono l'interfaccia Grid verso una Farm costituita da<br />

no<strong>di</strong> <strong>di</strong> calcolo (Worker Node – WN) e gestiscono i job <strong>di</strong> calcolo tramite un<br />

batch-queue system; tramite il batch system e possibile partizionare l'insieme <strong>di</strong><br />

risorse <strong>di</strong> calcolo (CPU) e definire delle policy <strong>di</strong> utilizzo da parte delle varie<br />

VO (CPU time, numero <strong>di</strong> job concorrenti) me<strong>di</strong>ante la creazione <strong>di</strong> code batch<br />

e ciascun Computing Element e fornito <strong>di</strong> certificato <strong>di</strong>gitale che attesta<br />

l'atten<strong>di</strong>bilita delle transazioni;<br />

– Worker nodes (WN) Sono no<strong>di</strong> <strong>di</strong> una farm, chiamati computer off-the-shelf, i<br />

quali offrono soltanto CPU e connettività senza periferiche <strong>di</strong> I/O. L <strong>di</strong>sco<br />

locale contiene solo il sistema operativo ed un'area dati che funge da buffer<br />

temporaneo<br />

Pietro Neroni 566/2833 Pagina 10 <strong>di</strong> 117


Figura 4: Comunicazione attraverso i Computing Element<br />

– HRL servizio per l'accounting per l'utilizzo delle risorse <strong>di</strong> calcolo da parte<br />

delle <strong>di</strong>verse Virtual Organization<br />

– Servizi <strong>di</strong> Storage:<br />

Lo Storage Element è il servizio che permette ad utenti o applicazioni <strong>di</strong><br />

memorizzare dati per usi futuri.I dati su un SE sono read-only: non possono<br />

essere mo<strong>di</strong>ficati, ma solo cancellati o sovrascritti.<br />

Il tipo <strong>di</strong> Storage Element utilizzato dal Tier2 <strong>di</strong> <strong>Napoli</strong> è l'SRM (storage<br />

resource manager) che è interfaccia verso <strong>di</strong>verse risorse <strong>di</strong> storage, gestite da<br />

più server. Lo spazio <strong>di</strong> storage può essere aggiunto <strong>di</strong>namicamente. In<br />

particolare si è utilizzato il DPM ( <strong>di</strong>sk pool manager) il quale è un server che<br />

fornisce un singolo punto <strong>di</strong> accesso verso un pool <strong>di</strong> server <strong>di</strong> <strong>di</strong>sco.<br />

Pietro Neroni 566/2833 Pagina 11 <strong>di</strong> 117


Figura 5: Schema tipico <strong>di</strong> un sito Grid<br />

2.1.2 Collocazione apparati del Tier2 <strong>di</strong> <strong>Napoli</strong><br />

Gli apparati sono collocati all'interno delle due sale secondo questa <strong>di</strong>sposizione :<br />

Pietro Neroni 566/2833 Pagina 12 <strong>di</strong> 117


Figura 6: Localizzazione <strong>degli</strong> apparati del Tier2 napoli<br />

I due locali sono collegati attraverso un link in fibra a 10 Gbps, la connessione verso il<br />

Tier1 è ottenuta tramite il POP GARR localizzato nell'e<strong>di</strong>ficio dei Centri Comuni del<br />

Complesso Universitario <strong>di</strong> Monte Sant'Angelo, e facente capo al CSI. Il collegamento<br />

fra il Tier2 ed il POP GARR è ottenuto tramite un router Cisco 3750, con un Link in<br />

fibra a 1 Gbps, ed il router ha una linea de<strong>di</strong>cata.<br />

Per quanto riguarda i dettagli tecnici <strong>degli</strong> apparati appartenenti al Tier2-<strong>Napoli</strong><br />

possiamo fare riferimento alle seguenti tabelle :<br />

Service Nodes<br />

Pietro Neroni 566/2833 Pagina 13 <strong>di</strong> 117


Figura 7: caratteristiche tecniche dei service nodes<br />

I Service Nodes sono gli apparati de<strong>di</strong>cati alla gestione dell'accounting <strong>degli</strong> utenti e<br />

dello smistamento dei job da eseguire alle macchine deputate ad eseguirli.<br />

Come si può notare sono macchine abbastanza eterogenee fra <strong>di</strong> loro dal momento che<br />

sono state installate con tempistiche <strong>di</strong>fferenti.<br />

Switch<br />

Figura 8: network switches<br />

Pietro Neroni 566/2833 Pagina 14 <strong>di</strong> 117


Sono gli apparati che si occupano della gestione del traffico dati fra le due sale ed<br />

anche da e verso l'esterno. Il trasferimento dei dati è un passaggio fondamentale per un<br />

tier-2, dal momento che il loro scopo principale è quello <strong>di</strong> elaborare i dati ricevuti dai<br />

tier-1 e passare i risultati <strong>di</strong> queste elaborazioni ai tier-3, per cui questi apparati devono<br />

essere tenuti sotto controllo specie per quanto riguarda il traffico generato.<br />

Storage Elements<br />

Figura 9: Risorse <strong>di</strong> storage<br />

sono gli apparati destinati a conservare i dati da elaborare.<br />

Sono collegati agli altri apparati attraverso dei canali in fibra ottica appositamente<br />

de<strong>di</strong>cati e sono gestiti attraverso vari server che si occupano delle operazioni <strong>di</strong> lettura<br />

e scrittura su <strong>di</strong> essi.<br />

Osservando la tabella si può notare che non sono tutti dello stesso tipo, dal momento<br />

che sono stati aggiunti alla rete in tempi <strong>di</strong>fferenti.<br />

Pietro Neroni 566/2833 Pagina 15 <strong>di</strong> 117


Worker Nodes<br />

Figura 10: caratteristiche tecniche dei worker node<br />

Sono gli apparati che eseguono i job sui dati contenuti negli Storage Elements, si nota<br />

imme<strong>di</strong>atamente che non tutti hanno le stesse caratteristiche tecniche. Inoltre come si<br />

evince dalle colonne relativo all'anno <strong>di</strong> acquisto e <strong>di</strong>smissione molti <strong>di</strong> essi sono stati<br />

aggiunti <strong>di</strong> recente, e quin<strong>di</strong> sono <strong>di</strong>versi dagli apparati più “anziani” . Per alcuni <strong>di</strong><br />

questi ultimi inoltre è già stata programmata la <strong>di</strong>smissione.<br />

Pietro Neroni 566/2833 Pagina 16 <strong>di</strong> 117


3 POWERFARM<br />

Con il termine farm inten<strong>di</strong>amo una serie <strong>di</strong> <strong>di</strong>spositivi <strong>di</strong>stinti (worker node, <strong>di</strong>sk<br />

server, computing element, storage, etc.) , che forniscono particolari servizi alla grid,<br />

ed hanno delle particolari caratteristiche hardware e software. Essa nasce con lo sopo<br />

<strong>di</strong> centralizzare le operazioni che si occupano <strong>di</strong> gestione, manutenzione e sicurezza <strong>di</strong><br />

un insieme <strong>di</strong> <strong>di</strong>spositivi. Ognuna <strong>di</strong> queste operazioni ha la necessità comune <strong>di</strong><br />

accedere o spegnere i <strong>di</strong>spositivi.<br />

Si pensi ad un aumento della temperatura all'interno dei rack che contengono i<br />

<strong>di</strong>spositivi, oppure si deve effettuare un operazione <strong>di</strong> manutenzione <strong>di</strong> un <strong>di</strong>spositivo<br />

malfunzionante, in entrambi i casi bisognerebbe spegnere prima i <strong>di</strong>spositivi coinvolti<br />

per poi riaccenderli. Per fare un operazione del genere si deve tener conto che ogni<br />

<strong>di</strong>spositivo ha una serie <strong>di</strong> <strong>di</strong>pendenze software e hardware.<br />

Quin<strong>di</strong> è necessario un sistema che consenta agli amministratori della farm <strong>di</strong> tenere<br />

sotto controllo in maniera centralizzata tutti i <strong>di</strong>spositivi presenti.<br />

Per questo motivo è stato creato “Powerfarm”[3] che è un sistema che consente <strong>di</strong><br />

gestire, controllare lo stato, attivare/<strong>di</strong>sattivare qualsiasi <strong>di</strong>spositivo della farm, sia<br />

manualmente che in modo automatico rispettando le <strong>di</strong>pendenze hardware e software<br />

dei <strong>di</strong>spositivi.<br />

3.1 Funzionamento Powerfarm<br />

Powerfarm viene innescato in corrispondenza <strong>di</strong> uno dei seguenti tre eventi:<br />

1 . Mancanza/ritorno della corrente (monitoraggio eseguito dal modulo UPSmon)<br />

2. Sensori <strong>di</strong> temperatura, umi<strong>di</strong>tà e allagamento fuori norma (monitoraggio eseguito<br />

dai moduli CMC)<br />

3. Operazione <strong>di</strong> manutenzione eseguite manualmente dagli operatori autorizzati della<br />

griglia.<br />

Lo script Powerfarm, quin<strong>di</strong>, può essere richiamato:<br />

• Nei primi due casi, automaticamente da uno dei programmi <strong>di</strong> monitoraggio della<br />

farm,<br />

• Nell’ultimo caso, me<strong>di</strong>ante un interfaccia web (creata appositamente per consentire<br />

agli amministratori del sito non solo <strong>di</strong> creare la struttura della farm, ma anche <strong>di</strong><br />

spegnere o accendere uno determinato <strong>di</strong>spositivo, un insieme <strong>di</strong> <strong>di</strong>spositivi, o tutta la<br />

farm) o da linea <strong>di</strong> comando (se si è un utente autorizzato).<br />

In entrambe le situazioni, Powerfarm è capace <strong>di</strong> evitare danni alle macchine e/o al<br />

Pietro Neroni 566/2833 Pagina 17 <strong>di</strong> 117


software spegnendo/accendendo correttamente server, worker node, risorse <strong>di</strong> storage,<br />

router e virtualmente un qualunque altro <strong>di</strong>spositivo, grazie all'utilizzo <strong>di</strong> appositi<br />

plugin scritti specificatamente per funzionare con il particolare hardware <strong>di</strong> cui si<br />

<strong>di</strong>spone, e rispettando le <strong>di</strong>pendenze espresse dal grafo aciclico che definisce la farm.<br />

Si è voluto, infatti, descrivere la topologia della farm me<strong>di</strong>ante una struttura a grafo<br />

aciclico. Le informazioni riguardo la topologia della farm e, <strong>di</strong> conseguenza, le<br />

caratteristiche dei singoli no<strong>di</strong> e le <strong>di</strong>pendenze tra questi, sono contenute all’interno <strong>di</strong><br />

due file XML, devices.xml e dependencies.xml, che contengono reciprocamente le<br />

informazioni relative al nodo, come il nome, l’in<strong>di</strong>rizzo, il tipo <strong>di</strong> <strong>di</strong>spositivo ( storage<br />

element, computing element,Ups, Pdu, dpm, host generici, switch, worker node,<br />

ecc…), e tutti i plugin che realizzano le operazioni <strong>di</strong> accensione, spegnimento e<br />

controllo <strong>di</strong> stato specifici <strong>di</strong> quel <strong>di</strong>spositivo:<br />

L’impiego dei plugin consente <strong>di</strong> ottenere un livello <strong>di</strong> astrazione che permette agli<br />

amministratori <strong>di</strong> una farm <strong>di</strong> poter controllare virtualmente qualunque tipo <strong>di</strong><br />

<strong>di</strong>spositivo: gli utenti possono, infatti, scriversi i propri plugin specifici per<br />

spegnere/accendere i particolari <strong>di</strong>spositivi hardware e software <strong>di</strong> cui <strong>di</strong>spongono.<br />

3.2 Architettura <strong>di</strong> Powerfarm<br />

Powerfam è un sistema software per la gestione remota dello spegnimento e<br />

dell'accensione (tenendo conto delle <strong>di</strong>pendenze hardware e software dei <strong>di</strong>spositivi)<br />

dei <strong>di</strong>spositivi della farm organizzate secondo il para<strong>di</strong>gma Grid.<br />

Tale software e in<strong>di</strong>pendente dalla piattaforma ed e scritto in Perl (modulo principale)<br />

e Java ,Javascript,JSP(interfaccia web), gira sotto Linux, anche se può essere<br />

esportato su altre piattaforme, grazie alla flessibilità dei linguaggi <strong>di</strong> programmazione<br />

utilizzati.<br />

L'architettura del Powerfarm è formata dalle seguenti componenti:<br />

• Il modulo principale;<br />

• Modulo per la gestione delle emergenze;<br />

• I plugin;<br />

• Modulo <strong>di</strong> notifica;<br />

• Modulo <strong>di</strong> log;<br />

• File <strong>di</strong> configurazione XML;<br />

• Interfaccia web e linea <strong>di</strong> comando.<br />

3.3 Modulo principale<br />

Il modulo principale si occupa della gestione dei <strong>di</strong>spositivi. Ogni <strong>di</strong>spositivo può<br />

Pietro Neroni 566/2833 Pagina 18 <strong>di</strong> 117


essere acceso / spento me<strong>di</strong>ante <strong>di</strong> tre funzioni: spegnimento hardware, spegnimento<br />

software e accensione hardware. Visto che Powerfarm viene richiamato in con<strong>di</strong>zioni<br />

<strong>di</strong> emergenza o per manutenzione, e doveroso prevedere eventuali malfunzionamenti<br />

dei <strong>di</strong>spositivi, che e il motivo per cui ci sono due tipi <strong>di</strong> procedure <strong>di</strong> spegnimento per<br />

i <strong>di</strong>spositivi.<br />

Lo spegnimento software spegne il <strong>di</strong>spositivo in modo canonico, che e per esempio<br />

tramite SSH se si tratta <strong>di</strong> un server Linux, o me<strong>di</strong>ante DRAC .<br />

Invece, lo spegnimento hardware viene richiamato solo se lo spegnimento software<br />

non va a buon fine , e quin<strong>di</strong> spegne i <strong>di</strong>spositivi fisicamente, ad esempio <strong>di</strong>sattivando<br />

la PDU che fornisce l'energia elettrica ad un rack.<br />

Tutte le procedure utilizzate, <strong>di</strong> accensione o <strong>di</strong> spegnimento, sui vari <strong>di</strong>spositivi<br />

considerano le <strong>di</strong>pendenze hardware/software tra essi. Quin<strong>di</strong>, per poter accendere<br />

uno specifico <strong>di</strong>spositivo si dovrà agire in modo ricorsivo su tutti i <strong>di</strong>spositivi a cui<br />

esso e collegato, mentre per poter spegnere un <strong>di</strong>spositivo sarà necessario spegnere<br />

prima tutti i <strong>di</strong>spositivi che sono collegati con lui. Questo verra spiegato nei dettagli<br />

successivamente.<br />

3.4 Modulo per la gestione delle emergenze<br />

Una trap SNMP è un pacchetto <strong>di</strong> informazioni inviate da un <strong>di</strong>spsitivo <strong>di</strong> rete che<br />

comunica me<strong>di</strong>ante il protocollo SNMP (Simple Network Management Protocol),<br />

basato su TCP/IP ed è usato per monitorare e gestire le periferiche <strong>di</strong> rete.<br />

Il modulo per la gestione delle emergenze è il modulo che ascolta e cattura trap SNMP,<br />

che arrivano da <strong>di</strong>spositivi <strong>di</strong> controllo e notifica il Modulo principale <strong>degli</strong> eventi<br />

accaduti con lo scopo <strong>di</strong> adottare le azioni corrispondenti. Come abbiamo detto<br />

Powerfarm puo venir richiamato manualmente o automaticamente quando si<br />

verificano dei principali eventi:<br />

• mo<strong>di</strong>fiche della alimentazione , per esempio, quando si verifica la per<strong>di</strong>ta <strong>di</strong> potenza,<br />

l'ups monitor puo richiamare Powerfarm con l'istruzione <strong>di</strong> spegnimento <strong>di</strong> tutto cio<br />

che e collegato al gruppo <strong>di</strong> continuita e probabilmente anche gli altri <strong>di</strong>spositivi che<br />

<strong>di</strong>pendono da quelli <strong>di</strong>rettamente coinvolti. Successivamente in caso <strong>di</strong> ritorno della<br />

corrente, l'ups monitor puo eseguire Powerfarm con le istruzioni <strong>di</strong> accensione <strong>di</strong> tutto<br />

cio che e collegato al gruppo <strong>di</strong> continuita e anche gli altri <strong>di</strong>spositivi che <strong>di</strong>pendono<br />

da quelli <strong>di</strong>rettamente coinvolti, sempre rispettando le <strong>di</strong>pendenze dei <strong>di</strong>spositivi;<br />

• manualmente dagli amministratori della farm per eventuali operazioni <strong>di</strong><br />

manutenzione.<br />

Infatti l'amministratore della farm puo decidere se effettuare operazioni su tutta la<br />

farm, su tutti i <strong>di</strong>spositivi presenti in un rack o collegati ad un particolare <strong>di</strong>spositivo,<br />

su uno specifico gruppo <strong>di</strong> <strong>di</strong>spositivi tipo i worker node, oppure procedere solo su un<br />

singolo <strong>di</strong>spositivo.<br />

• per agire su uno o piu <strong>di</strong>spositivi al verificarsi <strong>di</strong> un evento anomalo (ad esempio, un<br />

Pietro Neroni 566/2833 Pagina 19 <strong>di</strong> 117


picco <strong>di</strong> temperatura, fumo o altri eventi monitorabili me<strong>di</strong>ante l'uso <strong>di</strong> sensori).<br />

Powerfarm viene richiamato quando si verifica un evento o un sensore supera il valore<br />

limite. Ad esempio, se la temperatura in un rack raggiunge un valore critico, viene<br />

richiamato Powerfarm per spegnere tutti i <strong>di</strong>spositivi appartenenti al rack; dopo<strong>di</strong>chè ,<br />

quando la temperatura raggiungera un valore normale <strong>di</strong> nuovo, verrà richiamato<br />

Powerfarm per accendere <strong>di</strong> nuovo la <strong>di</strong>spositivi nel rack.<br />

Tali eventi generati dai sensori vengono rilevati tramite un programma ,che effettua<br />

continue interrogazioni attraverso SNMP, e solo dopo aver verificato con certezza <strong>di</strong><br />

trovarsi in uno stato <strong>di</strong> allarme invoca Powerfarm.<br />

3.5 Modulo <strong>di</strong> notifica<br />

Il modulo <strong>di</strong> notifica ha la funzione <strong>di</strong> informare gli amministratori della farm in<br />

presenza <strong>di</strong> un evento anomalo, queste notifiche possono essere inviate tramite e-mail<br />

o SMS se quest'ultima opzione è abilitata.<br />

L'invio delle notifiche attraverso e-mail avviene quando viene richiamato Powerfarm<br />

in seguito al verificarsi <strong>di</strong> un comportamento anomalo rilevato dai sensori, come un<br />

picco della temperatura o il rilevamento <strong>di</strong> fumo.<br />

3.6 Modulo <strong>di</strong> log<br />

Vengono registrati in un modulo <strong>di</strong> log tutti gli eventi e le attivita che si svolgono .<br />

In questo modulo sono presenti tutte le informazioni verificatesi (accensione e<br />

spegnimento automatica o manuale , picchi <strong>di</strong> temperatura) e i <strong>di</strong>spositivi coinvolti che<br />

hanno comportato l'azionamento <strong>di</strong> Powerfarm, or<strong>di</strong>nate per data in cui si sono<br />

verificate, in modo da consentire una ricostruzione <strong>degli</strong> eventi.<br />

3.7 Riga <strong>di</strong> Comando e Interfaccia Web<br />

Powerfarm puo essere utilizzato in due mo<strong>di</strong>, me<strong>di</strong>ante linea <strong>di</strong> comando<br />

o me<strong>di</strong>ante l'interfaccia web (<strong>di</strong> solito utilizzata dall'amministratore della farm per<br />

operazioni <strong>di</strong> manutenzione). Anche i file <strong>di</strong> configurazione XML possono essere<br />

mo<strong>di</strong>ficati manualmente o tramite l'interfaccia web, pero dopo l'esecuzione <strong>di</strong> un<br />

operazione <strong>di</strong> mo<strong>di</strong>fica dei file <strong>di</strong> configurazione me<strong>di</strong>ante interfaccia Web, affinchè il<br />

sito si aggiorni sulla base delle mo<strong>di</strong>fiche effettuate, si deve ricompilare il file <strong>di</strong><br />

configurazione utilizzando l'apposita sezione, che in seguito verra spiegata in dettaglio<br />

Pietro Neroni 566/2833 Pagina 20 <strong>di</strong> 117


L'interfaccia web si basa su un sito web composto da pagine JSP e le principali azioni<br />

consentite sono:<br />

• visualizzare il grafo delle <strong>di</strong>pendenze;<br />

• controllare lo stato corrente <strong>di</strong> accensione e spegnimento dei <strong>di</strong>spositivi;<br />

• controllare lo stato della farm;<br />

• aggiungere, aggiornare o cancellare un <strong>di</strong>spositivo della farm;<br />

• ricerca <strong>di</strong> un <strong>di</strong>spositivo;<br />

• aggiornare le impostazioni dell'applicazione, me<strong>di</strong>ante la registrazione in memoria<br />

dei file <strong>di</strong> configurazione XML mo<strong>di</strong>ficati dopo aver effettuato almeno un'operazione<br />

<strong>di</strong> mo<strong>di</strong>fica <strong>di</strong> tali file.<br />

Il tipico ciclo <strong>di</strong> vita d'iterazione consiste principalmente in tre operazioni:<br />

1) ricerca <strong>di</strong> uno o piu <strong>di</strong>spositivi da gestire;<br />

2) procedere con una delle due operazioni possibili accensione o spegnimento su uno o<br />

un gruppo <strong>di</strong> <strong>di</strong>spositivi selezionati<br />

3) Controllare che su tutti i <strong>di</strong>spositivi coinvolti sia effettuata l'operazione richiesta,<br />

consultando il log generato o verificando lo stato in cui si trovano nella schermata<br />

principale.<br />

L'interfaccia Web verrà spiegata in dettaglio nei capitoli successivi<br />

3.8 La gestione delle <strong>di</strong>pendenze<br />

Uno dei principali aspetti che Powerfarm tiene conto sono le <strong>di</strong>pendenze tra i<br />

<strong>di</strong>spositivi. Dal punto <strong>di</strong> vista logico infatti , ciascun <strong>di</strong>spositivo ha un proprio ruolo<br />

nella farm e svolge compiti specifici, invece dal punto <strong>di</strong> vista fisico ogni <strong>di</strong>spositivo<br />

e collegato ad un alimentatore ed e risiede all'interno del rack. Quin<strong>di</strong> ogni <strong>di</strong>spositivo<br />

ha una serie <strong>di</strong> <strong>di</strong>pendenze logiche e fisiche da rispettare e pertanto prima <strong>di</strong> effettuare<br />

un operazione <strong>di</strong> accensione o spegnimento bisogna creare una vera e propria catena<br />

delle <strong>di</strong>pendenze tra tutti i <strong>di</strong>spositivi presenti nella farm.<br />

Per esempio, per <strong>di</strong>sattivare un <strong>di</strong>sco <strong>di</strong> storage bisogna <strong>di</strong>sattivare prima tutti i worker<br />

node che utilizzano tale <strong>di</strong>sco, altrimenti si verificherebbe che togliamo lo spazio <strong>di</strong><br />

storage ad un worker node che ancora e attivo. Questo vale anche per l'attivazione,<br />

infatti per poter attivare un worker node bisogna prima attivare lo spazio <strong>di</strong> storage che<br />

deve utilizzare.<br />

Powerfarm per rappresentare le <strong>di</strong>pendenze sia hardware che software utilizza un grafo<br />

delle <strong>di</strong>pendenze che vedremo nel dettaglio nei capitoli successivi.<br />

Pietro Neroni 566/2833 Pagina 21 <strong>di</strong> 117


3.9 I Plugin<br />

Per le funzioni <strong>di</strong> controllo dello stato e gestione <strong>di</strong> tutti i <strong>di</strong>spositivi della farm quali<br />

server, worker node, risorse <strong>di</strong> storage, router, Powefarm utilizza dei Plugin realizzati<br />

in un qualsiasi linguaggio <strong>di</strong> programmazione o <strong>di</strong> scripting che sono eseguibili sotto<br />

linux e ritornano il valore 0 se il plugin è stato eseguito con successo oppure un valore<br />

<strong>di</strong>verso da 0 in caso contrario e inoltre ritorna il co<strong>di</strong>ce d'errore ed eventualmente la<br />

descrizione dell'errore.<br />

I plugin vengono utilizzati da Powerfarm oltre per accendere o spegnere uno o piu<br />

<strong>di</strong>spositivi o l'intera farm, ma anche per controllare se il un <strong>di</strong>spositivo è online oppure<br />

offline. Quin<strong>di</strong> ci sonp <strong>di</strong>verse librerie <strong>di</strong> plugin per i vari <strong>di</strong>spositivi, ad esempio,<br />

SSH, Intelligent Platform Management Interface (IPMI), Baseboard Management<br />

Controller (BMC), Dell Remote Administration Controller (DRAC), Power<br />

<strong>di</strong>stribution Unit (PDU), Chassis Management Controller (CMC). Inoltre se si vuole<br />

aggiungere un particolare <strong>di</strong>spositivo si può scrivere un nuovo plugin per gestire il<br />

nuovo <strong>di</strong>spositivo.<br />

I plugin utilizzati si occupano principalmente:<br />

- Accensione;<br />

- Spegnimento software;<br />

- Spegnimento hardware;<br />

- Controllo stato <strong>di</strong> accensione;<br />

- Controllo stato <strong>di</strong> spegnimento.<br />

Per ogni plugin è presente un parametro, (timeout) che rappresenta il tempo massimo<br />

entro il quale il plugin deve completare la sua esecuzione. Nel caso dello spegnimento<br />

software <strong>di</strong> un <strong>di</strong>spositivo, se non si spegne entro il timeout previsto, verrà richiamato<br />

il plugin per lo spegnimento hardware che consistera nello spegnere in modo fisico il<br />

<strong>di</strong>spositivo, come ad esempio <strong>di</strong>sattivando il unita <strong>di</strong> alimentazione (ad esempio PDU)<br />

per il <strong>di</strong>spositivo.<br />

Se anche il plugin dello spegnimento hardware fallisce, dopo il timeout <strong>di</strong> scadenza, si<br />

agirebbe in base al valore <strong>di</strong> ritorno del blocco, se il processo dovrebbe continuare o<br />

no, in questa situazione il valore <strong>di</strong> default per il blocco off e 0, il che significa che il<br />

processo deve andare avanti anche se la <strong>di</strong>spositivo non si spegne.<br />

Come quello per lo spegnimento il plugin per l'accensione ha il timeout e se non viene<br />

portato a temine entro il temine stabilito si agirebbe in base al valore che il blocco<br />

ritorna, <strong>di</strong> solito il valore <strong>di</strong> default e 1 che significa che il processo deve fermarsi,<br />

perche non può effettuare l'accensione in modo ricorsivo sugli altri <strong>di</strong>spositivi che<br />

<strong>di</strong>pendono dal <strong>di</strong>spositivo non acceso, quin<strong>di</strong> bisogna rispettare sempre le <strong>di</strong>pendenze<br />

tra i vari <strong>di</strong>spositivi.<br />

I plugin per il controllo dello stato <strong>di</strong> accensione o spegnimento sono utilizzati per<br />

verificare se un <strong>di</strong>spositivo e acceso o spento.<br />

Pietro Neroni 566/2833 Pagina 22 <strong>di</strong> 117


Nel seguente paragrafo presentiamo i <strong>di</strong>spositivi hardware a <strong>di</strong>sposizione, le<br />

tecnologie adottate e i Plugin realizzati per controllare con Powerfarm tali <strong>di</strong>spositivi.<br />

3.9.1 Tecnologie e plugin utilizzati<br />

IPMI<br />

La specifica denominata Intelligent Platform Management Interface (IPMI) definisce<br />

un insieme <strong>di</strong> interfacce verso un <strong>di</strong>spositivo informatico che un amministratore <strong>di</strong><br />

sistema può usare per controllare lo stato <strong>di</strong> salute dell’hardware e per gestire alcuni<br />

parametri <strong>di</strong> funzionamento quali ad esempio il circuito <strong>di</strong> alimentazione del<br />

<strong>di</strong>spositivo.<br />

L’IPMI opera in<strong>di</strong>pendentemente dal sistema operativo e permette agli amministratori<br />

<strong>di</strong> gestire il sistema monitorato <strong>di</strong>rettamente da remoto persino in assenza <strong>di</strong> sistema<br />

operativo o a <strong>di</strong>spositivo spento. L’IPMI può comunque funzionare anche quando il<br />

sistema operativo è avviato e pienamente funzionante. La specifica dell’IPMI<br />

stabilisce solo lo standard della struttura e del formato delle interfacce, mentre<br />

l’implementazione può variare a seconda dei costruttori e <strong>degli</strong> sviluppatori.<br />

L’IPMI è costituito da un controller principale denominato Baseboard Management<br />

Controller (BMC) e da altri controller periferici connessi al BMC attraverso<br />

l’interfaccia denominata IPMB (Intelligent Platform Management Bus/Bridge). I<br />

controller periferici gestiscono gli attuatori ed i sensori che consentono <strong>di</strong> controllare i<br />

vari aspetti del sistema.<br />

Per il controllo dell’interfaccia IPMI è usato il tool IPMITOOL liberamente<br />

<strong>di</strong>sponibile all’in<strong>di</strong>rizzo http://sourceforge.net/projects/ipmitool/.<br />

Dispositivi<br />

I <strong>di</strong>spositivi che <strong>di</strong>spongono dell’IPMI nella sala del Tier2 <strong>di</strong> Atlas sono i seguenti:<br />

Device In<strong>di</strong>rizzzo IP device In<strong>di</strong>rizzo Ip IPMI<br />

atlaswn16.na.infn.it 172.16.20.116 172.16.10.128<br />

atlaswn17.nf.infn.it 172.16.20.117 172.16.20.117<br />

atlasce01.nf.infn.it 192. 167. 203.183 172.16.10.129<br />

atlasse02.nf.infn.it 192. 167. 203. 187 172.16.10.10.45<br />

atlase04nf.infn.it 192. 167. 203. 188 172.16.10.10.46<br />

Plugin<br />

I plugin usati per gestire le macchine che <strong>di</strong>spongono <strong>di</strong> IPMI sono i seguenti:<br />

• ipmi_hard_on.pl<br />

Pietro Neroni 566/2833 Pagina 23 <strong>di</strong> 117


• ipmi_hard_off.pl<br />

• ipmi_ssh_shutdown.pl<br />

PDU<br />

Una Power Distribution Unit (comunemente abbreviato in PDU) è un <strong>di</strong>spositivo che<br />

<strong>di</strong>stribuisce l’energia elettrica all’interno del Rack. Le PDU possono essere <strong>di</strong> tipo<br />

“intelligente” ovvero controllabili e gestibili da remoto. In particolare, i singoli socket<br />

(prese <strong>di</strong> corrente) delle PDU possono essere accesi o spenti tramite l’unità <strong>di</strong><br />

controllo CMC (Chassis Management Controller) con coman<strong>di</strong> SNMP.<br />

Laddove si <strong>di</strong>sponga <strong>di</strong> PDU intelligenti, esse possono essere sfruttate per controllare<br />

da remoto e in maniera automatica l’energia elettrica erogata alle singole prese dei<br />

<strong>di</strong>spositivi, controllando in tal modo l’effettiva accensione o spegnimento dei<br />

<strong>di</strong>spositivi ad esse collegati.<br />

I <strong>di</strong>spositivi che possono essere controllati tramite PDU sono quelli che sono collegati<br />

interamente alle PDU intelligenti. Ovviamente, se un <strong>di</strong>spositivo <strong>di</strong>spone già <strong>di</strong> un<br />

metodo alternativo per l’accensione /spegnimento hardware (es. IPMI) non è<br />

necessario utilizzare la PDU ma si può usare il metodo principale senza bisogno <strong>di</strong><br />

andare ad interrogare la PDU corrispondente.<br />

Plugin<br />

I plugin usati per gestire le macchine collegate alle PDU intelligenti sono i seguenti:<br />

• pdu_hard_on.pl<br />

• pdu_hard_off.pl<br />

• pdu_ssh_shutdown.pl<br />

• check_pdu_on.pl<br />

• check_pdu_off.pl<br />

DRAC<br />

Il Dell® Remote Access Controller (DRAC) permette <strong>di</strong> accedere, monitorare e gestire<br />

sia i server blade che il cestello da remoto e in<strong>di</strong>pendentemente dallo stato del sistema<br />

operativo dei server blade stessi. Il DRAC può essere usato per accendere / spegnere<br />

via software i server blade ed il cestello.<br />

Il DRAC presenta però alcune limitazioni: non supporta <strong>di</strong> fatto il multiple sign-on,<br />

ovvero – anche se è possibile collegarsi al DRAC da più istanze contemporaneamente<br />

(ad es. tramite l’utility a linea <strong>di</strong> comando, il terminal server e l’interfaccia web) – poi<br />

in realtà i coman<strong>di</strong> <strong>di</strong> accensione / spegnimento che vengono impartiti sono eseguiti<br />

solo alla <strong>di</strong>sconnessione <strong>di</strong> tutte le istanze oppure non sono eseguiti affatto. E’ dunque<br />

in<strong>di</strong>spensabile che i coman<strong>di</strong> vengano eseguiti uno per volta e che non vi nessuna altra<br />

istanza che si stia interfacciando con il DRAC nel momento in cui viene eseguito il<br />

comando <strong>di</strong> accensione / spegnimento. Il DRAC inoltre, nella versione precedente<br />

(presente nella Farm sui worker node dal 18 al 27) è molto lento nella risposta ai<br />

coman<strong>di</strong> che gli vengono impartiti.<br />

Pietro Neroni 566/2833 Pagina 24 <strong>di</strong> 117


Per interfacciarsi con il DRAC è usato il tool racadm liberamente scaricabile dal sito<br />

http://www.dell.com<br />

La guida in linea del racadm è consultabile all’in<strong>di</strong>rizzo:<br />

http://www.cs.uwaterloo.ca/~brecht/servers/docs/PowerEdge2600/en/Racadm/racadmc<br />

1.htm<br />

Dispositivi<br />

I <strong>di</strong>spositivi controllabili me<strong>di</strong>ante il sistema DRAC sono i seguenti:<br />

Device In<strong>di</strong>rizzzo IP device descrizione<br />

atlasdrac01.na.infn.it 172.16.20.100 Cestello wn 18-27<br />

atlasdrac02.nf.infn.it 172.16.20.87 Cestello wn 28-38<br />

Plugin<br />

Il plugin usato per gestire i <strong>di</strong>spositivi DRAC è il seguente:<br />

• drac_chassis.exp<br />

Plugin<br />

In Powerfarm vi sono 4 tipologie <strong>di</strong> plugin:<br />

I. Plugin <strong>di</strong> accensione<br />

<strong>II</strong>. Plugin <strong>di</strong> spegnimento software<br />

<strong>II</strong>I. Plugin <strong>di</strong> spegnimento hardware<br />

IV. Plugin <strong>di</strong> controllo stato ON | OFF<br />

Ciascuna tipologia <strong>di</strong> plugin può essere composta da vari plugin che realizzano la<br />

medesima funzionalità ma con tecnologie <strong>di</strong>verse e che vengono quin<strong>di</strong> usati su device<br />

<strong>di</strong>versi. Tutti i plugin rispettano la seguente logica: essi ritornano il valore 0 (zero) se<br />

sono stati eseguiti con successo, un valore <strong>di</strong>verso da 0 altrimenti.<br />

Elenco Plugin<br />

ELENCO PLUGIN<br />

Plugin <strong>di</strong> accensione<br />

ipmi_hard_on.pl<br />

Plugin per l'accensione <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante IPMI<br />

Pietro Neroni 566/2833 Pagina 25 <strong>di</strong> 117


pdu_hard_on.pl<br />

drac_chassis.exp<br />

drac_blade.exp<br />

Plugin <strong>di</strong> spegnimento software<br />

ipmi_ssh_shutdown.pl<br />

pdu_ssh_shutdown.pl<br />

drac_chassis.exp<br />

Plugin <strong>di</strong> spegnimento hardware<br />

ipmi_hard_off.pl<br />

pdu_hard_off.pl<br />

Plugin <strong>di</strong> controllo stato ON|OFF<br />

Plugin per l'accensione <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante l'accensione dei<br />

socket della PDU<br />

Plugin per l'accensione (e spegnimento software) del cestello Dell<br />

contenente i blade server che usano il DRAC<br />

Plugin per l'accensione e spegnimento (sia hardware che software)<br />

dei server blade del cestello Dell che usano il DRAC<br />

Plugin per lo spegnimento software me<strong>di</strong>ante SSH <strong>di</strong> un <strong>di</strong>spositivo<br />

con IPMI<br />

Plugin per lo spegnimento software me<strong>di</strong>ante SSH <strong>di</strong> un <strong>di</strong>spositivo<br />

senza IPMI ma collegato ad una PDU intelligente<br />

Si vede drac_chassis.exp come plugin <strong>di</strong> accensione<br />

Plugin per lo spegnimento hardware <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante<br />

IPMI<br />

Plugin per lo spegnimento hardware <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante<br />

spegnimento dei socket della PDU<br />

check_ping_on.pl<br />

check_ping_off.pl<br />

check_pdu_on.pl<br />

check_pdu_off.pl<br />

Plugin per il controllo dello stato ON <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante<br />

ping<br />

Plugin per il controllo dello stato OFF <strong>di</strong> un <strong>di</strong>spositivo me<strong>di</strong>ante<br />

ping<br />

Plugin per il controllo dello stato ON dei socket <strong>di</strong> una PDU<br />

Plugin per il controllo dello stato OFF dei socket <strong>di</strong> una PDU<br />

Plugin e Delay <strong>di</strong> accensione<br />

I device necessitano tipicamente <strong>di</strong> un tempo <strong>di</strong> start-up per essere realmente operativi<br />

che va da alcuni secon<strong>di</strong> a <strong>di</strong>versi minuti dopo l’accensione (si pensi, ad es., al<br />

caricamento <strong>di</strong> un sistema operativo e all’avvio <strong>di</strong> tutti i servizi). Quando si accende<br />

un <strong>di</strong>spositivo è necessario attendere che esso sia completamente operativo prima <strong>di</strong><br />

passare ad accendere il <strong>di</strong>spositivo al livello successivo nel grafo delle <strong>di</strong>pendenze.<br />

Questo meccanismo è realizzato grazie all’uso dei plugin <strong>di</strong> check-on che<br />

perio<strong>di</strong>camente controllano se un <strong>di</strong>spositivo è acceso ed operativo prima <strong>di</strong> passare<br />

Pietro Neroni 566/2833 Pagina 26 <strong>di</strong> 117


all’accensione del successivo (ad es., nel caso <strong>di</strong> un device con sistema operativo,<br />

controllando se il <strong>di</strong>spositivo risponde al ping). Il check-on avviene perio<strong>di</strong>camente<br />

entro e comunque non oltre il tempo <strong>di</strong> timeout impostato per l’accensione del device.<br />

Se, entro il tempo <strong>di</strong> timeout, il <strong>di</strong>spositivo si è acceso ed è operativo allora si passa<br />

all’accensione del <strong>di</strong>spositivo al livello successivo. Se, al contrario, il <strong>di</strong>spositivo non<br />

si è acceso neanche allo scadere del timeout, allora si va a controllare il valore<br />

dell’attributo lock-on per stabilire se si può comunque proseguire con l’accensione del<br />

livello successivo o se bisogna arrestare il processo <strong>di</strong> accensione a causa<br />

della mancata accensione/operatività del device corrente.<br />

Tuttavia, per alcuni device particolari, il meccanismo del check-on non è <strong>di</strong>rettamente<br />

implementabile, poiché non c’è un modo <strong>di</strong> stabilire da remoto se il <strong>di</strong>spositivo è<br />

realmente operativo oppure no. E’ questo il caso, ad esempio, <strong>degli</strong> slot <strong>di</strong> espansione<br />

del sistema <strong>di</strong> <strong>di</strong>schi dell’IBM DS4700 (device exp01, exp02, exp03). Questi device –<br />

che vengono accesi tramite PDU – impiegano dall’accensione 30 secon<strong>di</strong> circa per<br />

essere realmente operativi ma una volta operativi essi non rispondono al ping né ad<br />

altro simile sistema <strong>di</strong> controllo remoto (è solo possibile controllare se la PDU<br />

corrispondente è accesa o spenta, ma questo controllo non garantisce che il device sia<br />

realmente operativo). E’ quin<strong>di</strong> necessario prevedere un meccanismo per “attendere”<br />

che questi <strong>di</strong>spositivi siano pienamente operativi prima <strong>di</strong> procedere all’accensione del<br />

successivo livello. Questo comportamento può essere facilmente ottenuto facendo si<br />

che il plugin responsabile dell’accensione del <strong>di</strong>spositivo attenda con uno sleep il<br />

tempo necessario all’accensione prima <strong>di</strong> ritornare il controllo a Powerfarm. In pratica,<br />

si mette uno sleep come ultima istruzione del plugin <strong>di</strong> accensione in modo da<br />

attendere i secon<strong>di</strong> necessari alla completa accensione del device. Quin<strong>di</strong>, si imposta in<br />

Powerfarm un timeout <strong>di</strong> accensione per quel device abbastanza alto da comprendere il<br />

tempo totale <strong>di</strong> esecuzione del plugin <strong>di</strong> accensione.<br />

Ad esempio, per il device exp01, il plugin <strong>di</strong> accensione pdu_hard_on.pl esegue come<br />

ultima istruzione uno sleep <strong>di</strong> 30 secon<strong>di</strong> mentre il timeout <strong>di</strong> esecuzione <strong>di</strong> questo<br />

plugin impostato in Powerfarm è <strong>di</strong> 60 secon<strong>di</strong>, un tempo sufficiente per l’esecuzione<br />

del plugin e per l’attesa dello sleep finale.<br />

Questo meccanismo dovrebbe essere realizzato per tutti i device per cui non si <strong>di</strong>spone<br />

<strong>di</strong> un metodo per controllare che essi siano – oltre che accesi – anche realmente<br />

operativi.<br />

Pietro Neroni 566/2833 Pagina 27 <strong>di</strong> 117


4 I FILE DI CONFIGURAZIONE XML<br />

I file <strong>di</strong> configurazione XML vengono utilizzati sia dal programma in perl, sia<br />

dall'interfaccia web, e rappresentano le informazioni gestite da Powerfarm.<br />

Esse infatti contengono tutte le informazioni sui <strong>di</strong>spositivi gestiti da Powerfarm<br />

(device.xml) e i corrispondenti link alle loro pagine <strong>di</strong> monitoraggio (links.xml), sulle<br />

loro <strong>di</strong>pendenze (dependencies.xml), ed eventualmente se fanno parte <strong>di</strong> un insieme <strong>di</strong><br />

<strong>di</strong>spositivi (set.xml).<br />

In seguito spiegheremo in dettaglio ognuno <strong>di</strong> questi file xml, fornendo una breve<br />

descrizione per ogni campo presente nei file xml.<br />

Device.xml<br />

Descrive i <strong>di</strong>spositivi che Powerfarm gestisce.<br />

Ha i seguenti campi:<br />

name: in<strong>di</strong>ca il nome del device<br />

description: una breve descrizione testuale del <strong>di</strong>spositivo<br />

address: in<strong>di</strong>ca l'in<strong>di</strong>rizzo IP del <strong>di</strong>spositivo<br />

type: in<strong>di</strong>ca il tipo del <strong>di</strong>spositivo ( worker node, computing element....)<br />

selected: può assumere 0 o 1. Quando è ad 1 seleziona automaticamente il campo<br />

select della riga corrispondente al device quando questo viene visualizzato a seguito<br />

ad una ricerca<br />

action: per i rispettivi plugin <strong>di</strong> accensione , spegnimento e controllo stato, in<strong>di</strong>ca<br />

dove essi risiedono, gli argomenti che devono essere passati, timeout che rappresenta<br />

il tempo massimo entro il quale il plugin deve completare la sua esecuzione, e una<br />

descrizione testuale del plugin<br />

Pietro Neroni 566/2833 Pagina 28 <strong>di</strong> 117


La struttura XML che è utilizzata viene rappresentato nel file device.dtd<br />

Figura 11: File <strong>di</strong> configurazione device.xml<br />

Dependences.xml<br />

Descrive le <strong>di</strong>pendenze tra i <strong>di</strong>spositivi<br />

Ogni <strong>di</strong>pendenza tra i <strong>di</strong>spositivi viene descritta dall'elemento arc che ha 3 attributi:<br />

source e target dove vanno inseriti i <strong>di</strong>spositivi che compongono la <strong>di</strong>pendenza e<br />

description che è un attributo facoltativo nel caso si voglia inserire una breve<br />

descrizione testuale sulla <strong>di</strong>pendenza tra source e target<br />

Pietro Neroni 566/2833 Pagina 29 <strong>di</strong> 117


Figura 12: File <strong>di</strong> configurazione dependences.xml<br />

Il file dependence.dtd rappresenta la struttura <strong>di</strong> base utilizzata nel file dependence.xml<br />

Links.xml<br />

Contiene i link dei <strong>di</strong>spositivi per l'integrazione dell'interfaccia web con Nagios e<br />

Ganglia<br />

Il nodo ra<strong>di</strong>ce del file è l'elemento links che ha come figlio l'elemento link, che a sua<br />

volta contiene altri 2 elementi , nagios e ganglia.<br />

Nell'attributo “name” dell'elemento link viene inserito il nome del <strong>di</strong>spositivo a cui<br />

verranno associati i link <strong>di</strong> Ganglia e Nagios. Le informazioni sui link vengono fornite<br />

dagli attributi dei due elementi nagios e ganglia.<br />

Pietro Neroni 566/2833 Pagina 30 <strong>di</strong> 117


Figura 13: File <strong>di</strong> configurazione links.xml<br />

Il file links.dtd rappresenta la struttura <strong>di</strong> base utilizzata nel file links.xml<br />

Plugins.xml<br />

Contiene per un particolare tipo <strong>di</strong> <strong>di</strong>spositivo , il path assoluto dei plugin ad esso<br />

associati. Questo file utilizzato nella pagina <strong>di</strong> configurazione <strong>di</strong> un <strong>di</strong>spositivo da una<br />

funzione in Javascript che verrà spiegata in dettaglio nei capitoli successivi.<br />

Figura 14: File <strong>di</strong> configurazione plugins.xml<br />

Ogni elemento plugin ha 6 attributi: il tipo del <strong>di</strong>spositivo, e i plugin utilizzati da<br />

Powerfarm per gestire un <strong>di</strong>spositivo (hard-on, off-soft, off-hard, check-on, check-off)<br />

Il file plugins.dtd rappresenta la struttura <strong>di</strong> base utilizzata nel file plugins.xml<br />

Pietro Neroni 566/2833 Pagina 31 <strong>di</strong> 117


Set.xml<br />

Questo file xml in<strong>di</strong>ca se un <strong>di</strong>spositivo fa parte <strong>di</strong> un particolare insieme <strong>di</strong><br />

<strong>di</strong>spositivi. Viene utilizzato durante la costruzione del grafo delle <strong>di</strong>pendenze, infatti se<br />

un <strong>di</strong>spositivo è presente in questo file , nel grafo delle <strong>di</strong>pendenze verrà rappresentato<br />

il corrispondente insieme invece del singolo <strong>di</strong>spositivo.<br />

Ha due campi:<br />

<strong>di</strong>spositivo dove c'è il nome del <strong>di</strong>spositivo che fa parte dell'insieme e<br />

insieme che in<strong>di</strong>ca il nome dell'insieme<br />

Figura 15: File <strong>di</strong> configurazione set.xml<br />

Il file set.dtd rappresenta la struttura <strong>di</strong> base utilizzata nel file set.xml<br />

Pietro Neroni 566/2833 Pagina 32 <strong>di</strong> 117


5 Gli STRUMENTI UTILIZZATI<br />

5.1 JAVA<br />

Java è stato progettato fin dall'inizio come un linguaggio con caratteristiche <strong>di</strong><br />

sicurezza e buona programmazione che lo rendono particolarmente adatto alle<br />

applicazioni Web.<br />

Java è un linguaggio orientato agli oggetti: questo lo rende <strong>di</strong> uso relativamente<br />

semplice, anche se non è un linguaggio <strong>di</strong> scripting.<br />

Le principali caratteristiche <strong>di</strong> Java sono:<br />

Fortemente tipato. Non ammette costrutti insicuri, quali un accesso a vettore senza<br />

controllo sugli in<strong>di</strong>ci, perché questo tipo <strong>di</strong> costrutti possono dare origine a<br />

comportamenti del programma non specificati e non pre<strong>di</strong>cibili.<br />

Gestione auomatica della memoria (garbage collector). Inoltre, evita tutti i problemi <strong>di</strong><br />

sicurezza collegati con le istruzioni <strong>di</strong> deallocazione della memoria.<br />

In<strong>di</strong>pendente dalla piattaforma, nel senso che viene compilato in un bytecode<br />

eseguibile da una Java Virtual Machine.<br />

Java risulta adeguato alle applicazioni Web perché ha determinate caratteristiche <strong>di</strong><br />

sicurezza: la maggior parte delle azioni <strong>di</strong> attacco ad un sistema non possono essere<br />

descritte come un programma Java.<br />

Il programma Java viene compilato in un bytecode che viene eseguito dalla macchina<br />

virtuale (che funge da interprete). In questo modo si ottiene un buon compromesso tra<br />

linguaggi compilati e linguaggi interpretati:<br />

• è più portabile <strong>di</strong> un linguaggio compilato;<br />

• è più efficiente <strong>di</strong> un linguaggio interpretato;<br />

• ha caratteristiche che un linguaggio interpretato <strong>di</strong> solito non ha (ad esempio è<br />

fortemente tipato).<br />

Ne deriva un linguaggio che pur <strong>di</strong> uso meno <strong>di</strong>retto <strong>di</strong> un linguaggio <strong>di</strong> scripting,<br />

Pietro Neroni 566/2833 Pagina 33 <strong>di</strong> 117


isulta molto più facile <strong>di</strong> altri linguaggi <strong>di</strong> programmazione, quali C e C++[4].<br />

5.2 HTML<br />

L'HyperText Markup Language (HTML) (traduzione letterale: linguaggio <strong>di</strong><br />

marcatura per ipertesti) è un linguaggio usato per descrivere la struttura dei<br />

documenti ipertestuali <strong>di</strong>sponibili nel Word Wide Web ossia su internet. L'HTML non<br />

è un linguaggio <strong>di</strong> programmazione, ma un linguaggio <strong>di</strong> markup, ossia descrive il<br />

contenuto, testuale e non, <strong>di</strong> una pagina web.<br />

5.3 XML<br />

E' l'acronimo <strong>di</strong> eXten<strong>di</strong>ble Markup Linguage<br />

XML è un insieme <strong>di</strong> specifiche dal World Wide Web Consortium (W3C):<br />

le specifiche sono <strong>di</strong>sponibili pubblicamente e in modo gratuito al sito www.3c.org<br />

E' un linguaggio <strong>di</strong> markup che definisce un meccanismo sintattico che consente <strong>di</strong><br />

estendere o controllare il significato <strong>di</strong> altri linguaggi <strong>di</strong> markup come html.<br />

XML deve descrivere i dati: si concentra dunque su cosa sono i dati<br />

XML non ESEGUE nulla: XML non è stato pensato per eseguire qualcosa, ma solo per<br />

strutturare, memorizzare e scambiare informazione.<br />

La caratteristica vincente <strong>di</strong> XML sta nella sua in<strong>di</strong>pendenza dalla piattaforma, dagli<br />

strumenti hardware e software[5].<br />

5.4 JSP<br />

JSP è l'acronimo <strong>di</strong> JavaServer Page[6]. Questa è una tecnologia java per lo sviluppo<br />

<strong>di</strong> applicazioni Web che forniscono contenuti <strong>di</strong>namici.<br />

Pietro Neroni 566/2833 Pagina 34 <strong>di</strong> 117


Me<strong>di</strong>ante i suoi tag, è possibile inserire all'interno delle pagine funzioni o co<strong>di</strong>ce Java.<br />

Alla tecnologia JSP è correlata quella Servlet. Infatti, all'atto della chiamata <strong>di</strong> una JSP,<br />

quest'ultima viene tradotta in una Servlet. .A questo punto, come una qualsiasi servlet,<br />

essa viene messa in esecuzione dal servlet engine: questo carica la classe con un class<br />

loader, e la esegue.<br />

Una pagina JSP ha in più alcuni elementi:<br />

• <strong>di</strong>rettive: <br />

• <strong>di</strong>chiarazioni: <br />

• scriptlet: <br />

• espressioni: <br />

• librerie <strong>di</strong> etichette<br />

Il meccanismo delle JSP converte in stringa il risultato <strong>di</strong> ogni espressione JSP, in<br />

modo da poterlo includere nella risposta che viene passata al client.<br />

L'uso , <strong>di</strong> JSP offre vantaggi non in<strong>di</strong>fferenti, quali:<br />

• velocità <strong>di</strong> sviluppo;<br />

• prestazioni;<br />

• portabilità;<br />

• ed altri aspetti inerenti alla qualità interna ed esterna dell'applicazione Web;<br />

5.5 Javascript<br />

Fu originariamente sviluppato da Brendan Eich della Netscape Comunication con il<br />

nome <strong>di</strong> Mocha e successivamente <strong>di</strong> LiveScript, ma in seguito è stato rinominato<br />

"JavaScript". È un linguaggio <strong>di</strong> scripting orientato agli oggetti e comunemente<br />

utilizzato nei siti Web. Esso risulta avere una sintassi molto vicina a quella Java. La<br />

caratteristica principale <strong>di</strong> questo linguaggio è che un linguaggio interpretato. Il co<strong>di</strong>ce<br />

viene quin<strong>di</strong> eseguito a runtime senza la necessità <strong>di</strong> essere compilato. Un aspetto<br />

molto importante è che il co<strong>di</strong>ce JavaScript lato client viene eseguito dal client, senza,<br />

quin<strong>di</strong>, la necessità sollecitare il server.<br />

5.6 Graphviz e Webdot<br />

Graphviz è un programma software open source sviluppato dai laboratori <strong>di</strong> ricerca <strong>di</strong><br />

Pietro Neroni 566/2833 Pagina 35 <strong>di</strong> 117


AT&T per la rappresentazione <strong>di</strong> grafi (sia orientati che non orientati) in <strong>di</strong>versi<br />

formati a partire da una loro descrizione in un semplice linguaggio testuale, sviluppato<br />

appositamente. La rappresentazione testuale dei grafi si basa su un linguaggio molto<br />

semplice, il DOT[7], che utilizza una sintassi simile a quella del linguaggio C.<br />

Per comprendere meglio , in figura 17, riportiamo la descrizione testuale del grafo <strong>di</strong><br />

figura 16<br />

La rappresentazione testuale inizia con l’asserzione che il grafo descritto `e un grafo<br />

orientato (il prefisso “<strong>di</strong>” corrisponde a “<strong>di</strong>rect”) denominato “G”. Le istruzioni<br />

successive impostano alcuni parametri globali per il grafo quali la <strong>di</strong>mensione,<br />

l’orientamento, ecc.<br />

Le istruzioni che seguono alternano descrizioni <strong>di</strong> no<strong>di</strong> a descrizioni <strong>di</strong> archi . Le<br />

descrizioni <strong>di</strong> no<strong>di</strong> riportano il nome del nodo (utilizzato sia per referenziare il nodo<br />

nelle descrizioni <strong>degli</strong> archi sia come etichetta nella rappresentazione del grafo) e sue<br />

proprietà quali il tipo <strong>di</strong> nodo, il colore, ecc.<br />

Figura 16: grafo generato<br />

con Graphviz<br />

Pietro Neroni 566/2833 Pagina 36 <strong>di</strong> 117


Figura 17: co<strong>di</strong>ce sorgente del grafo <strong>di</strong> firura 12<br />

Webdot è un programma CGI che converte una descrizione testuale <strong>di</strong> un grafo scritto<br />

in linguaggio DOT, in un immagine <strong>di</strong> formato selezionabile(come ad esempio<br />

bmp,gif, png, jpg, ps, ecc...)che può essere inclusa in una pagina web.<br />

Per poter utilizzare Webdot è necessario avere:<br />

• le librerie <strong>di</strong> graphviz installate<br />

• un web server come Apache[8]<br />

Pietro Neroni 566/2833 Pagina 37 <strong>di</strong> 117


6 L'OBIETTIVO DELLA TESI: SITO WEBPOWERFARM<br />

6.1 Introduzione<br />

Il sito WebPowerfarm rappresenta l'interfaccia web del sistema Powerfarm. Esso è<br />

stato sviluppato appositamente per consentire agli amministratori non solo <strong>di</strong> creare<br />

la struttura della farm, ma anche <strong>di</strong> spegnere o accendere uno determinato<br />

<strong>di</strong>spositivo, un insieme <strong>di</strong> <strong>di</strong>spositivi, o tutta la farm.<br />

Il sito è composto da pagine JSP, nelle quali sono inclusi anche script lato client<br />

scritti in Javascript. Inoltre la pagine JSP utilizzano delle classi sviluppate in JAVA<br />

per compiere operazioni come leggere o mo<strong>di</strong>ficare i file <strong>di</strong> configurazione xml.<br />

Come si può osservare dal <strong>di</strong>agramma dei casi d'uso <strong>di</strong> figura 18, le funzionalità<br />

consentite da WebPowerfarm sono:<br />

• aggiungere, aggiornare o cancellare un <strong>di</strong>spositivo della farm<br />

• accendere o spegnere un <strong>di</strong>spositivo o un insieme <strong>di</strong> <strong>di</strong>spositivi<br />

• ricerca <strong>di</strong> un <strong>di</strong>spositivo<br />

• visualizzare il grafo delle <strong>di</strong>pendenze logiche dei <strong>di</strong>spositivi<br />

• aggiornare i file <strong>di</strong> configurazione xml, nel caso siano stati mo<strong>di</strong>ficati<br />

manualmente senza utilizzare l'interfaccia web<br />

Nel seguito del capitolo verranno descritte le funzionalità sopra elencate, e in maniera<br />

più dettagliata quelle che riguardano il mio lavoro <strong>di</strong> tesi che sono:<br />

• la visualizzazione nella home page del sito del grafo orientato aciclico che<br />

rappresenta le <strong>di</strong>pendenze tra i <strong>di</strong>spositivi( vedere paragrafo 6.5)<br />

• inserimento <strong>di</strong> nuove funzionalità e nuovi controlli per la pagina <strong>di</strong><br />

configurazione del sistema (vedere paragrafo 6.6)<br />

Pietro Neroni 566/2833 Pagina 38 <strong>di</strong> 117


6.2 Diagramma dei casi d'uso<br />

Figura 18: Diagramma dei casi d'uso del sito WebPowerfarm<br />

Pietro Neroni 566/2833 Pagina 39 <strong>di</strong> 117


6.3 L'architettura<br />

L'architettura su cui si basa la Web Application realizzata è Client/Server a tre<br />

livelli(three-tier):<br />

• Il primo livello è de<strong>di</strong>cato alla presentazione dei dati.<br />

• Il secondo livello de<strong>di</strong>cato alla logica applicativa<br />

• Il terzo livello de<strong>di</strong>cato alla gestione dei dati<br />

Figura 19: Architettura Client/Server a tre livelli<br />

Si ha quin<strong>di</strong> bisogno <strong>di</strong> un Web Server, un' Application Server ed un DataBase (Fig.<br />

19).<br />

L'ambiente, in cui il sistema opera, poggia su un unico server fisico con Sistema<br />

Operativo Red Hat AS 5.0, sul quale sono installati sia Tomcat, come Application<br />

Server, che MySQL come RDBMS.<br />

Il Web Server accetta richiesta da parte dei Client e invia a questi ultimi ciò che gli è<br />

stato richiesto Il Client sottomette le richieste me<strong>di</strong>ante il Web Browser così come,<br />

me<strong>di</strong>ante quest'ultimo, ha la possibilità <strong>di</strong> ottenere risposte dal Web Server.<br />

L'Application Server si occupa della logica applicativa. In particolare esso offre un<br />

Pietro Neroni 566/2833 Pagina 40 <strong>di</strong> 117


ambiente per poter sviluppare ed eseguire applicazioni web che solitamente, come<br />

pure nel nostro caso, sono three-tier e dove ciascun livello, come già detto<br />

precedentemente, ha un compito ben preciso.<br />

L'Application Server utilizzato è Tomcat[8]. Sia per la sua robustezza sia per il fatto<br />

che risulta essere <strong>di</strong>sponibile per Sistemi Operativi Windows e Linux, e sia perchè esso<br />

è attualmente l'Application Server più <strong>di</strong>ffuso.<br />

A <strong>di</strong>re il vero, Tomcat è un Servlet Container ed un JSP Engine. E' quin<strong>di</strong> capace <strong>di</strong><br />

eseguire, lato server, applicazoni web basate su tecnologia J2EE e costituite da<br />

componenti Servlet e da pagine JSP.<br />

L'applicazione Web è stata sviluppata secondo il para<strong>di</strong>gma MVC(Model-View-<br />

Control), traendo così i vantaggi insiti in esso. Questo Design Pattern è una linea guida<br />

per la sud<strong>di</strong>visione delle responsabilità fra le <strong>di</strong>verse classi che compongono<br />

l'applicazione web. Seguendo tale Design Pattern, infatti, l'applicazione viene<br />

sud<strong>di</strong>visa in tre componenti principali:<br />

• model: rappresenta le classi che si interessano dei dati nu<strong>di</strong> e cru<strong>di</strong>;<br />

• view : è la porzione dell'applicazione de<strong>di</strong>cata alla rappresentazione dei dati.<br />

Qui sono presenti le classi che, a partire dai dati contenuti nel “model”, offrono una<br />

presentazione della pagina all'utente;<br />

• controller: questa categoria <strong>di</strong> classi si interessa dell'interazione con l'utente.<br />

Tenendo presente il pattern Observer, il para<strong>di</strong>gma MVC prevede che le classi<br />

controller siano <strong>degli</strong> “Observer” che ricevono coman<strong>di</strong>(eventi) dall'utente e allo<br />

stesso modo, le view siano <strong>degli</strong> “Observer” delle classi model.<br />

Pietro Neroni 566/2833 Pagina 41 <strong>di</strong> 117


Figura 20: Architettura dell'applicazione utilizzando il para<strong>di</strong>gma MVC<br />

Sviluppando in tal modo l'applicazione, le richieste poste dall'utente saranno gestite<br />

dalla servlet(controller), la quale provvederà a istanziare una classe che si occupa<br />

della gestione dei dati(Model) che serviranno poi alle pagine html (View) per la<br />

presentazione dei dati.<br />

6.4 Interfaccia Utente<br />

La pagina principale dell’applicazione, è composta da tre aree contestuali ognuna<br />

contenente:<br />

1) Un menu <strong>di</strong> scelta, dove è possibile navigare verso la pagina:<br />

a) Principale<br />

b) Di configurazione, ve<strong>di</strong> sezione Configurazione<br />

c) Di impostazioni, ve<strong>di</strong> sezione Impostazioni<br />

d) Di ricerca, ve<strong>di</strong> sezione Ricerca <strong>di</strong> un device<br />

e) Di stato, ve<strong>di</strong> sezione Accensione e spegnimento<br />

2) Una barra <strong>di</strong> ricerca dei no<strong>di</strong><br />

3) Un’area contenuto dove viene visualizzato l’output della ricerca o della pagina<br />

Pietro Neroni 566/2833 Pagina 42 <strong>di</strong> 117


cercata<br />

La barra <strong>di</strong> ricerca veloce permette una rapida selezione dei no<strong>di</strong> su cui operare. Sia<br />

query la stringa scritta nella barra <strong>di</strong> ricerca rapida, la selezione da parte<br />

dell’interfaccia avviene tramite il seguente filtraggio a priorità:<br />

1. Se query corrisponde al nome <strong>di</strong> una farm, allora in risposta l’interfaccia visualizza<br />

tutti i device della farm query.<br />

2. Se query è il nome <strong>di</strong> un particolare device viene visualizzato esattamente il device<br />

query.<br />

3. Altrimenti vengono restituiti tutti i device del tipo query oppure con in<strong>di</strong>rizzo query.<br />

E’ possibile usare espressioni regolari per raffinare una selezione veloce (ad esempio<br />

per selezionare tutti i device <strong>di</strong> tipo WN oppure SE è sufficiente scrivere “WN|SE” ).<br />

Pietro Neroni 566/2833 Pagina 43 <strong>di</strong> 117


Figura 21: pagina <strong>di</strong> ricerca <strong>di</strong> un <strong>di</strong>spositivo SE<br />

Una volta operata la ricerca veloce i risultati vengono riportati nell’area contenuto.<br />

Le possibili operazioni su un particolare device riguardano:<br />

1. Verifica dello stato (online, offline, grafico <strong>di</strong> utilizzo)<br />

Ogni riga riporta un riepilogo delle informazioni salienti dei device selezionati. In<br />

particolare viene visualizzato lo stato con l’orario in cui è avvenuto l’ultimo<br />

controllo(ONLINE, OFFLINE, UNKNOWN), il tipo del device e l’in<strong>di</strong>rizzo.<br />

Pietro Neroni 566/2833 Pagina 44 <strong>di</strong> 117


Cliccando inoltre sulla freccia a sinistra del nome <strong>di</strong> ogni device è possibile<br />

visualizzare dei grafici <strong>di</strong> utilizzo <strong>di</strong> memoria e cpu .<br />

2. Spegnimento<br />

Cliccando sul link power-off (attivo solo se il device risulta acceso o in uno stato<br />

sconosciuto) si procede allo spegnimento del device. Si rimanda alla sezione<br />

spegnimento e accensione.<br />

3. Accensione<br />

Cliccando sul link power-on (attivo solo se il device risulta spento o in uno stato<br />

sconosciuto) si procede all’accensione del device. Si rimanda per approfon<strong>di</strong>menti alla<br />

sezione spegnimento e accensione.<br />

4. Mo<strong>di</strong>fica dei parametri<br />

Cliccando sul link e<strong>di</strong>t si procede alla mo<strong>di</strong>fica dei parametri del particolare device. Si<br />

rimanda alla sezione configurazione per approfon<strong>di</strong>menti<br />

5. Ganglia e Nagios<br />

Il sistema prevede l’integrazione con altre utility <strong>di</strong> monitoraggio ad esempio Ganglia<br />

e Nagios, cliccando sui link si è <strong>di</strong>rezionati verso le rispettive pagine <strong>di</strong> configurazione<br />

<strong>di</strong> quel particolare nodo.<br />

Figura 22: Grafici <strong>di</strong> utilizzo del <strong>di</strong>spositivo atlasse01.na.infn.it<br />

Pietro Neroni 566/2833 Pagina 45 <strong>di</strong> 117


Impostazioni<br />

Da questa pagina è possibile aggiornare il database in memoria dei no<strong>di</strong>. La base<br />

<strong>di</strong> dati dell’interfaccia è implementata me<strong>di</strong>ante file <strong>di</strong> dati scritti in linguaggio XML.<br />

Cliccando sul bottone validate <strong>di</strong>sponibile nella pagina Settings è possibile registrare<br />

in memoria gli eventuali cambiamenti apportati ai file tramite e<strong>di</strong>ting manuale.<br />

Figura 23: Pagina impostazioni<br />

Ricerca <strong>di</strong> un device<br />

Oltre alla ricerca rapida l’interfaccia <strong>di</strong>spone <strong>di</strong> una ricerca avanzata richiamabile<br />

me<strong>di</strong>ante il tasto search del menu principale. La ricerca è strutturata nel modo riportato<br />

in figura 24.<br />

Pietro Neroni 566/2833 Pagina 46 <strong>di</strong> 117


Figura 24: pagina <strong>di</strong> ricerca avanzata<br />

Ricerca Avanzata<br />

E’ possibile fissare i seguenti criteri nel filtro <strong>di</strong> ricerca:<br />

• Farm <strong>di</strong> appartenenza<br />

• Tipo del device<br />

• Intervallo <strong>di</strong> in<strong>di</strong>rizzi<br />

• Nome del device<br />

• Stato del device (online, offline), utile per visualizzare tutti e soli i device spenti o<br />

accesi.<br />

La selezione avviene tramite congiunzione dei succitati parametri.<br />

Spegnimento e accensione<br />

Scopo principale dell’applicazione è spegnere o accendere un particolare device (o<br />

insieme <strong>di</strong> device) rispettando le <strong>di</strong>pendenze <strong>di</strong> spegnimento o accensione.<br />

Per effettuare un operazione <strong>di</strong> spegnimento (accensione) è necessario:<br />

1. In<strong>di</strong>viduare i no<strong>di</strong> su cui operare, utilizzando la ricerca rapida o avanzata descritte<br />

in precedenza.<br />

2. Confermare la selezione tramite l’abilitazione dei checkbox <strong>di</strong> ciascuna riga dei<br />

Pietro Neroni 566/2833 Pagina 47 <strong>di</strong> 117


device.<br />

3. Selezionare l’opzione power off (power on) selected.<br />

4. Cliccare sul tasto proceed che appare dopo il riepilogo dei no<strong>di</strong> da spegnere<br />

(accendere), ve<strong>di</strong> figura 25.<br />

5.Verificare i risultati nella pagina <strong>di</strong> stato Power, ve<strong>di</strong> figura 26.<br />

Figura 25: pagina <strong>di</strong> riepilogo<br />

Pietro Neroni 566/2833 Pagina 48 <strong>di</strong> 117


Figura 26: pagina <strong>di</strong> stato<br />

La pagina <strong>di</strong> stato, ve<strong>di</strong> figura 26, mostra un riepilogo delle azioni che lo script <strong>di</strong><br />

sistema<br />

effettua per portare a termine l’operazione prevista.<br />

Esistono due aree:<br />

• Power.<br />

Nell’area power è possibile avere un resoconto <strong>di</strong> tutte le operazioni richieste tramite<br />

Pietro Neroni 566/2833 Pagina 49 <strong>di</strong> 117


l’interfaccia. Il sistema prevede una coda con politica <strong>di</strong> scheduling <strong>di</strong> tipo FIFO. E’<br />

possibile interrompere o invertire qualunque processo in esecuzione me<strong>di</strong>ante il link<br />

alla colonna kill e revert rispettivamente.<br />

• Log history<br />

Nella sezione log history è riportato il log delle azioni svolte dallo script <strong>di</strong> sistema.<br />

L’area si auto aggiorna ogni 5 secon<strong>di</strong>.<br />

6.5 Visualizzazione del grafo delle <strong>di</strong>pendenze<br />

Per comprendere meglio le <strong>di</strong>pendenze fra i <strong>di</strong>spositivi, è stato realizzato per<br />

Powerfarm un <strong>di</strong>rected acyclic graf (DAG), dei <strong>di</strong>spositivi dove ogni nodo<br />

rappresenta un <strong>di</strong>spositivo o un insieme <strong>di</strong> <strong>di</strong>spositivi gestiti da Powerfarm, e gli archi<br />

rappresentano le <strong>di</strong>pendenze tra i <strong>di</strong>spositivi.<br />

Ogni <strong>di</strong>spositivo puo avere qualsiasi <strong>di</strong>pendenza con altri <strong>di</strong>spositivi, l'unica regola da<br />

tener conto e <strong>di</strong> evitare <strong>di</strong> formare cicli nel grafico.<br />

Un esempio <strong>di</strong> grafo delle <strong>di</strong>pendenze, applicato alla farm del Tier2-ATLAS è il<br />

seguente, formato da due parti in<strong>di</strong>penenti, una relativa allo storage e la seconda alle<br />

risorse <strong>di</strong> calcolo<br />

Pietro Neroni 566/2833 Pagina 50 <strong>di</strong> 117


Figura 27: Grafo delle <strong>di</strong>pendenze<br />

Questo grafo viene creato <strong>di</strong>namicamente, ogni volta si accede alla home page del sito<br />

web, esaminando i file <strong>di</strong> configurazione che contengono le informazioni sui<br />

<strong>di</strong>spositivi e sulle loro <strong>di</strong>pendenze.<br />

Ogni nodo del grafo ha un colore a seconda del tipo <strong>di</strong> <strong>di</strong>spositivo che<br />

rappresenta.Inoltre i <strong>di</strong>spositivi che sono dello stesso tipo ed hanno le stesse<br />

<strong>di</strong>pendenze logiche, vengono raggruppati, in un unico nodo del grafo.<br />

Come precedentemente accennato, il grafico rappresenta le <strong>di</strong>pendenze <strong>di</strong> accensione e<br />

spegnimento e la priorita tra i vari <strong>di</strong>spositivi gestiti, che provengono dai vincoli logici<br />

dei <strong>di</strong>spositivi, come il ruolo che ciascun <strong>di</strong>spositivo svolge nella farm.<br />

Powerfarm non fa nessuna <strong>di</strong>stinzione tra le varie <strong>di</strong>pendenze ma li tratta tutti allo<br />

stesso modo perche non sono altro che <strong>di</strong>pendenze che devono essere eseguite per<br />

identificare i <strong>di</strong>spositivi che devono essere accesi o spenti e il loro or<strong>di</strong>ne.<br />

L'operazione <strong>di</strong> accensione o spegnimento puo essere eseguita su un unico <strong>di</strong>spositivo,<br />

su un tipo <strong>di</strong> <strong>di</strong> <strong>di</strong>spositivo (ad esempio tutti i worker node o tutti gli storage element,<br />

etc.), un elenco specifico <strong>di</strong> <strong>di</strong>spositivi (esempio: uno o piu specifici worker node e/o<br />

uno o piu specifici storage element, etc.), l'intera farm, tutto cio che e collegato ad un<br />

<strong>di</strong>spositivo (ad esempio tutti i <strong>di</strong>spositivi appartenenti ad un rack).<br />

In tale struttura stratificata ad albero, ad ogni livello ci possono essere <strong>di</strong>spositivi che<br />

hanno <strong>di</strong>pendenze tra <strong>di</strong> loro e quin<strong>di</strong> possono essere risolte contemporaneamente,<br />

Pietro Neroni 566/2833 Pagina 51 <strong>di</strong> 117


identificando cosi uno strato comune <strong>di</strong> esecuzione chiamato <strong>di</strong>pendenza <strong>di</strong> strato,<br />

oppure <strong>di</strong>spositivi che non hanno <strong>di</strong>pendenze tra <strong>di</strong> loro.<br />

Da notare che nella <strong>di</strong>pendenza <strong>di</strong> strato si possono avere anche <strong>di</strong>versi tipi <strong>di</strong><br />

<strong>di</strong>spositivi e questo e tutto normale e serve a ottimizzare il processo <strong>di</strong><br />

parallelizzazione delle operazioni sui <strong>di</strong>spositivi.<br />

Per poter effettuare un'operazione <strong>di</strong> accensione dei vari <strong>di</strong>spositivi tenendo conto<br />

delle <strong>di</strong>pendenze si agisce all'alto verso il basso secondo il modello top-down, mentre<br />

per poter effettuare un'operazione <strong>di</strong> spegnimento si agisce dal basso verso l'alto<br />

secondo il modello bottom-up.<br />

Le modalita <strong>di</strong> funzionamento rispettando le <strong>di</strong>pendenze sono tre e sono l'accensione,<br />

l'accensione in modo ricorsivo, e lo spegnimento.<br />

• Accensione<br />

Ve<strong>di</strong>amo come si effettua l'accensione, ad esempio, del <strong>di</strong>spositivo SE08, che<br />

corrisponde ad uno Storage Element: tenendo conto del grafo, si agisce dall'alto verso<br />

il basso accendendo prima il controller e4_03a e la sua espansione , e dopo aver<br />

constatato che questi si sono accesi correttamente si passa all'accensione dello storage<br />

element SE08<br />

Figura 28: Accensione del storage element SE08<br />

• Accensione ricorsiva<br />

Per poter effettuare Accensione ricorsiva (figura 29) si attivano non solo i no<strong>di</strong> come<br />

nella procedura normale <strong>di</strong> accensione ma anche tutti i <strong>di</strong>spositivi che stanno sotto e<br />

che hanno un percorso <strong>di</strong> <strong>di</strong>pendenze con il <strong>di</strong>spositivo che deve essere acceso. Nel<br />

nostro caso quin<strong>di</strong>, oltre ad affettuare l'accensione delle espansioni del controller, del<br />

Pietro Neroni 566/2833 Pagina 52 <strong>di</strong> 117


controller e dello storage element, verrà acceso pure il Dpm che sta al <strong>di</strong> sotto <strong>di</strong> esso.<br />

Figura 29: accensione ricorsiva dello storage element SE08<br />

• Spegnimento<br />

Per poter effettuare lo Spegnimento (figura 30) si agisce dal basso verso l'alto<br />

partendo dalle foglie che hanno <strong>di</strong>pendenze con il <strong>di</strong>spositivo da spegnere. Infatti per<br />

spegnere CE01 si da parte tutti i WN e dopo che tutti sono spenti si effettua lo<br />

spegnimento del CE1 Il grafo rappresenta le <strong>di</strong>pendenze <strong>di</strong> accensione , se lo si guarda<br />

da basso verso l'alto, e <strong>di</strong> spegnimento , se lo si guarda dall'alto verso il basso.<br />

Pietro Neroni 566/2833 Pagina 53 <strong>di</strong> 117


Figura 30: Spegnimento del computing element CE01<br />

Per avere maggiori informazioni su un <strong>di</strong>spositivo o su un gruppo <strong>di</strong> <strong>di</strong>spositivi si può<br />

cliccare su un corrispondente nodo e si verrà in<strong>di</strong>rizzati ad una pagina che per il<br />

<strong>di</strong>spositivo scelto conterrà:<br />

il suo in<strong>di</strong>rizzo IP<br />

la sua descrizione<br />

un link alla sua pagina <strong>di</strong> configurazione dove si possono cambiare gli attributi del<br />

<strong>di</strong>spositivo i link alle pagine <strong>di</strong> monitoraggio Ganglia e Nagios del <strong>di</strong>spositivo<br />

Pietro Neroni 566/2833 Pagina 54 <strong>di</strong> 117


Figura 31: Click <strong>di</strong> un nodo dal grafo delle <strong>di</strong>pendenze<br />

DETTAGLI IMPLEMENTATIVI<br />

Per visualizzare il grafo delle <strong>di</strong>pendenze logiche, si è utilizzato Webdot, uno script<br />

lato server che utilizza un file DOT contenente la descrizione testuale <strong>di</strong> un grafo e la<br />

trasforma in un immagine <strong>di</strong> formato selezionabile(come ad esempio bmp,gif, png,<br />

jpg, ps, ecc...). Nel nostro caso, poiché viene richiesto che ogni nodo del grafo sia<br />

cliccabile l'immagine sarà una mappa cliccabile lato server dove ad ogni nodo del<br />

grafo gli sarà associato un url che corrisponde alla sua pagina <strong>di</strong> configurazione.<br />

Pietro Neroni 566/2833 Pagina 55 <strong>di</strong> 117


La descrizione testuale del grafo viene creata da una classe Java ,nei seguenti passi:<br />

• viene estratto l'elemento che contiene la <strong>di</strong>pendenza tra i <strong>di</strong>spositivi nel file<br />

dependencies.xml, che ha i due attributi source e target. Se rappresenta una<br />

<strong>di</strong>pendenza fisica, la ignora e passa al prossimo elemento.<br />

• Si va a leggere il tipo dei due <strong>di</strong>spositivi che compongono la <strong>di</strong>pendenza dal file<br />

<strong>di</strong> configurazione device.xml, a seconda del tipo il <strong>di</strong>spositivo viene<br />

rappresentato nel grafo con un colore <strong>di</strong>verso<br />

• Si controlla nel file <strong>di</strong> configurazione set.xml se uno dei due <strong>di</strong>spositivi o<br />

entrambi fanno parte <strong>di</strong> un insieme <strong>di</strong> <strong>di</strong>spositivi. In questo caso il <strong>di</strong>spositivo<br />

verrà sostituito dal suo insieme<br />

• Infine viene scritta la <strong>di</strong>pendenza nel file DOT e i due <strong>di</strong>spositivi ( o insiemi <strong>di</strong><br />

<strong>di</strong>spositivi) con i loro attributi (colore e URL)<br />

Per ottenere informazioni sui file <strong>di</strong> configurazione viene fatto il parsing dei<br />

documenti xml. Il parsing <strong>di</strong> documenti xml in Java, passa principalmente attraverso<br />

due famiglie <strong>di</strong> API: DOM e SAX[9]. Si è utilizzato l'approccio DOM che consiste nel<br />

caricare in memoria tutto l'albero del documento xml e su <strong>di</strong> esso potrà essere scelto<br />

un algoritmo <strong>di</strong> esplorazione. In questa struttura ogni elemento del documento xml<br />

<strong>di</strong>venta un nodo dell'albero rappresentato da una classe che implementa l'interfaccia<br />

org.w3c.dom.Node. Questa interfaccia fornisce meto<strong>di</strong> per esplorare o mo<strong>di</strong>ficare<br />

l'albero e per conoscere le proprietà <strong>di</strong> ogni nodo.<br />

6.6 Inserimento, mo<strong>di</strong>fica, eliminazione <strong>di</strong> un <strong>di</strong>spositivo<br />

La pagina <strong>di</strong> Configurazione, che permette impostare l'intero sistema, è stata per molti<br />

aspetti mo<strong>di</strong>ficata e migliorata.<br />

Si è introdotto un meccanismo che associa automaticamente il tipo del <strong>di</strong>spositivo<br />

introdotto con i plugin necessari per la sua gestione.<br />

Dopo<strong>di</strong>che sono stati inseriti dei controlli sui campi obbligatori e sull'in<strong>di</strong>rizzo IP che<br />

deve essere del tipo x.x.x.x con 0≤x≤255 .<br />

Infine si è curata la parte che riguarda la gestione delle <strong>di</strong>pendenze, permettendo <strong>di</strong><br />

visualizzare il grafo delle <strong>di</strong>pendenze considerando anche il nuovo <strong>di</strong>spositivo, e<br />

inserendo il controllo per non assegnare al <strong>di</strong>spositivo delle <strong>di</strong>pendenze che causano<br />

cicli all'interno del grafo. Nel seguito del paragrafo descriveremo in maniera più<br />

dettagliata queste funzionalità.<br />

Pietro Neroni 566/2833 Pagina 56 <strong>di</strong> 117


Tramite la pagina Configurazione è possibile:<br />

1. Aggiungere una nuova risorsa da monitorare e/o gestire<br />

2. Mo<strong>di</strong>ficare i parametri <strong>di</strong> un device presente nel sistema, selezionando la voce e<br />

3. Eliminare un device dal sistema<br />

Aggiunta <strong>di</strong> un nuovo device<br />

Per aggiungere una nuova risorsa da monitorare è sufficiente cliccare sul tasto<br />

Configure dal menu <strong>di</strong> scelta in alto sulla pagina principale.<br />

Descriviamo in dettaglio la pagina relativa all'inserimento <strong>di</strong> un <strong>di</strong>spositivo:<br />

Figura 32: Pagina <strong>di</strong> inserimento <strong>di</strong> un nuovo <strong>di</strong>spositivo<br />

Pietro Neroni 566/2833 Pagina 57 <strong>di</strong> 117


La pagina relativa all'aggiunta <strong>di</strong> un <strong>di</strong>spositivo , è una pagina JSP ed ha i seguenti<br />

campi:<br />

1) Il nome univoco del device, nel campo name (obbligatorio)<br />

2) La farm a cui il device appartiene, nel campo farm (facoltativo)<br />

3) In<strong>di</strong>rizzo IP del device, nel campo IP (obbligatorio)<br />

4) Il tipo del device (es. WN, SE, UPS, ecc.), nel campo type (facoltativo)<br />

5)L'insieme a cui appartiene, se fa parte <strong>di</strong> un insieme <strong>di</strong> <strong>di</strong>spositivi<br />

6) I valori dei parametri lock on e lock off, nei rispettivi campi (obbligatorio).<br />

7) La conferma <strong>di</strong> abilitazione del device quando selezionato, nel campo select on<br />

search. Quando è attiva questa opzione seleziona automaticamente il campo select<br />

della riga corrispondente al device quando questo viene visualizzato in seguito ad una<br />

ricerca.<br />

8) Il percorso assoluto del plugin <strong>di</strong> accensione del device, con i relativi argomenti,<br />

descrizione e timeout nel campo power on (facoltativo).<br />

9) Il percorso assoluto del plugin <strong>di</strong> spegnimento software del device, con i relativi<br />

argomenti , descrizione e timeout nel campo power off-soft (facoltativo).<br />

10) Il percorso assoluto del plugin <strong>di</strong> spegnimento hardware del device, con i relativi<br />

argomenti , descrizione e timeout nel campo power off-hard (facoltativo).<br />

11) Il percorso assoluto del plugin <strong>di</strong> controllo stato online del device, con i relativi<br />

argomenti , descrizione e timeout nel campo check-on (facoltativo).<br />

12) Il percorso assoluto del plugin <strong>di</strong> controllo stato offline del device, con i relativi<br />

argomenti , descrizione e timeout nel campo check-off (facoltativo).<br />

13) Il percorso del link alla pagina <strong>di</strong> Nagios del particolare device visualizzato nella<br />

finestra <strong>di</strong> riepilogo, nel campo link nagios (facoltativo).<br />

14) Il percorso del link alla pagina <strong>di</strong> Ganglia del particolare device visualizzato<br />

nella finestra <strong>di</strong> riepilogo, nel campo link ganglia (facoltativo).<br />

15) Il percorso del primo dei due grafici visualizzati nella riga <strong>di</strong> riepilogo del device<br />

nell’area <strong>di</strong> selezione, nel campo image report left (facoltativo).<br />

16) Il percorso del secondo dei due grafici visualizzati nella riga <strong>di</strong> riepilogo del<br />

device nell’area <strong>di</strong> selezione, nel campo image report right (facoltativo).<br />

17) Le <strong>di</strong>pendenze <strong>di</strong> spegnimento, ovvero tutti i no<strong>di</strong> che è necessario spegnere<br />

prima del device in considerazione, nel campo dependencies (facoltativo).<br />

Una volta che si è provveduto a riempire tutti i campi obbligatori è sufficiente cliccare<br />

sulbottone add per inserire il nodo appena configurato.<br />

Il controllo sui campi obbligatori viene fatto da uno script lato client che controlla se è<br />

stato inserito un nome al <strong>di</strong>spositivo e se è stato inserito un in<strong>di</strong>rizzo IP corretto<br />

Quando viene selezionato il tipo del <strong>di</strong>spositivo, uno script lato client cercherà in un<br />

Pietro Neroni 566/2833 Pagina 58 <strong>di</strong> 117


file xml (plugin.xml) gli ultimi plugin che erano stati associati a quel tipo, e se li trova<br />

li mette automaticamente nei campi plugin.<br />

Figura 33: Inserimento automatico dei plugin in base al tipo<br />

L'utente ha anche la possibilità <strong>di</strong> associare dei plugin ad un nuovo tipo <strong>di</strong> <strong>di</strong>spositivo.<br />

Infatti creando un nuovo tipo l'utente può assegnare dei plugin che verranno ricordati<br />

ogniqualvolta si tenti <strong>di</strong> aggiungere un <strong>di</strong>spositivo dello stesso tipo.<br />

Affianco ai plugin on, off-soft, off-hard c'è il pulsante exec che quando viene cliccato<br />

apre una finestra <strong>di</strong> popup dove viene eseguito il plugin presente nel campo plugin e<br />

con gli argomenti presenti nel campo args.<br />

Figura 34: Esecuzione <strong>di</strong> un plugin tramite il tasto exec<br />

Pietro Neroni 566/2833 Pagina 59 <strong>di</strong> 117


Affianco al campo che contiene le <strong>di</strong>pendenze del <strong>di</strong>spositivo, c'è il pulsante grafo.<br />

Se i clicchiamo si apre una pagina <strong>di</strong> popoup dove viene creato il grafo delle<br />

<strong>di</strong>pendenze relativo al nuovo <strong>di</strong>spositivo e alle sue <strong>di</strong>pendenze attualmente assegnate.<br />

Questo è molto utile perché si può notare come l'inserimento del <strong>di</strong>spositivo con le<br />

<strong>di</strong>pendenze assegnate possa influenzare altri <strong>di</strong>spositivi della farm.<br />

Figura 35: Finestra pop-up per la visualizzazione del grafo delle <strong>di</strong>pendenze con<br />

l'inserimento del worker node nuovo_wn<br />

DETTAGLI IMPLEMENTATIVI<br />

Per inserire i plugin in modo automatico a seconda del tipo selezionato si deve leggere<br />

il file plugins.xml. Si è utilizzata quin<strong>di</strong> una funzione javascript che fa uso<br />

dell'oggetto XMLHttpRequest, oggetto che varia a seconda del browser che stiamo<br />

utilizzando per visualizzare la pagina. Questo oggetto è parte <strong>di</strong> un ActiveX e quin<strong>di</strong><br />

esposto maggiormente a restrizioni sulla configurazione del browser dell’utente, ed è<br />

supportato, seppur manualmente, da versioni obsolete dei più comuni browser in<br />

circolazione. Grazie a quest'oggetto possiamo caricare il documento xml in una<br />

variabile javascript ed ottenere informazioni su <strong>di</strong> esso tramite il metodo<br />

getElementByTagName.<br />

Pietro Neroni 566/2833 Pagina 60 <strong>di</strong> 117


Per quel che riguarda l'esecuzione <strong>di</strong> uno specifico plugin tramite il tasto “exec”<br />

oppure la visualizzazione del grafo delle <strong>di</strong>pendenze per quel <strong>di</strong>spositivo, è stata<br />

utilizzata la funzione window.open <strong>di</strong> Javascript che ci permette <strong>di</strong> aprire finestre<br />

personalizzabili. Essa accetta tre parametri: un percorso (relativo o assoluto) <strong>di</strong> un<br />

pagina html, il nome della finestra (opzionale), lo stile che specifica la forma, la<br />

<strong>di</strong>mensione e la posizione della finestra, se la finestra non sia ri<strong>di</strong>mensionale, o che<br />

non ci siano le barre <strong>degli</strong> strumenti e le barre <strong>di</strong> scorrimento.<br />

Mo<strong>di</strong>fica <strong>di</strong> un device esistente<br />

Per mo<strong>di</strong>ficare la configurazione <strong>di</strong> un device esistente è necessario selezionare il<br />

device tramite la barra <strong>di</strong> ricerca veloce o avanzata e cliccare sul link e<strong>di</strong>t nella riga<br />

corrispondente. Il sistema fornirà una pagina dove è possibile mo<strong>di</strong>ficare i parametri<br />

del device (eccetto il nome) secondo quanto scritto nella seziona aggiunta <strong>di</strong> un nuovo<br />

device.<br />

Pietro Neroni 566/2833 Pagina 61 <strong>di</strong> 117


Eliminazione <strong>di</strong> un device esistente<br />

Per eliminare un device è sufficiente accedere alla sua pagina <strong>di</strong> configurazione, come<br />

visto in precedenza, cliccare sul pulsante delete e confermare.<br />

Figura 36: Eliminazione del computing element atlasce01.na.infn.it<br />

Pietro Neroni 566/2833 Pagina 62 <strong>di</strong> 117


6.7 Diagrammi <strong>di</strong> Cockburn<br />

a) Aggiunta <strong>di</strong> un <strong>di</strong>spositivo<br />

Use case #1<br />

Obiettivo nel<br />

contesto<br />

Precon<strong>di</strong>zioni<br />

Con<strong>di</strong>zione finale<br />

<strong>di</strong> successo<br />

Con<strong>di</strong>zione finale<br />

<strong>di</strong> fallimento<br />

Attore primario<br />

Con<strong>di</strong>zione <strong>di</strong><br />

inizio<br />

Aggiungi <strong>di</strong>spositivo<br />

Aggiungere un <strong>di</strong>spositivo che verrà gestito con Powerfarm<br />

L'utente ha effettuato il login<br />

Il <strong>di</strong>spositivo è stato aggiunto<br />

Il <strong>di</strong>spositivo non è stato aggiunto<br />

Utente<br />

L'utente seleziona il pulsante “Configure”<br />

Descrizione Step Utente Sistema<br />

Extension 1:<br />

L'utente non ha<br />

inserito nulla nei<br />

campi obbligatori<br />

Extension 2:<br />

E' stato inserito un<br />

in<strong>di</strong>rizzo IP del<br />

<strong>di</strong>spositivo non<br />

valido<br />

1 Azione Trigger<br />

2 Richiede all'utente <strong>di</strong><br />

inserire le informazioni<br />

riguardanti il <strong>di</strong>spositivo<br />

3 Inserisce i dati del <strong>di</strong>spositivo e clicca sul<br />

pulsante “add”<br />

4 Conferma i dati inseriti<br />

dall'utente. Registra il<br />

nuovo <strong>di</strong>spositivo e<br />

mostra i suoi dati<br />

Step Utente non identificato<br />

Sistema<br />

4.a Mostra un messaggio<br />

d'errore “Inserire Campi<br />

Obbligatori”<br />

Step Utente non identificato<br />

Sistema<br />

4.b Mostra un messaggio<br />

d'errore “In<strong>di</strong>rizzo IP non<br />

valido”<br />

Pietro Neroni 566/2833 Pagina 63 <strong>di</strong> 117


Extension 3:<br />

E' stata aggiunta<br />

una <strong>di</strong>pendenza<br />

che provoca cicli<br />

all'interno del<br />

grafo delle<br />

<strong>di</strong>pendenze<br />

4.c Mostra un messaggio<br />

d'errore “Impossibile<br />

aggiungere le seguenti<br />

<strong>di</strong>pendenze” con la lista<br />

delle <strong>di</strong>pendenze non<br />

valide<br />

b) Eliminazione <strong>di</strong> un <strong>di</strong>spositivo<br />

Use case #1<br />

Obiettivo nel<br />

contesto<br />

Precon<strong>di</strong>zioni<br />

Con<strong>di</strong>zione finale<br />

<strong>di</strong> successo<br />

Con<strong>di</strong>zione finale<br />

<strong>di</strong> fallimento<br />

Attore primario<br />

Con<strong>di</strong>zione <strong>di</strong><br />

inizio<br />

Elimina Dispositivo<br />

Elimina il <strong>di</strong>spositivo scelto<br />

L'utente ha effettuato il login<br />

Il <strong>di</strong>spositivo è stato eliminato<br />

Il <strong>di</strong>spositivo non è stato eliminato<br />

Utente<br />

L'utente seleziona il pulsante “e<strong>di</strong>t” accanto al <strong>di</strong>spositivo<br />

Descrizione Step Utente Sistema<br />

1 Azione Trigger<br />

2 Mostra le informazioni<br />

relativi al <strong>di</strong>spositivo<br />

3 Seleziona il pulsante “delete”<br />

4 Chiede all'utente <strong>di</strong><br />

confermare l'eliminazione<br />

del <strong>di</strong>spositivo<br />

5 Conferma l'eliminazione del <strong>di</strong>spositivo<br />

6 Elimina il <strong>di</strong>spositivo e<br />

ritorna alla pagina <strong>di</strong><br />

configurazione<br />

Extension 1: Step Utente non identificato Sistema<br />

Pietro Neroni 566/2833 Pagina 64 <strong>di</strong> 117


6.a Mostra un messaggio<br />

d'errore “Impossibile<br />

eliminare il <strong>di</strong>spositivo”<br />

Pietro Neroni 566/2833 Pagina 65 <strong>di</strong> 117


6.8 Class Diagram<br />

Figura 37: class <strong>di</strong>agram relativo alla pagina <strong>di</strong> configurazione<br />

Pietro Neroni 566/2833 Pagina 66 <strong>di</strong> 117


6.9 Sequence Diagram<br />

Sequence Aggiungi <strong>di</strong>spositivi<br />

Figura 38: Sequence <strong>di</strong>agram per l'inserimento del <strong>di</strong>spositivo<br />

Pietro Neroni 566/2833 Pagina 67 <strong>di</strong> 117


Figura 39: continuo del sequence <strong>di</strong>agram per l'inserimento del <strong>di</strong>spositivo<br />

Pietro Neroni 566/2833 Pagina 68 <strong>di</strong> 117


Sequence Elimina Dispositivo<br />

Figura 40: Sequence <strong>di</strong>agram relativo all'eliminazione <strong>di</strong> un <strong>di</strong>spositivo<br />

Pietro Neroni 566/2833 Pagina 69 <strong>di</strong> 117


Sequence Visualizza grafo delle <strong>di</strong>pendenze<br />

Figura 41: Sequence <strong>di</strong>agram relativo alla visualizzazione del grafo delle<br />

<strong>di</strong>pendenze<br />

Pietro Neroni 566/2833 Pagina 70 <strong>di</strong> 117


7 VALIDAZIONE E TESTING<br />

Al termine della fase <strong>di</strong> progettazione sono stati effettuati dei test sull'applicazione.La<br />

prima funzionalità che è stata testata è quella relativa all'inserimento <strong>di</strong> un <strong>di</strong>spositivo<br />

omettendo i campi obbligatori (nome e in<strong>di</strong>rizzo IP). Ciò che è stato ottenuto è un<br />

messaggio d'errore che ci avvisa che i campi obbligatori non sono stati inseriti.<br />

Figura 42: Messaggi d'errore per il mancato<br />

inserimento dei campi obbligatori<br />

Pietro Neroni 566/2833 Pagina 71 <strong>di</strong> 117


Si è cercato poi <strong>di</strong> inserire un in<strong>di</strong>rizzo IP non valido ed è stato ottenuto il seguente<br />

messaggio<br />

Figura 43: Messaggio d'errore per l'inserimento <strong>di</strong> un<br />

in<strong>di</strong>rizzo IP non valido<br />

Si è poi testato il caso in cui durante l'inserimento del <strong>di</strong>spositivo, si sia provato a<br />

visualizzare il grafo con le <strong>di</strong>pendenze assegnate a quel <strong>di</strong>spositivo,senza che sia stata<br />

inserita una <strong>di</strong>pendenza. Sono stati ottenuti i seguenti messaggi d'errore<br />

Pietro Neroni 566/2833 Pagina 72 <strong>di</strong> 117


Infine è stato inserito un <strong>di</strong>spositivo con delle <strong>di</strong>pendenze che provocassero dei cicli<br />

nel grafo delle <strong>di</strong>pendenze.Nel nostro caso si è provato ad assegnare allo storage<br />

element SE08 la <strong>di</strong>pendenza con il controller e4_03a e una delle sue espansioni, questo<br />

come possiamo vedere dalla figura 44 genera dei cicli all'interno del grafo delle<br />

<strong>di</strong>pendenze.<br />

Figura 44: Assegnazione <strong>di</strong> <strong>di</strong>pendenze che causano cicli<br />

Figura 45: Visualizzazione del grado con delle <strong>di</strong>pendenze cicliche<br />

Pietro Neroni 566/2833 Pagina 73 <strong>di</strong> 117


Perciò le <strong>di</strong>pendenze non saranno assegnate e verrà mostrata la seguente pagina:<br />

Figura 46: Pagina <strong>di</strong> confugurazione del <strong>di</strong>spositivo atlasse08.na.infn.it dopo l'assegnazione<br />

<strong>di</strong> <strong>di</strong>pendenze cicliche<br />

Pietro Neroni 566/2833 Pagina 74 <strong>di</strong> 117


8 CONCLUSIONI E SVILUPPI FUTURI<br />

In conclusione, l'interfaccia web <strong>di</strong> Powerfarm consente agli amministratori del sito<br />

non solo <strong>di</strong> creare la struttura della farm, ma anche <strong>di</strong> spegnere o accendere un<br />

determinato <strong>di</strong>spositivo, un insieme <strong>di</strong> <strong>di</strong>spositivi, o tutta la farm.<br />

Attualmente, Powerfarm gestisce i <strong>di</strong>spositivi che fanno parte del Data Center Tier2<br />

del progetto ATLAS.<br />

La configurazione <strong>di</strong> un <strong>di</strong>spositivo tramite l'interfaccia web <strong>di</strong> Powefarm permette <strong>di</strong><br />

evitare errori che invece potrebbero capitare tramite l'inserimento manuale <strong>di</strong> un<br />

<strong>di</strong>spositivo, quali:<br />

• avere un <strong>di</strong>spositivo senza nome o senza in<strong>di</strong>rizzo IP oppure con uno non valido<br />

• un <strong>di</strong>spositivo con dei plugin non adeguati al suo tipo oppure con un percorso<br />

all'interno del file system errato.<br />

• grazie al controllo delle <strong>di</strong>pendenze hardware e software al momento della<br />

configurazione del <strong>di</strong>spositivo, saranno create delle farm che non conterranno<br />

delle <strong>di</strong>pendenze cicliche.<br />

Inoltre grazie al grafo delle <strong>di</strong>pendenze logiche sviluppato, si riesce <strong>di</strong> avere una<br />

visione complessiva del sistema che prima mancava completamente e allo stesso<br />

tempo permette <strong>di</strong> accedere facilmente ai dettagli dei <strong>di</strong>spositivi, facilitando ogni<br />

operazione che si vuole compiere.<br />

In futuro si prevede l'inserimento <strong>di</strong> una nuova farm da gestire tramite Powefarm,<br />

magari facendo con<strong>di</strong>videre uno o più <strong>di</strong>spositivi tra le varie farm.<br />

Un ulteriore possibile estensione potrebbe riguardare l'inserimento del modulo per la<br />

gestione delle emergenze nell'interfaccia web.<br />

Pietro Neroni 566/2833 Pagina 75 <strong>di</strong> 117


9 BIBLIOGRAFIA<br />

[1] Alessandra Doria Atlas Calcolo 2003<br />

[2] Grid computing - URL: http://it.wikipe<strong>di</strong>a.org/wiki/Grid_computing<br />

[3] Powerfarm: Power and Emergency Management Thread-based Software System<br />

for Grid and Data Center Infrastructures - S. Ricciar<strong>di</strong>, S. Iengo, M.Staffa, A.Doria, G.<br />

Carlino, L.Merola<br />

[4] Java: http://www.java.sun.com.<br />

[5] Xml.com: http://www.xml.com.<br />

[6] JavaServer Pages (JSP) <strong>Prof</strong>.ssa Anna Corazza<br />

http://people.na.infn.it/~corazza/<strong>di</strong>dattica<br />

[7] Drawing graphs with dot ,Emden R. Gansner and Eleftherios Koutsofios and<br />

Stephen North December 22, 2009 http://www.graphviz.org/pdf/dotguide.pdf<br />

[8] Apache Software Foundation:http://www.apache.org.<br />

[9] Tomcat:http://jakarta.apache.org/tomcat/index.html.<br />

[10]The Java Api for XML Parsing (JAXP) Tutorial:<br />

http://www.java.sun.com/xml/tutorial_intro.html.<br />

[11]Sara Eusebio, Sylvain Féjoz., Atlas Collaboration Records,<br />

http://library.web.cern.ch/library/Archives/isad/isaatlas.html<br />

Pietro Neroni 566/2833 Pagina 76 <strong>di</strong> 117


10 APPENDICE<br />

10.1 L'esperimento ATLAS<br />

Atlas ,acronimo <strong>di</strong> A Toroidal LHCApparatuS , è un rilevatore <strong>di</strong> particelle .<br />

Insieme ad altri 4 rilevatori ( ALICE, TOTEM, CMS, LHCb) fa parte della catena <strong>di</strong><br />

accellerazione collegata all'accelleratore <strong>di</strong> particelle LHC (Large Hadron Collider)<br />

del CERN <strong>di</strong> Ginevra.All'esperimento prendono parte 165 istituti <strong>di</strong>stribuiti su 35<br />

nazioni, composti da scienziati e ingegneri.<br />

Lo scopo del progetto ATLAS è quello <strong>di</strong> osservare fenomeni che riguardano particelle<br />

pesanti che non sono mai state stu<strong>di</strong>ate utilizzando gli accelleratori a bassa energia,<br />

con l'obiettivo <strong>di</strong> far luce su nuove teorie della fisica delle particelle oltre il modello<br />

standard[11].<br />

Infatti uno dei principali obiettivi <strong>di</strong> ATLAS è quello <strong>di</strong> investigare sull'ultimo pezzo<br />

del Modello Standard, il Bosone <strong>di</strong> Higgs.<br />

Il Bosone <strong>di</strong> Higgs è la particella ipotizzata dal fisico scozzese Peter Higgs per<br />

spiegare la <strong>di</strong>fferenza <strong>di</strong> massa tra fotoni e bosoni vettori W e Z, il bosone <strong>di</strong> Higgs<br />

interagirebbe insieme alle altre particelle determinandone la massa.<br />

L'obiettivo <strong>di</strong> un rilevatore <strong>di</strong> particelle è osservare il comportamento delle particelle<br />

prodotte da un acceleratore <strong>di</strong> particelle. Non basta quin<strong>di</strong> produrre particelle come i<br />

Pietro Neroni 566/2833 Pagina 77 <strong>di</strong> 117


protoni per rivelare tutti i fenomeni legati ad essi, ed alle loro interazioni, ma sono<br />

necessari i rilevatori per analizzare le particelle, la loro massa, quantità <strong>di</strong> moto,<br />

energie, cariche e spin nucleari.<br />

Per in<strong>di</strong>viduare tutte le particelle prodotte nel punto <strong>di</strong> interazione quando i raggi <strong>di</strong><br />

particelle collidono, i rivelatori solitamente sono progettati con una struttura “a<br />

cipolla” .<br />

Gli strati sono composti da rivelatori <strong>di</strong> vari tipi, e ciascuno stu<strong>di</strong>a uno specifico tipo <strong>di</strong><br />

particelle. Le <strong>di</strong>verse reazioni che le particelle causano in ogni strato, consentono la<br />

loro identificazione e la misura della quantità <strong>di</strong> moto delle energie.<br />

Più l'energia delle particelle prodotte aumenta, più il corrispondente rivelatore deve<br />

crescere in <strong>di</strong>mensioni per fermare effettivamente e misurare particelle più<br />

energetiche.<br />

Attualmente ATLAS è il più grande rivelatore <strong>di</strong> particelle mai costruito presso un<br />

collider.<br />

Il rivelatore ATLAS è composto da una serie <strong>di</strong> cilindri concentrati intorno al punto <strong>di</strong><br />

interazione, dove si svolge lo scontro fra i fasci <strong>di</strong> protoni uscenti da LHC, che si può<br />

<strong>di</strong>videre in quattro parti principali:<br />

– rivelatore interno<br />

Pietro Neroni 566/2833 Pagina 78 <strong>di</strong> 117


– calorimetri<br />

– spettrometri muonici<br />

– sistema <strong>di</strong> magneti<br />

Ciascuna <strong>di</strong> queste parti a sua volta si può <strong>di</strong>videre in <strong>di</strong>versi strati.<br />

I rivelatori sono complementari: quello interno traccia precisamente le particelle, i<br />

calorimetri misurano l'energia delle particelle più facili da fermare e lo spettrometro<br />

muonico produce misure ulteriori sui muoni più penetranti.<br />

Il sistema <strong>di</strong> magneti <strong>di</strong>rotta le particelle cariche nel rivelatore interno e nello<br />

spettrometro muonico per permettere la misurazione della quantità <strong>di</strong> moto.<br />

L'esperimento ATLAS sull'acceleratore <strong>di</strong> particelle LHC, farà scontrare protoni e<br />

protoni ad altissima energia producendo particelle tra cui forse il Bosone <strong>di</strong> Higgs.<br />

Questo non verrà svelato <strong>di</strong>rettamente ma me<strong>di</strong>ante i suoi prodotti <strong>di</strong> deca<strong>di</strong>mento,<br />

come quattro muoni energetici o attraverso lo stu<strong>di</strong>o delle violazioni della<br />

conservazione della quantità <strong>di</strong> moto durante una collisione.<br />

L'analisi dei dati raccolti ad LHC è oggi possibile solo tramite modelli <strong>di</strong> calcolo che<br />

operano secondo il modello delle griglie computazionali.<br />

10.2 Il co<strong>di</strong>ce<br />

XMLDatabase.java<br />

package powerfarm;<br />

import java.io.*;<br />

import java.util.*;<br />

import java.io.File;<br />

import java.io.FileInputStream;<br />

import java.io.FileOutputStream;<br />

import java.io.OutputStream;<br />

import java.util.ArrayList;<br />

import java.util.Arrays;<br />

import java.util.Hashtable;<br />

import java.util.Iterator;<br />

import java.util.List;<br />

import java.util.Map;<br />

import java.util.Map.Entry;<br />

import java.util.Set;<br />

import java.util.concurrent.locks.ReentrantLock;<br />

import javax.xml.parsers.DocumentBuilder;<br />

import javax.xml.parsers.DocumentBuilderFactory;<br />

Pietro Neroni 566/2833 Pagina 79 <strong>di</strong> 117


import javax.xml.transform.Transformer;<br />

import javax.xml.transform.TransformerFactory;<br />

import javax.xml.xpath.XPath;<br />

import javax.xml.xpath.XPathConstants;<br />

import javax.xml.xpath.XPathExpression;<br />

import javax.xml.xpath.XPathFactory;<br />

import org.apache.xml.serialize.OutputFormat;<br />

import org.apache.xml.serialize.XMLSerializer;<br />

import org.w3c.dom.Document;<br />

import org.w3c.dom.Element;<br />

import org.w3c.dom.NamedNodeMap;<br />

import org.w3c.dom.Node;<br />

import org.w3c.dom.NodeList;<br />

import org.xml.sax.ErrorHandler;<br />

import org.xml.sax.SAXParseException;<br />

/*<br />

* Classe utilizzata dalla classe webpowerfam per la gestione dei file <strong>di</strong> configurazione<br />

*/<br />

public class XMLDatabase implements IDatabase, ErrorHandler<br />

{<br />

protected String basePath;<br />

protected Document device;<br />

protected Document dependency;<br />

protected Document link;<br />

protected Document set;<br />

protected Document plugins;<br />

protected File deviceFile;<br />

protected File dependencyFile;<br />

protected File linkFile;<br />

protected File setFile;<br />

protected File pluginsFile;<br />

protected String deviceDtdFileName;<br />

protected String dependencyDtdFileName;<br />

protected String linkDtdFileName;<br />

protected String setDtdFileName;<br />

protected String pluginsDtdFileName;<br />

protected TransformerFactory tranFact;<br />

protected Transformer transfor;<br />

protected DocumentBuilder builder;<br />

protected String powerOffDependencyName;<br />

protected String powerOnDependencyName;<br />

protected boolean validated;<br />

protected ReentrantLock mutex;<br />

protected String error;<br />

protected String deviceFileName;<br />

protected String dependencyFileName;<br />

protected String linkFileName;<br />

protected String setFileName;<br />

protected String pluginsFileName;<br />

long deviceFileLastMo<strong>di</strong>fy;<br />

long dependencyFileLastMo<strong>di</strong>fy;<br />

long linkFileLastMo<strong>di</strong>fy;<br />

long setFileLastMo<strong>di</strong>fy;<br />

long pluginsFileLastMo<strong>di</strong>fy;<br />

/**<br />

* Ritorna true se non sono state effettuate ultieriori mo<strong>di</strong>fiche dei file <strong>di</strong> configurazione<br />

dall'ultimo reload<br />

* @return boolean<br />

*/<br />

public boolean isUpdated()<br />

{<br />

try<br />

{<br />

return ((this.deviceFileLastMo<strong>di</strong>fy >= new File(this.basePath +<br />

this.deviceFileName).lastMo<strong>di</strong>fied()) &&<br />

Pietro Neroni 566/2833 Pagina 80 <strong>di</strong> 117


(this.dependencyFileLastMo<strong>di</strong>fy >= new File(this.basePath +<br />

this.dependencyFileName).lastMo<strong>di</strong>fied()) &&<br />

(this.linkFileLastMo<strong>di</strong>fy >= new File(this.basePath +<br />

this.linkFileName).lastMo<strong>di</strong>fied())&&<br />

(this.setFileLastMo<strong>di</strong>fy >= new File(this.basePath +<br />

this.setFileName).lastMo<strong>di</strong>fied())&&<br />

(this.pluginsFileLastMo<strong>di</strong>fy >= new<br />

File("/usr"+"/local"+"/tomcat"+"/webapps"+"/Webpowerfarm"+"/" +<br />

this.pluginsFileName).lastMo<strong>di</strong>fied()));<br />

}<br />

catch (Exception e) {<br />

}<br />

return false;<br />

}<br />

/**<br />

* Aggiorna tutti i file <strong>di</strong> configurazione xml utilizzati da Powerfarm<br />

* @throws Exception<br />

* @return boolean<br />

*/<br />

public boolean reload() throws Exception<br />

{<br />

try {<br />

this.deviceDtdFileName = this.deviceFileName.replaceFirst(".xml", ".dtd");<br />

this.dependencyDtdFileName = this.dependencyFileName.replaceFirst(".xml", ".dtd");<br />

this.linkDtdFileName = this.linkFileName.replaceFirst(".xml", ".dtd");<br />

this.setDtdFileName = this.setFileName.replaceFirst(".xml", ".dtd");<br />

this.pluginsDtdFileName = this.pluginsFileName.replaceFirst(".xml", ".dtd");<br />

this.deviceFile = new File(this.basePath + this.deviceFileName);<br />

this.dependencyFile = new File(this.basePath + this.dependencyFileName);<br />

this.linkFile = new File(this.basePath + this.linkFileName);<br />

this.setFile = new File(this.basePath + this.setFileName);<br />

this.pluginsFile = new File("/usr"+"/local"+"/tomcat"+"/webapps"+ "/WebPowerfarm"<br />

+"/"+ this.pluginsFileName);<br />

this.deviceFileLastMo<strong>di</strong>fy = this.deviceFile.lastMo<strong>di</strong>fied();<br />

this.dependencyFileLastMo<strong>di</strong>fy = this.dependencyFile.lastMo<strong>di</strong>fied();<br />

this.linkFileLastMo<strong>di</strong>fy = this.linkFile.lastMo<strong>di</strong>fied();<br />

this.setFileLastMo<strong>di</strong>fy = this.setFile.lastMo<strong>di</strong>fied();<br />

this.pluginsFileLastMo<strong>di</strong>fy = this.pluginsFile.lastMo<strong>di</strong>fied();<br />

this.device = this.builder.parse(this.deviceFile);<br />

this.dependency = this.builder.parse(this.dependencyFile);<br />

this.link = this.builder.parse(this.linkFile);<br />

this.set = this.builder.parse(this.setFile);<br />

this.plugins = this.builder.parse(this.pluginsFile);<br />

return true;<br />

}<br />

catch (Exception e) {<br />

throw e;<br />

}<br />

}<br />

public XMLDatabase() throws Exception {<br />

this("xml/");<br />

}<br />

public XMLDatabase (String xmlDirPath)<br />

throws Exception<br />

{<br />

this.deviceFileName = "devices.xml";<br />

this.dependencyFileName = "dependencies.xml";<br />

this.linkFileName = "links.xml";<br />

this.setFileName="set.xml";<br />

Pietro Neroni 566/2833 Pagina 81 <strong>di</strong> 117


this.pluginsFileName="plugins.xml";<br />

this.deviceFileLastMo<strong>di</strong>fy = 0L; this.dependencyFileLastMo<strong>di</strong>fy = 0L;<br />

this.linkFileLastMo<strong>di</strong>fy = 0L;<br />

this.setFileLastMo<strong>di</strong>fy=0L; this.pluginsFileLastMo<strong>di</strong>fy=0L;<br />

try<br />

{<br />

this.mutex = new ReentrantLock();<br />

this.error = "";<br />

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();<br />

factory.setValidating(true);<br />

factory.setNamespaceAware(true);<br />

this.builder = factory.newDocumentBuilder();<br />

this.basePath = xmlDirPath + "/";<br />

reload();<br />

this.tranFact = TransformerFactory.newInstance();<br />

this.transfor = this.tranFact.newTransformer();<br />

this.transfor.setOutputProperty("omit-xml-declaration", "no");<br />

this.transfor.setOutputProperty("enco<strong>di</strong>ng", "ISO-8859-1");<br />

this.powerOnDependencyName = "power-on";<br />

this.powerOffDependencyName = "power-off";<br />

this.builder.setErrorHandler(this);<br />

}<br />

catch (Exception e) {<br />

throw e;<br />

}<br />

}<br />

/**<br />

* Effettua tramite XPath la query contenuta nel parametro xq, sul DOM doc<br />

* @param xq<br />

* @param doc<br />

* @return NodeList<br />

*/<br />

protected NodeList XPath(String xq, Document doc) {<br />

try {<br />

XPathFactory factory = XPathFactory.newInstance();<br />

XPath xpath = factory.newXPath();<br />

XPathExpression expr = xpath.compile(xq);<br />

Object result = expr.evaluate(doc, XPathConstants.NODESET);<br />

return ((NodeList)result);<br />

}<br />

catch (Exception e) {<br />

}<br />

return null;<br />

}<br />

/**<br />

* Ritorna la lista <strong>di</strong> tutti i <strong>di</strong>spositivi presenti nel file device.xml<br />

* @return NodeList<br />

*/<br />

protected NodeList selectNodes() {<br />

return XPath("devices/device/@name", this.device); }<br />

/**<br />

* Ritorna la lista delle farm presenti nel file device.xml<br />

* @return NodeList<br />

*/<br />

protected NodeList selectFarms() {<br />

return XPath("devices/device/[@type=\"farm\"]", this.device); }<br />

/**<br />

* Ritorna l'elemento nel file device.xml che rappresenta il <strong>di</strong>spositivo name<br />

* @param name<br />

* @return NodeList<br />

*/<br />

protected NodeList selectNode(String name) {<br />

return XPath("devices/device[@name=\"" + name + "\"]", this.device);<br />

}<br />

Pietro Neroni 566/2833 Pagina 82 <strong>di</strong> 117


**<br />

* Ritorna la lista dei <strong>di</strong>spositivi presenti nel file <strong>di</strong> configurazione device.xml<br />

* @return String[]<br />

*/<br />

public String[] getDevices()<br />

{<br />

ArrayList names = new ArrayList();<br />

try {<br />

NodeList nodes = this.device.getElementsByTagName("device");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if (!(node.getAttribute("type").toLowerCase().equals("farm")))<br />

names.add(node.getAttribute("name"));<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); names.clear(); }<br />

return ((String[])names.toArray(new String[0])); }<br />

/**<br />

* Ritorna la lista delle farm presenti nel file <strong>di</strong> configurazione device.xml<br />

* @return String[]<br />

*/<br />

public String[] getFarms() {<br />

ArrayList names = new ArrayList();<br />

try {<br />

NodeList nodes = this.device.getElementsByTagName("device");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if (node.getAttribute("type").toLowerCase().equals("farm"))<br />

names.add(node.getAttribute("name"));<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); names.clear(); }<br />

return ((String[])names.toArray(new String[0])); }<br />

/**<br />

* Ritorna la lista <strong>di</strong> <strong>di</strong>spositivi che appartengono alla farm farmName<br />

* @param String farmName<br />

* @return String[]<br />

*/<br />

public String[] getDevicesOfFarm(String farmName) {<br />

ArrayList names = new ArrayList();<br />

try {<br />

NodeList nodes = XPath("dependencies/arc[@source=\"" + farmName +<br />

"\"]/@target", this.dependency);<br />

for (int i = 0; i < nodes.getLength(); ++i)<br />

names.add(nodes.item(i).getNodeValue());<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); names.clear(); }<br />

return ((String[])names.toArray(new String[0])); }<br />

/**<br />

* Ritorna il nome della farm a cui appartiene il <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @return String<br />

*/<br />

public String getFarmOfDevice(String deviceName) {<br />

try {<br />

NodeList nodes = XPath("dependencies/arc[@target=\"" + deviceName +<br />

"\"]/@source", this.dependency);<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Node node = nodes.item(i);<br />

if (Arrays.asList(getFarms()).contains(node.getNodeValue()))<br />

Pietro Neroni 566/2833 Pagina 83 <strong>di</strong> 117


eturn node.getNodeValue();<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

return null;<br />

}<br />

/**<br />

* Ritorna gli attributi presenti nel file <strong>di</strong> configurazione device.xml del <strong>di</strong>spositivo name<br />

* @param String name<br />

* @return Hashtable<br />

*/<br />

public Hashtable getAttributesOfDevice(String name) {<br />

Hashtable attributes = new Hashtable();<br />

try<br />

{<br />

NodeList nodes = selectNode(name);<br />

if (nodes == null) {<br />

return attributes;<br />

}<br />

Node node = nodes.item(0);<br />

NamedNodeMap nodeMap = node.getAttributes();<br />

for (int i = 0; i < nodeMap.getLength(); ++i)<br />

attributes.put(nodeMap.item(i).getNodeName(),<br />

nodeMap.item(i).getNodeValue());<br />

}<br />

catch (Exception e)<br />

{<br />

this.error = e.toString(); }<br />

return attributes;<br />

}<br />

protected Hashtable getTagOf(String name, String query,<br />

Document doc) {<br />

Hashtable plugins = new Hashtable();<br />

NodeList nodes = XPath(query, doc);<br />

if (nodes == null) {<br />

return plugins;<br />

}<br />

Node node = nodes.item(0);<br />

for (int i = 0; i < node.getChildNodes().getLength(); ++i) {<br />

Node child = node.getChildNodes().item(i);<br />

if (child == null) {<br />

continue;<br />

}<br />

NamedNodeMap nodeMap = child.getAttributes();<br />

if (nodeMap == null) {<br />

continue;<br />

}<br />

Hashtable attributes = new Hashtable();<br />

for (int j = 0; j < nodeMap.getLength(); ++j) {<br />

attributes.put(nodeMap.item(j).getNodeName(),<br />

nodeMap.item(j).getNodeValue());<br />

}<br />

plugins.put(child.getNodeName(), attributes);<br />

}<br />

return plugins;<br />

}<br />

/**<br />

* Effettua la serializzazione del DOM doc sul canale <strong>di</strong> uscita out<br />

* @param doc<br />

* @param out<br />

* @throws Exception<br />

*/<br />

protected void serialize(Document doc, OutputStream out) throws Exception {<br />

OutputFormat format = new OutputFormat(doc);<br />

format.setLineWidth(100);<br />

Pietro Neroni 566/2833 Pagina 84 <strong>di</strong> 117


format.setIndenting(true);<br />

format.setIndent(2);<br />

format.setPreserveEmptyAttributes(true);<br />

XMLSerializer serializer = new XMLSerializer(out, format);<br />

serializer.serialize(doc);<br />

}<br />

/**<br />

* Effettua le mo<strong>di</strong>fiche sulla base DOM doc al file xmlFile<br />

* @param doc<br />

* @param xmlFile<br />

* @param dtdFileName<br />

* @return Document<br />

*/<br />

protected Document saveDocument(Document doc, File xmlFile, String dtdFileName) {<br />

try {<br />

this.mutex.lock();<br />

File tmpFile = new File(xmlFile.getParentFile() + "/tmp.xml");<br />

doc.normalize();<br />

FileOutputStream tFos = new FileOutputStream(tmpFile);<br />

serialize(doc, tFos);<br />

tFos.close();<br />

this.validated = true;<br />

doc = this.builder.parse(tmpFile);<br />

if (!(this.validated)) {<br />

throw new Exception();<br />

}<br />

FileInputStream fis = new FileInputStream(tmpFile);<br />

FileOutputStream fos = new FileOutputStream(xmlFile);<br />

try {<br />

byte[] buf = new byte[1024];<br />

int i = 0;<br />

while ((i = fis.read(buf)) != -1)<br />

fos.write(buf, 0, i);<br />

}<br />

catch (Exception e)<br />

{<br />

throw e;<br />

}<br />

fis.close();<br />

fos.close();<br />

tmpFile.delete();<br />

this.mutex.unlock();<br />

}<br />

catch (Exception e) {<br />

this.mutex.unlock();<br />

return null;<br />

}<br />

return doc;<br />

}<br />

/**<br />

* Inserisce nel file <strong>di</strong> configurazione device.xml il <strong>di</strong>spositivo name<br />

* @param String name<br />

* @return boolean<br />

*/<br />

public boolean addDevice(String name) {<br />

try {<br />

if (this.device.getElementById(name) == null)<br />

{Element node = this.device.createElement("device");<br />

node.setAttribute("name", name);<br />

node.setAttribute("type", "");<br />

node.setAttribute("description", "");<br />

node.setAttribute("address", "");<br />

node.setAttribute("lock-on", "");<br />

node.setAttribute("lock-off", "");<br />

node.setAttribute("selected", "");<br />

node.setIdAttribute("name", true);<br />

Element actionElement = this.device.createElement("action");<br />

Pietro Neroni 566/2833 Pagina 85 <strong>di</strong> 117


Element onElement = this.device.createElement("on");<br />

onElement.setAttribute("plugin", "");<br />

onElement.setAttribute("args", "");<br />

onElement.setAttribute("description", "");<br />

onElement.setAttribute("timeout", "");<br />

Element offSoftElement = this.device.createElement("off-soft");<br />

offSoftElement.setAttribute("plugin", "");<br />

offSoftElement.setAttribute("args", "");<br />

offSoftElement.setAttribute("description", "");<br />

offSoftElement.setAttribute("timeout", "");<br />

Element offHardElement = this.device.createElement("off-hard");<br />

offHardElement.setAttribute("plugin", "");<br />

offHardElement.setAttribute("args", "");<br />

offHardElement.setAttribute("description", "");<br />

Element checkOnElement = this.device.createElement("check-on");<br />

checkOnElement.setAttribute("plugin", "");<br />

checkOnElement.setAttribute("args", "");<br />

checkOnElement.setAttribute("description", "");<br />

Element checkOffElement = this.device.createElement("check-off");<br />

checkOffElement.setAttribute("plugin", "");<br />

checkOffElement.setAttribute("args", "");<br />

checkOffElement.setAttribute("description", "");<br />

actionElement.appendChild(onElement);<br />

actionElement.appendChild(offSoftElement);<br />

actionElement.appendChild(offHardElement);<br />

actionElement.appendChild(checkOnElement);<br />

actionElement.appendChild(checkOffElement);<br />

node.appendChild(actionElement);<br />

this.device.getLastChild().appendChild(node);<br />

this.device.normalize();<br />

Document tmp = saveDocument(this.device, this.deviceFile,<br />

this.deviceDtdFileName);<br />

if (tmp != null)<br />

this.device = tmp;<br />

else<br />

return false;<br />

}<br />

}<br />

catch (Exception e)<br />

{return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Aggiorna nel file <strong>di</strong> configurazione device.xml l'elemento node con gli attributi attributes<br />

* @param Element node<br />

* @param Hashtable attributes<br />

* @return boolean<br />

*/<br />

protected boolean updateAttributes(Element node, Hashtable attributes) {<br />

while (node.getAttributes().getLength() > 0) {<br />

node.removeAttribute(node.getAttributes().item(0).getNodeName());<br />

}<br />

for (Iterator it = attributes.entrySet().iterator(); it.hasNext(); ) {<br />

Map.Entry entry = (Map.Entry)it.next();<br />

node.setAttribute((String)entry.getKey(), (String)entry.getValue());<br />

}<br />

return true;<br />

}<br />

/**<br />

* Inserisce nel file <strong>di</strong> configurazione device.xml gli attributi attributes del <strong>di</strong>spositivo<br />

name<br />

* @param String name<br />

* @param Hashtable attributes<br />

* @return boolean<br />

*/<br />

Pietro Neroni 566/2833 Pagina 86 <strong>di</strong> 117


public boolean setAttributesOfDevice(String name, Hashtable attributes)<br />

{<br />

try {<br />

if (attributes == null) {<br />

return false;<br />

}<br />

Element node = this.device.getElementById(name);<br />

if (node == null) {<br />

return false;<br />

}<br />

attributes.put("name", name);<br />

updateAttributes(node, attributes);<br />

Document tmp = saveDocument(this.device, this.deviceFile,<br />

this.deviceDtdFileName);<br />

if (tmp != null) {<br />

this.device = tmp; return true;<br />

}<br />

return false;<br />

}<br />

catch (Exception e) {<br />

return false;<br />

}<br />

}<br />

protected boolean setNodeTag(String nodeName, String tagName, String tagSubName,<br />

Hashtable attributes) {<br />

boolean ret = true;<br />

try {<br />

Node root = this.device.getElementById(nodeName);<br />

if (root != null) {<br />

Node plugin = null;<br />

NodeList select = XPath("devices/device[@name=\"" + nodeName + "\"]/" +<br />

tagName, this.device);<br />

if (select.getLength() == 0) {<br />

plugin = this.device.createElement(tagName);<br />

root.appendChild(plugin);<br />

}<br />

else {<br />

plugin = select.item(0);<br />

}<br />

Node pluginSub = null;<br />

select = XPath("devices/device[@name=\"" + nodeName + "\"]/" + tagName +<br />

"/" + tagSubName, this.device);<br />

if (select.getLength() == 0) {<br />

pluginSub = this.device.createElement(tagSubName);<br />

plugin.appendChild(pluginSub);<br />

}<br />

else<br />

{pluginSub = select.item(0);<br />

}<br />

updateAttributes((Element)pluginSub, attributes);<br />

}<br />

else {<br />

ret = false;<br />

}<br />

Document tmp = saveDocument(this.device, this.deviceFile,<br />

this.deviceDtdFileName);<br />

if (tmp != null) {<br />

this.device = tmp; return ret;<br />

}<br />

return false;<br />

}<br />

catch (Exception e) {<br />

return false;<br />

}<br />

}<br />

/**<br />

Pietro Neroni 566/2833 Pagina 87 <strong>di</strong> 117


* Inserisce nel file <strong>di</strong> configurazione dependences.xml la <strong>di</strong>pendenza che rappresenta<br />

l'appartenenza del <strong>di</strong>spositivo deviceName alla farm farmName<br />

* @param String farmName<br />

* @param String deviceName<br />

* @return boolean<br />

*/<br />

public boolean setFarmOfDevice(String farmName, String deviceName)<br />

{<br />

if (!(Arrays.asList(getDevices()).contains(deviceName))) {<br />

return false;<br />

}<br />

if (!(Arrays.asList(getFarms()).contains(farmName))) {<br />

addFarm(farmName);<br />

}<br />

String oldFarmName = getFarmOfDevice(deviceName);<br />

if (farmName.equals(oldFarmName)) {<br />

return true;<br />

}<br />

if ((oldFarmName != null) && (!(removeDeviceOfFarm(deviceName, oldFarmName)))) {<br />

return false;<br />

}<br />

Element arcElement = this.dependency.createElement("arc");<br />

if (arcElement == null) {<br />

return false;<br />

}<br />

arcElement.setAttribute("source", farmName);<br />

arcElement.setAttribute("target", deviceName);<br />

this.dependency.getLastChild().appendChild(arcElement);<br />

Document tmp = saveDocument(this.dependency, this.dependencyFile,<br />

this.dependencyDtdFileName);<br />

if (tmp != null)<br />

this.dependency = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Rimuove dal file <strong>di</strong> configurazione dependences.xml la <strong>di</strong>pendenza che rappresenta<br />

l'appartenenza del <strong>di</strong>spositivo deviceName alla farm farmName<br />

* @param String farmName<br />

* @param String deviceName<br />

* @return boolean<br />

*/<br />

public boolean removeDeviceOfFarm(String deviceName, String farmName)<br />

{<br />

String oldFarmName;<br />

if ((!(Arrays.asList(getFarms()).contains(farmName))) ||<br />

(!(Arrays.asList(getDevices()).contains(deviceName))) ||<br />

((oldFarmName = getFarmOfDevice(deviceName)) == null))<br />

{<br />

return false;<br />

}<br />

NodeList nodes = XPath("dependencies/arc[@source=\"" + farmName + "\"][@target=\"" +<br />

deviceName + "\"]", this.dependency);<br />

if (nodes == null) {<br />

return false;<br />

}<br />

Node arcElement = nodes.item(0);<br />

arcElement.getParentNode().removeChild(arcElement);<br />

Document tmp = saveDocument(this.dependency, this.dependencyFile,<br />

this.dependencyDtdFileName);<br />

if (tmp != null)<br />

this.dependency = tmp;<br />

else {<br />

return false;<br />

}<br />

Pietro Neroni 566/2833 Pagina 88 <strong>di</strong> 117


nodes = XPath("dependencies/arc[@source=\"" + farmName + "\"]", this.dependency);<br />

if (nodes.getLength() == 0) {<br />

return removeFarm(farmName);<br />

}<br />

return true;<br />

}<br />

/**<br />

* Rimuove dal file <strong>di</strong> configurazione device.xml il <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @return boolean<br />

*/<br />

public boolean removeDevice(String deviceName)<br />

{<br />

if (!(Arrays.asList(getDevices()).contains(deviceName))) {<br />

return false;<br />

}<br />

boolean success = true;<br />

String farm = getFarmOfDevice(deviceName);<br />

if ((farm != null) && (!(farm.equals("")))) {<br />

success = removeDeviceOfFarm(deviceName, farm);<br />

}<br />

success = removeDependenciesOfDevice(deviceName, true);<br />

success = removeDependenciesOfDevice(deviceName, false);<br />

Element deviceElement = this.device.getElementById(deviceName);<br />

if (deviceElement == null) {<br />

return false;<br />

}<br />

deviceElement.getParentNode().removeChild(deviceElement);<br />

Document tmp = saveDocument(this.device, this.deviceFile, this.deviceDtdFileName);<br />

if (tmp != null)<br />

this.device = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Rimuove dal file <strong>di</strong> configurazione device.xml il <strong>di</strong>spositivo farmName che rappresenta la<br />

farm da eliminare<br />

* @param String farmName<br />

* @return boolean<br />

*/<br />

protected boolean removeFarm(String farmName)<br />

{<br />

if (!(Arrays.asList(getFarms()).contains(farmName))) {<br />

return false;<br />

}<br />

Element deviceElement = this.device.getElementById(farmName);<br />

if (deviceElement == null) {<br />

return false;<br />

}<br />

deviceElement.getParentNode().removeChild(deviceElement);<br />

Document tmp = saveDocument(this.device, this.deviceFile, this.deviceDtdFileName);<br />

if (tmp != null)<br />

this.device = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Inserisce nel file <strong>di</strong> configurazione device.xml un <strong>di</strong>spositivo farmName che rappresenta la<br />

nuova farm creata<br />

* @param String farmName<br />

* @return boolean<br />

Pietro Neroni 566/2833 Pagina 89 <strong>di</strong> 117


*/<br />

protected boolean addFarm(String farmName) {<br />

try {<br />

if (this.device.getElementById(farmName) == null)<br />

{Element node = this.device.createElement("device");<br />

node.setAttribute("name", farmName);<br />

node.setAttribute("type", "farm");<br />

node.setIdAttribute("name", true);<br />

Element actionElement = this.device.createElement("action");<br />

Element onElement = this.device.createElement("on");<br />

onElement.setAttribute("plugin", "");<br />

Element offSoftElement = this.device.createElement("off-soft");<br />

offSoftElement.setAttribute("plugin", "");<br />

Element offHardElement = this.device.createElement("off-hard");<br />

offHardElement.setAttribute("plugin", "");<br />

Element checkOnElement = this.device.createElement("check-on");<br />

checkOnElement.setAttribute("plugin", "");<br />

Element checkOffElement = this.device.createElement("check-off");<br />

checkOffElement.setAttribute("plugin", "");<br />

actionElement.appendChild(onElement);<br />

actionElement.appendChild(offSoftElement);<br />

actionElement.appendChild(offHardElement);<br />

actionElement.appendChild(checkOnElement);<br />

actionElement.appendChild(checkOffElement);<br />

node.appendChild(actionElement);<br />

this.device.getLastChild().appendChild(node);<br />

this.device.normalize();<br />

Document tmp = saveDocument(this.device, this.deviceFile,<br />

this.deviceDtdFileName);<br />

if (tmp != null)<br />

this.device = tmp;<br />

else<br />

return false;<br />

}<br />

}<br />

catch (Exception e) {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Restituisce tutte le <strong>di</strong>pendenze del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param boolean incoming<br />

* @return String[]<br />

*/<br />

public String[] getDependenciesOfDevice(String deviceName, boolean incoming) {<br />

ArrayList names = new ArrayList();<br />

NodeList nodes = (incoming) <br />

XPath("dependencies/arc[@target=\"" + deviceName + "\"]/@source",<br />

this.dependency) :<br />

XPath("dependencies/arc[@source=\"" + deviceName +<br />

"\"]/@target", this.dependency);<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

String dep = nodes.item(i).getNodeValue();<br />

if (!(Arrays.asList(getFarms()).contains(dep)))<br />

names.add(dep);<br />

}<br />

return ((String[])names.toArray(new String[0]));<br />

}<br />

protected String[] getAllDepthDependenciesOfDevice(String name, ArrayList reached,<br />

boolean incoming) {<br />

for (String child : getDependenciesOfDevice(name, incoming)) {<br />

getAllDepthDependenciesOfDevice(child, reached, incoming);<br />

}<br />

reached.add(name);<br />

Pietro Neroni 566/2833 Pagina 90 <strong>di</strong> 117


eturn ((String[])reached.toArray(new String[0])); }<br />

public String[] getAllDepthDependenciesOfDevice(String name, boolean incoming) {<br />

return getAllDepthDependenciesOfDevice(name, new ArrayList(), incoming); }<br />

public String[] getAllDepthDependenciesOfDevice(String[] list, boolean incoming) {<br />

ArrayList depList = new ArrayList();<br />

for (String parent : list) {<br />

for (String child : getAllDepthDependenciesOfDevice(parent, incoming)) {<br />

if (!(depList.contains(child))) {<br />

depList.add(child);<br />

}<br />

}<br />

}<br />

return ((String[])depList.toArray(new String[0])); }<br />

public String[] getAllDepthDependenciesOfDevice(ArrayList list, boolean incoming) {<br />

return getAllDepthDependenciesOfDevice((String[])list.toArray(new String[0]),<br />

incoming);<br />

}<br />

/**<br />

* Inserisce nel file <strong>di</strong> configurazione dependencies.xml tutte le <strong>di</strong>pendenze dependences del<br />

<strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param String[] dependences<br />

* @param boolean incoming<br />

* @return boolean<br />

*/<br />

public boolean setDependenciesOfDevice(String deviceName, String[] dependencies, boolean<br />

incoming) {<br />

removeDependenciesOfDevice(deviceName, incoming);<br />

for (String dep : dependencies) {<br />

if (!(Arrays.asList(getDevices()).contains(dep))) {<br />

this.error = "device '" + dep + "' not exists.";<br />

return false;<br />

}<br />

}<br />

Hashtable attributes = new Hashtable();<br />

for (String dep : dependencies) {<br />

Element newDep = this.dependency.createElement("arc");<br />

if (!(incoming)) {<br />

newDep.setAttribute("source", deviceName);<br />

newDep.setAttribute("target", dep);<br />

}<br />

else {<br />

newDep.setAttribute("source", deviceName);<br />

newDep.setAttribute("target", dep);<br />

}<br />

this.dependency.getLastChild().appendChild(newDep);<br />

}<br />

Document tmp = saveDocument(this.dependency, this.dependencyFile,<br />

this.dependencyDtdFileName);<br />

if (tmp != null)<br />

this.dependency = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

public boolean removeDependenciesOfDevice(String deviceName, boolean incoming)<br />

{<br />

if (!(Arrays.asList(getDevices()).contains(deviceName))) {<br />

return false;<br />

}<br />

NodeList nodes = (incoming) <br />

Pietro Neroni 566/2833 Pagina 91 <strong>di</strong> 117


XPath("dependencies/arc[@target=\"" + deviceName + "\"]",<br />

this.dependency) :<br />

XPath("dependencies/arc[@source=\"" + deviceName + "\"]",<br />

this.dependency);<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Node node = nodes.item(i);<br />

Node parent = node.getParentNode();<br />

parent.removeChild(node);<br />

}<br />

Document tmp = saveDocument(this.dependency, this.dependencyFile,<br />

this.dependencyDtdFileName);<br />

if (tmp != null)<br />

this.dependency = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Restituisce una lista <strong>di</strong> plugin del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @return String[]<br />

*/<br />

public String[] getActionsOfDevice(String deviceName) {<br />

try {<br />

Hashtable plugin = getTagOf(deviceName, "devices/device[@name=\"" + deviceName<br />

+ "\"]/action", this.device);<br />

return ((String[])plugin.keySet().toArray(new String[0]));<br />

}<br />

catch (Exception e) {<br />

}<br />

return new String[0];<br />

}<br />

/**<br />

* Restituisce i link delle pagine <strong>di</strong> monitoraggio del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @return String[]<br />

*/<br />

public String[] getLinksOfDevice(String deviceName)<br />

{<br />

try {<br />

Hashtable plugin = getTagOf(deviceName, "links/link[@name=\"" + deviceName +<br />

"\"]", this.link);<br />

return ((String[])plugin.keySet().toArray(new String[0]));<br />

}<br />

catch (Exception e) {<br />

}<br />

return new String[0];<br />

}<br />

/**<br />

* Restituisce gli attributi del plugin passato come argomento del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param String action<br />

* @return Hashtable<br />

*/<br />

public Hashtable getActionAttributesOfDevice(String deviceName, String action)<br />

{<br />

try {<br />

Hashtable plugin = getTagOf(deviceName, "devices/device[@name=\"" + deviceName<br />

+ "\"]/action", this.device);<br />

return ((Hashtable)plugin.get(action));<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

Pietro Neroni 566/2833 Pagina 92 <strong>di</strong> 117


eturn null;<br />

}<br />

/**<br />

* Restituisce gli attributi del link passato come argomento del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param String link<br />

* @return Hashtable<br />

*/<br />

public Hashtable getLinkAttributesOfDevice(String deviceName, String link)<br />

{<br />

try {<br />

Hashtable plugin = getTagOf(deviceName, "links/link[@name=\"" + deviceName +<br />

"\"]", this.link);<br />

return ((Hashtable)plugin.get(link));<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

return null;<br />

}<br />

/**<br />

* Imposta gli attributi del plugin passato come argomento del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param String action<br />

* @param Hashtable attributes<br />

* @return boolean<br />

*/<br />

public boolean setActionAttributesOfDevice(String deviceName, String action, Hashtable attributes)<br />

{<br />

try {<br />

Node node = XPath("devices/device[@name=\"" + deviceName + "\"]/action/" +<br />

action, this.device).item(0);<br />

if (!(updateAttributes((Element)node, attributes))) {<br />

return false;<br />

}<br />

Document tmp = saveDocument(this.device, this.deviceFile,<br />

this.deviceDtdFileName);<br />

if (tmp != null)<br />

this.device = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

catch (Exception e) {<br />

}<br />

return false;<br />

}<br />

/**<br />

* Imposta gli attributi del link passato come argomento del <strong>di</strong>spositivo deviceName<br />

* @param String deviceName<br />

* @param String link<br />

* @param Hashtable attributes<br />

* @return boolean<br />

*/<br />

public boolean setLinkAttributesOfDevice(String deviceName, String link, Hashtable attributes)<br />

{<br />

try {<br />

if (XPath("links/link[@name=\"" + deviceName + "\"]", this.link).getLength() ==<br />

0) {<br />

Element linkElement = this.link.createElement("link");<br />

linkElement.setAttribute("name", deviceName);<br />

this.link.getLastChild().appendChild(linkElement);<br />

Pietro Neroni 566/2833 Pagina 93 <strong>di</strong> 117


}<br />

if (XPath("links/link[@name=\"" + deviceName + "\"]/" + link,<br />

this.link).getLength() == 0) {<br />

Element subLinkElement = this.link.createElement(link);<br />

XPath("links/link[@name=\"" + deviceName + "\"]",<br />

this.link).item(0).appendChild(subLinkElement);<br />

}<br />

Node node = XPath("links/link[@name=\"" + deviceName + "\"]/" + link,<br />

this.link).item(0);<br />

if (!(updateAttributes((Element)node, attributes))) {<br />

return false;<br />

}<br />

Document tmp = saveDocument(this.link, this.linkFile, this.linkDtdFileName);<br />

if (tmp != null)<br />

this.link = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

catch (Exception e) {<br />

}<br />

return false;<br />

}<br />

public void fatalError(SAXParseException e) {<br />

error(e); }<br />

public void warning(SAXParseException e) { }<br />

public void error(SAXParseException e) { this.error = e.toString(); this.validated = false; }<br />

public String getLastErrorMessage() { return this.error;<br />

}<br />

/**<br />

* Ritorna l'insieme del <strong>di</strong>spositivo passato come argomento<br />

* @param String device<br />

* @return String<br />

*/<br />

public String getSet(String device)<br />

{<br />

String tmp=null;<br />

try {<br />

NodeList nodes = this.set.getElementsByTagName("componente");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if(node.getAttribute("<strong>di</strong>spositivo").equals(device))<br />

tmp=node.getAttribute("insieme");<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

return tmp;<br />

}<br />

/**<br />

* Ritorna una lista <strong>di</strong> <strong>di</strong>spositivi dell'insieme passato come argomento<br />

* @param String set<br />

* @return ArrayList<br />

*/<br />

public ArrayList getDeviceofSet(String set) {<br />

ArrayList risultato=new ArrayList();<br />

try {<br />

NodeList nodes = this.set.getElementsByTagName("componente");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if(node.getAttribute("insieme").equals(set))<br />

Pietro Neroni 566/2833 Pagina 94 <strong>di</strong> 117


isultato.add(node.getAttribute("<strong>di</strong>spositivo"));<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

return risultato;<br />

}<br />

/**<br />

* Inserisce nel file set.xml un nuovo elemento contenente il nome del <strong>di</strong>spositivo e l'insieme<br />

a cui appartiene<br />

* @param String <strong>di</strong>spositivo<br />

* @param String insieme<br />

* @return boolean<br />

*/<br />

public boolean setComponenteInsieme(String <strong>di</strong>spositivo, String insieme)<br />

{<br />

boolean trovato=false;<br />

try {<br />

NodeList nodes = this.set.getElementsByTagName("componente");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if(node.getAttribute("<strong>di</strong>spositivo").equals(<strong>di</strong>spositivo)) {<br />

node.setAttribute("insieme", insieme);<br />

trovato=true;<br />

}<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

if(!trovato){<br />

Element newComp = this.set.createElement("componente");<br />

newComp.setAttribute("insieme", insieme);<br />

newComp.setAttribute("<strong>di</strong>spositivo", <strong>di</strong>spositivo);<br />

this.set.getLastChild().appendChild(newComp);<br />

}<br />

Document tmp = saveDocument(this.set, this.setFile, this.setDtdFileName);<br />

if (tmp != null)<br />

this.set = tmp;<br />

else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Crea un file in linguaggio DOT contenente la descrizione testuale del grafo delle <strong>di</strong>pendenze<br />

logiche considerando anche il <strong>di</strong>spositivo passato come argomento e le sue <strong>di</strong>pendenze.<br />

*/<br />

public String creaGrafo(){<br />

Map no<strong>di</strong>=new HashMap();<br />

Set archi=new HashSet();<br />

String tmp=null;<br />

String tmp1,tmp2,tmp5,tmp6,set , source_name,target_name, name_url;<br />

String[]tmp3, tmp4, temp_set, tmp_url;<br />

String target,target2,source, source2 = null;<br />

FileOutputStream file2;<br />

PrintStream Output = null;<br />

//crea il file DOT<br />

try {<br />

file2 = new FileOutputStream("/usr/local/apache2/htdocs/webdot/grafo5.dot");<br />

Output = new PrintStream(file2);<br />

}<br />

catch (IOException e) {<br />

System.out.println("Errore: " + e);<br />

System.exit(1);<br />

}<br />

Output.println("<strong>di</strong>graph mainmap {");<br />

Pietro Neroni 566/2833 Pagina 95 <strong>di</strong> 117


NodeList nodes = this.dependency.getElementsByTagName("arc");<br />

//legge le <strong>di</strong>pendenze tra i <strong>di</strong>spositivi nel file <strong>di</strong> configurazione dependences.xml<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

source=node.getAttribute("source");<br />

target=node.getAttribute("target");<br />

//se la <strong>di</strong>pendenza rappresenta una <strong>di</strong>pendenza fisica la ignora<br />

if(target.equals("atlas")) continue;<br />

else if(source.equals("atlas")) continue;<br />

else if (target.contains("rack")) continue;<br />

else if(source.contains("rack")) continue;<br />

//mo<strong>di</strong>fica il nome dei <strong>di</strong>spositivi che rappresentano la <strong>di</strong>pendenza per rendere<br />

il grafo più leggibile<br />

source_name=getNameDevice(source);<br />

target_name=getNameDevice(target);<br />

tmp1= source.split(".na")[0];<br />

tmp2=target.split(".na")[0];<br />

tmp3=tmp1.split("atlas");<br />

tmp4=tmp2.split("atlas");<br />

if(tmp3.length>1) tmp5=tmp3[1] ;<br />

else tmp5=tmp1 ;<br />

if(tmp4.length>1) tmp6=tmp4[1];<br />

else tmp6=tmp2 ;<br />

//se uno dei due <strong>di</strong>spositivi fa parte <strong>di</strong> un insieme viene sostituito da<br />

quest'ultimo<br />

if (getSet(source)!=null) {<br />

set=getSet(source);<br />

set=set.split(".na")[0];<br />

temp_set=set.split("atlas");<br />

if(temp_set.length>1) set=temp_set[1];<br />

source2="espansioni_"+set;<br />

}<br />

else source2=source_name;<br />

if (getSet(target)!=null) {<br />

set=getSet(target);<br />

set=set.split(".na")[0];<br />

temp_set=set.split("atlas");<br />

if(temp_set.length>1) set=temp_set[1];<br />

target2="espansioni_"+set;<br />

}<br />

else target2=target_name;<br />

no<strong>di</strong>.put(source2,getAttributesOfDevice(source).get("type"));<br />

no<strong>di</strong>.put(target2,getAttributesOfDevice(target).get("type"));<br />

archi.add(source2.replace("-", "_")+"->"+target2.replace("-", "_"));<br />

source=node.getAttribute("source");<br />

target=node.getAttribute("target");<br />

if (getSet(source)!=null) source2="espansioni_"+getSet(source);<br />

else source2=source;<br />

if (getSet(target)!=null) target2="espansioni_"+getSet(target);<br />

else target2=target;<br />

no<strong>di</strong>.put(source2,getAttributesOfDevice(source).get("type"));<br />

no<strong>di</strong>.put(target2,getAttributesOfDevice(target).get("type"));<br />

archi.add(source2.replace("-", "_")+"->"+target2.replace("-", "_"));<br />

}<br />

for(String n:no<strong>di</strong>.keySet()){<br />

String colore=null, nodo=null;<br />

String tipo=no<strong>di</strong>.get(n);<br />

if(tipo!=null){<br />

//assegna un colore al nodo a seconda del tipo <strong>di</strong> <strong>di</strong>spositivo che<br />

rappresenta<br />

if(tipo.equals("wn")) colore="red";<br />

else if (tipo.equals("se")) colore="blue";<br />

else if (tipo.equals("exp")) colore="yellow";<br />

else if (tipo.equals("ce")) colore="green";<br />

else colore="gray";<br />

}<br />

tmp_url=n.split("espansioni_");<br />

if(tmp_url.length>1)name_url=tmp_url[1];<br />

Pietro Neroni 566/2833 Pagina 96 <strong>di</strong> 117


else name_url=tmp_url[0];<br />

//scrive il nodo e i suoi attributi nel file DOT<br />

Output.println(n.replace("-", "_")+"<br />

[URL=\"http://localhost:8080/WebPowerfarm/index.jspvalue="+name_url+"&action=search\"]");<br />

Output.println(n.replace("-", "_")+" [color="+colore+"]");<br />

}<br />

for(String a:archi){<br />

//scrive la <strong>di</strong>pendenza nel file DOT<br />

Output.println(a);<br />

}<br />

Output.println("}");<br />

return tmp;<br />

}<br />

/**<br />

* Mo<strong>di</strong>fica il nome del <strong>di</strong>spositivo<br />

* @param String <strong>di</strong>spositivo<br />

* @return String<br />

*/<br />

public String getNameDevice(String <strong>di</strong>spositivo){<br />

String tmp1, result;<br />

String []tmp3;<br />

tmp1= <strong>di</strong>spositivo.split(".na")[0];<br />

tmp3=tmp1.split("atlas");<br />

if(tmp3.length>1) result=tmp3[1] ;<br />

else result=tmp1 ;<br />

return result;<br />

}<br />

/**<br />

* Inserisce nel file plugins.xml un nuovo elemento contenente il tipo ed i plugin ad esso<br />

associati: se i plugin per quel tipo sono già presenti li sostituisce con i nuovi<br />

* @param String type<br />

* @param Hashtable plugin<br />

* @return boolean<br />

*/<br />

public boolean setPlugin(String type, Hashtable plugin)<br />

{<br />

boolean trovato=false;<br />

try {<br />

NodeList nodes = this.plugins.getElementsByTagName("plugin");<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

if(node.getAttribute("type").equals(type)) {<br />

node.setAttribute("on", plugin.get("on"));<br />

node.setAttribute("off-soft", plugin.get("off-soft"));<br />

node.setAttribute("off-hard", plugin.get("off-hard"));<br />

node.setAttribute("check-on", plugin.get("check-on"));<br />

node.setAttribute("check-off",plugin.get("check-off"));<br />

trovato=true;<br />

}<br />

}<br />

}<br />

catch (Exception e) {<br />

this.error = e.toString(); }<br />

if(!trovato){<br />

Element newComp = this.plugins.createElement("plugin");<br />

newComp.setAttribute("type", type);<br />

newComp.setAttribute("on", plugin.get("on"));<br />

newComp.setAttribute("off-soft", plugin.get("off-soft"));<br />

newComp.setAttribute("off-hard", plugin.get("off-hard"));<br />

newComp.setAttribute("check-on", plugin.get("check-on"));<br />

newComp.setAttribute("check-off",plugin.get("check-off"));<br />

this.plugins.getLastChild().appendChild(newComp);<br />

}<br />

Document tmp = saveDocument(this.plugins, this.pluginsFile, this.pluginsDtdFileName);<br />

if (tmp != null)<br />

this.plugins = tmp;<br />

Pietro Neroni 566/2833 Pagina 97 <strong>di</strong> 117


else {<br />

return false;<br />

}<br />

return true;<br />

}<br />

/**<br />

* Crea un file in linguaggio DOT contenente la descrizione testuale del grafo delle <strong>di</strong>pendenze<br />

logiche considerando anche il <strong>di</strong>spositivo passato come argomento e le sue <strong>di</strong>pendenze.<br />

* @param String deviceName<br />

* @param Set dependences<br />

*/<br />

public String graph(String deviceName, Set dependences){<br />

Map no<strong>di</strong>=new HashMap();<br />

Set archi=new HashSet();<br />

String tmp=null;<br />

String tmp1,tmp2,tmp5,tmp6,set , source_name,target_name, name_url;<br />

String[]tmp3, tmp4, temp_set, tmp_url;<br />

String target,target2,source, source2 = null;<br />

FileOutputStream file2;<br />

PrintStream Output = null;<br />

// creazione del file DOT<br />

try {<br />

file2 = new FileOutputStream("/usr/local/apache2/htdocs/webdot/grafo_add.dot");<br />

Output = new PrintStream(file2);<br />

}<br />

catch (IOException e) {<br />

System.out.println("Errore: " + e);<br />

System.exit(1);<br />

}<br />

Output.println("<strong>di</strong>graph mainmap {");<br />

NodeList nodes = this.dependency.getElementsByTagName("arc");<br />

//legge le <strong>di</strong>pendenze tra i <strong>di</strong>spositivi nel file <strong>di</strong> configurazione dependences.xml<br />

for (int i = 0; i < nodes.getLength(); ++i) {<br />

Element node = (Element)nodes.item(i);<br />

source=node.getAttribute("source");<br />

target=node.getAttribute("target");<br />

//se la <strong>di</strong>pendenza rappresenta una <strong>di</strong>pendenza fisica la ignora<br />

if(target.equals("atlas")) continue;<br />

else if(source.equals("atlas")) continue;<br />

else if (target.contains("rack")) continue;<br />

else if(source.contains("rack")) continue;<br />

//mo<strong>di</strong>fica il nome dei <strong>di</strong>spositivi che rappresentano la <strong>di</strong>pendenza per rendere<br />

il grafo più leggibile<br />

source_name=getNameDevice(source);<br />

target_name=getNameDevice(target);<br />

tmp1= source.split(".na")[0];<br />

tmp2=target.split(".na")[0];<br />

tmp3=tmp1.split("atlas");<br />

tmp4=tmp2.split("atlas");<br />

if(tmp3.length>1) tmp5=tmp3[1] ;<br />

else tmp5=tmp1 ;<br />

if(tmp4.length>1) tmp6=tmp4[1];<br />

else tmp6=tmp2 ;<br />

//se uno dei due <strong>di</strong>spositivi fa parte <strong>di</strong> un insieme viene sostituito da<br />

quest'ultimo<br />

if (getSet(source)!=null) {<br />

set=getSet(source);<br />

set=set.split(".na")[0];<br />

temp_set=set.split("atlas");<br />

if(temp_set.length>1) set=temp_set[1];<br />

source2="espansioni_"+set;<br />

}<br />

else source2=source_name;<br />

if (getSet(target)!=null) {<br />

set=getSet(target);<br />

set=set.split(".na")[0];<br />

temp_set=set.split("atlas");<br />

Pietro Neroni 566/2833 Pagina 98 <strong>di</strong> 117


if(temp_set.length>1) set=temp_set[1];<br />

target2="espansioni_"+set;<br />

}<br />

else target2=target_name;<br />

no<strong>di</strong>.put(source2,getAttributesOfDevice(source).get("type"));<br />

no<strong>di</strong>.put(target2,getAttributesOfDevice(target).get("type"));<br />

archi.add(source2.replace("-", "_")+"->"+target2.replace("-", "_"));<br />

source=node.getAttribute("source");<br />

target=node.getAttribute("target");<br />

if (getSet(source)!=null) source2="espansioni_"+getSet(source);<br />

else source2=source;<br />

if (getSet(target)!=null) target2="espansioni_"+getSet(target);<br />

else target2=target;<br />

no<strong>di</strong>.put(source2,getAttributesOfDevice(source).get("type"));<br />

no<strong>di</strong>.put(target2,getAttributesOfDevice(target).get("type"));<br />

archi.add(source2.replace("-", "_")+"->"+target2.replace("-", "_"));<br />

}<br />

for(String n:no<strong>di</strong>.keySet()){<br />

String colore=null, nodo=null;<br />

String tipo=no<strong>di</strong>.get(n);<br />

if(tipo!=null){<br />

//assegna un colore al nodo a seconda del tipo <strong>di</strong> <strong>di</strong>spositivo che<br />

rappresenta<br />

if(tipo.equals("wn")) colore="red";<br />

else if (tipo.equals("se")) colore="blue";<br />

else if (tipo.equals("exp")) colore="yellow";<br />

else if (tipo.equals("ce")) colore="green";<br />

else colore="gray";<br />

}<br />

//scrive il nodo e i suoi attributi nel file DOT<br />

Output.println(n.replace("-", "_")+" [color="+colore+"]");<br />

}<br />

for(String dep: dependences){<br />

String dep_device=getNameDevice(dep);<br />

if(getSet(dep)!=null){<br />

set=getSet(dep);<br />

set=set.split(".na")[0];<br />

temp_set=set.split("atlas");<br />

if(temp_set.length>1) set=temp_set[1];<br />

dep_device="espansioni_"+set;<br />

}<br />

//scrive la <strong>di</strong>pendenza nel file DOT<br />

archi.add(dep_device+"->"+deviceName.replace("-", "_"));<br />

}<br />

for(String a:archi){<br />

Output.println(a);<br />

}<br />

Output.println("}");<br />

return tmp;<br />

}<br />

}<br />

WebPowerfarm.java<br />

package webpowerfarm;<br />

import powerfarm.*;<br />

import java.util.*;<br />

public class Webpowerfarm{<br />

protected IDatabase database;<br />

protected Ping ping;<br />

protected ICommand command;<br />

Pietro Neroni 566/2833 Pagina 99 <strong>di</strong> 117


public List commandQueue;<br />

public void updateCommandQueue(CommandInstance comm){<br />

if(comm!=null) this.commandQueue.add(comm);<br />

for(int i = 0; i < this.commandQueue.size(); ){<br />

try{<br />

commandQueue.get(i).getProcess().exitValue();<br />

commandQueue.remove(i);<br />

}catch(IllegalThreadStateException e){<br />

i++;<br />

continue;<br />

}<br />

}<br />

}<br />

public Webpowerfarm(String XMLpathDir, String COMpathDir) throws Exception{<br />

try{<br />

this.database = new XMLDatabase(XMLpathDir);<br />

this.ping = new Ping(10, 10, 60);<br />

this.command = new PerlCommand(COMpathDir, "powerfarm.pl");<br />

this.commandQueue = new ArrayList();<br />

this.synch();<br />

}<br />

catch(Exception e){<br />

throw e;}<br />

finally<br />

{}<br />

}<br />

public IDatabase getDatabase(){ return this.database; }<br />

public Ping getPing(){ return this.ping; }<br />

public ICommand getCommand(){ return this.command; }<br />

public boolean synch(){<br />

try{<br />

List oldSet = new ArrayList();<br />

List newSet = Arrays.asList(this.database.getDevices());<br />

for(Enumeration en = this.ping.getStatus().keys(); en.hasMoreElements();)<br />

oldSet.add(en.nextElement());<br />

//delete old<br />

for(String d : oldSet){<br />

if(!newSet.contains(d))<br />

this.ping.delete(d);<br />

}<br />

//add new<br />

for(String d : newSet){<br />

if(!this.ping.contains(d)){<br />

String address, command;<br />

String[] commandArgs;<br />

try{<br />

Hashtable attr = database.getAttributesOfDevice(d);<br />

Hashtable pingAttr =<br />

database.getActionAttributesOfDevice(d, "check-on");<br />

address = attr.get("address");<br />

command = pingAttr.get("plugin");<br />

commandArgs = pingAttr.get("args").split(" ");<br />

}<br />

catch(Exception e){<br />

address = command = "";<br />

commandArgs = new String[]{};<br />

}<br />

if(command!=null && !command.equals("")){<br />

int lastIndexOfDot = command.lastIndexOf(".");<br />

Pietro Neroni 566/2833 Pagina 100 <strong>di</strong> 117


String extension = (lastIndexOfDot>=0) <br />

command.substring(lastIndexOfDot) : "";<br />

if(extension.equals(".pl"))<br />

command = "perl " + command;<br />

this.ping.add(d, command, commandArgs);<br />

}<br />

else {<br />

//this.ping.add(d, "ping", new String[]{"-c","3",(address!=null && !<br />

address.equals(""))address:d});<br />

this.ping.add(d, "", new String[]{});<br />

//System.out.println("ad<strong>di</strong>ng: " + d + " - " + address);<br />

}<br />

}<br />

}<br />

return true;<br />

}<br />

catch(Exception e){<br />

return false;<br />

}<br />

}<br />

}<br />

e<strong>di</strong>t.jsp<br />

<br />

<br />

<br />

<br />

<br />

var stile = "top=10, left=10, width=800, height=200, status=no, menubar=no, toolbar=no<br />

scrollbar=yes";<br />

/*<br />

Apre una finestra <strong>di</strong> pop-up dove viene eseguito il plugin e viene mostrato l'output<br />

ottenuto<br />

*/<br />

function Popup(apri, command, args) {<br />

window.open(apri + 'command=' + command.value + '&args=' + args.value, "", stile);<br />

}<br />

/*<br />

Apre una finestra <strong>di</strong> pop-up dove viene eseguito il plugin e viene mostrato l'output<br />

ottenuto<br />

*/<br />

function showGraph(){<br />

if (document.form1.attr_name.value=="") {<br />

alert('Per visualizzare il grafo è necessario inserire il nome del<br />

<strong>di</strong>spositivo');<br />

return false;<br />

}<br />

device=document.form1.attr_name.value;<br />

dep=document.form1.listtextSelection;<br />

if(dep.options.length==0){<br />

alert('Per visualizzare il grafo è necessario assegnare almeno una<br />

<strong>di</strong>pendenza');<br />

return false;<br />

}<br />

dependences=dep.options[0].value + '_';<br />

for(i = 1; i < dep.options.length; i++)<br />

dependences+=dep.options[i].value + '_';<br />

window.open("graph.jsp" + 'dependences=' + dependences + '&device=' + device, "",<br />

stile);<br />

}<br />

Pietro Neroni 566/2833 Pagina 101 <strong>di</strong> 117


<br />

<br />

<br />

<br />


Hashtable plugin=new Hashtable();<br />

String[] actionNames = new String[]{"on","off-soft","off-hard","check-on","check-off"};<br />

for(String act : actionNames){<br />

Hashtable tmp;<br />

actions.put(act,tmp=new Hashtable());<br />

plugin.put(act,((field = request.getParameter("action_"+act+"_plugin"))!=null<br />

&& !field.equals(""))field:"");<br />

tmp.put("plugin",((field = request.getParameter("action_"+act+"_plugin"))!=null && !<br />

field.equals(""))field:"");<br />

tmp.put("args",((field = request.getParameter("action_"+act+"_args"))!=null && !<br />

field.equals(""))field:"");<br />

tmp.put("description",((field = request.getParameter("action_"+act+"_description"))!<br />

=null && !field.equals(""))field:"");<br />

if(!act.equals("check-on") && !act.equals("check-off"))<br />

tmp.put("timeout",((field = request.getParameter("action_"+act+"_timeout"))!<br />

=null && !field.equals(""))field:"");<br />

}<br />

/*<br />

Link alle pagine <strong>di</strong> monitoraggio<br />

*/<br />

String link_nagios = ((field = request.getParameter("link_nagios"))!=null)field:"";<br />

String link_ganglia = ((field = request.getParameter("link_ganglia"))!=null)field:"";<br />

String link_imgReport1 = ((field = request.getParameter("link_imgReport1"))!=null)<br />

field:"";<br />

String link_imgReport2 = ((field = request.getParameter("link_imgReport2"))!=null)<br />

field:"";<br />

String[] dependencies = (request.getParameterValues("dependencies")!=null)<br />

request.getParameterValues("dependencies"):new String[]{};<br />

//Aggiornamento o inserimento <strong>di</strong> un <strong>di</strong>spositivo<br />

if(!webpowerfarm.getDatabase().setPlugin(type,plugin)){<br />

throw new Exception("error in plugin");<br />

}<br />

if(!webpowerfarm.getDatabase().setAttributesOfDevice(value,attributes)){<br />

throw new Exception("error in attributes");<br />

}<br />

if(farm.equals("")){<br />

String oldFarm = webpowerfarm.getDatabase().getFarmOfDevice(value);<br />

if(oldFarm!=null)<br />

if(!webpowerfarm.getDatabase().removeDeviceOfFarm(value, oldFarm))<br />

throw new Exception("error while removing farm");<br />

}<br />

else<br />

if(!webpowerfarm.getDatabase().setFarmOfDevice(farm, value))<br />

throw new Exception("error while setting farm");<br />

for(String act : actionNames){<br />

if(!webpowerfarm.getDatabase().setActionAttributesOfDevice(value, act,<br />

actions.get(act)))<br />

throw new Exception("error in actions text");<br />

}<br />

Hashtable nagiosAttr = new Hashtable();<br />

nagiosAttr.put("href",link_nagios);<br />

Hashtable gangliaAttr = new Hashtable();<br />

gangliaAttr.put("href",link_ganglia);<br />

gangliaAttr.put("imgReport1",link_imgReport1);<br />

gangliaAttr.put("imgReport2",link_imgReport2);<br />

if(!webpowerfarm.getDatabase().setLinkAttributesOfDevice(value,"ganglia",gangliaAttr))<br />

Pietro Neroni 566/2833 Pagina 103 <strong>di</strong> 117


throw new Exception("error in links ganglia text");<br />

if(!webpowerfarm.getDatabase().setLinkAttributesOfDevice(value,"nagios",nagiosAttr))<br />

throw new Exception("error in links nagios text");<br />

if(dependencies==null || dependencies.length==0){<br />

if(!webpowerfarm.getDatabase().removeDependenciesOfDevice(value, false))<br />

throw new Exception("error removing dependnecies");<br />

}<br />

else{<br />

/*<br />

viene controllato se le <strong>di</strong>pendenze assegnate al <strong>di</strong>spositivo causano cicli<br />

*/<br />

boolean cyclic = false;<br />

List badArcs = new ArrayList();<br />

for(String target : dependencies){<br />

String[] all =<br />

webpowerfarm.getDatabase().getAllDepthDependenciesOfDevice(target, false);<br />

if(Arrays.asList(all).contains(value) || target.equals(value)){<br />

cyclic = true;<br />

badArcs.add(target);<br />

}<br />

}<br />

/*<br />

Nel caso causano cicli queste non vengono assegnate e viene stampata la lista delle<br />

<strong>di</strong>pendenze che causano cicli<br />

*/<br />

if(cyclic){<br />

String message = "Non si possono assegnare le <strong>di</strong>pendenze al <strong>di</strong>spositivo <br />

i seguenti archi causano cicli: ";<br />

for(String arc : badArcs){<br />

message += "("+value+"->"+arc+")";<br />

}<br />

%><br />

<br />

<br />

<br />

error occurred while updating <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Pietro Neroni 566/2833 Pagina 104 <strong>di</strong> 117


<br />

<br />

<br />

<br />

<br />

<br />

<br />

/*<br />

Controlla se i campi obbligatori sono stati inseriti<br />

*/<br />

function check_obbligatori(){<br />

if(document.form1.attr_address.value=="" || document.form1.attr_name.value=="") {<br />

var msg="I seguenti campi obbligatori non sono stati inseriti:\n";<br />

if(document.form1.attr_address.value=="" ) msg+="In<strong>di</strong>rizzo IP\n";<br />

if( document.form1.attr_name.value=="") msg+="Nome <strong>di</strong>spositivo";<br />

alert(msg);<br />

return false;<br />

}<br />

var ip=document.form1.attr_address.value.split(".");<br />

if(ip.length!=4){<br />

alert('In<strong>di</strong>rizzo IP non valido');<br />

return false;<br />

}<br />

for(i=0;i3){<br />

alert('IP errato');<br />

return false;<br />

}<br />

}<br />

return true;<br />

}<br />

/*<br />

Crea una lista <strong>di</strong> <strong>di</strong>spositivi che verra utilizzata per rappresentare le <strong>di</strong>pendenze<br />

*/<br />

arrDevice = new Array();<br />

arrSelected = new Array();<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

/*arrDevice[0] = ['altlaswn01.na.infn.it','wn','atlas'];<br />

...<br />

arrDevice[14] = ['pamelace01.na.infn.it','ce','pamela'];*/<br />

<br />

<br />

<br />

<br />

<br />

<br />

/*arrSelected[0] = 'altlaswn01.na.infn.it';<br />

...<br />

arrSelected[2] = 'altlaswn03.na.infn.it';*/<br />

Pietro Neroni 566/2833 Pagina 105 <strong>di</strong> 117


*<br />

Inserisce nella tabella usata per assegnare le <strong>di</strong>pendenze il tipo o il <strong>di</strong>spositivo , a<br />

seconda del parametro wichBox<br />

*/<br />

function populate(whichBox){<br />

var farmSelected =<br />

document.form1.listtextFarm.options[document.form1.listtextFarm.selectedIndex].value;<br />

if(whichBox == 'type'){<br />

document.form1.listtextType.options.length = 0;<br />

document.form1.listtextDevice.options.length = 0;<br />

document.form1.listtextType.options[0] = new Option("ALL", "ALL");<br />

for(i=0,j=1;i


document.form1.listtextDevice.options[i].value){<br />

insert = false;<br />

break;<br />

}<br />

if(insert)<br />

document.form1.listtextSelection.options[document.form1.listtextSelection.optio<br />

ns.length]=new Option(document.form1.listtextDevice.options[i].value,<br />

document.form1.listtextDevice.options[i].value);<br />

else<br />

alert("The device '" + document.form1.listtextSelection.options[k].value + "'<br />

is already selected");<br />

}<br />

}<br />

//alert(document.form1.listtextDevice.options[0].selected);<br />

}<br />

/*<br />

Rimuove il <strong>di</strong>spositivo selezionato dalla lista delle <strong>di</strong>pendenze assegnate<br />

*/<br />

function removeSelected(){<br />

var myArr = new Array();<br />

for(i = 0, j = 0; i < document.form1.listtextSelection.options.length; i++){<br />

if(!document.form1.listtextSelection.options[i].selected){<br />

myArr.push(document.form1.listtextSelection.options[i]);<br />

}<br />

}<br />

document.form1.listtextSelection.options.length = 0;<br />

}<br />

for(i = 0, j = 0; i < myArr.length; i++){<br />

document.form1.listtextSelection.options[i]=myArr[i];<br />

}<br />

function selectAll(obj){<br />

for(i = 0; i < obj.options.length; i++)<br />

obj.options[i].selected = true;<br />

}<br />

function onLoad(){<br />

document.form1.listtextSelection.options.length=0;<br />

for( i = 0; i < arrSelected.length; i++)<br />

document.form1.listtextSelection.options[i] = new Option(arrSelected[i],<br />

arrSelected[i]);<br />

}<br />

/*<br />

Viene attivata ogni qualvolta si cambia il tipo della farm, se il tipo selezionato è new si<br />

abilita un campo <strong>di</strong> testo per inserire il nome della nuova farm<br />

*/<br />

function farmSelection_onChange(){<br />

var val =<br />

document.form1.farmSelection.options[document.form1.farmSelection.selectedIndex].value;<br />

if(val=="NEW"){<br />

document.form1.farmText.setAttribute("value","");<br />

document.form1.farmText.removeAttribute("<strong>di</strong>sabled");<br />

}<br />

else if(val=="NONE"){<br />

document.form1.farmText.setAttribute("value","");<br />

document.form1.farmText.setAttribute("<strong>di</strong>sabled","<strong>di</strong>sabled");<br />

}<br />

else{<br />

document.form1.farmText.setAttribute("value",document.form1.farmSelection.options[doc<br />

ument.form1.farmSelection.selectedIndex].value);<br />

Pietro Neroni 566/2833 Pagina 107 <strong>di</strong> 117


document.form1.farmText.setAttribute("<strong>di</strong>sabled","<strong>di</strong>sabled");<br />

}<br />

}<br />

/*<br />

Viene attivata ogni qualvolta si cambia il tipo del <strong>di</strong>spositivo, se il tipo selezionato è<br />

new si abilita un campo <strong>di</strong> testo per inserire il nome della nuova farm. Inoltre richiama la<br />

funzione setPlugin per assegnare in automatico i plugin per quel tipo<br />

*/<br />

function typeSelection_onChange(){<br />

var val =<br />

document.form1.typeSelection.options[document.form1.typeSelection.selectedIndex].value;<br />

if(val=="NEW"){<br />

document.form1.typeText.setAttribute("value","");<br />

document.form1.typeText.removeAttribute("<strong>di</strong>sabled");<br />

}<br />

else if(val=="NONE"){<br />

document.form1.typeText.setAttribute("value","");<br />

document.form1.typeText.setAttribute("<strong>di</strong>sabled","<strong>di</strong>sabled");<br />

}<br />

else{<br />

document.form1.typeText.setAttribute("value",document.form1.typeSelection.options[doc<br />

ument.form1.typeSelection.selectedIndex].value);<br />

document.form1.typeText.setAttribute("<strong>di</strong>sabled","<strong>di</strong>sabled");<br />

setPlugin(val);<br />

}<br />

}<br />

/*<br />

Legge nel file plugins.xml i plugin relativi al tipo passato come parametro e li assegna<br />

automaticamente al nuovo <strong>di</strong>spositivo<br />

*/<br />

function setPlugin(tipo)<br />

{var errore = 0;<br />

try{<br />

var ff = new XMLHttpRequest();<br />

ff.open('GET', "plugins.xml", false);<br />

ff.send(null);<br />

var connect = ff.responseXML;<br />

var plugin=connect.getElementsByTagName("plugin")<br />

var trovato=false;<br />

for (i=0; i


}<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

name:<br />

<br />

<br />

<br />

<br />

The device name can be made of any char except space char. e.g.<br />

myhost.mydomain.com<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

farm:<br />

<br />

<br />

<br />

<br />

NONE<br />

NEW<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the belonging farm, eventually blank.<br />

<br />

<br />

<br />

<br />

<br />

<br />

IP address:<br />

<br />

<br />

<br />

<br />

Insert the ip address of the device.<br />

<br />

<br />

<br />

<br />

<br />

type:<br />

<br />

<br />

Pietro Neroni 566/2833 Pagina 109 <strong>di</strong> 117


<br />

NONE<br />

NEW<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the device type, e.g. WN for worker node, SE for storage element<br />

etc.<br />

<br />

<br />

<br />

<br />

<br />

component of:<br />

<br />

<br />

<br />

description:<br />

<br />

<br />

<br />

<br />

lock on/off:<br />

<br />

<br />

<br />

/<br />

<br />

<br />

lock-on/off pair value control the ability to wait for power on/off completion<br />

when running power on/off operations respectively. In case of doubt leave the default<br />

value.<br />

<br />

<br />

<br />

<br />

<br />

<br />

select on search:<br />

<br />

<br />

<br />

<br />

<br />

<br />

Enable the checkbox if you want the device automatically selected on search<br />

results.<br />

<br />

<br />

<br />

<br />

<br />

Pietro Neroni 566/2833 Pagina 110 <strong>di</strong> 117


power on:<br />

<br />

<br />

<br />

plugin<br />

args<br />

description<br />

timeout<br />

test<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the absolute path of the<br />

power-on plugin. Plugins are available in the plugin <strong>di</strong>rectory of powerfarm<br />

package.<br />

<br />

<br />

<br />

<br />

<br />

<br />

power off-soft:<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the absolute path of the<br />

power-off simple plugin. Plugins are available in the plugin <strong>di</strong>rectory of powerfarm<br />

package.<br />

<br />

<br />

<br />

<br />

<br />

<br />


webpowerfarm.getDatabase().getActionAttributesOfDevice(value,"off-hard") : null; %><br />

power off-hard:<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the absolute path of the power-off hard<br />

plugin. Plugins are available in the plugin <strong>di</strong>rectory of powerfarm package.<br />

<br />

<br />

<br />

<br />

<br />

<br />

check on:<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the absolute path of the check-on plugin.<br />

Plugins are available in the plugin <strong>di</strong>rectory of powerfarm package.<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

check off:<br />

<br />

<br />

<br />

<br />

<br />

<br />

Insert the absolute path of the power-off<br />

plugin. Plugins are available in the plugin <strong>di</strong>rectory of powerfarm package.<br />

<br />

Pietro Neroni 566/2833 Pagina 112 <strong>di</strong> 117


<br />

<br />

<br />

<br />

<br />

<br />

link nagios:<br />

<br />

<br />

hypertext reference<br />

<br />

<br />

Place here the URL of the nagios page of the<br />

device. This information will appear in the nagios link of the device when<br />

searched.<br />

<br />

<br />

<br />

<br />

<br />

<br />

link ganglia:<br />

<br />

<br />

<br />

<br />

Place here the URL of the ganglia page of the<br />

device. This information will appear in the ganglia link of the device when<br />

searched.<br />

<br />

<br />

<br />

<br />

<br />

<br />

image report left/right:<br />

<br />

<br />

hypertext reference<br />

<br />

<br />

<br />

<br />

/<br />

<br />

Place in the left (right) field the graph to show on<br />

the left (right) side of the device tag.<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Set all the power-off dependencies. e.g. if you select<br />

host "x","y" and "z" means that when shutting down this device "x","y" and "z" must be turned<br />

off first.<br />

Dependencies, all the device that mustbe shut before this:<br />

Pietro Neroni 566/2833 Pagina 113 <strong>di</strong> 117


<br />

<br />

<br />

farm(s)type(s)device(s)dependencies<br />

<br />

<br />

<br />

ALL<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />


onclick="selectAll(document.form1.listtextSelection)"><br />

<br />

<br />

<br />

<br />

<br />

<br />

graph.jsp<br />

<br />

<br />

<br />

<br />

Grafo delle <strong>di</strong>pendenze per: <br />

<br />

<br />

<br />

}catch(Exception e){ %><br />

Impossibile visualizzare il grafo<br />

<br />

<br />

index.jsp<br />

<br />

<br />

<br />

<br />

<br />

WebPowerfarm<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />


order="0"><br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Pietro Neroni 566/2833 Pagina 116 <strong>di</strong> 117


<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

}<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

Pietro Neroni 566/2833 Pagina 117 <strong>di</strong> 117

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!