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
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