Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica tesi di laurea Grid on Cloud : Implementazione e Monitoraggio Anno Accademico 2013-2014 relatore Ch.mo prof. Marcello Cinque correlatore Ch.mo Ing. Flavio Frattini Ch.mo Ing. Davide Bottalico candidato Antonio Nappi matr. M63000141 Alla mia famiglia,alla mia Pazza,agli amici e a tutti quelli che mi sono stati vicino in questi anni 2 “ Lascia dormire il futuro come merita. Se si sveglia prima del tempo, si ottiene un presente assonnato,, 3 Indice Introduzione 1 1 Problematiche del Grid computing 1.1 Grid Computing . . . . . . . . . . . . . . . . . . . . . . 1.1.1 Componenti di un sistema Grid . . . . . . . . . 1.1.2 Un esempio di sistema Grid: SCOPE . . . . . . 1.1.3 Limiti del Grid . . . . . . . . . . . . . . . . . . 1.2 Cloud Computing . . . . . . . . . . . . . . . . . . . . . 1.2.1 Modelli di servizio . . . . . . . . . . . . . . . . 1.2.2 Modelli di distribuzione . . . . . . . . . . . . . 1.2.3 Vantaggi e svantaggi del Cloud nei sistemi Grid 2 Il monitoraggio dei sistemi informatici 2.1 Definizione e tipi di monitoraggio . . . 2.2 Il processo di monitoraggio . . . . . . . 2.3 Requisiti di un sistema di monitoring . 2.4 Performance monitoring . . . . . . . . 2.5 Tassonomia . . . . . . . . . . . . . . . 2.6 Metriche da valutare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 10 11 15 19 21 22 23 . . . . . . 26 27 29 29 31 33 33 3 Virtualizzazione e piattaforma Cloud: installazione e configurazione 3.1 Virtualizzazione . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 3.1.1 Virtualizzazione Hypervisor-based e virtualizzazione Non-Hypervisor-based . . . . . . . . . . . . . . . 3.2 KVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 36 39 i 3.3 3.4 Openstack . . . . . . . . . . . . . . . . . . 3.3.1 Architettura Concettuale . . . . . 3.3.2 Architettura Logica . . . . . . . . . 3.3.3 I componenti di Openstack . . . . . Installazione e configurazione di Openstack 3.4.1 FlatManager . . . . . . . . . . . . 3.4.2 FlatDHCPManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 41 42 43 50 55 56 4 Implementazione di un sistema di monitoraggio basato su Ganglia 4.1 Architettura di Ganglia . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Ganglia Monitoring Daemon . . . . . . . . . . . . . . . 4.1.2 Ganglia Meta Daemon(gmetad) . . . . . . . . . . . . . 4.1.3 Ganglia Web Fronted . . . . . . . . . . . . . . . . . . . 4.1.4 RRDtool . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.5 Estendere Ganglia . . . . . . . . . . . . . . . . . . . . 4.1.6 Moduli C/C++ . . . . . . . . . . . . . . . . . . . . . . 4.1.7 Moduli Python . . . . . . . . . . . . . . . . . . . . . . 4.2 Installazione e configurazione di Ganglia . . . . . . . . . . . . 4.2.1 Abilitazione del monitoraggio virtuale . . . . . . . . . . 4.2.2 Abilitazione e scrittura dei moduli python . . . . . . . 4.2.3 Metriche monitorate . . . . . . . . . . . . . . . . . . . 5 Verifica del Sistema: un semplice esperimento 5.1 Preparazione del job . . . . . . . . . . . . . . . 5.1.1 Sottomissione del job . . . . . . . . . . . 5.2 Analisi sperimentale . . . . . . . . . . . . . . . 5.2.1 Nodo fisico . . . . . . . . . . . . . . . . 5.2.2 Host del nodo virtuale . . . . . . . . . . 6 Conclusioni e sviluppi futuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 60 61 64 65 66 68 74 79 85 85 87 94 103 . 103 . 106 . 108 . 109 . 111 113 A Installazione Openstack 115 A.1 Installazione e configurazione di Keystone . . . . . . . . . . . 115 A.2 Installazione e configurazione di Image Service . . . . . . . . . 120 ii A.3 A.4 A.5 A.6 Configurare l’hypervisor . . . . . . . . . . . Installazione e configurazione NOVA . . . . Installazione e configurazione Block Storage Installazione e configurazione Dashboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 121 123 123 B Installazione Ganglia 124 B.1 Installazione server . . . . . . . . . . . . . . . . . . . . . . . . 124 B.2 Installazione client . . . . . . . . . . . . . . . . . . . . . . . . 127 C Script creati C.1 File per estendere Ganglia . . . . . C.1.1 m600.pyconf . . . . . . . . . C.1.2 m600.py . . . . . . . . . . . C.1.3 chassisX.pyconf . . . . . . . C.1.4 chassisX.py . . . . . . . . . C.1.5 rackX.pyconf . . . . . . . . C.1.6 rackX.py . . . . . . . . . . . C.2 File per la migrazione dati . . . . . C.2.1 Analisi log torque01 . . . . C.2.2 Migrazione da RRA a mysql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 . 129 . 129 . 130 . 133 . 134 . 137 . 140 . 156 . 156 . 167 Bibliografia 172 Ringraziamenti 174 iii Elenco delle figure 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 2.1 2.2 2.3 Virtual Organization . . . . . . . . . . . . . . . . . . . . . . Modello a clessidra . . . . . . . . . . . . . . . . . . . . . . . Confronto tra l’architettura Grid e il modello ISO/OSI . . . I protocolli,servizi,API dei livelli Collective e Resource possono essere combinati in molti modi per fornire funzionalit`a alle applicazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . I software development kits implementano delle API specifiche. Queste API a loro volta utilizzano i protocolli Grid per interagire coi servizi di rete che forniscono le capacit`a agli utenti. Gli SDKs possono fornire funzionalit`a che non sono direttamente mappate con uno specifico protocollo, ma possono combinare pi` u operazioni di diversi protocolli . . . . . . . . Architettura Grid . . . . . . . . . . . . . . . . . . . . . . . . Consumo in kilowatts di 500k computer . . . . . . . . . . . . Analisi del consumo di potenza . . . . . . . . . . . . . . . . Analisi dell’utilizzo dei core del datacenter di Lione . . . . . Rapporto tra il consumo energetico e l’utilizzo delle risorse . Vantaggi e svantaggi del Cloud Computing . . . . . . . . . . Modelli di servizio . . . . . . . . . . . . . . . . . . . . . . . Server Consolidation . . . . . . . . . . . . . . . . . . . . . . . . . 6 7 8 . 10 . . . . . . . . . 11 12 17 17 18 18 20 21 24 Architettura di un sistema Grid . . . . . . . . . . . . . . . . . 31 Un republisher implementa sia l’interfaccia di procuder che di consumer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Esempio di tassonomia . . . . . . . . . . . . . . . . . . . . . . 33 iv 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 Tipologie di Hypervisor . . . . . . . . . KVM . . . . . . . . . . . . . . . . . . . Architettura concettuale di Openstack Architettura logica di Openstack . . . Esempio di Dashboard . . . . . . . . . Architettura reale . . . . . . . . . . . . Requisiti hardware per l’installazione . Esempio di bridge . . . . . . . . . . . . FlatManager . . . . . . . . . . . . . . . FlatDHCPManager . . . . . . . . . . . Doppio gateway . . . . . . . . . . . . . Pagina di login . . . . . . . . . . . . . Pagina dell’amministratore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 40 41 42 43 51 52 54 55 56 57 58 58 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 Architettura di Ganglia . . . . . . . . . . . . . . . Architettura di Gmond . . . . . . . . . . . . . . . Architettura di Gmetad . . . . . . . . . . . . . . Funzionamento di RRA . . . . . . . . . . . . . . . Funzionamento di sFlow . . . . . . . . . . . . . . Agent hsflowd . . . . . . . . . . . . . . . . . . . . Esempio di MIB . . . . . . . . . . . . . . . . . . . Controllo Rack . . . . . . . . . . . . . . . . . . . RRA in XML . . . . . . . . . . . . . . . . . . . . Metriche dei rack monitorate da Ganglia . . . . . Consumo chassis . . . . . . . . . . . . . . . . . . Potenza aggregata del cluster SCOPE . . . . . . . Potenza di un gruppo di host del cluster SCOPE Tabella dei job . . . . . . . . . . . . . . . . . . . Tabella dei Worker Node . . . . . . . . . . . . . . Tabella dei rack . . . . . . . . . . . . . . . . . . . Tabella dei chassis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 63 65 68 86 87 92 94 96 96 97 99 100 100 101 101 102 5.1 5.2 5.3 Infrastruttura Grid virtuale . . . . . . . . . . . . . . . . . . . 104 Output del job . . . . . . . . . . . . . . . . . . . . . . . . . . 107 CPU wio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 v 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 Potenza media: 243.15 ± 47.56 Watts . . . . . Utilizzo medio della system CPU : 0.8 ± 0.01% Utilizzo medio della user CPU : 97.84 ± 4.03% Numero di processi in esecuzione . . . . . . . . Potenza media: 215.47 ± 32.26 Watts . . . . . Utilizzo medio della system CPU : 9.17 ± 0.07% Utilizzo medio della user CPU : 90.65 ± 0.46% Numero di processi in esecuzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 109 110 110 111 111 112 112 A.1 A.2 A.3 A.4 A.5 Lista utenti . . . . . . . . . . Lista dei tenant . . . . . . . . Lista dei servizi . . . . . . . . Lista delle immagini di Glance Servizi Nova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 118 120 121 122 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi Elenco delle tabelle 4.1 4.2 Funzioni di consolidamento . . . . . . . . . . . . . . . . . . . . 67 Metriche di default di gmond . . . . . . . . . . . . . . . . . . 69 6.1 Tempi di calcolo del job . . . . . . . . . . . . . . . . . . . . . 113 vii Introduzione Negli ultimi anni il Cloud Computing ha trovato larga diffusione in numerose applicazioni, dalla condivisione di file alla proliferazione del software as a service, fino alla fornitura di infrastrutture hardware remote accessibili via Internet. Oggi, inizia a evolversi e diffondersi anche come paradigma per migliorare la gestione dei data center. Ci`o `e principalmente dovuto all’utilizzo della virtualizzazione nei sistemi di Cloud computing e ai vantaggi che da essa ne derivano. Infatti, la virtualizzazione consente di consolidare il carico di un sistema in un numero ridotto di macchine fisiche, cos`ı da aumentare l’efficienza energetica del data center, nonch´e di migliorarne l’affidabilit`a attraverso l’utilizzo di tecniche di fault tolerance, la cui implementazione `e impraticabile per macchine fisiche[1]. Un caso particolare `e costituito dai sistemi batch (batch systems), cio`e supercomputer che eseguono attivit`a di lavoro (job) senza l’intervento umano. Anche i batch systems utilizzati per le elaborazioni scientifiche e facenti parte di un sistema Grid stanno migrando verso il paradigma del Cloud computing, sebbene ci`o possa causare un degrado delle prestazioni del sistema. La presenza di un maggior numero di strati software, quali i middleware per la gestione del Cloud, nonch´e il tempo necessario alla creazione e distruzione delle stesse macchine virtuali, introducono delle operazioni aggiuntive da effettuare prima di poter eseguire i job sottomessi dagli utenti. Dopo che un job `e sottomesso, un gestore delle risorse deve individuare una macchina fisica che che sia in grado di ospitare una macchina virtuale per l’esecuzione del job stesso, avviare la macchina virtuale, eseguire il job e, quando questo `e terminato, distruggere la macchina virtuale e liberare le risorse occupate. Inoltre, la presenza di un virtual machine monitor per la gestione delle macchine virtuali in esecuzione su macchine fisiche, introduce un overhead che 1 influisce sulle prestazione del sistema. L’altra faccia della medaglia, per`o, `e costituita dalla semplificazione della gestione delle macchine che consente il Cloud e dal consolidamento del carico su un numero ridotto di esse cos`ı da ottenere un guadagno in termini di consumo di energia elettrica. Mentre non `e possibile compattare macchine fisiche, quelle virtuali necessarie all’esecuzione dei job possono essere raggruppate su un numero ridotto di server fisici e tenere spenti o in stand-by quelli inutilizzati. Inoltre, le pi` u recenti piattaforme per il Cloud computing consentono, oltre alla virtualizzazione delle macchine che eseguono i job (worker node), la virtualizzazione della rete e, quindi, dei canali di comunicazione tra i componenti costituenti il supercomputer. Ci`o permette di determinare e salvare lo stato dell’intero sistema , altrimenti difficile, se non irrealizzabile, per sistemi non virtualizzati, dove lo stato dei canali di comunicazione potrebbe non essere accessibile e quindi i messaggi in transito non noti in fase di determinazione dello stato del sistema. Altro componente chiave di un batch system, cos`ı come di un qualsiasi data center, `e il sistema di monitoraggio, il quale permette di analizzare il comportamento del sistema al fine di migliorarne l’utilizzo e la gestione. Esso consente di individuare in tempi rapidi comportamenti anomali e quindi avviare prontamente operazioni di ripristino o, ancora, di studiare i trend del sistema per effettuare operazioni di prevenzione. Inoltre, volendo valutare l’effetto del Cloud e della virtualizzazione si un batch sysem, il sistema di monitoraggio deve anche fornire metriche di performance e consumo relative sia all’esecuzione di un certo carico su macchine fisiche che del medesimo carico su macchine virtuali. Partendo da tali considerazioni, questo lavoro di tesi si incentra sulla implementazione di un batch system virtualizzato nonch´e del relativo sistema di monitoraggio. Il sistema batch considerato `e S.Co.P.E., il supercalcolatore della Universit`a Federico II facente parte della Grid nazionale ed Europea, nonch´e del progetto ATLAS per lo studio del Bosone di Higgs. La tesi `e strutturata come segue. Nel Capitolo 1 si introducono il Grid computing e il Cloud computing e si discutono i limiti del primo e come il Cloud pu`o essere utilizzato per superarli. Nel Capitolo 2 si evidenzier`a il ruolo e l’utilit`a del 2 monitoraggio in tali sistemi. Il Capitolo 3 `e incentrato sulla virtualizzazione, illustrandone i principi base di funzionamento, e sulla presentazione della piattaforma software Cloud utilizzata. Nel Capitolo 4 si presenta il sistema di monitoraggio installato, le metriche da esso tenute in considerazione e le estensioni implementate per monitorare la potenza e altre metriche non presenti nel sistema di monitoraggio di base. Il Capitolo 5 mostra il corretto funzionamento delle infrastrutture Cloud e di monitoraggio attraverso un esperimento che confronta il sistema virtualizzato ed il sistema non virtualizzato attraverso l’andamento delle metriche monitorate durante l’esecuzione degli esperimenti. Infine, al Capitolo 6, si traggono le conclusioni e si delineano i possibili sviluppi futuri. 3 Capitolo 1 Problematiche del Grid computing In questo capitolo vengono presentati prima il Grid computing, con le sue principali caratteristiche e i suoi problemi, e successivamente il Cloud Computing. Inoltre si spiega come quest’ultimo possa contribuire a superare i limiti presenti nel Grid. 1.1 Grid Computing Esistono molte definizioni di Grid computing: • Plaszczak e Wellner[5] definiscono la tecnologia Grid come una tecnologia che abilita la virtualizzazione delle risorse,la fornitura di queste on-demand,e la condivisione di risorse e servizi tra organizzazioni. • IBM [6] definisce il Grid computing come l’abilit`a di utilizzare un insieme di standard e protocolli open, per guadagnare l’accesso alle applicazioni e ai dati, incrementare la potenza di elaborazione,e aumentare la capacit`a di storage. Il Grid `e un tipo di sistema parallelo e distribuito che abilita la condivisione,la selezione e l’aggregazione di risorse distribuite tramite domini amministrativi diversi basati sui propri requisiti di disponibilit`a,capacit`a,performance e costi e QoS degli utenti. 4 • CERN[7],che rappresenta uno dei pi` u grandi utenti della tecnologia Grid, ne parla definendolo come un servizio per la condivisione delle capacita di data storage e di calcolo attraverso internet In generale il Grid computing o sistemi Grid sono un’infrastruttura di calcolo distribuito, utilizzati per l’elaborazione di grandi quantit`a di dati, mediante l’utilizzo di una vasta quantit`a di risorse. In particolare, tali sistemi permettono la condivisione coordinata di risorse all’interno di un’organizzazione virtuale. Ci`o che distingue il Grid computing dai sistemi di calcolo ad alte prestazioni convenzionali come cluster di calcolo, `e che le reti tendono ad essere pi` u debolmente accoppiate , eterogenee e geograficamente disperse. Il Grid pu`o essere visto come un super computer virtuale , composto da molti computer debolmente accoppiati che agiscono insieme per eseguire compiti di grandi dimensioni. Questo `e in contrasto con la nozione tradizionale di un supercomputer , composto da molti processori collegati tramite un bus ad alta velocit`a. Le dimensioni di una griglia possono variare da piccole - confinata ad una rete di pochi computer all’interno di una societ`a ` , per esempio, a grandi collaborazioni pubbliche in molte aziende e reti. E con la nascita del Grid computing, che vengono coniati nuovi termini come Virtual Organization, col quale ci si riferisce all’insieme dinamico di individui o istituzioni, definiti attorno a un insieme di condizioni e di regole per la condivisione delle risorse. Tutte queste organizzazioni virtuali condividono alcuni elementi comuni tra di loro, comprese le preoccupazioni e le esigenze , ma possono variare di dimensione, di obbiettivi, di durata, e di struttura. I requisiti principali per il Grid computing possono essere riassunti in questo modo: • Integrare e coordinare risorse, stabilendo un insieme di regole e permessi di condivisione garantite da procedure di autenticazione e autorizzazione. • Gestire le risorse in modo trasparente, gli utenti devono accedere alle risorse remote come se fossero locali. • Garantire servizi in termini di : performance, sicurezza, tolleranza ai guasti , disponibilit`a e tempi di risposta. 5 • Accounting delle risorse: le informazioni sono raccolte in un database (Home Location Register) che non si appoggia su alcun archivio centrale, ma su una rete di server indipendenti usati per mantenere i record delle transazioni effettuate dagli utenti sulle risorse (il servizio pu`o essere usato per tracciare classiche informazioni computazionali come il tempo di CPU o l’uso della memoria). Tali informazioni possono essere aggregate in diversi modi: la granularit`a arriva fino al singolo job eseguito sul Grid Figura 1.1: Virtual Organization Solitamente l’architettura Grid `e rappresentata come una clessidra o come nell’immagine 1.3 in cui viene evidenziato il parallelismo con il modello ISO/OSI. Come si pu`o vedere dalle due figure l’infrastruttura `e divisa su pi` u livelli: • Fabric • Connectivity • Resource • Collective 6 Figura 1.2: Modello a clessidra • Application Il livello Fabric `e il livello che fornisce le risorse che possono essere di tipo computazionale,oppure sistemi di storage o di rete, o ancora cataloghi e sensori. Ma una risorsa pu`o essere anche un entit`a logica,come un file system distribuito, un cluster di computer. Per accedere a queste risorse vengono utilizzati i protocolli della griglia. Il livello Connectivity definisce il cuore dei protocolli di comunicazione e di autentificazione richiesti per le transazioni di rete per lo specifico Grid. I protocolli di comunicazione abilitano lo scambio di dati tra le risorse del livello Fabric.I requisiti di comunicazione includono trasporto, routing e naming. Il protocollo di autentificazione `e costruito sui servizi di comunicazione per fornire meccanismi di sicurezza crittografica, allo scopo di verificare l’identit`a di utenti e risorse. Le soluzioni per gli ambienti di VO devono avere le seguenti caratteristiche : • Single sign on: l’utente deve essere capace di fare il log in una sola volta e avere l’accesso multiplo alle risorse del Grid definite nel livello Fabric, senza ulteriori interventi dell’utente 7 Figura 1.3: Confronto tra l’architettura Grid e il modello ISO/OSI • Delegation: l’ utente deve essere in grado di dotare un programma con l’abilit`a di eseguire a nome suo, in modo che quest’ultimo possa accedere alle risorse per le quali l’utente `e autorizzato • Integration with various local security solutiuons: ogni fornitore di risorse dovrebbe implementare le soluzioni per la sicurezza locale in modo che non interferiscano con quelli pre-esistenti • User-based trust relationships: per permettere a un utente di usare risorse da pi` u provider contemporaneamente, senza che il sistema di sicurezza richieda all’utente di ri-autentificarsi Il livello Resource costruito sul livello Connectivity `e utilizzato per definire dei protocolli per l’iniziazione sicura, per il monitoraggio, e il controllo delle operazioni di condivisione sulle risorse individuali. Il layer Resource implementa questi protocolli invocando le funzioni del livello Fabric per accedere e controllare le risorse locali. I protocolli del livello Resource si interessano delle risorse individualmente e quindi ignora i problemi dello stato globale. Ci sono due classi di protocolli per il layer Resource : • Information protocols che sono usati per ottenere informazioni circa la struttura e lo stato delle risorse. • Management protocols sono usati per negoziare l’accesso alle risorse condivise, specificando i requisiti delle risorse e le operazioni che devono 8 essere eseguite. Quindi i protocolli di management sono responsabili per l’istanziazione di relazioni di condivisione. Il livello Collective, a differenza del livello Resource che focalizza l’attenzione su una singola risorsa., contiene protocolli e servizi che non sono associati a una specifica risorsa ma piuttosto sono globali e catturano le interazioni tra collezioni di risorse. Esso possono implementare una grande variet`a di comportamenti di condivisione senza imporre nuovi requisiti su risorse che devono essere condivise. Per esempio: • Directory services permette ai partecipanti della VO di scoprire l’esistenza e le propriet`a delle risorse della VO • Co-allocation, scheduling and brokering services permettono ai partecipanti della VO di richiedere l’allocazione di una o pi` u risorse per uno specifico scopo e di schedulare i task sulle risorse appropriate • Monitoring and diagnostics service supporta il monitoraggio delle risorse della VO. • Data replication services supporta la gestione delle risorse di storage della VO in modo da massimizzare le performance dell’accesso ai dati. • Grid-enabled programming systems abilita modelli di familiaret`a che sono usati in ambiente Grid. • Software discovery services scova e seleziona la miglior implementazione software e la piattaforma di esecuzione in base ai parametri del problema da risolvere L’ultimo livello dell’architettura Grid comprende le applicazioni degli utenti che lavorano in un ambiente VO. La figura sottostante mostra una vista dal lato del programmatore dell’architettura Grid. Le applicazioni sono costruite in termini di servizi definiti a ogni livello. A ogni livello sono stati definiti protocolli che forniscono l’accesso a servizi utili: management delle risorse, accesso ai dati, scoperta delle risorse e tant altro. Ad ogni livello possono essere definiti API la cui implementazione scambia messaggi con gli appropriati servizi per far si che vengano eseguite le azioni desiderate. 9 Figura 1.4: I protocolli,servizi,API dei livelli Collective e Resource possono essere combinati in molti modi per fornire funzionalit` a alle applicazioni 1.1.1 Componenti di un sistema Grid In qualsiasi infrastruttura Grid i componenti fondamentali sono gli stessi. Esso `e composto da : 1. Computing element : `e l’insieme di risorse di elaborazione localizzate in un sito(un cluster). Un CE include un Grid Gate che agisce come una generica interfaccia col cluster. 2. Worker Node : sono i veri e propri nodi che ospitano l’elaborazione dei dati. Essi sono gestisti dal CE. 3. Storage Element: fornisce un accesso uniforme alle risorse di dati di storage. Inoltre supporta diversi protocolli e interfacce per l’accesso ai dati. 4. User Interface: pu`o essere una qualsiasi macchina dove gli utenti hanno un account personale e dove i loro certificati sono installati. Da una UI un utente pu`o essere autentificato e autorizzato per usare le risorse. Le operazioni principali che si possono eseguire sono sottomettere un job, cancellare un job, richiedere la lista di tutte le risorse usate per eseguire un job, prendere l’output di un job finito o mostrare lo status di uno in esecuzione. 10 Figura 1.5: I software development kits implementano delle API specifiche. Queste API a loro volta utilizzano i protocolli Grid per interagire coi servizi di rete che forniscono le capacit` a agli utenti. Gli SDKs possono fornire funzionalit` a che non sono direttamente mappate con uno specifico protocollo, ma possono combinare pi` u operazioni di diversi protocolli 5. Information Service: fornisce le informazioni riguardo le risorse e il loro stato. 6. Workload management: ha lo scopo di accettare i job degli user, di assegnarli al compute element pi` u appropriato e salvare il loro stato e prenderne l’output. 1.1.2 Un esempio di sistema Grid: SCOPE S.Co.P.E. `e un’iniziativa dell’Universit`a degli Studi di Napoli Federico II. Nasce con l’obiettivo di creare un’infrastruttura di supercomputing general purpose, basata sul paradigma del Grid e sulle pi` u moderne tecnologie di calcolo distribuito, a supporto della ricerca di base e delle Piccole e Medie Imprese. Sulla base di una preesistente infrastruttura di rete metropolitana, che connette al gigabit tutte le maggiori strutture di ricerca dell’Ateneo, l’architettura di S.Co.P.E. prevede di integrare le risorse di calcolo e storage attualmente disponibili, con nuovo hardware ad alte prestazioni. Tali risorse 11 Figura 1.6: Architettura Grid verranno infine inglobate in un unica piattaforma di tipo Grid, basata su middleware di nuova generazione, integrandosi altres`ı con le altre infrastrutture di griglia nazionali ed internazionali. L’architettura finale consiste dunque nella creazione di una Grid Metropolitana capace di unire le sinergie dei dipartimenti e strutture di ricerca afferenti o in collaborazione con la Federico II, distribuite nella citt`a di Napoli. S.Co.P.E. promuove inoltre lo sviluppo scientifico per la ricerca di base e l’innovazione tecnologica, finalizzata alla creazione di codici innovativi ed applicativi nei 4 settori strategici: • Scienze del Microcosmo e del Macrocosmo • Scienze dei Materiali e dell’Ambiente • Scienze della Vita In queste aree di interesse `e impegnata una grande comunit`a scientifica forte delle esperienze e delle competenze maturate in numerosi progetti pregressi ed in stretta collaborazione con l’INFN ed altre strutture di ricerca 12 locali e nazionali. I nodi principali coinvolti nel progetto sono il CAMPUSGrid, sede del polo scientifico dell’ateneo e del Data Center SCoPE, le strutture di Ingegneria, il Policlinico ed il CSI (Centro di ateneo per i Servizi Informativi). Le risorse di calcolo del Data Center del progetto S.C.O.P.E vantano di hardware ad altissime prestazioni, che lo rendono una struttura molto competitiva nel campo del calcolo intensivo ad alte prestazioni. L’intera struttura dispone di: • Pi` u di 300 Worker Node bi-processore quadcore a 64bit 8 o 16GB RAM (con un totale di 2432 core), in soluzione blade; • 16 lame per shelf, con connessioni infiniband a 10 Gbit/sec; • Risorse di storage di 200 TB connesse in Fiber Channel; • 32 TB di storage iSCSI connesse in Ethernet; • 10 Storage Element con connessioni Fiber Channel; • 33 Rack con raffreddamento interno; • Rete infiniband su ogni macchina. Per quanto riguarda le risorse di rete invece il data center dispone di una divisione LAN e WAN: LAN: • Dorsale di rete a 10 Gbit/sec. • Rete ridondata divisa a 1 Gbit/sec. • Rete a bassa latenza infiniband a 10 Gbit/sec. WAN • Collegamenti Intranet a 2.4 Gbit/sec, ridondati • Collegamenti Internet a 1 Gbit/sec, ridondati 13 gLite gLite `e un middleware per il Grid Computing usato negli esperimenti LHC del ` stato implementato dalla collaborazione CERN e dal datacenter S.Co.P.E. E di pi` u di 80 persone di 12 tra centri di ricerca industriali o accademici in Europa. gLite fornisce un framework per costruire applicazioni nel calcolo distribuito e tra le risorse di storage attraverso Internet. I servizi di gLite sono utilizzati da pi` u di 250 centri di calcolo e usati da pi` u di 15000 ricercatori in Europa e nel resto del mondo. I primi prototipi furono sviluppati tra il 2004 e il 2005 ma `e solo nel 2006, con l’uscita della release gLite 3.0 che diventa il middleware ufficiale del progetto Enabling Grids for E-scienceE (EGEE). I componenti principali di gLite sono : • User Interface • Computing element • Storage Element • Information service • Workload management La User Interface `e il punto di acceso al Grid gLite. Si trova su una qualsiasi macchina dove gli utenti hanno un account personale e dove il loro certificato `e stato installato. Dalla UI, un utente pu`o essere autorizzato e autenticato ad usare le risorse, e ad accedere alle funzionalit`a offerte. Inoltre fornisce alcune operazioni base sul Grid : • visitare la lista di tutte le risorse disponibili per eseguire un determinato job • sottomettere job • cancellare job • richiamare l’output dei job finiti • mostrare lo stato dei job sottomessi 14 • richiamare le informazioni di logging del job • copiare, replicare e cancellare i file dal Grid • richiamare lo stato di risorse differente dall’Information System. Il Computing Element `e come detto prima un insieme di risorse di calcolo localizzate in un sito. Questi include un GridGate che agisce come interfaccia generica per il cluster, un Local Resourse Management System/LRMS) e un insieme di Worker Nodes. Lo Storage Element fornisce un accesso uniforme alle risorse di data storage. Supporta vari tipi di protocolli d’accesso ai dati. Inoltre spesso le risorse vengono gestite da un Storage Resource Manager, che `e un servizio che fornisce capacit`a come la migrazione trasparente tra dischi. L’Information Service fornisce informazioni sulle risorse del Grid e sul loro stato. Le informazioni sono essenziali per il funzionamento dell’intero Grid in quanto `e attraverso l’IS che le risorse sono scoperte. Le informazioni pubblicate sono anche usate per scopi di monitoraggio e accounting. Lo scopo del Workload management System `e di accettare i job degli utenti, per assegnargli il Computing Element, per memorizzare il loro stato e richiamare il loro output. Il Resource Broker `e la macchina dove girano i servizi di WMS. I job che devono essere sottomessi sono descritti usando il linguaggio Job Description Language (JDL).La scelta del CE al quale `e inviato il job `e fatta da un processo chiamato match-making, che selezioni il primo, tra i CE disponibili, che soddisfano i requisiti espressi dall’utente. 1.1.3 Limiti del Grid Una caratteristica ormai evidente nella stragrande maggioranza dei moderni Data Center `e che continuano ad espandersi sempre pi` u sia in termini di investimento tecnologico, sia in termini di capacit`a di calcolo. Assistiamo anno dopo anno, infatti, alla progressiva introduzione di nuovi apparati o soluzioni software, anche differenti tra loro, al fine di soddisfare esigenze crescenti ed agevolare comunicazione e rapporti verso clienti e fornitori. Si nota spesso, dunque, come le tradizionali metodologie, finora utilizzate per il monitoraggio degli ambienti e degli apparati dei Data Center, non siano pi` u sufficienti 15 a dare un quadro completo ed immediato della condizione dell’intero centro, ma solo dei singoli componenti o dei sistemi facenti parte della stessa soluzione informatica. La capacit`a di disporre in tempo reale di una visione d’insieme delle risorse e del loro stato permetterebbe, invece, di intervenire in modo mirato e significativo in caso di anomalie o indisponibilit`a delle stesse, prevenendo in certi casi la stessa indisponibilit`a. Il pi` u delle volte grosse aziende ed enti pubblici, tra cui le universit`a, dispongono di pi` u sistemi di monitoraggio, uno per ogni tipologia di sistema informatico che viene integrato nella rete, e ci`o comporta una frammentazione dei report dello stato di salute di tutti gli apparati e servizi, con la conseguente quasi impossibilit`a di monitorare in maniera globale il funzionamento dell’infrastruttura complessiva. Spesso, infatti, accade che il responsabile o l’amministratore dei sistemi informativi rilevi anomalie, guasti o disservizi solo al momento della segnalazione da parte di utenti, dipendenti, collaboratori interni e esterni, partner, etc. provocando enormi disagi e ingenti rallentamenti nel lavoro da svolgere. Inoltre una soluzione del genere costringe l’utente a dover navigare tra diverse interfacce durante l’osservazione, l’analisi della rete e la ricerca delle cause di un problema su di essa. Un altro discorso da affrontare, sempre nell’ambito del monitoraggio dei Data Center, riguarda il fatto che attualmente in circolazione ci sono moltissimi sistemi commerciali in grado di effettuare il monitoring delle apparecchiature, ma non tutti, se non nessuno, sono in grado di soddisfare le esigenze di un intero gruppo di lavoro che molto spesso ha bisogno di un vero e proprio sistema personalizzato.Un’altra sfida che si presenta in un architettura Grid `e la riduzione del consumo di potenza. Dall’immagine 1.7 ci rendiamo conto come la cattiva gestione dei workernodes in un infrastruttura Grid pu`o portare a un consumo di potenza eccessivo. Prendiamo in considerazione il caso di Grid5000. Questi `e un testbed sperimentale francese, progettato per le ricerche parallele su larga scala. E’ composto da: • 9 siti • 5000 cores • una rete Gb dedicata 16 Figura 1.7: Consumo in kilowatts di 500k computer Grazie a un recente studio fatto sul sito di Lione[8] che ha permesso il monitoraggio in potenza dei 135 nodi del cluster si pu`o valutare l’impatto dello stato idle del sistema sul consumo di potenza. Nell’immagine 1.8 notiamo infatti come tra lo stato di idle e lo stato di stress ci sia una variazione minima nel consumo di potenza, Figura 1.8: Analisi del consumo di potenza e se immaginiamo che il Grid `e solitamente sottoutilizzato(si parla del 6070% delle sue potenzialit`a [? ] )si pu`o capire quanto sarebbe facile abbattere i costi sul consumo di potenza con una gestione ottimale delle risorse. Nell’immagine 1.9 viene mostrato a prova di quello appena detto la percentuale di utilizzo delle risorse nel sito di Lione. 17 Figura 1.9: Analisi dell’utilizzo dei core del datacenter di Lione Nell’immagine 1.10 `e mostrato, a prova di quello detto precedentemente, il rapporto che solitamente c’`e tra il consumo di potenza e l’utilizzo effettivo delle risorse. Figura 1.10: Rapporto tra il consumo energetico e l’utilizzo delle risorse Altro problema `e l’utilizzo di strategie per la fault tolerance. Spesso i job di un Grid sono molti grandi e l’ambiente in cui eseguono pu`o facilmente fallire,cos`ı diventa importante dare una QoS agli utenti Grid. Date le dimensioni dei job, provare a fare un recovering da un fault in un Grid `e molto pi` u difficile che in una normale applicazione[10]. Il termine fault tolerance significa continuare a lavorare correttamente anche in presenza di fault anche se con performance ridotte . Un sistema indipendente `e incline a crashare e inoltre i componenti individuali in un sistema di calcolo potrebbero fallire senza fermare l’intero sistema di computing. Il Grid come detto in precedenza `e composto da grandi insiemi di risorse, distribuite geograficamente in posti diversi ma che sono raggruppate logicamente in un virtual computer per l’esecuzione di applicazioni specifiche. Poich`e il numero di componenti del Grid tende ad aumentare, anche la probabilit`a di guasto diventa pi` u alta di quella in uno scenario di calcolo parallelo tradizionale. Le applicazio18 ni Grid di tipo compute intensive spesso richiedono tempi di lavoro lunghi per risolvere un singolo problema. Cos`ı, l’enorme potenziale elaborativo del Grid, spesso, rimane inesplorato soprattutto a causa della loro suscettibilit`a ai fallimenti come, process failure,crash di macchine, violazione delle deadline e dei contratti di lavoro, impossibilit`a a fornire il servizio, cos`ı da avere una QoS degradata rispetto alle attese dell’utente. La gestione dei guasti `e quindi un importante sfida per gli sviluppatori di applicazioni per Grid. ` stato dimostrato che i guasti nell’interazione,nel timing e nelle omissione E sono quelli che si manifestano maggiormente. Nei paragrafi successivi faremo una breve panoramica sul Cloud computing e spiegheremo come la virtualizzazione pu`o essere utile nella risoluzione di alcuni dei problemi che affliggono il Grid computing. 1.2 Cloud Computing Il NIST (National Institute of Standard and Technology) definisce il Cloud come[11]]: Cloud computing is a model for enabling ubiquitous, convenient, on-demand network access to a shared pool of configurable computing resources (e.g., networks, servers, storage, applications, and services) that can be rapidly provisioned and released with minimal management effort or service provider interaction. cio`e un modello per abilitare in qualunque luogo,in modo conveniente l’accesso su richieste a un pool di risorse di calcolo condivise, e che pu`o essere rapidamente rifornito e rilasciato col minimo sforzo di gestione o con l’interazione con il service provider. Sempre il NITS identifica cinque caratteristiche essenziali: 1. On-demand self-service. Un cliente pu`a unilateralmente richiedere le capacit`a di elaborazione, come server time o network storage , automaticamente senza l’interazione umana col provider. 19 2. Broad network access. Capacit`a di essere available attraverso la rete e accesso tramite meccanismi standard che promuovono l’uso di piattaforme eterogenee 3. Resource pooling. Le risorse del provider sono messe insieme per servire pi` u clienti usando un modello multi-tenant, con risorse fisiche e virtuali differenti dinamicamente assegnate e riassegnate in accordo alle richieste del consumatore. 4. Rapid elasticity. Capacit`a che indica l’elasticit`a nel fornire e rilasciare le risorse, in alcuni casi automaticamente, per scalare rapidamente a seconda della domanda. Per il consumatore, l’idea di aver accesso a risorse che appaiono illimitate e che possono essere utilizzate in ogni luogo e in ogni momento 5. Measured service. Il sistema Cloud automaticamente deve controllare e ottimizzare l’uso delle risorse, sfruttando una capacit`a di misurazione a un certo livello di astrazione appropriato per il tipo di servizio. L’utilizzo delle risorse pu`o e deve essere controllato e segnalato riportando trasparenza sia per il provider che per il consumatore del servizio Figura 1.11: Vantaggi e svantaggi del Cloud Computing 20 1.2.1 Modelli di servizio Nonostante il termine sia piuttosto vago e sembri essere utilizzato in diversi contesti con significati differenti tra loro, si possono distinguere tre tipologie fondamentali di servizi Cloud computing : • infrastructure as a service (IaaS) • platform as a service (PaaS) • software as a service (SaaS) Figura 1.12: Modelli di servizio L’espressione Software as a Service `e legata principalmente al mondo commerciale. I clienti non pagano per il possesso del software bens`ı per l’utilizzo dello stesso. Solitamente l’accesso al software `e possibile tramite API o spesso tramite Web service o REST. Il SaaS `e un insieme di mezzi,servizi e competenze che consente alle aziende di esternalizzare completamente alcuni aspetti del loro sistema informativo (messaggistica, sicurezza ...) e sostituirlo con un costo di funzionamento piuttosto che con un investimento vero e proprio. Il SaaS pu`o essere visto come il lato marketing del Service-Oriented Architecture (SOA) Il Platform as a service(PaaS) `e la distribuzione di piattaforme di elaborazione (Computing platform) e di solution stack come servizio. Gli 21 elementi del PaaS permettono di sviluppare, testare, implementare e gestire le applicazioni aziendali senza i costi e le complessit`a associate all’acquisto, la configurazione, l’ottimizzazione e la gestione dell’hardware e del software di base. Gli elementi del PaaS possono essere impiegati per la progettazione , sviluppo di applicazioni e di servizi applicativi come la collaborazione in team, l’integrazione Web, l’integrazione del database, la sicurezza e la gestione dello stato. Tali servizi possono essere impiegati come una soluzione integrata sul Web. L’Infrastructure as a service (IaaS) E’ un modello di fornitura nel quale un’ organizzazione esternalizza le attrezzature utilizzate per varie operazioni, incluso storage,hardware,server e componenti di rete. Il provider fornisce le risorse ed `e responsabile per la custodia, per l’esecuzione e per la manutenzione. 1.2.2 Modelli di distribuzione Se le caratteristiche indicavano come deve essere un servizio di Cloud computing e i modelli di servizi indicavano il cosa, i modelli di distribuzione indicano invece dove deve essere organizzato un modello di Cloud computing. In questo caso le possibili alternative sono quattro[10]. Private Cloud L’infrastruttura Cloud `e utilizzata per l’uso esclusivo di una singola organizzazione che comprende diversi clienti (business units). Esso potrebbe essere di propriet`a,gestito e operato da un organizzazione, da terze parti o da una combinazione di questi,e pu`o esistere in sede o fuori sede. Public Cloud L’infrastruttura `e fornita per uso pubblico. Esso pu`o essere di propriet`a, gestito e operato da un business, universit`a o un organizzazione governativi o da una combinazione di queste. Viene fisicamente allocato nella sede del provider Cloud. Hybrid Cloud. L’infrastruttura Cloud `e composta da due o pi` u distinte infrastrutture Cloud che rimangono entit`a a se stanti, ma sono legate insieme da tecnologie proprietari o standardizzate che abilitano la portabilit`a dei dati e delle applicazioni. Community Cloud L’infrastruttura Cloud `e fornita per uso esclusivo di una specifica comunit`a di consumatori dalle organizzazioni che condivido- 22 no preoccupazioni. Esso potrebbe essere di propriet`a, gestito da una o pi` u organizzazioni nella comunit`a, da una terza parte o da una combinazione di questo. 1.2.3 Vantaggi e svantaggi del Cloud nei sistemi Grid Una macchina virtuale `e una piattaforma di elaborazione che crea uno strato virtualizzato tra l’hardware e l’applicazione. Un utente Grid potrebbe beneficiarne in vari aspetti: • On demand creation and customization: gli utenti possono creare una macchina virtuale personalizzata, che fornisce risorse personalizzate agli utenti. • Performance isolation : gli utenti di una macchina virtuale possono aspettarsi ambienti di calcolo dedicati che sono difficili da trovare in server reali • Legacy software support : possono essere create macchine virtuali personalizzate che sono compatibili con le applicazione binarie legacy. • Easy management : solitamente gli utenti possono accedere ai server di calcolo con account che hanno privilegi ristretti. Questo rende difficile effettuare lavori come la compilazione, l’installazione e la configurazione di particolari ambienti. Al contrario le macchine virtuali possono offrire agli utenti la possibilit`a di accedere come root, in modo da poter gestire al meglio il proprio ambiente di lavoro. Se questi appena presentati sono i vantaggi della virtualizzazione per un utente di un sistema Grid, pensiamo invece ai vantaggi che una soluzione Cloud pu`o portare a un amministratore di sistemi Grid reali. Spesso si sente parlare di Server Consolidation[12]. E’ un approccio all’uso pi` u efficiente delle risorse nell’ottica della riduzione del numero totale di server necessari ad una azienda. Difatti spesso l’aggiunta di un servizio o di un’applicazione comportava l’installazione di un altro server, col conseguente sottoutilizzo delle risorse a disposizione. Grazie alla virtualizzazione un amministratore pu`o avere diversi vantaggi: 23 Figura 1.13: Server Consolidation • Backup e disaster recovery pi` u rapidi ed efficienti : il salvataggio `e pi` u semplice, e le immagini esportate possono essere anche caricate su hardware di fortuna. • Uso efficiente dello storage centralizzato :dove presente, l’utilizzo di un sistema SAN accoppiato ad un pool di server aumenta enormemente la flessibilit`a del sistema: ad esempio `e possibile spostare le istanze tra diversi server in relazione al carico richiesto • Minore occupazione di spazio e consumi inferiori: un uso pi` u razionale dello spazio in sala server e minori richieste in termini di alimentazione sono amici delle economie di scala. • Maggiore affidabilit` a: i problemi relativi all’aging e agli errori di configurazione sono ridotti notevolmente. Questo perch`e si presuppone che le macchine virtuali una volta utilizzate vengano spente e quindi il reboot continuo permette di evitare i bug relativi all’aging. Gli errori di configurazione invece sono evitati perch`e la configurazione viene fatta un’ unica volta(si spera in maniera corretta) e ogni qualvolta servisse verrebbe utilizzata sempre la stessa istanza. Se questi sono gli aspetti positivi della virtualizzazione in ambiente Grid, bisogna dire che esistono anche diversi aspetti negativi. Nelle applicazioni High-Performance Computing (HPC) tipiche dei sistemi Grid, `e richiesto un throughput elevato e il livello di virtualizzazione che si crea tra la guest e l’host pu`o diventare un grosso problema, soprattutto in quelle applicazioni 24 di tipo I/O che richiedono un accesso alle risorse hardware dell’host. Inoltre, al normale ciclo di vita di un job e quindi al tempo della sua esecuzione, si aggiunge anche il tempo impiegato per istanziare una macchina virtuale e per eliminarla. In pi` u bisogna tener conto che le VM vanno dimensionate in modo che la somma delle loro risorse non sia troppo vicina alle risorse fisiche reali. In quanto potrebbe accadere che con macchine virtuali che lavorano a pieno regime su uno stesso host, queste concorrino per l’accesso in memoria facendo s`ı che le risorse vengano utilizzate pi` u per lo swap che per l’effettivo bisogno. Quindi e’ importante valutare la giusta configurazione, in quanto a causa di una cattiva configurazione, si potrebbe avere un notevole degrado delle prestazioni. Anche il monitoraggio `e uno dei limiti del Cloud[13]. L’utente non ha la possibilit`a di utilizzare la propria infrastruttura di monitoraggio, e le informazioni limitate che riceve potrebbero non essere sufficienti per il livello di dettaglio richiesto . Lo stesso problema esiste potenzialmente anche per gli sviluppatori e gli amministratori del Cloud, dato che le risorse astratte di solito passano attraverso diversi strati di virtualizzazione e altri livelli di incapsulamento e tener traccia dei problemi lungo lo stack software/hardware potrebbe essere difficile. Nel prossimo capitolo viene presentato il problema del monitoraggio e le tecniche utilizzate. 25 Capitolo 2 Il monitoraggio dei sistemi informatici Il Grid lo si pu`o descrivere come un sistema distribuito di larga scala che permette a comunit`a sparpagliate di formare una VO, allo scopo di collaborare per la realizzazione di obbiettivi comuni. Questa collaborazione prende la forma di condivisione e gestione di risorse on-line. Le risorse Grid, possono dinamicamente entrare e andar via. Data questa natura transiente, gli utenti devono essere supportati per trovare e mantenere traccia delle risorse di loro interesse. Questo `e lo scopo principale del Grid Information Service. Allo scopo di indirizzare gli utenti a ci`o che necessitano, i servizi devono sistematicamente collezionare informazioni riguardo le attuali, e talvolta passate, risorse. Questo processo `e detto monitoring. Il monitoring `e cruciale per vari aspetti come lo scheduling, la replicazione dei dati, l’accounting,le analisi delle performance e l’ottimizzazione dei sistemi distribuiti o delle applicazioni utente, applicazioni auto sincronizzanti e molto altro. Cos`ı con l’incremento del numero di risorse, il monitoring real-time della loro disponibilit`a e utilizzazione `e diventato essenziale per la gestione, in particolare per quanto riguarda la rilevazione di guasti e colli di bottiglia e in alcuni casi anche la loro risoluzione automatica. A differenza dei dati prodotti da programmi, quelli provenienti da monitoring sono caratterizzati da un tempo di utilizzo generalmente fisso e breve, poich`e le informazioni relative alle prestazioni del sistema tendono a diventare obsolete molto rapidamente, possono 26 cambiare prima di essere lette. Spesso `e impossibile definire le performance di una risorsa o del componente di un’applicazione, utilizzando un singolo valore: le informazioni di performance (performance information) dovrebbero contenere metriche addizionali che quantificano l’accuratezza del valore stesso, il tempo di vita ed altri parametri calcolati a partire dai raw data. Il monitoraggio `e fondamentale per evitare situazioni avverse permettendo dei controlli preventivi prima che l’intero sistema IT fallisca con conseguente perdita dei lavori. E’ importante quindi un monitoraggio costante del sistema per verificare che tutto funzioni come dovrebbe. Nella forma primaria il monitoraggio di un sistema `e legato direttamente al concetto di produttivit`a. Ma nel nostro caso il sistema di monitoraggio `e fondamentale per comprendere gli effetti del Cloud sul Grid. In questa tesi vogliamo dimostrare che le ipotesi fatte sull’introduzione del Cloud in un sistema Grid siano veritiere. Per questo sar`a importante monitorare le macchine che faranno parte di questo progetto e quello che non ne faranno parte, e confrontare i risultati del monitoraggio per capire cosa cambia in termini di consumo di potenza, di throughput, di utilizzo della cpu e della memoria ram. Inoltre verranno monitorati costantemente gli chassis per rilevare ed evitare picchi di potenza e i rack per determinare eventuali malfunzionamenti legati al sistema di raffreddamento dell’infrastruttura SCOPE, delle ventole di raffreddamento, e per monitorare costantemente la temperatura che in questi sistemi pu`o raggiungere valori in grado di danneggiare irrimediabilmente le macchine. 2.1 Definizione e tipi di monitoraggio In questo paragrafo definiremo meglio il significato del monitoraggio e faremo alcuni esempi di monitoraggio. Una prima definizione[14] data da Hellawell e modificata da Brown successivamente afferma: Il monitoraggio `e una serie intermittente(regolare o irregolare) di osservazioni, nel tempo, effettuate per mostrare il grado di conformit`a rispetto a uno standard o il grado di deviazione da un comportamento aspettato. 27 Solitamente si monitora per osservare i cambiamenti che occorrono nel tempo o per osservare il comportamento o le comunicazioni tra individui o gruppi. L’IT performance management `e un termine che si riferisce al monitoraggio e alla misurazione delle metriche di performance per valutare la performance delle risorse IT. Esistono varie categorie di IT performance management: • Network performance management: `e un insieme di funzioni che valuta e riporta l’efficacia della rete o degli elementi della rete. Esso include anche sotto funzioni come ad esempio la raccolta di dati statistici, mantiene ed esamina i log, determina le prestazioni del sistema sotto condizioni artificiali e naturali e come varia il sistema sotto queste condizioni • System performance management : include il monitoraggio e l’utilizzo delle risorse dei sistemi operativi, incluso CPU, memoria, I/O, e uso del disco. Questo include sia sistemi fisici che virtuali • Application performance management (APM) : `e la disciplina nella gestione dei sistemi che si focalizza sul monitoraggio e la gestione delle performance e dell’availability delle applicazioni software. APM controlla il flusso di lavoro e i relativi strumenti informatici per rilevare,diagnosticare,rimediare e riportare i problemi sulle performance delle applicazioni per assicurare che le prestazioni dell’applicazione coincidano con le aspettative degli utenti • Business transaction management (BTM) `e la disciplina nella gestione dei sistemi che monitora le transazioni di business attraverso il data center allo scopo di gestire le performance IT. L’Environmental monitoring `e un altra tipologia di monitoring che descrive i processi e le attivit`a di cui si necessita per definire e monitorare la qualit`a dell’ambiente. Tutte le strategie di monitoraggio hanno ragione di esistere per stabilire lo stato attuale dell’ambiente e gli effetti che pu`o portare un cambiamento nelle condizioni ambientali. Pi` u in particolare nel caso di 28 un datacenter `e importante capire ad esempio come varia la temperatura all’interno, in modo da valutare se ci sono anomalie nel funzionamento del sistema di raffreddamento. 2.2 Il processo di monitoraggio I sistemi distribuiti di monitoraggio, e quindi anche Grid, tipicamente includono 4 passi: 1. generazione degli eventi, cio`e sensori che indagano le entit`a e codificano le misure in accordo a un dato schema. 2. La processazione degli eventi generati `e specifica per ogni applicazione, e pu`o prendere spazio durante ogni fase del processo di monitoraggio, tipicamente include il filtering in accordo ad alcuni criteri, o riassumendo un gruppo di eventi(cio`e calcolandone la media) 3. la distribuzione si riferisce alla trasmissione degli eventi dalla sorgente a ogni altra parte interessata 4. in ultimo, la presentazione tipicamente coinvolge alcune ulteriori elaborazioni in modo che l’immenso numero di eventi ricevuti sar`a fornito in una serie di astrazione allo scopo di far in modo che l’utente finale riesca a trarre conclusione circa il funzionamento del sistema monitorato. Una presentazione, tipicamente `e fornita da un’applicazione GUI che fa uso di tecniche di visualizzazione, che potrebbero usare sia stream real time di eventi o tracce registrate che usualmente vengono prese da un archivio 2.3 Requisiti di un sistema di monitoring Il monitoring `e un area di ricerca aperta, dove molti team di ricercatori definiscono requisiti e progettano soluzioni, basandosi sui seguenti requisiti basilari per un sistema di monitoring[13] : 29 • Fault tolerance: i componenti di un sistema di monitoring devono essere capaci di tollerare fallimenti, fallimenti sul sistema di reporting, sul sistema di directory, sulla rete. Il sistema di monitoring deve essere in grado di riconnettersi e sincronizzarsi automaticamente; • Low latency: le informazioni sulle prestazioni del sistema hanno generalmente un tempo di utilizzo breve, il delay di trasmissione della rilevazione deve essere minimo; • High data rate: il sistema di monitoring dovrebbe essere in grado di acquisire dati di performance anche se generati con un alto tasso; ottenendo valori medi e di picco in anticipo per evitare di sovraccaricare le componenti consumer del sistema; • Low overhead : ogni misurazione non deve essere intrusiva e deve usare solo una parte tollerabile delle risorse disponibili, altrimenti i valori misurati risulterebbero essere il sovraccarico introdotto stesso; • Scalability: i servizi di monitoring devono essere in grado di lavorare con centinaia di elementi. Alcuni usano un approccio centralizzato ma il problema con questo approccio `e che questo causa un traffico considerevole sulla rete in sistemi molto grandi. Una soluzione `e utilizzare vari componenti che cooperano per riconoscere eventi e stati tra un certo numero di nodi. Questo riduce la quantit`a di comunicazione, lo storage e l’overheads di processing. • Filtering and Correlation: spesso in sistemi molto grandi la quantit`a e la frequenza dei report di monitoring generati `e talmente elevato che pu`o velocemente consumare le risorse di storage, di comunicazione e l’available di elaborazione. Tramite tecniche di filtraggio e algoritmi di coalescenza si cerca di riconoscere eventi utili da quelli inutili e di associare a un unico evento pi` u log che provengono da diverse applicazioni.(ad esempio riconoscere il reboot) 30 2.4 Performance monitoring I principali componenti di un sistema di monitoraggio Grid sono: • un Producer `e un processo che implementa almeno una API produttore per fornire eventi • un Consumer `e un qualsiasi processo che riceve eventi usando un implementazione di almeno una API consumatore • un Registry `e un servizio di ricerca che permette ai produttori di pubblicare i tipi di eventi che loro generano, e ai consumatori di trovare gli eventi di cui sono interessanti. Inoltre, un registry memorizza i dettagli richiesti per stabilire la comunicazione con le parti registrate. (indirizzi, protocolli supportati, requisiti di sicurezza). Anche per i sistemi senza la nozione di eventi, i registri possono essere utili per i produttori e i consumatori in modo da trovarsi l’un l’altro. Figura 2.1: Architettura di un sistema Grid Dopo aver scoperto l’un l’altro attraverso il registry, i produttori e i consumatori comunicano direttamente. Esistono tre tipi di interazioni tra produttori e consumatori: • Publish/subscribe: si riferisce all’interazione a 3 fasi che consiste di una sottoscrizione per un specifico evento, un flusso di eventi dal produttore 31 al consumatore e una terminazione della sottoscrizione. Sia la parte di iniziazione che terminazione della sottoscrizione possono essere iniziate da una delle due parti • Query/response `e un interazione una tantum iniziata dal consumatore e seguito dalla risposta di un singolo produttore che contiene uno o pi` u eventi • Notification: pu`a essere mandata una notifica da un produttore a un consumatore senza un ulteriore interazione Rispetto ai tre componenti principali possono essere definiti anche : • Republisher: `e un singolo componente che implementa sia il produttore che l’interfaccia di consumatore allo scopo di filtrare,aggregare,riassumere,diffondere e fare caching • Schema repository mantiene lo schema dell’evento che `e la collezione dei tipi di eventi definiti. Figura 2.2: consumer Un republisher implementa sia l’interfaccia di procuder che di 32 2.5 Tassonomia L’obiettivo della tassonomia `e quello di fornire un semplice mezzo per descrivere le caratteristiche di un sistema di monitoraggio rispetto : 1. ai rapporti con i componenti principali dell’architettura Grid 2. ai target principali delle entit`a monitorare 3. se un sistema pu`o o deve operare sul top di un altro sistema Figura 2.3: Esempio di tassonomia 2.6 Metriche da valutare In questo paragrafo vedremo alcune delle metriche rappresentative del monitoraggio. Le divideremo in due gruppi, le metriche relative all’IT performance management e quelle relative al monitoraggio ambientale. Nel primo gruppo rientrano: • CPU: e’ utile nel caso della CPU valutare i vari stati in cui la cpu pu`o essere(idle,nice,wait) o valutarne l’utilizzo da parte del sistema, da parte dell’utente. • Potenza: pu`o essere fondamentale capire, grazie alle misure sulla potenza consumata, come questa varia a seconda dell’utilizzo della CPU o del tipo di carico sulla macchina 33 • Load: definire il carico e il tipo di carico e valutarne l’effetto sul sistema • Memoria: valutare l’utilizzo della memoria, la memoria inutilizzata, capire come modellarla per ridurre al minimo l’accesso al disco fisico • Rete: tener traccia dei pacchetti inviarti e ricevuti per capire se ci sono problemi di comunicazione tra gli host • Velocit` a delle ventole : controllare quanti giri al secondo effettuano le ventole di raffreddamento dei rack `e importante per capire quando una di queste smette di funzionare Nel secondo invece : • Temperatura: in un ambiente come quello Grid, `e importante controllare le temperature all’interno dei rack, in modo da evitare danni all’hardware. • Temperatura dell’acqua in ingresso e in uscita : `e fondamentale sapere quale sia la temperatura dell’acqua utilizzata per raffreddare i rack e quale sia la sua temperatura all’uscita dai rack in modo tale da effettuare modifiche se necessarie e per controllare che il sistema funzioni nella maniera adeguata. 34 Capitolo 3 Virtualizzazione e piattaforma Cloud: installazione e configurazione In questo capitolo sono introdotti i concetti base della virtualizzazione. Essa `e la tecnologia alla base delle piattaforme per il Cloud, consentendo la condivisione di dispositivi server e di storage e aumentandone l’utilizzo. Le applicazioni possono facilmente migrare da un server fisico a un altro. Inoltre la virtualizzazione aiuta nella gestione elastica delle risorse, intesa come la capacit`a di rilasciare e riprendere le risorse nel modo pi` u veloce possibile. Viene poi illustrata Openstack, la piattaforma software utilizzata in questa tesi. Si introducono i componenti dell’architettura di Openstack e illustrata l’installazione su dei nodi del supercomputer S.Co.P.E. 3.1 Virtualizzazione Con il termine Virtualizzazione[15] si intende la creazione virtuale di una risorsa computazionale di norma fornita fisicamente, come una piattaforma hardware, un sistema operativo, un dispositivo di memorizzazione o una risorsa di rete. Il sistema operativo di un calcolatore fornisce una separazione tra le risorse fisiche disponibili e il loro utilizzo da parte dell’utente, attraverso la creazione di una vista logica dei componenti ad un maggiore livello 35 di astrazione. La virtualizzazione opera una funzione logicamente analoga, costruendo una molteplicit`a di prospettive logiche sulle risorse fisiche, ognuna delle quali pu`o essere utilizzata per interagire con un particolare utente a seconda delle necessit`a. Enunciato formalmente, la virtualizzazione costruisce un isomorfismo tra il sistema virtuale chiamato guest e il sistema reale denominato host. Nella prospettiva delle risorse, la virtualizzazione crea una pluralit`a di sottoinsiemi logici dal set completo di risorse fisiche disponibili (CPU, Memoria, I/O, rete). Se il sottoinsieme individua e si comporta come un reale calcolatore si parla di virtual machine. L’utente percepisce ed utilizza unicamente le astrazioni fornite dal layer di virtualizzazione, ignorando i dettagli delle risorse. 3.1.1 3.1.1 Virtualizzazione Hypervisor-based e virtualizzazione Non-Hypervisor-based Il componente software che consente l’interfacciamento della macchina virtuale con la piattaforma su cui esso risiede `e chiamato Virtual Machine Monitor o Hypervisor. Ne esistono due tipologie fondamentali: • Native: L’hypervisor `e in esecuzione direttamente sull’hardware, consentendone il controllo diretto per offrire le funzionalit`a di virtualizzazione. Individua pertanto un layer di separazione tra il sistema operativo e la piattaforma fisica. Un esempio significativo `e Hyper-V della Microsoft. L’hypervisor prevede che l’esecuzione dei diversi sistemi operativi nei rispettivi ambienti sia completamente isolata. Uno degli ambienti, o partizioni, deve contenere obbligatoriamente il sistema operativo host, nello specifico Windows Server 2008, il quale `e in grado di creare le partizioni figlie con i relativi sistemi operativi guest. Tali sistemi sono quindi direttamente in esecuzione sull’hypervisor. Un altro esempio `e costituito dal progetto open-source Xen, largamente utilizzato da diversi service provider in ambito Cloud come Amazon. • Hosted: L’hypervisor `e in esecuzione sul sistema operativo host, il quale risiede a sua volta sulla piattaforma fisica. Risulta particolarmente 36 efficace nelle situazioni in cui si desideri accesso immediato sia al sistema operativo host (solitamente individuato dal SO desktop dell’utente) che al guest. Prevede servizi di supporto per la virtualizzazione, ma si affida al sistema host per quanto concerne gestione della memoria, allocazione delle risorse, scheduling e driver dei dispositivi. Esempi conosciuti di hypervisor appartenenti a questa categoria sono VMware e VirtualBox. Figura 3.1: Tipologie di Hypervisor Esistono diverse tipologie di virtualizzazione hardware, non necessariamente basate su hypervisor. Le tecniche principali di virtualizzazione basate sull’hypervisor sono tre : • Full virtualization • Hardware assisted virtualization • Paravirtualization Mentre nel caso di tecniche non basate sull’hypervisor quella che va per la maggiore `e : • Operating system level virtualization 37 Nella Full Virtualization l’hypervisor virtualizza completamente l’hardware (memoria, CPU, rete ecc..) garantendo di conseguenza piena compatibilit`a con un qualsiasi sistema operativo che supporti l’infrastruttura fisica virtuale. I sistemi guest e host sono completamente isolati. Il primo esempio significativo di full virtualization `e rappresentato dal sistema operativo IBM CP-40 sviluppato nel 1967, in grado di eseguire istanze multiple di sistemi operativi client. I citati Hyper-V, VMware e VirtualBox garantiscono compatibilit`a con tale tipologia di virtualizzazione. L’ Hardware Assisted Virtualization, conosciuta anche con le espressioni hardware virtual machine (HVM) o native virtualization. Si tratta di un approccio full virtualization esteso, in cui il processore prevede il supporto architetturale per facilitare la costruzione dell’hypervisor e per inoltrare diverse chiamate del sistema operativo guest direttamente all’hardware fisico, aumentando le performance globali del sistema. Gli hypervisor Xen, VMware, VirtualBox e Hyper-V sono compatibili con tale tecnologia. Nella Paravirtualization invece l’hypervisor non simula l’hardware ma ne espone una interfaccia modificata funzionalmente simile a quella reale. L’interfaccia si concretizza in un insieme di API denominate Virtual Hardware API, le quali sono progettate nell’ottica di un uso specifico da parte di una macchina virtuale. L’assenza di emulazione hardware si traduce in maggiori performance, tuttavia i sistemi operativi guest necessitano di modifiche per garantire la compatibilit`a con l’interfaccia virtuale, individuando una minore flessibilit`a nella soluzione. L’hypervisor Xen `e compatibile con tale approccio. La soluzione dell’Operating system level virtualization prevede un sistema operativo host centrale condiviso, dotato di un kernel opportunamente modificato. I sistemi operativi guest, chiamati anche containers o virtual private servers (VPS), devono essere necessariamente dello stesso tipo dell’host. Le funzionalit`a sono quindi replicate senza la necessit`a di effettuare onerose chiamate di sistema tra i diversi layer. Esempi di sistemi operativi host compatibili con tale tipologia di virtualizzazione sono Linux (tramite il supporto a VServer o OpenVZ) e Solaris (Zones). 38 3.2 KVM Come hypervisor della nostra infrastruttura Cloud `e stato scelto KVM. KVM sta per Kernel-based Virtual Machine e, come dice il nome, `e composto da un modulo integrato nel kernel linux (dalla release 2.6.20) che permette di sfruttare le estensioni di virtualizzazione dei processori moderni. I motivi principali per cui la scelta `e ricaduta su KVM sono : • `e un progetto opensource che nasce dall’ambiente linux • `e facile da installare • `e molto veloce e facile da utilizzare Di per s`e KVM non effettua nessun tipo di emulazione, si limita ad attivare le estensioni della CPU e a mettere a disposizione dello userspace un dispositivo in grado di riservare le risorse hardware da mettere a disposizione dei sistemi virtuali. Un programma userspace (in particolare le libvirt o QMU) si occuper`a di richiedere al modulo di riservare questa o quella risorsa e di svolgere le operazioni necessarie per l’esecuzione della VM. Inoltre KVM si occupa di aggiungere una terza modalit`a all’esecuzione del kernel, la Guest Mode. Normalmente il kernel ha due modalit`a di esecuzione, la Kernel mode (o Ring0) in cui solo software fidato (quindi, di fatto, solo il kernel) pu`o essere eseguito con la massima priorit`a per operazioni privilegiate come l’accesso diretto all’hardware, e la User Mode, in cui vengono eseguite tutte le operazioni non privilegiate relative ai programmi userspace. L’introduzione di KVM ha introdotto la Guest Mode, una modalit`a particolare in cui il kernel del sistema host (che `e il sistema vero e proprio che ospita i sistemi guest, cio`e le virtual machine) permette ai kernel dei sistemi virtualizzati di eseguire operazioni privilegiate come l’accesso diretto all’hardware virtuale. Il punto di forza di KVM sta proprio in questa sua semplicit`a, il cuore del sistema di virtualizzazione (l’hypervisor come vedremo poco pi` u avanti) svolge poche fondamentali operazioni, mentre tutta la parte di emulazione dell’hardware viene demandata a componenti esterne e specializzate (come le libvirt o Qemu). La semplicit`a dell’hypervisor `e per`o legata anche al suo punto debole (se cos`ı si pu`o definire) di KVM: la dipendenza da hardware specializzato. 39 KVM riesce ad essere cos`ı semplice e rapido proprio grazie all’utilizzo delle estensioni speciali inserite nei processori x86 di ultima generazione: AMD-V per i processori AMD e VT-x per i processori Intel, senza le quali KVM non pu`o funzionare. L’architettura si presenta come nell’immagine 3.2. La parte dell’hypervisor (in arancione) `e divisa in due parti, la prima legata allo userspace, le libvirt e QEMU che si occupano di fornire la parte di emulazione dell’hardware (forniscono cio`e i virtual device che verranno visti dai sistemi guest), mentre la seconda risiede all’interno del kernel, il modulo di KVM, l’hypervisor appunto che permette la gestione dell’hardware di virtualizzazione (le famose estensioni VTX e AMD-V) e che espone un device file in /dev/kvm usato per associare i sistemi guest alle risorse assegnate. Figura 3.2: KVM 3.3 Openstack La scelta della piattaforma Cloud che avremmo dovuto usare per la virtualizzazione `e ricaduta su Openstack. Questo perch`e tra le piattaforme opensource, Openstack sembra essere quella pi` u affidabile e stabile. Difatti, il progetto Openstack ha numerosi partner industriali, come Rackspace e Citrix, che piuttosto che vendere il prodotto, commercializzano il servizio di supporto. Inoltre la piattaforma `e facilmente adattabile alle esigenze di chi la usa, l’ideale per il nostro progetto di Grid computing virtuale. Per i 40 nostri esperimenti abbiamo utilizzato la versione OpenStack Grizzly. Questa versione che si presenta pi` u stabile rispetto alla precedente. Ha 7 componenti (quella iniziale ne contava solamente 3) che vedremo a breve. 3.3.1 Architettura Concettuale L’idea alla base di Openstack `e quella di fornire un sistema operativo Cloud scalabile. Per ottenere ci`o ogni componente costituente `e stato progettato per cooperare con gli altri al fine di fornire una completa IaaS. L’integrazione `e facilitata dall’utilizzo di interfacce pubbliche di programmazione. Queste APIs(scritte in Python) permettono ad ogni servizio di poter usufruire del lavoro degli altri, permettendo ad un implementatore di passare da un servizio ad un altro senza problemi a patto di utilizzare le API ufficiali. Queste sono le stesse APIs che sono utilizzabili dagli utenti finali del Cloud. Figura 3.3: Architettura concettuale di Openstack L’immagine 3.3 `e una vista semplificata e stilizzata dell’architettura, nell’ipotesi che un implementatore stia allo stesso tempo tutti i servizi(`e anche la configurazione pi` u comune).Comunque, Openstack non impone un approccio tutto o niente. Molti implementatori possono installare solo i componenti di cui hanno bisogno. Per esempio, Swift `e un object store popolare per tanti provider di servizi Cloud, anche se essi usano un altra infrastruttura Cloud. 41 3.3.2 Architettura Logica L’architettura logica `e molto pi` u complicata dell’architettura concettuale mostrata prima. Come qualsiasi architettura orientata ai servizi, i diagrammi diventano velocemente disordinati nel tentativo di illustrare tutte le possibili combinazioni di comunicazioni tra i servizi. Il diagramma della figura 20 mostra l’ architettura pi` u comune utilizzata dagli implementatori di Openstack. Tuttavia, come gi`a detto prima,Openstack supporta una grande variet`a di tecnologie, e quindi questa non rappresenta l’unica architettura possibile. Figura 3.4: Architettura logica di Openstack L’immagine 3.4 `e simile all’architettura concettuale mostrata prima in questi punti: • Gli utenti finali interagiscono tra loro grazie ad un’ interfaccia web comune o direttamente utilizzando le API associate a un determinato servizio • L’autentificazione di tutti i servizi avviene tramite una sorgente comune(Keystone) • I servizi individuali interagiscono gli uni con gli altri attraverso le loro APIs 42 3.3.3 I componenti di Openstack In questo paragrafo e nei successivi descriveremo in dettaglio i componenti e i loro compiti. I componenti della versione Grizzly sono 7 (mentre erano 3 quelli della versione iniziale) • Dashboard (Horizon) • Compute (Nova) • Object Store(Swift) • Image Store (Glance) • Identity (Keystone) • Network (Quantum) • Block Storage (Cinder) Dashboard Horizon fornisce un interfaccia utente modulare per tutti i servizi di Openstack. Figura 3.5: Esempio di Dashboard L’interfaccia dispone di schermate per gli utenti allo scopo di : 43 • avere informazioni d’uso e quote disponibili per ogni progetto • lanciare istanze di macchine virtuali • avere un volume management per controllare la creazione,la cancellazione e la connettivit`a al block storage • creare immagini e snapshot di macchine virtuali per il backup e il boot di nuove istanze • fornire accesso e sicurezza nella gestione delle coppie di chiavi e dei gruppi di sicurezza(regole di firewall) Oltre ad un’interfaccia per gli utenti, ne fornisce una anche per gli operatori del Cloud. L’interfaccia degli operatori vede tutto il Cloud e aggiunge alcune schermate di configurazione come: • Flavors per definire cataloghi di servizio che offrono CPU, memoria e disco di memoria per il boot • una schermata di gestione dei progetti • Una schermata di gestione degli utenti • Informazioni di sistema per sapere quali servizi girano nel Cloud e le quote assegnate ai progetti Con questa GUI web, tutte le operazioni sono eseguibili semplicemente utilizzando il browser,senza dover necessariamente conoscere i comandi specifici per ogni servizio. Rispetto alle release precedenti Horizon aggiunge nuove caratteristiche: • Networking • Caricamento diretto delle immagini a Glance • Supporto per specifiche di flavor supplementari • Migrazione di istanze ad altri compute host • Miglioramenti sull’esperienza utente 44 Compute Nova `e il componente pi` u complicato di Openstack. .Un gran numero di processi cooperano per trasformare le richieste degli utenti finali in macchine virtuali in esecuzione. Tra le principali operazioni possibili grazie a Nova abbiamo : • inizializzare,riadattare,fermare e interrogare le macchine virtuali • assegnare e rimuove indirizzi IP pubblici • attaccare o staccare blocchi di memoria • attaccare,cancellare,modificare i gruppi di sicurezza,mostra le console delle istanze • fare snapshot delle istanze che stanno eseguendo Rispetto alle release precedenti c’`e stato il deprezzamento di nova-network e nova-volume e il disaccoppiamento di nova compute dal database. I processi che fanno parte di Nova in questa release sono: • nova-api `e una famiglia di demoni che accetta e risponde alle chiamate dell’end user,. Supporta Openstack Compute API, le API EC2 di Amazon e una API admin speciale. Esso `e anche iniziatore di molte attivit`a di orchestrazione(come ad esempio l’esecuzione di un istanza) • Il processo nova-compute `e prima di tutto un demone worker che crea e termina le istanze virtuali attraverso le APIs dell’hypervisor • Il processo nova-scheduler `e concettualmente il pi` u semplice pezzo di codice nel Nova di Openstack: prende una richiesta di istanziazione di una macchina virtuale dalla coda e determina dove deve essere eseguita (in particolare , quale compute host deve ospitarlo) in pratica `e il pi` u complicato • Un nuovo servizio chiamato nova-conductor `e stato aggiunto a questa release. Esso media l’accesso al database per gli altri demoni per fornire maggiore sicurezza 45 • La coda fornisce un hub centrale per lo scambio di messaggi tra demoni. Questo `e solitamente implementato con RabbitMQ, ma potrebbe andar bene qualsiasi coda di messaggi AMPQ • Il database SQL memorizza la maggior parte dei tempi di costruzione e i stati del run-time per un infrastruttura Cloud. Questo include i tipi di istanze che sono disponibili ,le istanze in uso, le reti disponibili e progetti. Teoricamente supporta ogni tipo di database SQL-Achemy ma i soli database correntemente ed enormemente usati sono sqlite3, MySQL e PostgreSQL • Nova fornisce anche i servizi di console che permettono agli utenti di accedere alle console delle loro macchine virtuali attraverso un proxy Nova interagisce con molti servizi Openstack: Keystone per l’autentificazione , Glance per le immagini e Horizon per l’interfaccia web. L’interazione con Glance `e quella principale. Le API possono caricare e interrogare Glance mentre nova-compute scaricher`a le immagini per usarle nelle istanze in lancio. Object Store L’Object Store permette di memorizzare o richiamare file (ma non di montare cartelle come fileserver). Diverse compagnie fornisco servizi commerciali di storage basati su Swift, ad esempio KT,Rackspace e Hewlett-Packard. Swift `e anche usato internamente a molte grandi compagnie per memorizzare i loro dati. A differenza dei normali file system, questo `e completamente distribuito,memorizza copie multiple di ogni oggetto per ottenere grande disponibilit`a e scalabilit`a. Swift fornisce le seguenti funzionalit`a utente: • memorizza e richiama oggetti(file) • setta e modifica metadati sugli oggetti(tag) • offre pagine web statiche e oggetti via HTTP L’architettura Swift `e distribuita per prevenire un singolo punto di fallimento e per scalare orizzontalmente. Esso include i seguenti componenti: 46 • Proxy server (swift-proxy-server) accetta le richieste che arrivano tramite le API di Openstack Object o tramite HTTP. Accetta file da caricare,modifiche ai metadata o creazione di contenitori. In pi` u fornisce la lista di file o di contenitori al web browser. Il proxy server potrebbe utilizzare una cache opzionale per migliorare le performance • Gli account server gestiscono account definiti con il servizio di object storage • I contenitori server gestiscono il mapping dei contenitori nel servizio di object storage • Object server gestiscono gli oggetti presenti sui nodi di storage Ci sono anche un numero di processi periodici che girano per eseguire task di pulizia sui dati immagazzinati. Il pi` u importante di questi `e la replicazione dei servizi che assicura consistenza e availability attraverso il cluster. Altri processi periodici includono auditors,updaters e reapers. L’autentificazione per il servizio di object storage `e gestito tramite un middleware configurabile WSGI. Image Store Openstack Image Store funge da catalogo e repository per le immagini di dischi virtuali. Ma non si limita a questo difatti: • Memorizza le immagini private e pubbliche che l’utente pu`o utilizzare per lanciare un istanza • Gli utenti possono interrogare il servizio per avere una lista delle immagini utilizzabili • Produce immagini da cui lanciare istanze • Possibilit`a di creare snapshot dalle istanze in esecuzione affinch´e siano memorizzate come macchine virtuali L’architettura di Glance `e sempre stata abbastanza stabile fin dalla release Cactus. I componenti principali sono 47 • glance-api accetta ed esegue le chiamate delle Image API per la ricerca,e la memorizzazione di immagini • glance-registry memorizza,processa e richiama i metadati di un immagine(tipo,dimensioni) • un database per memorizzare i metadati dell’immagine. • Una repository per le immagini attuali. Nel la figura 20 `e mostrato come repository di immagini Swift ma `e configurabile. Oltre a Swift, Glance supporta normali filesystem,RADOS block devicesm, Amazon S3 e HTTP. Per`o queste si usano solo in lettura. Ci sono molti processi periodici che girano su Glance per supportare il caching. Il pi` u importante di questi `e il servizio di replicazione che assicura consistenza e disponibilit`a attraverso il cluster. Identity l service Identity fornisce autentificazione e autorizzazione per tutti i servizi Openstack. I suoi compiti principali sono: • Autenticare gli utenti e rilasciare token per l’accesso ai servizi • Memorizzare utenti e progetti per un modello di accesso basato sui ruoli • Fornire un catalogo dei servizi • Creare policy tra utenti e servizi Dal punto di vista architetturale Keystone `e molto semplice: • keystone gestisce le richieste API oltre a fornire servizi d’identity token, cataloghi e policy configurabili • Ogni funzione di Keystone ha un backend pluggable che permette di utilizzare il servizio in modo personalizzato. La maggior parte degli standard di backend come LDAP o SQ, oltre a Key Value Store(KVS) 48 Network Quantum fornisce la connettivit`a di rete come un servizio tra le interfacce dei dispositivi gestiti dagli atri servizi di Openstack. Esso permette agli utenti di : • creare la propria rete e poi attaccargli le interfacce server • aggiungere estensioni che permettono servizi di rete addizionali come il load balancing Come molti servizi di Openstack, Quantum `e altamente configurabile grazie alla sua architettura plug-in. I componenti dell’architettura sono : • quantum-server che accetta le richiesta API e poi le gira all’appropriato plugin quantum per lavorare • i plugin e gli agenti di quantum eseguono il lavoro attuale come l’aggiunta e la rimozione di porti, la creazione di reti o sottoreti e l’indirizzamento IP. Questi plugin e agents differiscono a seconda del vendor e delle tecnologie usate nel Cloud • la maggior parte delle installazioni di Quantum fa uso di una coda di messaggi per trasportare le informazioni tra i server quantum e vari agents inoltre ha un database per memorizzare gli stati della rete per particolari plugin • Quantum interagisce con Nova, in quanto fornir`a reti e connettivit`a per le istanze. Block Storage Cinder estrapola la funzionalit`a del blocco di storage persistente che faceva prima parte di Openstack Compute in un servizio vero e proprio. Le API di Openstack Block Storage permettono la manipolazione di volumi, di tipi di volume e gli snapshot dei volumi: 49 • crea,modifica e cancella volumi • fa snapshot o backup dei volumi • fa query sullo stato dei volumi e sui metadati Questa architettura segue quella di quantum , in quanto `e anch’essa pluggabile. • cinder-api accetta le richieste e le gira a cinder-volume per eseguirle • cinder-volume agisce sulle richieste leggendo o scrivendo sul database Cinder per la gestione dello stato, interagendo con gli altri processi attraverso una coda di messaggi e direttamente sul blocco di memoria fornendo hardware o software. Esso pu`o interagire con una grande variet`a di fornitori di storage • cinder-backup `e un servizio che fa il back up dei dati da un volume(non uno snapshot) verso un servizio di backend. Per ora l’unico backend `e swift • cinder fa uso di code di messaggi per girare le informazioni tra i processi di cinder 3.4 Installazione e configurazione di Openstack In questo paragrafo mostreremo i vari passi che hanno portato alla creazione della nostra infrastruttura Cloud. L’installazione `e avvenuta su Ubuntu 12.04 in quanto in quel momento Ubuntu era il sistema operativo su cui Openstack girava meglio ed era maggiormente documentato. Il primi passo `e stato quello di provare a installare openstack tramite uno script automatico:Devstack. Questi `e appunto uno script per creare rapidamente un ambiente di sviluppo Openstack. Esso pu`o essere usato anche per mostrare come i servizi Openstack funzionano e fornisce esempi di utilizzo. Tutti i componenti di Openstack non vengono eseguiti come processi ma come screen. Dopo vari 50 tentativi si `e deciso di passare all’installazione componente per componente in quanto Devstack crea si un ambiente Openstack ma `e pi` u adatto per capirne il funzionamento e fare piccoli test in quanto l’ambiente risulta molto instabile. Ogni volta che la macchina fisica che ospita devstack, viene riavviato, tutti gli screen che rappresentano i componenti di Openstack devono essere rilanciati e le macchine virtuali cancellate. Per una infrastruttura pi` u robusta come detto prima si `e preferita l’installazione manuale. L’architettura che si `e scelto di installare `e simile a quella in figura. C’`e un nodo che fa da Controller e su cui sono installato la maggior parte dei servizi di Openstack e tutti gli altri nodi sono nodi Compute su cui verranno fatte girare le VM. La differenza con l’architettura costruita in questa tesi `e solo nel numero di nodi Compute che sono due. Figura 3.6: Architettura reale 51 I requisiti necessari a livello hardware sono mostrati in tabella Figura 3.7: Requisiti hardware per l’installazione Inoltre per permettere che tutti i servizi tra le diverse macchine fisiche fossero sincronizzati, `e stato necessario installare NTP (Network Time Protocol) 1 sudo apt - get install -y ntp Essendo un’architettura a pi` u nodi `e stato necessario configurare il Controller Node come server NTP modificando il file ntp.conf sed -i ’s / server ntp . ubuntu . com / server ntp . ubuntu . com \ nserver ,→ 127.127.1.0\ nfudge 127.127.1.0 stratum 10/ g ’ / etc / ntp . ,→ conf service ntp restart Mentre sui Compute Node `e stato installato NTP client e poi sincronizzati i Compute Node con Il Controller. Per fare ci`o il modo pi` u sem52 1 2 plice `e aggiungere un job cron giornaliero che sincronizza il clock dei compute con il controller. Per fare ci`o si `e aggiunto un file root eseguibile in /etc/cron.daily/ntpdate che contiene le seguenti righe di codice : 1 2 ntpdate < hostname or IP address of controller > hwclock -w Prima di iniziare l’installazione sono state fatte delle assunzioni per facilitare l’installazione in quanto esistono molte configurazioni diverse. Queste sono : • Scelto un nodo che fa da Cloud Controller su cui gireranno tutti i servizi(RabbitMQ.mysql,Identity,Image,nova-api ,nova-network,nova-scheduler,novavolume, nova-conductor) tranne che nova-compute e i servizi di rete • La partizione dei dischi sul controller deve essere gestita da Logical Volume Manager(LVM) Il controller ha un volume LVM chiamato cindervolume per fornire storage persistente alle guest VM. • KVM come hypervisor • Abilitare la repository Cloud Archive aggiungendo il file /etc/apt/source.list.d/grizzly.list col seguente contenuto 1 2 deb http :// ubuntu - Cloud . archive . canonical . com / ubuntu ,→ precise - updates / grizzly main e poi 1 2 sudo apt - get install ubuntu - Cloud - keyring • FlatDHCP con una singola interfaccia di rete Prima di spiegare i vari passi per l’installazione `e importante dare informazioni riguardo la configurazione di rete. Openstack per rispondere alle 53 esigenze dei diversi utenti `e dotato di un gruppo di ’manager di rete’. Un manager di rete definisce la topologia di rete per una determinata distribuzione Openstack. Con grizzly si possono scegliere tre differenti tipi di manager di rete: FlatManager, FlatDHCP, VlanManager. FlatManager e FlatDHCPManager hanno molto in comune. Entrambi si basano sul concetto di bridged networking, con un singolo dispositivo che fa da bridge. Se consideriamo una rete multi-host, per ogni nodo compute viene creato un singolo bridge virtuale che nel nostro caso si chiama br100. Per fare ci`o bisogna aggiungere nel file di configurazione di Nova l’opzione: 1 f l at _ n et w o rk _ b ri d g e = br100 Tutte le macchine virtuali generate da Openstack si attaccano a questo bridge dedicato. Figura 3.8: Esempio di bridge Questo approccio (singolo bridge per i nodi compute) soffre di una limitazione nota comune nel bridged networking: un bridge linux pu`o essere 54 attaccato solo a una singola interfaccia fisica su una macchina host. Per questo non c’`e un isolamento di Livello 2 tra gli host. Tutti condividono lo stesso dominio broadcast ARP. L’idea alla base di FlatManager e FlatDHCPManager `e di avere un pool di indirizzi definiti attraverso il cluster. Questo spazio di indirizzi `e condiviso tra tutte le istanze dell’utente, indipendentemente a quale progetto appartengono. Ogni progetto `e libero di prendere qualsiasi indirizzo disponibile nel pool. 3.4.1 FlatManager FlatManager fornisce il principale set di operazioni primitive. Il suo ruolo si riduce al collegare l’istanza al bridge sul nodo compute. Di default, non configura l’indirizzo IP delle istanze. Questo compito `e lasciato all’amministratore dei sistemi e pu`o essere fatto da un server DHCP esterno. Figura 3.9: FlatManager 55 3.4.2 FlatDHCPManager FlatDHCPManager inserisce una determinata istanza nel bridge, e fornisce anche servizi da server DHCP. Su ogni nodo compute: • il bridge di rete viene dato un indirizzo dal pool degli IP • un processo server DHCP( dnsmasq ) viene generato e si mette in ascolto sull’interfaccia IP del bridge • il bridge agisce come un gateway predefinito per tutte le istanze che girano sul compute node Figura 3.10: FlatDHCPManager Per quanto riguarda dnsmascq, FlatDHCPManager crea un file statico per ogni nodo di calcolo per garantire lo stesso indirizzo IP per un istanza nel corso del tempo. Il file di locazione `e costruito in base ai dati sull’istanza (MAC,IP,nome host ) forniti dal database Nova. Il server dnsmasq dovrebbe distribuire gli indirizzi solo per le istanze che sono in esecuzione localmente sul nodo di calcolo. Per ottenere ci`o, i dati dell’istanza da mettere nel file di locazione DHCP sono filtrati per campo host. Nella figura 3.10 si pu`o notare come viene dato un differente gateway di default a seconda del nodo compute su cui risiedono le istanze. 56 Figura 3.11: Doppio gateway Una volta effettuata l’installazione come in Appendice A non ci rimane che visitare l’indirizzo 143.225.20.189. Qui ci sar`a la pagina di login alla Dashboard. 57 Figura 3.12: Pagina di login Una volta effettuato il login ci troveremmo di fronte una pagina come quella in 3.13 Figura 3.13: Pagina dell’amministratore nella quale vengono mostrati i progetti creati e le risorse associate 58 Capitolo 4 Implementazione di un sistema di monitoraggio basato su Ganglia Per monitorare il nostro sistema Grid virtuale, `e stato preso in considerazione il sistema di monitoraggio Ganglia, perch`e oltre alle qualit`a che citeremo a breve, era gi`a utilizzato nell’ambito SCOPE. Ganglia `e un progetto open source, originalmente progettato dall’universit`a della California. Esso agisce come un sistema di monitoraggio distribuito per sistemi ad alte performance come cluster e (appunto) Grid. Per una definizione pi` u formale si pu`o definire Ganglia come[16]: Un sistema di monitoraggio scalabile distribuito per sistemi di computer ad alte performance come cluster e Grid. Esso `e basato su un progetto gerarchico mirato a federazioni di cluster. Si affida enormemente alle tecnologie usate come XML per la rappresentazione dati, XDR per il trasporto dei data, e RRDtool per lo storage dei dati e la visualizzazione I termini maggiormente usati in Ganglia sono: • Host/nodo :tipicamente `e una macchina 59 • Cluster: un gruppo di nodi • Grid : un gruppo di cluster • Metriche : i grafici che sono mostrati • RRDs o RoundRobinDatabases : in accordo al suo sito web, RRDtool `e un sistema per memorizzare e mostrare i dati in serie di tempo(cio`e banda di rete, temperatura della stanza delle macchine, carico medio del server). Esso memorizza i Dati in modo compatto per mantenere la grandezza degli archivi gestibile. RRDtool presenta grafici utili elaborando i dati per eseguire una certa densit`a di dati. 4.1 Architettura di Ganglia In questo paragrafo illustriamo l’architettura e i suoi componenti e i loro ruoli. I componenti principali sono : • Ganglia monitoring daemon (gmond) • Ganglia meta daemon (gmetad) • RRD • Ganglia fronted 60 Figura 4.1: Architettura di Ganglia 4.1.1 Ganglia Monitoring Daemon Gmond `e un demone multi-thread che gira su ogni node del cluster che vogliamo monitorare. Gmond ha quattro responsabilit`a principali: • monitorare i cambiamenti nello stato dell’host • diffusione dei cambiamenti rilevanti • ascoltare lo stato di tutti gli altri nodi ganglia attraverso un canale multicast • rispondere alle richieste per una descrizione XML dello stato del cluster Gmond ha vari thread che ascoltano il canale multicast e scrivono i dati collezionati in una tabella hash in memoria veloce. Tutte le metriche per ogni nodo del cluster sono processate e salvate. Si potrebbe pensare che questo richieda una grande quantit`a di memoria ma gmond pu`o mantenere dati in memoria per una quantit`a pari a 16+136*n nodes+364*n metrics bytes. Per esempio se avessimo un cluster di 1024 nodi e monitoriamo 25 metriche su 61 ogni macchina, allora gmond utilizzer`a solo 16 +136*1024 +364*25 = 148380 bytes o appena 144 kilobytes di memoria. La tabella hash `e completamente multithread con i lock read/write implementati da thread mutexes POSIX e variabili di condizione per ogni host individuale nel cluster. Questo significa che i thread multipli possono simultaneamente leggere e scrivere nell’hash senza interferire l’un l’altro. Molto scalabile. Ganglia `e utilizzato per cluster con pi` u di 500 nodi. Ogni gmond trasmette in due modi differenti lo stato dell’host • in multicasting in un rappresentazione esterna dei dati (XDR) • inviando XML su una connessione TCP. Gmond diffonde a tutti una metrica che sta monitorando solo per due ragioni: un cambiamento nel valore della metrica che eccede il valore di soglia o quando gmond non invia le informazioni riguardanti la metrica per un tempo superiore al tempo di soglia. Il valore di soglia assicura che gmond diffonda solo quando `e necessario. Naturalmente i valori cambiano in continuazione e la soglia assicura che piccoli cambiamenti non crescano fino a diventare grandi perch`e la notifica `e troppo lenta. Queste soglie riducono drasticamente il traffico sul canale multicast. Per esempio, il numero di CPU su un host `e inviato solo una volta all’ora finch`e `e costante mentre 1 minuto di carico pu`o essere inviato ogni 15 secondi a seconda del cambiamento del valore. Poich`e tutti i gmond nel cluster memorizzano lo stato del cluster, `e importante che tutti i nodi abbiano la stessa immagine del cluster. Gmond si auto-organizza e conosce come fare in modo che tutti i gmond siano sulla stessa pagina. Ogni volta che gmond riceve un pacchetto multicast da un nuovo host, esso fa scadere la soglia del tempo per tutte le sue metriche. Questo significa che tutti i dati delle metriche verranno mandati al nuovo gmond anche se esso non `e stato precedentemente schedulato per essere inviato. Per esempio , il numero di CPU `e diffuso solo una volta all’ora. Se il gmond local non fa scadere il suo tempo di soglia allora il nuovo gmond non pu`o conoscere il numero di CPU su quella macchina in un ora. Gmond `e anche ottimo per gestire i fallimenti. E’ inevitabile che i nodi nel cluster si guastino occasionalmente e che gmond fallisca. Recuperare da questi fallimenti temporanei `e importante. Il payload di un messaggio di 62 battito cardiaco `e il timestamp di quando gmond `e stato startato sul nodo . Se anche quel timestamp cambia allora gmond si rende conto del restart di un gmond su un altro nodo. Questo allarme porter`a il gmond a far scadere la sua soglia di tempo su tutte le metriche allo scopo di aggiornare, il pi` u velocemente possibile, il nuovo gmond del suo stato. Ogni gmond processa i propri dati multicast localmente attraverso loopback. Ci`o significa che esso salva in memoria i dati che sta inviando ai gmond remoti. Quando `e chiesto, gmond scriver`a lo stato completo del cluster in XML includendo i suoi DTS. Comunque gmond condivider`a quei dati solo con gli host che sono nella tabella hash in memoria o con un host specifico con la lista dei trusted hosts nel suo file di configurazione. E’ possibile inviare anche le metriche personalizzate sul canale multicast di Ganglia. Gmond monitora dozzine di metriche di default ma ci`o non significa che siano le sole metriche che si possono monitorare. Figura 4.2: Architettura di Gmond La scatola grigia rappresenta Ganglia Monitoring Daemon (gmond) con tutti i suoi componenti: • il thread schedulatore di metriche • i thread che ascoltano sul canale multicast 63 • la tabella hash • i thread di output XML Il metric scheduler thread controlla lo stato dell’host su cui gmond sta girando e diffonde ogni cambiamento rilevante. Gmond decide che cosa sia rilevante usando le soglie di valore e di tempo. Il metric scheduler ricorda che valore ha diffuso per ultimo e quando lo ha inviato. Se la differenza tra l’ultimo valore diffuso e il nuovo valore `e maggiore della soglia di valore, allora il metric scheduler diffonder`a il valore. Anche se il tempo trascorso da quando il valore della metrica `e stato diffuso `e maggiore della soglia del tempo esso verr`a inviato incurante del suo valore. Le due soglie sono specifiche per ogni metrica e sono basate su caratteristiche della metrica. I multicast listening threads ascoltano sul canale multicast di ganglia i messaggi che arrivano inclusi quelli che arrivano da se stesso(tramite loopback). Tutti i dati sono immagazzinati nella tabella hash in memoria. Questa tabella mantiene i dati per tutti gli host inviando dati sul canale multicast del cluster attraverso gmond o gmetric. I XML output thread sono responsabili per l’elaborazione delle richieste di connessioni in entrata. Quando la richiesta in XML `e fatta i thread di output controllano se il client `e 127.0.0.1, cercano l’hash degli host conosciuti sul canale multicast di ganglia e poi la lista di trusted host. Se l’host non `e trovato, questi chiude la connessione, altrimenti una descrizione completa XML dello stato di tutti gli host `e diffusa sul canale multicast locale. Per vedere questa descrizione basta usare telnet: telnet localhost 8649 4.1.2 Ganglia Meta Daemon(gmetad) L’immagine 4.3 mostra come Ganglia Meta Daemon (gmetad) lavora con Ganglia Monitoring Daemons (gmond) per permettere facilmente il monitoraggio del cluster attraverso rotte unicast. Mentre gmond usa canali multica64 st in modalit`a peer-to-peer, gmetad prende la descrizione XML dalle sorgenti ganglia (sia gmond che un altro gmetad) attraverso XML su un rotta unicast. Figura 4.3: Architettura di Gmetad Gmetad `e il backend per ganglia web fronted. Gmetad memorizza le informazioni storiche in database Round-Robin ed esporta riassunti in XML che il fronted web utilizza per presentare snapshots e utili trend per tutti gli host monitorati da ganglia. 4.1.3 Ganglia Web Fronted Ganglia web Fronted fornisce una vista delle informazione raccolte attraverso pagine web dinamiche real-time. Questo mostra i dati di Ganglia in modo significativo per gli amministratori e gli utenti dei computer. Sebbene il web front end sia nato come una semplice vista HTML di un albero XML, esso si `e evoluto in un sistema che mantiene una storia colorata dei dati collezionati Il web fronted di ganglia si rivolge agli amministratori di sistemi e agli utenti. Per esempio si pu`o vedere l’utilizzo di CPU nell’ultima ora,giorno,settimana, mese o anno. Il web fronted mostra grafici simili per l’uso di Memoria, l’uso di disco, statistiche di rete, il numero di processi in esecuzione e tutte le altre metriche Ganglia. Il web fronted lega la sua esistenza a Gmetad che gli fornisce i dati dalle diverse sorgenti Ganglia. In particolare il web fronted aprir`a la porta locale al porto 8651(di default) e aspetta di ricevere gli alberi 65 XML di Ganglia. Le pagine web sono loro stesse molto dinamiche; qualsiasi cambiamento ai dati ganglia appare immediatamente sul sito. Questo comportamento porta a un sito molto reattivo, ma richiede che sia fatto il parsing dell’intero albero XML ad ogni accesso di pagina. Pertanto, il web fronted ganglia potrebbe girare su una macchina dedicata abbastanza potente se esso presentasse una grande quantit`a di dati. Il web fronted Ganglia `e scritto in PHP, e i grafici degli utenti sono generati da Gmetad per mostrare le informazioni storiche. 4.1.4 RRDtool Abbiamo parlato del ruolo di gmetad ma non `e stato specificato come gestisce i dati che vengono raccolti dalle diverse sorgenti ganglia. I dati raccolti vengono memorizzati grazie a RRDtool. L’acronimo sta per round-robin database tool. Questo tool memorizza i dati in un database round robin(buffer circolare), cosi che la memoria occupata rimane costante nel tempo. Esso include tool per estrarre dati RRD in un formato grafico, per i quali `e stato originalmente creato. RRDtool assume dati variabili nel tempo in intervalli di una certa lunghezza. Questo intervallo, `e solitamente chiamato step, `e specificato al momento della creazione del file RRD e non pu`o essere cambiato in corso. Poich`e i dati potrebbero non essere sempre disponibili proprio al momento giusto, RRDtool automaticamente interpoler`a qualsiasi dato sottomesso per soddisfare il suo time-steps interno. Il valore per lo specifico step, che `e stato interpolato `e chiamato primary data point (PDP). PDP multipli potrebbero essere consolidati in accordo a una funzione di consolidamento (CF) per formare un consolidated data point (CDP). Tipicamente le funzioni di consolidamento sono 4 : 66 CF Significato AVERAGE Media LAST MIN MAX Descrizione Prende la media aritmetica dei valori collezionati Ultimo valore letto Prende l’ultimo valore collezionato Valore minimo letto Prende il valore pi` u piccolo tra quelli collezionati Valore massimo letto Prende il valore pi` u alto collezionato Tabella 4.1: Funzioni di consolidamento Dopo che i dati sono stati consolidati, il CDP risultante `e memorizzato in un archivio round-robin(RRA). Un archivio round-robin memorizza un numero fissato di CDP e specifica quanti PDP dovrebbero essere consolidati in un CDP e che CF usare. Il tempo totale coperto da un RRA pu`o essere calcolato come: time covered = (CDP memorizzate) * ( PDP per CDP) * steps Dopo questo tempo l’archivio si riavvolge: il prossimo inserimento sovrascriver`a il valore pi` u vecchio. Questo comportamento `e detto appunto roundrobin. Per coprire diversi intervalli di tempo e/o diverse funzioni di consolidamento, un RRD file pu`o contenere RRA multipli. La funzione di recupero dati di un RRDtool automaticamente seleziona l’archivio con la pi` u alta risoluzione che ancora copre l’intervallo di tempo richiesto. Questo meccanismo `e anche usato per modellare i grafici di sottosistemi con RRDtool. Nell’immagine 4.4 abbiamo visto come funzionano gli archivi RRA, vediamo ora il formato generale utilizzato per gli RRA: RRA:CF:xfl:steps:rows 67 Figura 4.4: Funzionamento di RRA Il campo CF rappresenta la funzione di consolidamento che pu`o essere una delle 4 che abbiamo accennato poco pi` u su. Il fattore xfl rappresenta la parte dell’intervallo di consolidamento potrebbe essere costituito da dati sconosciuti mentre il valore di consolidamento `e ancora considerato come noto. Esso `e dato come una media tra i PDP sconosciuti ammessi e il numero di PDP nell’intervallo. Cosi il suo range va da 0 a 1 (escluso) Step definisce quanti di questi primary data points sono usati per costruire un consolidated data point che andr`a nell’archivio. Il campo rows definisce quante generazioni di valori di dati sono mantenuti in un RRA. Ovviamente, questo deve essere maggiore di zero.. RRA:AVERAGE:0.5:40:52704 Questo RRA `e quello utilizzato nei nostri esperimenti. Gmetad raccoglie dati ogni 15 secondi e ogni 40 di questi valori ne fa la media (CF average) e lo memorizza per un anno. In pratica avremmo i dati di un anno mediati ogni 10 minuti. Difatti basta fare 40*15 =600 che sono 10 minuti cio`e la distanza tra ogni step di RRA che moltiplicata per le rows otteniamo 600*52704= 31662400 secondi che sono un anno. 4.1.5 Estendere Ganglia In Ganglia le metriche predefinite che vengono raccolte sono quelle riportate nella tabella sottostante: 68 Tabella 4.2: Metriche di default di gmond Nome della metrica load one Unit`a riportata Media nel periodo cpu intr Percentuale load five Media nel periodo cpu sintr Percentuale load fifteen Media nel periodo cpu idle Percentuale cpu aidle Percentuale Descrizione Media del carico in un minuto Percentuale del tempo della CPU in cui partecipa alle interruzioni I/O Media del carico in cinque minuti Percentuale del tempo della CPU in cui partecipa alle interruzioni-soft I/O Media del carico nei quindici minuti Percentuale di tempo in cui la CPU o le CPU sono idle e il sistema non ha richieste di I/O in sospeso Percentuale del tempo di idle della CPU fin dal boot (non disponibile su tutti i sistemi operativi) Tipo CPU CPU CPU CPU CPU CPU CPU 69 cpu nice Percentuale cpu user Percentuale cpu system Percentuale cpu wio Percentuale cpu num Conteggio cpu speed Mhz part max used Percentuale Percentuale di utilizzo della CPU che si ha quando sta eseguendo a livello utente con priorit`a nice Percentuale di utilizzo della CPU che si ha quando sta eseguendo a livello utente Percentuale di utilizzo della CPU che si ha quando sta eseguendo a livello sistema Pecentuale del tempo della CPU o delle CPU in cui sono idle e durante il quale il sistema non ha avuto interruzioni I/O in sospeso(non disponibile su tutti i sistemi operativi) Numero totale di CPU Velocit`a della CPU in termini di MHz Massima percentuale usata per tutte le partizioni CPU CPU CPU CPU CPU CPU Disco 70 disk total disk free mem total proc run mem cached swap total mem free mem buffers mem shared proc total swap free pkts out pkts in Gb Spazio totale sul disco disponibile, aggregato tra tutte le partizioni Gb Spazio totale libero nel disco aggregato tra tutte le partizioni kb Quantit`a totale di memoria mostrata in KBs Conteggio Numero totale di processi in esecuzione kb Quantit`a di memoria cache kb Quantit`a totale dello spazio swap in KBs kb Quantit`a di memoria disponibile kb Quantit`a della memoria bufferizzata kb Quantit`a della memoria condivisa Conteggio Numero totale dei processi kb Quantit`a di memoria swap disponibile Pacchetti/secondo Pacchetti out per secondo Pacchetti/secondo Pacchetti in per secondo Disco Disco Memoria Memoria Memoria Memoria Memoria Memoria Memoria Memoria Memoria Rete Rete 71 bytes in Bytes/secondo bytes out Bytes/secondo os release Stringa gexec mtu Booleano Intero location Stringa os name Stringa boottime Tempo sys clock Tempo heartbeat machine type Intero Stringa Numero di bytes in per secondo Numero di bytes out per secondo Data di rilascio del sistema operativo gexec disponibile Unit`a di trasmissione di rete massima Locazione delle macchine Nome del sistema operativo L’ultimo volta che il sistema `e stato startato Tempo riportato dal clock di sistema Last heartbeat Architettura del sistema Rete Rete Sistema Sistema Sistema Sistema Sistema Sistema Sistema Sistema Sistema Esistono per`o 2 modi principali per poter aumentare il numero di metriche che Ganglia pu`o monitorare. Questi sono : • gmetric • moduli C/C++ e/o moduli Python Gmetric Gmetric permette di sottomettere valori senza dover contare sullo scheduler presente in gmond. In pratica ha l’abilit`a di impersonificare le metriche per un host che, per qualche ragione, non ha gmond in esecuzione. Questo `e particolarmente utile per i device che richiedono solo una o due metriche, o 72 per quando far eseguire gmond sull’host non `e praticabile. Fare lo spoofing di un valore gmetric comporta la sottomissione di un hostname spoofed e di un indirizzo IP. Moduli Nelle prime versioni di ganglia l’unico modo per iniettare nuove metriche in Ganglia era gmetric. Gmetric `e ottimo per un aggiunta veloce di semplici metriche ma per ogni metrica che si vuole raccogliere, bisogna creare un’istanza separata di gmetric con la propria configurazione. L’idea dietro l’introduzione delle interfacce modulari in gmond era di permettere la raccolta di metriche sfruttando qualcosa che gmond stava gi`a mettendo in pratica. E’ un modo per configurare e raccogliere una serie di metriche esattamente allo stesso modo delle metriche principali che sono state gi`a raccolte. Caricando un modulo di raccolta metriche in gmond, non c’`e bisogno di configurare lo scheduler per ogni metrica aggiuntiva. Gmond gestisce tutto tramite lo stesso file di configurazione e raccoglie le nuove metriche nello stesso modo con cui si comporta con quelle predefinite. Ovviamente come in tutte le cose c’`e un trade-off. Se nelle vecchie versioni gmond poteva essere considerato come un unico file eseguibile da poter copiare su qualsiasi host per poi essere eseguito, il nuovo gmond modulare richiede moduli che sono separati dinamicamente dai moduli caricabili. Nella nuova versione di gmond, esistono due tipi di moduli aggiuntivi C/C++ e Python. Ovviamente la differenza tra i due tipi di moduli dipende dai linguaggi. Il C fornisce allo sviluppatore una visuale del sistema a livello pi` u basso e un guadagno in termini di prestazione che derivano da un linguaggio precompilato. Tuttavia il C non `e conveniente quanto il linguaggio di scripting Python. Il Python offre molti aspetti convenienti che rendono pi` u semplice rispetto al C, la stesura di un modulo gmond. Il Python nasconde la complessit`a dei linguaggi compilati come il C a costo di un maggior utilizzo di memoria e di processazione. Per queste ragioni il Python `e stato scelto come linguaggio per la creazione dei moduli gmond aggiuntivi sviluppati in questa tesi che avrebbero monitorato la potenza, e altri fattori. 73 4.1.6 Moduli C/C++ La creazione di un modulo C/C++ comporta per lo pi` u la creazione di una struttura di tipo mmodule. Questa struttura `e composta da tre puntatori a funzione e un altra struct contenente informazioni sulla metrica. Poich`e Ganglia si basa sull’ Apache Portable Runtime Library molte delle strutture dati coinvolte sono di tipo APR. Per far in modo di rendere pi` u facile la scrittura di moduli in C sono state fornite delle funzioni che nascondono le strutture APR sottostanti. Il problema nell’uso di queste funzioni, `e che `e necessario definire in anticipo e in modo statico i metadati delle metriche in una struttura ’metric info’. Se questa struttura viene dichiarata all’interno del mmodule, GMOND far`a l’interazione APR per noi. Se non `e dichiarata in anticipo si dovranno gestire i lavori APR da soli. La differenza principale tra la scrittura di un modulo Dinamico e quello Statico `e che quello dinamico avr`a bisogno di interagire con APR. La maggior parte dei moduli utilizzati per la raccolta dei dati si adatta bene alla categoria statica. Ma vediamo meglio la struttura mmodule. Prendiamo ad esempio un modulo gmond che `e usato per collezionare metriche relative alla memoria: 1 2 3 4 5 6 7 8 9 10 mmodule mem_module = { STD_MMODULE_STUFF , mem_metric_init , mem_metric_cleanup , mem_metric_info , mem_metric_handler , } • STD MMODULE STUFF : `e lo stesso per ogni modulo • metric init: Una funzione che `e necessario definire ( static int metric init ( apr pool t* )) . La funzione di init `e la prima funzione chiamata da GMOND una volta che ha letto nella definizione del nostro mmodule 74 • metric cleanup: Una funzione che dobbiamo definire (static void metric cleanup ( void )) . Questa funzione `e chiamata prima che il nostro modulo sia scaricato da GMOND. Solitamente `e definita ma non usata. • metric info Una struttura che si deve definire. La struttura metric info contiene i metadati di ogni metrica che si vuole misurare. La funzione init chiama la funzione handler una volta per ogni elemento in questa struttura. Questa verr`a descritta in dettaglio nel paragrafo successivo • metric handler : Una funzione che bisogna definire (static g val t metric handler ( int )). Questa funzione `e chiamata da metric init una volta per ogni elemento nella struttura metric info Rifacendoci all’esempio sulla memoria, una struttura metric info conterr`a queste poche linee static Ganglia_25metric mem_metric_info [] = { \{0 ," mem_total " ,1200 , GANGLIA_VALUE_FLOAT ," KB " ," zero ,→ " ,"%.0 f " , UDP_HEADER_SIZE +8 , " Total amount of memory ,→ displayed in Kbs "} , \{0 , " mem_free " , 180 , GANGLIA_VALUE_FLOAT , " KB " , " ,→ both " , "%.0 f " , UDP_HEADER_SIZE +8 , " Amount of ,→ available memory "} , \{0 , " mem_shared " , 180 , GANGLIA_VALUE_FLOAT , " KB " , " ,→ both " , "%.0 f " , UDP_HEADER_SIZE +8 , " Amount of shared ,→ memory "} , < snip > } Questo esempio da un idea di che tipo di metadati `e tenuta traccia per ogni metrica. I campi da sinistra verso destra sono: • int key: chiave • char* name: nome della metrica, per RRD • int tmax, il tempo massimo in secondi tra le chiamate di collezione metriche 75 1 2 3 4 5 6 7 8 • Ganglia value types type : usato da APR per creare storage dinamico per la metrica, questo pu`o essere: string,uint,float,double oppure un ganglia Global • char*units: unit`a della metrica per RRD • char*slope, uno tra zero,positive,negative o both (utili per la rappresentazione grafica) • char*fmt stringa di formato printf per la metrica che deve corrispondere al type field • int msg size, UDP HEADER SIZE+8 • char*desc una descrizione testuale della metrica Osserviamo la funzione init riguardante il nostro esempio static int mem_metric_init ( apr_pool_t * p ) \{ int i ; libmetrics_init () ; for ( i = 0; mem_module . metrics_info [ i ]. name != NULL ; i ++) ,→ { M M E T R I C _ I N I T _ M E T A D A T A (&( mem_module . metrics_info [ i ]) , ,→ p ) ; M M E T R I C _ A D D _ M E T A D A T A (&( mem_module . metrics_info [ i ]) , ,→ MGROUP ," memory ") ; \} return 0; \} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ` abbastanza semplice, un for itera ogni elemento della struttura meE trics info, e chiama MMETRIC INIT METADATA e MMETRIC ADD METADATA su ogni elemento nella struttura. Queste sono funzioni APR. 76 • MMETRIC INIT METADATA crea storage APR per la struttura metric info • MMETRIC ADD METADATA chiama la funzione handler e accoppia i risultati con i metadati forniti in metric info. Spesso non si pu`o predire come sar`a la struttura metric info. Ad esempio, se si considera un modulo contatore di processi che prende un elenco separato da spazi di nomi di processi (come bash httpd gmond) e poi per ogni nome di processo, conta il numero di istanze attive di quel processo. Allo scopo di ottenere ci`o, si ha la necessit`a di prendere l’input dall’utente (attraverso la configurazione nel file gmond.conf) e dinamicamente crea la struttura metric info a tempo di esecuzione basato sull’input dell’utente. La differenza sostanziale con i moduli statici sta nella definizione del mmodule e della funzione metric init. 1 2 3 4 5 6 7 8 9 mmodule mem_module = \{ STD_MMODULE_STUFF , mem_metric_init , mem_metric_cleanup , NULL ,7* Dinamicamente definito in cp_metric_init () */ mem_metric_handler , } Difatti il metric info `e nullo perch`e questo verr`a definito a tempo di esecuzione. Quando viene dichiarato il nome della metric info nella struttura mmodule, gmond crea un array APR dinamico . Altri cambiamenti importanti devono essere fatti alla funzione metric init che acquisisce molta importanza. Di base la funzione deve leggere l’input dell’utente, creare dinamicamente l’array e poi iterarlo con METRIC INFO e METRIC ADD tutte all’interno di init. Per iniziare necessita di alcune variabili: Ganglia 25metric *gmi; metric info = apr array make(p, 1, sizeof(Ganglia 25metric)); 77 Abbiamo bisogno di un puntatore Ganglia 25metric all’interno del campo della funzione init, cos`ı noi possiamo modificare il contenuto degli elementi individuali dell’array all’interno di metric info, e lo stesso metric info necessit`a di essere inizializzato come un array APR. Ora c’`e il bisogno di leggere l’input da utente da gmond.conf. 1 2 3 4 5 6 7 8 9 if ( list_params ) { params = ( mmparam *) list_params - > elts ; for ( i =0; i < list_params \ - > nelts ; i ++) \{ if (! strcasecmp ( params [ i ]. name , " ProcessNames ") ) { processNames = params [ i ]. value ; } } } La configurazione in gmond.conf dovr`a essere del tipo: { int i ; libmetrics_init () ; for ( i = 0; mem_module . metrics_info [ i ]. name != NULL ; i ++) ,→ { M M E T R I C _ I N I T _ M E T A D A T A (&( mem_module . metrics_info [ i ]) , ,→ p ) ; M M E T R I C _ A D D _ M E T A D A T A (&( mem_module . metrics_info [ i ]) , ,→ MGROUP ," memory ") ; 1 2 3 4 5 6 7 8 9 10 11 12 13 } return 0; } 78 Quindi si passa una lista separata da spaziin gmond.conf e poi `e iterata tramite la list params nel nostro modulo. Una volta avuta la lista si pu`o popolare gmi con le informazioni. Quando vogliamo aggiungere una riga alla metric info, dobbiamo settare gmi al prossimo slot disponibile nell’array metric info chiamando apr array push in questo modo : gmi = apr array push(metric info); e poi possiamo lavorare direttamente su gmi in questo modo : 1 2 3 4 5 6 7 8 9 10 11 12 for ( i =0; processName != NULL ; i ++) \{ gmi = apr_array_push ( metric_info ) ; gmi - > name = apr_pstrdup (p , processName ) ; gmi - > tmax = 512; gmi - > type = G A N G L I A _ V A L U E _ U N S I G N E D _ I N T ; gmi - > units = apr_pstrdup (p , " count ") ; gmi - > slope = apr_pstrdup (p , " both ") ; gmi - > fmt = apr_pstrdup (p , "\% u ") ; gmi - > msg_size = UDP_HEADER_SIZE +8; gmi - > desc = apr_pstrdup (p , " process count ") ; } Ora gli elementi sono stati creati dinamicamente, e possono chiamare INIT METADATA, e ADD METADATA proprio come succedeva nel caso statico. La funzione handler invece `e uguale in entrambi i casi. 4.1.7 Moduli Python In questo paragrafo ci interesseremo solamente all’estensione di ganglia tramite moduli python, in quanto le metriche sulla potenza e sui dati di chassis e rack `e stata prelevata grazie a questi. Mod Python `e un modulo gmond che per`o attualmente non raccoglie metriche per se. Invece `e un modulo che `e stato completamente progettato per agire da proxy per gli altri moduli di raccolta metriche. Mod python `e stato scritto nel linguaggio di programmazione 79 C, e il suo scopo primario `e fornire un ambiente integrato Python nel quale gli altri moduli gmond eseguiranno. Con l’introduzione di questo molta della complessit`a dell’implementazione di un modulo gmond in C `e stata rimossa. Lo sviluppatore di moduli gmond non deve pi` u preoccuparsi della struttura degli mmodule, delle macro MMETRIC INIT METADATA, o della gestione delle APR. Tutti questi elementi di un modulo gmond sono nascosti sotto Python. Difatti uno degli aspetti pi` u convenienti di un modulo scritto in Python `e che non necessita anche di gmond. Un modulo Python pu`o attualmente essere completamente progettato, implementato, debuggato, e testato senza aver bisogno di una singola istanza di gmond. Un osservazione molto importante da fare a questo punto `e che non esiste nessun legame speciale tra il linguaggio di scripting Python e Ganglia. L’esistenza di Mod Python e con esso la possibilit`a di estendere gmond con una metrica nuova attraverso moduli Python `e solo una comodit`a. Ci`o potrebbe essere fatto con qualsiasi linguaggio di scripting, come PHP o perl. Per poter utilizzare le potenziali di Python in ganglia `e necessario configurare gmond per supportare i moduli python. In particolare bisogna configurare il modulo Mod Python. Il nome del modulo caricabile dinamicamente `e modpython.so; il suo file di configurazione corrispondente `e chiamato modpython.conf. Questo file solitamente si trova nella cartella /etc/conf.d. Il file contiene una configurazione semplice e lineare che segue lo stesso pattern di ogni altro modulo gmond. Di sotto c’`e un tipico esempio di configurazione Mod Python: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 modules { module { name = " python_module " path = " modpython . so " params = " < directory_path_for_python_modules >" } } include ( ’../ etc / conf . d /*. pyconf ’) 80 La parte pi` u importante parte della configurazione Mod Python `e la direttiva params. Indica il percorso in cui sono memorizzati i moduli python. Mod Python cercher`a questa locazione per ogni file con l’estensione .py. Per ognuno di questi moduli Python che trova, tenter`a di individuare anche il blocco di configurazione, con estensione .pyconf. Scrivere un modulo python La prima cosa da capire quando si inizia a implementare un modulo python `e che ci sono tre funzioni che ogni modulo Python deve includere e implementare: • metric init(params) • metric handler(name) • metric cleanup() Nelle righe successive si mostrer`a il template di un tipico modulo Python. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import sys , os descriptors = list () def M y _ C a l l b a c k _ F u n c t i o n ( name ) : ’’’ Return a metric value . ’ ’ ’ return < Some_Gathered_Value_Here > def metric_init ( params ) : ’’’ Initialize all necessary initialization here . ’ ’ ’ global descriptors if ’ Param1 ’ in params : p1 = params [ ’ Param1 ’]) d1 = \{ ’ name ’: ’ My_First_Metric ’ , ’ call_back ’: My_Callback_Function , ’ time_max ’: 90 , ’ value_type ’: ’ uint ’ , ’ units ’: ’N ’ , ’ slope ’: ’ both ’ , ’ format ’: ’%u ’ , ’ description ’: ’ Example module metric ’ , ’ groups ’: ’ example ’} 81 21 22 23 24 25 26 27 28 29 30 31 32 33 34 descriptors = [ d1 ] return descriptors def metric \ _cleanup () : ’’’ Clean up the metric module . ’ ’ ’ pass # This code is for debugging and unit testing if __name__ == ’ __main__ ’: params = { ’ Param1 ’: ’ Some_Value ’} metric_init ( params ) for d in descriptors : v = d [ ’ call_back ’]( d [ ’ name ’]) print ’ value for % s is %u ’ % ( d [ ’ name ’] , v ) Mentre le funzioni di cleanup e init devono esistere esplicitamente e chiamarsi in quel modo. La funzione My Callback pu`o chiamarsi in un modo qualsiasi. Vediamo ora in dettaglio i ruoli di queste funzioni. La funzione metric init(params) verr`a chiamata una sola volta al tempo di inizializzazione. Il suo scopo primario `e di costruire e ritornare un dizionario di definizioni di metriche, ma esso pu`o anche eseguire altre funzionalit`a di inizializzazione richieste per raccogliere l’insieme delle metriche che servono. Il parametro params che `e passato nella funzione contiene un coppia nome/valore che sono specificate come direttive di configurazione per i module nella sezione ’module’ del file di configurazione .pyconf. Ogni definizione di metrica ritornata dalla funzione di init come un oggetto dizionario, deve fornire almeno questi elementi: • name : nome della metrica • call back : funzione da chiamare quando bisogna collezionare i dati • time max : massimo tempo in secondi tra le chiamate per la collezione di metriche • value type : pu`o essere string, uint, float o double • units : unit`a della metrica 82 • slope : pu`o assumere i valori zero, positive,negative,both • descrizione descrizione della propria metrica (che `e visibile nel fronted web) • group : il gruppo di metriche ( le metriche nel web frontend dell’host sono raggruppate secondo questo valore) Il descrittore della metrica pu`o contenere attributi addizionali e valori che potranno essere aggiunti ai metadati della metrica come extra data. Per esempio due attributi potrebbero essere SPOOF HOST e SPOOF NAME ( il concetto di spoofing `e stato illustrato nel paragrafo dello spoofing con gmetric) L’elemento call back designato come funzione che verr`a richiamata se i dati per questa metrica necessitano di essere raccolti. Il nome di questa funzione pu`o essere qualunque, ma il nome assegnato alla funzione di callback deve coincidere con il nome dato nella definizione della metrica. Un modulo python deve implementare almeno una funzione handler(callback) , ma pu`o anche scegliere di implementarne di pi` u server. La definizione dell’handler deve essere simile a questa: def My Metric Handler(name): l valore del parametro name sar`a il nome della metrica che si deve raccogliere. Questo `e il nome che `e stato definito nella definizione della metrica ritornata dalla funzione init descritta prima. Passando il nome della metrica come parametro alla funzione di callback, una funzione di handler guadagna l’abilit`a di processare pi` u di una metrica e di determinare quale metrica `e stata raccolta in quel frangente. La funzione di callback dovrebbe implementare tutto il codice necessario che `e richiesto per determinare l’identit`a della metrica da raccogliere,raccogliere il valore della metrica e ritornare il valore a gmond. Il valore ritornare dalla funzione di callback deve matchare il tipo di data che `e stato specificato nella definizione corrispondente della metrica. Infine la terza funzione che deve essere implementata in tutti i moduli Python `e la funzione di cleanup che ha tipicamente questa forma: def metric cleanup(): 83 Questa funzione sar`a chiamata quando gmond viene fermato. La funzione di cleanup dovrebbe includere il codice che `e richiesto per chiudere i file, disconnettersi dalla rete e ogni altri tipo di funzionalit`a di clean up. Come la funzione metric init, la funzione cleanup deve essere chiamata metric cleanupt e non deve prendere nessun parametro. Inoltre non deve ritornare nessun valore. Quindi costruire un modulo Python per la raccolta di una metrica richiede l’implementazione della funzione init e della funzione di cleanup,di almeno una definizione di metrica, e almeno una funzione di callback. Al di fuori di questi requisiti, il modulo `e libero di fare qualunque cosa di cui necessita allo scopo di raccogliere e ritornare i dati della metrica supportata. Uno degli aspetti pi` u convenienti dell’implementare un modulo gmond in Python `e che Ganglia non `e richiesto durante lo sviluppo. L’intera implementazione, il debugging e il testing del modulo pu`o essere fatto al di fuori dell’ambiente Ganglia. Nell’esempio precedente abbiamo visto nelle ultime righe, il codice necessario per testare il nostro modulo. L’altro passo per completare l’implementazione di un modulo Python `e configurarlo. La sua configurazione non `e differente da qualsiasi altro modulo. Tutti i moduli python sono caricati e gestiti da Mod Python piuttosto che da gmond, il path che punta alla locazione dei python module `e definito nella configurazione del Mod Python. Un file pyconf dovr`a avere una forma del genere 1 2 3 4 5 6 7 8 9 10 11 12 13 modules { module { name = " example " language = " python " param < param_1 > { value = Whatever } param < param_2 > { value = NewValue } } } 84 La sezione ’module’ deve contenere le direttive language e name. Il valore della direttiva name deve essere uguale al nome del file del modulo python .py. Quando Mod Python carica ogni modulo python, prima cerca ogni file che include l’estensione .py attraverso la directory dei moduli python che `e stata specificata nel file di configurazione di Mod Python. Quando trova e conferma che il file .py `e un modulo python , cerca allora per il blocco di configurazione del modulo di cui il nome coincide col nome del file python .py. Per ogni modulo bisogna specificare che linguaggio si `e utilizzato per scriverli. Quindi , il valore della direttiva language per il modulo python deve essere python. La parte finale del modulo di configurazione specifica i valori dei parametri che dovrebbero essere passati alla funzione di metric initi(). Questa parte pu`o avere pi` u blocchi param. Ogni blocco param deve includere un nome e un valore. Il nome del blocco param rappresenta la chiave che corrisponde al valore del parametro nell’oggetto dizionario che `e passato a metric init(). Infine la direttiva value specifica il valore del parametro. Una cosa da notare `e che il valore del parametro `e sempre passato come stringa. Per utilizzare altri tipi di dati basta fare il casting all’interno dell’init. 4.2 Installazione e configurazione di Ganglia Nell’appendice B ci sono tutti i dettagli tecnici necessari per l’installazione di ganglia sia da lato server che da lato client. In questo capitolo ci occuperemo della configurazione per il monitoraggio delle macchine virtuali e dei moduli python scritti per monitorare le metriche accennate nel capitolo 2. 4.2.1 Abilitazione del monitoraggio virtuale Un problema rilevante `e stato quello di monitorare le macchine virtuali. I sistemi di monitoraggio attuali non sono sempre abilitati per rilevare le metriche delle macchine virtuali. L’immagine mostra gli elementi utilizzati da Ganglia per risolvere questo problema. Come si evince, viene utilizzato un nuovo protocollo: sFlow. sFlow `e una tecnologia per monitorare dispositivi di rete, wireless e host. sFlow utilizza il campionamento per ottenere scalabilit`a, e per questo `e ap85 Figura 4.5: Funzionamento di sFlow plicabile a reti ad alta velocit`a. Un sistema sFlow consiste di dispositivi multipli che eseguono due tipi di campionamento: campionamento random di pacchetti o operazioni a livello applicativo e campionamento basato sul tempo di contatori. Il primo tipo `e basato sulla definizione di un rate di campionamento, solitamente `e campionato un pacchetto su n. Questo tipo di campionamento non fornisce un risultato accurato al 100%. Il secondo time definisce un intervallo di polling che indica quanto spesso il dispositivo di rete invia i contatori di interfaccia. Il dato campionato `e inviato come un pacchetto UDP a uno specifico host e porto. Il numero di porto ufficiale `e il porto 6343. Il payload UDP contiene il datagramma sFlow. Ogni datagramma fornisce un informazione sulla versione di sFlow, l’indirizzo IP del dispositivo originatore, un numero di sequenza, il numero dei campioni che contiene e uno o pi` u flussi di campionamento. Come si vede dall’immagine ogni server invia pacchetti sFlow al processo di gmond che costruisce un database in memoria che contiene le statistiche del server. Il processo di gmetad periodicamente interroga il database gmond e aggiorna i diagrammi di trend che sono disponibili attraverso l’interfaccia web. Per abilitare sFlow in ganglia bisogna aggiungere queste righe nel file di configurazione gmond.conf: 1 2 3 4 /* sFlow channel */ udp_recv_channel { port = 6343 86 5 } Per abilitare la raccolta tramite sFlow sugli host che ospitano macchine virtuali da monitorare bisogna installare l’agent Host sFlow che `e un implementazione di sFlow. Su macchina Ubuntu l’agent si chiama hsflowd. Figura 4.6: Agent hsflowd Per procurarselo e installare bisogna visitare il sito ufficiale e poi : 1 2 3 4 5 6 7 tar - xzf hsflowd - X . XX . tar . gz cd hsflowd - X . XX make make install make schedule service hsflowd start 4.2.2 Abilitazione e scrittura dei moduli python In questo paragrafo verranno illustrati i passi che hanno permesso la scrittura e l’abilitazione dei moduli Python che monitorano la potenza di ogni singolo host e le informazioni relative ai rack e chassis. Per permettere l’abilitazione dei moduli Python bisogna installare il pacchetto ganglia python e gangliagmond-modules-python con le relative dipendenze. 1 yum install ganglia - python ganglia - gmond - modules - python Fatto questo per capire se l’implementazione `e corretta bisogna controllare che sussistano queste condizioni : • gmond.conf ha una linea che indica dove trovare i file .pyconf che come detto in precedenza rappresentano i file di configurazione dei moduli python 87 • modpython.conf esiste in /etc/ganglia/conf.d , contiene una direttiva che includer`a i file pyconf. • Che abbia modpython.so in /usr/lib{64}/ganglia • che la directory /usr/lib{64}/ganglia/python modules esiste. Questa `e la directory dove i moduli python dovranno essere salvati come file .py. Altrimenti si pu`o: – creare il file /etc/ganglia/conf.d/modpython.conf in questo modo 1 2 3 4 modules { module { name = " python_module " path = "/ usr / lib (64) / ganglia / ,→ modpython . so " params = "/ usr / lib (64) / ganglia / ,→ python_modules " 5 6 7 8 9 } } – Creare la directory /usr/lib(64)/ganglia/python modules – Assicurarsi che /usr/lib(64)/ganglia/modpython.so esista gi`a Nei paragrafi precedenti `e stata illustrata la struttura generale di un modulo python. Di seguito viene illustrato il procedimento che `e stato seguito per rilevare la potenza istantanea dei singoli elementi del Grid. Ogni modulo python creato raccoglie le informazioni grazie a query SNMP. In pratica la funzione handler far`a delle query SNMP sugli host per rilevare le informazioni che gli servono, utilizzando una funzione creata ad hoc runSnmp(oidDict,ip) che prende in ingresso l’indirizzo ip e gli OID degli oggetti da interrogare. 1 2 def runSnmp ( oidDict , ip ) : 88 3 4 # Esegue la query SNMP , nell ’ ordine con cui sono passati ,→ gli OID determina l ’ ordine dei risultati def runSnmp ( oidDict , ip ) : errorIndication , errorStatus , errorIndex , varBindTable = ,→ cmdgen . CommandGenerator () . nextCmd ( # SNMP v2 # cmdgen . CommunityData ( ’ test - agent ’ , ’ public ’) , cmdgen . CommunityData ( ’2c ’ , ’ public ’) , cmdgen . U dp Tr an sp or tT ar ge t (( ip , 161) ) , oidDict [ ’ SingleWatts ’] , ) # Check for SNMP errors if errorIndication : print ( errorIndication ) else : if errorStatus : print ( ’% s at % s \n ’ % ( errorStatus . prettyPrint () , errorIndex and ,→ varBindTable [ -1][ int ( errorIndex ) -1] or ,→ ’? ’ )) else : 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 return ( varBindTable ) Per far funzionare il codice python e le query snmp c’`e stato bisogno di installare alcuni componenti aggiuntivi: • net-snmp • pysnmp • OMSA 89 • pyasn Net-snmp rappresenta una suite di applicazioni utilizzate per implementare le varie versioni del protocollo SNMP(v1,v2c,v3) usando sia IPv4 che Ipv6. Questa suite include: • applicazioni di linea di comando per raccogliere informazioni da un device SNMP, sia usando una singola richiesta che multiple richieste., per manipolare informazioni di configurazione su device SNMP e per convertire le forme testuali e numeriche degli OID MIB e mostrare il contenuto e la struttura • un browser grafic MIB • un applicazione demone per ricevere le notifiche SNMP. • un agent estendibile per rispondere alle queries SNMP per gestire le informazioni (snmpd) • un libreria per sviluppare nuove applicazioni SNMP Pysnmp `e un package di python open source che implementa le entit`a SNMP e che necessita della libreria pyasnn1 0.1.7 per funzionare. Quest’ultima non si pu`o scaricare dalle repository in quanto non presentano una versione che pu`o lavorare con pysnmp. Dal sito originale `e possibile scaricare il pacchetto pyasn1 e installare seguendo questi semplici passi: 1 2 3 4 5 tar zxf pyasn1 -0.1.7. tar . gz cd pyasn1 -0.1.7 python setup . py install python setup . py test # run unit tests infine DELL OpenManage Server Administrator (OMSA) che `e un agente software che fornisce una soluzione di gestione di sistemi. OMSA `e progettato per gli amministratori di sistemi che possono gestire sistemi server sia localmente che remotamente sulla rete. Questo componente interagir`a con l’agent 90 SNMP. Questi componenti sono stati installati su ogni macchina da monitorare e configurati tramite uno script lanciato su ogni macchina in maniera automatica: tar xvf / opt / exp_soft / TEMP / m600py . tgz -C / yum install -y net \ - snmp \ - python pysnmp cd / opt / exp_soft / TEMP / pyasn1 -0.1.7 python setup . py install yum install -y libcmpiCppImpl0 libwsman1 sblim - sfcb libwsman1 ,→ openwsman - client openwsman - server wget -q -O - http :// linux . dell . com / repo / hardware / latest / ,→ bootstrap . cgi | bash yum install -y srvadmin - all service dataeng enablesnmp source / etc / profile srvadmin - services . sh restart service gmond restart Il file m600.py rappresenta il modulo Python che si preoccupa di interrogare l’agent SNMP per ricevere i dati sulla potenza. Oltre alla potenza sono stati installati anche moduli python per tenere traccia dei dati sulla potenza complessiva degli chassis e dei rack. Questo script `e composto in pratica da 3 script diversi : • copia.sh : copia tutti i file avvio.sh e migrazione.py nelle sottocartelle di ogni nodo monitorato, e lancia sequenzialmente tutti gli script avvio.sh • avvio.sh : cerca tutti i file rrd(rappresentano le metriche monitorate di un nodo) nella cartelle e li trasforma in file XML. Fatto questo invoca il file migrazione.py • migrazione.py : questo file crea una tabella in cui ogni colonna rappresenta una metrica, fa il parsing del file XML associato alla colonna e ne salva i valori all’interno del database mysql 91 1 2 3 4 5 6 7 8 9 10 11 12 Management Information Base In questo sotto-paragrafo e nel prossimo verranno spiegati meglio il concetto di MIB e le caratteristiche del protocollo SNMP- Un management information base (detto anche MIB) `e un tipo di database per la gestione di dispositivi nelle reti di comunicazione. Un MIB comprende una collezione di oggetti in un database (virtuale) usato per gestire le entit`a (ad esempio router e switch) facenti parte di una rete. Gli oggetti di un MIB vengono definiti utilizzando un sottoinsieme della notazione Abstract Syntax Notation One (ASN.1) chiamato Structure of Management Information Version 2 (SMIv2) . Il software che ne effettua il parsing viene chiamato compilatore MIB. Il database `e di tipo gerarchico (ovvero strutturato ad albero) ed ogni entry viene indirizzata attraverso un identificatore di oggetto (object identifier ). Figura 4.7: Esempio di MIB SNMP In informatica e telecomunicazioni Simple Network Management Protocol (SNMP) `e un protocollo di rete che appartiene alla suite di protocolli Internet definito dalla IETF (Internet Engineering Task Force). Il protocollo opera al livello 7 del modello OSI e consente la configurazione, la gestione e 92 la supervisione (monitoring) di apparati collegati in una rete (siano essi nodi interni di commutazione come i dispositivi di rete e nodi terminali di utenza), riguardo a tutti quegli aspetti che richiedono azioni di tipo amministrativo (management). I tre componenti logici fondamentali del framework SNMP per il suo funzionamento sono: 1. sistema gestito (managed object); 2. agente di gestione (management agent o master agent) e vari subagent (su sistema gestito); 3. sistema di gestione (manager ) da remoto; Ogni sistema gestito (per esempio un semplice nodo, un router, una stampante o qualsiasi altro dispositivo che fornisca un’interfaccia di gestione SNMP) ospita un agente di gestione (master agent) e solitamente un certo numero di subagent. Il master agent ha almeno il ruolo di intermediario fra il manager (che `e l’applicazione remota che prende le decisioni di gestione, per esempio sotto il controllo diretto dell’operatore umano) e i subagent (che sono gli esecutori di tali decisioni). Ciascun subagent `e incaricato di attuare le decisioni di gestione da parte del manager nel contesto di un particolare sottosistema o relativamente a un particolare aspetto del sistema gestito. In sistemi che forniscono meccanismi di gestione particolarmente semplici, master agent e subagent possono confluire in un unico componente software capace sia di dialogare con il manager che di attuarne le decisioni; in questo caso si parler`a semplicemente di agent. SNMP utilizza quindi una chiara separazione fra il protocollo di gestione e la struttura dell’oggetto gestito. Nell’architettura SNMP, per ogni sottosistema `e definita una base di dati detta MIB (Management Information Base), gestita dal corrispondente subagent, la quale rappresenta lo stato del sottosistema gestito, o meglio, una proiezione di tale stato limitata agli aspetti di cui si vuole consentire la gestione. Si tratta di una base dati che si potrebbe definire, mutuando un termine dalla riflessione, casualmente connessa: in altre parole, ogni modifica alla MIB causa un corrispondente mutamento nello stato del sottosistema rappresentato, e viceversa. Garantire questa propriet`a della MIB `e la funzione principale del subagent che la gestisce. 93 4.2.3 Metriche monitorate Come abbiamo gi`a visto in precedenza esistono diversi rack all’interno del progetto SCOPE. Ognuno di questi ha un interfaccia grafica che ne permette il controllo real-time. In pratica `e possibile sapere istante per istante le caratteristiche del rack in termini di velocit`a delle ventole, temperatura interna ed esterna dei server, capacit`a di raffreddamento e temperatura dell’acqua che entra nel sistema per il raffreddamento(di solito molto bassa) e la temperatura dell’acqua che ne fuoriesce una volta finito il suo compito di raffreddamento. Il problema fondamentale `e che per`o questi dati non possono essere memorizzati per effettuare analisi atte a migliorare le tecniche di gestione del datacenter. Figura 4.8: Controllo Rack Grazie agli appositi moduli python creati durante la tesi `e stato possibile portare queste informazioni in ganglia e memorizzarle in appositi archivi round robin. Essendo impossibile installare gmond su ogni rack (sono entit`a che non hanno un sistema operativo) `e stato necessario monitorarle in remoto. Questo rappresenta una forzatura rispetto al funzionamento normale di ganglia, difatti provando a lanciare un unico script a cui venivano passati come parametri, tutti i rack ,a livello python funzionava ma i grafici del web fronted di ganglia erano sballati . A questo punto `e stato necessario 94 replicare lo stesso script (modificando opportunamente il nome delle metriche) per ogni rack, bisogna inoltre fare attenzione che quando tutti gli script vengono caricati dallo stesso gmond, alcune metriche non vengono caricate. Questo perch`e probabilmente esiste un numero massimo di metriche caricabili in gmond oltre a quelle di default(non esiste una conferma ufficiale ma `e un problema riscontrato anche da altri utenti ganglia,probabilmente dipende dalla memoria ram). Per questo motivo `e stato necessario creare due macchine virtuali, ognuna con gmond installato e successivamente caricare gli script nei loro gmond. . Ognuno di questi script fa delle query SNMP al rack per ottenere le informazioni che gli servono. Una query snmp ha una forma del tipo 1 \ snmpgetnext -v 1 -c public INDIRIZZOIP ,→ 1 . 3 . 6 . 1 . 4 . 1 . 2 6 0 6 . 4 . 2 . 6 . 5 . 2 . 1 . 5 . 2 3 Dove la direttiva -v indica la versione di snmp da utilizzare, -c la community che nel nostro caso sar`a pubblica poi l’indirizzo ip della macchina che si vuole interrogare e infine l’OID che identifica un MIB.Nel caso specifico l’OID poco pi` u sopra rappresenta quello dell’acqua in uscita dal sistema di raffreddamento. Una volta che ha ottenuto le informazioni, queste vengono elaborate e salvate in appositi RRA secondo la configurazione presente in gmetad. Nell’immagine 4.9 possiamo vedere come la traduzione degli rra in file xml permetta la lettura dei valori memorizzati. Nel file xml vediamo un tag che indica l’inizio dell’archivio Round Robin. Altri tag indicano il tipo di CF, il fattore xfl,le pdp per row che il valore di una riga del database `e la media(CF) di un solo elemento raccolto ogni 15 secondi. Poco pi` u sotto ci sono i valori di questa metrica e infine inizia l’elemento database che contiene i valori istante per istante. Vediamo che una sotto-elemento di database `e composto anche da un commento che ci indica il momento in cui `e stato rilevato quel valore. Questo commento `e espresso sia in linguaggio umano che in timestamp assoluto. Nell’immagine 95 Figura 4.9: RRA in XML 4.10 invece si possono vedere i grafici che vengono generati in ganglia dopo aver prelevato i valori delle metriche che abbiamo accennato prima. Figura 4.10: Metriche dei rack monitorate da Ganglia Altri script sono stati invece creati per interrogare gli chassis (che raggruppano 15 macchine ). E’ possibile infatti dall’interfaccia web di ganglia ottenere i grafici che rappresentano l’andamento della potenza negli chassis(come mostrato nella figura 4.11). In questo modo sapremo se uno chassis `e in sovraccarico o meno. Anche in questo caso i file sono stati replicati e smistati sulle due macchine virtuali. Il principio di funzionamento `e lo stesso dei rack solo che in questo caso la versione di snmp `e 2c. 96 Figura 4.11: Consumo chassis Infine c’`e il file m600 che `e caricato da tutti i gmond del cluster SCOPE. Anche questo fa una query snmp all’OID ricevendo in risposta la potenza istantanea del nodo interrogato. Nell’immagine 4.12 si pu`o notare la potenza aggregata di tutti i nodi Mentre nella figura 4.13 si ha una panoramica su un gruppo di nodi monitorati in potenza. Questi script risultano inutili se i dati memorizzati non vengono sfruttati e analizzati. Ma fare ci`o `e estremamente difficile lavorando con gli archivi RRA. Perci`o `e stato necessario creare opportuni script per effettuare la migrazione dei dati da questo tipo di archivi a database mysql. Questi script si occupano di creare il file xml relativo a un archivio RRA e di farne il parsing per poi prendere i dati che ci interessano e inserirli nel database Mysql. Il tutto `e automatizzato a partire dalla generazione del file xml,al parsing e alla gestione delle tabelle (compresa la creazione). Nell’immagine 4.14 si evidenzia la struttura della tabella che raccoglie i dati sui job. Questa ha vari campi : • jobid : ID univoco del job sul Grid • jopbname : Nome del job • user : Utente che ha sottomesso il job • queue : Coda a cui `e stato associato il job 97 • job enqueuing : Istante in cui `e stato accodato • job dequeuing : Istante in cui `e stato rimosso dalla coda • job run : Istante in cui `e iniziata l’esecuzione • exit status : Codice che indica come `e terminato il job – 0 : terminato con successo – 271 : cancellato dall’utente – Altri : dovuti a errori • cput : tempo di lavoro della cpu • mem : memoria utilizzata • vmem : memoria virtuale utilizzata (swap) • wall time : tempo percepito dall’utente dal momento della sottomissione al momento della terminazione del job • deleted : Istante in cui il job `e stato cancellato • nodes : Nodi su cui `e stato eseguito il job Mentre lo script che trasforma i file rrd in file xml e ne fa il parsing memorizzando il tutto in un database mysql crea tabella del tipo 4.15 Che ovviamente sar`a diversa da quelle dei rack 4.16e degli chassis 4.16: 98 Figura 4.12: Potenza aggregata del cluster SCOPE 99 Figura 4.13: Potenza di un gruppo di host del cluster SCOPE Figura 4.14: Tabella dei job 100 Figura 4.15: Tabella dei Worker Node Figura 4.16: Tabella dei rack 101 Figura 4.17: Tabella dei chassis 102 Capitolo 5 Verifica del Sistema: un semplice esperimento In questo capitolo mostriamo il piccolo esperimento effettuato sulla piattaforma virtuale e fisica, allo scopo di dimostrare che il sistema funzioni e di provare a fare delle supposizioni sui risultati. Le macchine fisiche a partire da quelle del Grid fisico fino ad arrivare all’host delle macchine virtuali hanno le stesse caratteristiche hardware, inoltre la macchina virtuale prender`a pieno possesso di tutte le risorse dell’host che la ospita. 5.1 Preparazione del job In questo paragrafo metteremo in evidenza il tipo di job utilizzato e com’`e stato realizzato. Per eseguire un job sul Grid `e necessario descrivere il job con una sintassi precisa che `e detta JDL(Job Description Language). Tramite questo file noi passiamo tutte le informazioni necessarie (dalle risorse di calcolo necessario alla quantit`a delle risorse, dall’input all’output). Il file jdl del nostro job `e questo: 1 2 3 4 Executable = runme \ _xeon64 ; StdOutput = intellinbench . out ; StdError = intellinbench . out ; 103 InputSandbox =( runme_xeon64 , lininpu_xeon64 , xlinpack_xeon64 ) ; OutputSandbox = { intellinbench . out }; # Requirements = RegExp ( emi2 - ce01 . scope . unina . it :8443/ cream ,→ pbs - unina_hpc , other . GlueCEUniqueID ) ; Requirements = RegExp ( once . scope . unina . it :8443/ cream - pbs ,→ unina , other . GlueCEUniqueID ) ; Peru salFil eEnabl e = true ; P e ru s a lT i m eI n t er v a l = 1800; RetryCount = 0; Il campo Executable indica l’eseguibile che deve svolgere il calcolo, invece Arguments indica gli argomenti dell’eseguibile. StdOutput e StdError indicano dove lo standard output e lo standard output veranno rediretti. Il campo OutputSandbox indica il nome del file che viene restituito dal Grid in output. Requirements invece viene utilizzato per selezionare le risorse di calcolo a cui appoggiarsi per eseguire il job. Nel nostro file jdl ci sono due campi il primo emi2-ce01 indica le risorse di tipo fisico a cui lo scheduler si rivolger`a una volta sottomesso il job. Il nostro job avr`a accesso esclusivo alla risorsa a cui viene assegnata. Mentre il campo once.scope.unina.it indica il Grid virtuale, in cui `e presente un unica risorsa che `e il nodo creato ad hoc per questo esperimento. Figura 5.1: Infrastruttura Grid virtuale Nell’immagine 5.1 `e mostrata l’infrastruttura Grid virtuale creata per quest’esperimento. La macchina SLWN2 `e worker node su cui verr`a eseguito 104 5 6 7 8 9 10 11 il job. Nella struttura del file jdl abbiamo parlato del campo OutputSandBox che contiene il nome del file eseguibile. Nel nostro caso `e runme xeon64. Il file conterr`a le seguenti linee di codice: echo " This is a SAMPLE run script for SMP LINPACK . Change it ,→ to reflect " echo " the correct number of CPUs / threads , problem input files ,→ , etc .." 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # Setting up affinity for better threading performance export KMP_AFFINITY = nowarnings , compact ,1 ,0 , granularity = fine # export OMP_NUM_THREADS =16 # echo -n " Inizio Job :" # date arch = xeon64 { chmod u + x ./ xlinpack_$arch date ./ xlinpack_$arch lininput_$arch echo -n " Done : " date } # date echo " Eseguito su $HOSTNAME " L’export serve per migliorare le performance del threading. La variabile arch rappresenta l’architettura del processore, che nel nostro caso `e uno xeon a 64 bit. Il comando ./xlinpack chiama il benchmark Linpack Intel, che `e proprietario, passandogli un file di configurazione. Linpack `e una libreria software sviluppata per eseguire operazioni di algebra lineare. Il file lininput $arch contiene le seguenti linee di codice : 1 2 Sample Intel ( R ) Optimized LINPACK Benchmark data file ( ,→ lininput_xeon64 ) Intel ( R ) Optimized LINPACK Benchmark data 1 # number of tests 3 4 105 5 6 7 8 40000 # problem sizes 40000 # leading dimensions 8 # times to run a test 4 # alignment values ( in KBytes ) La prima riga significativa `e quella che indica il numero dei test che deve essere non-negativo. Le 4 righe successive sono i parametri che verranno passati al benchmark: 1. problem sizes: questo indica il numero di equazioni da risolvere. Deve essere positivo. 2. leading dimension : `e numero che deve essere positivo e non minore del numero di equazioni(`e il numero delle incognite) 3. time to run a test : indica il numero di volte che sar`a ripetuto il test 4. data alignment value (Kb) il valore di allineamento permette agli array di essere allineati a un valore specifico, zero significa che verr`a effettuato nessun allineamento - gli array vengono utilizzati nel momento in cui vengono allocati I due parametri problem sizes e leading dimension sono legati alla memoria su cui viene eseguito il Benchmark. Difatti il prodotto (problem size)*(leading dimension)*8 restituisce il numero di bytes utilizzati. Perci`o `e buona norma fare in modo che questo valore non superi la memoria RAM della macchina altrimenti il test diventa meno preciso dato che molte delle risorse della macchina verrebbero utilizzare per scrivere sul disco fisso. 5.1.1 Sottomissione del job Per poter accedere alle risorse del Datacenter `e necessario possedere un certificato personale. Una volta entrati in possesso del certificato sar`a possibile collegarsi all’interfaccia utente per la gestione dei propri job. Per collegarsi all’interfaccia utente `e necessario collegarsi in ssh all’host: 1 ui . scope . unina . it 106 e inserire le proprie credenziali. A questo punto sar`a necessario creare un certificato proxy utente per la sottomissione del job. 1 voms - proxy - init -- voms unina . it Una volta terminato il job per recuperare l’output `e necessario usare il comando : 1 glite - wms - job - output JOBID L’output sar`a come quello mostrato in figura 5.2 [h] Figura 5.2: Output del job Oltre alle caratteristiche tecniche delle macchina su cui girava e i parametri di input che ha ricevuto, ci restituisce per ogni iterazione anche il tempo di risoluzione del singolo sistema e il numero di operazioni eseguite dalla CPU in un secondo. Nell’immagine notiamo anche che sono evidenziati in rosso l’istante di inizio e l’istante di fine del job. Il tempo che intercorre tra 107 questi due istanti temporali `e diverso dal tempo utilizzato dalla CPU per risolvere i sistemi lineari . Questo perch`e tiene conto anche dell’iniziazione del sistema lineare e della relativa deallocazione delle risorse dopo la risoluzione. Per rendersi conto di ci`o basta notare che la somma dei secondi nell’output, fornisce un tempo di esecuzione diverso dalla sottrazione tra l’istante finale e quello iniziale. Nel prossimo paragrafo vengono analizzati i risultati che si sono ottenuti dall’esecuzione del job sull’infrastruttura reale e su quella virtuale. 5.2 Analisi sperimentale In questo paragrafo mettiamo a confronto i risultati ottenuti con l’esecuzione dei job fisici e dei job virtuali. Si `e scelto un job cpu intensive dato che risulta essere maggiormente descrittivo sotto il profilo della potenza in quanto la CPU `e completamente sotto stress e la potenza dissipata aumenta. L’immagine 5.3 ci mostra come sia effettivamente CPU intensive il nostro algoritmo,difatti la cpu wio (cpu waiting I/O) cio`e il tempo in cui la cpu rimane idle nell’attesa di un interruzione I/O , `e nullo durante l’esecuzione. Figura 5.3: CPU wio A destra c’`e il caso del job fisico che a partire dalle 15(istante in cui `e stato lanciato) fino al completamento aveva una percentuale di CPU wio nulla cos`ı come il job sulla macchina virtuale(a sinistra)che invece `e stato lanciato alle 17. Nei prossimi paragrafi analizzeremo separatamente i grafici del nodo fisico e quelli del nodo che fa da host alla macchina virtuale. 108 5.2.1 Nodo fisico L’immagine 5.4 mostra l’andamento della potenza durante l’esperimento sul nodo fisico wn065 che `e quello su cui `e stato eseguito il job. Come possiamo notare il grafico ha un andamento a scalini: Figura 5.4: Potenza media: 243.15 ± 47.56 Watts Ogni scalino rappresenta la risoluzione del sistema lineare in 40000 equazione e 40000 incognite. La distanza tra uno scalino e l’altro invece comprende sia la fase di preparazione del sistema lineare (generazione dei coefficienti del sistema) sia quella di deallocazione dello spazio utilizzato. In questo caso entra in gioco la system CPU come si pu`o pu`o notare dal grafico 5.5 Figura 5.5: Utilizzo medio della system CPU : 0.8 ± 0.01% Difatti i picchi della system CPU avvengono proprio tra i gradini rappresentati nel grafico 5.4, da notare che il valore `e sempre molto basso. La user CPU invece ha un andamento come quello nel grafico 5.6 109 Figura 5.6: Utilizzo medio della user CPU : 97.84 ± 4.03% L’uso della cpu da parte dell’utente `e quasi totale. Un altro aspetto da tener conto `e quello del numero di processi che girano sulla macchina. Pu`o sembrare inutile ma esister`a sicuramente una differenza in quanto sull’host della macchina virtuale girano anche i vari processi di virtualizzazione. Figura 5.7: Numero di processi in esecuzione 110 5.2.2 Host del nodo virtuale Partiamo anche in questo caso con l’osservare il grafico sulla potenza 5.8 : Figura 5.8: Potenza media: 215.47 ± 32.26 Watts Anche in questo caso la potenza ha un andamento a gradini anche se la distanza tra un gradino e l’altro aumenta, ci`o vuol dire che il sistema impiega pi` u tempo a creare il sistema lineare da risolvere. Se nel caso del nodo fisico la system CPU aveva valori decisamente bassi nel caso dell’host che ospita il nodo virtuale la situazione `e diversa 5.9: Figura 5.9: Utilizzo medio della system CPU : 9.17 ± 0.07% Il valore della system CPU `e 10 volte maggiore rispetto al caso del nodo fisico su cui gira il job. Questo perch´e probabilmente l’hypervisor si riserva una parte di CPU per la gestione della macchina virtuale, difatti l’utilizzo medio della user CPU `e pi` u basso rispetto al nodo fisico: Come accennato prima il numero dei processi sull’host `e maggiore del nodo di calcolo fisico 5.11 : 111 Figura 5.10: Utilizzo medio della user CPU : 90.65 ± 0.46% Figura 5.11: Numero di processi in esecuzione 112 Capitolo 6 Conclusioni e sviluppi futuri Dai risultati dell’esperimento del capitolo precedente, possiamo evidenziare subito come ci sia una perdita di performance da parte del nodo virtuale. Come si pu`o vedere in tabella il tempo che impiega il nodo virtuale per eseguire il benchmark LINPACK `e notevolmente superiore. Viene fatta una distinzione tra tempo di esecuzione, inteso come il tempo tra il momento in cui il job inizia a essere eseguito e l’istante in cui termina, e il tempo di risoluzione che invece indica quanto tempo impiega il nodo ` un risultato che non sorprende anche a risolvere il sistema di equazioni. E ripensando ai dati sull’uso della CPU. La perdita in termini di performance per`o ha assicurato un guadagno in termini di elasticit`a. Difatti grazie al Cloud si possono fornire risorse solo quando necessarie e configurate per il carico del sistema in un determinato periodo. Questa tesi ha quindi dimostrato che `e possibile creare un infrastruttura virtuale che sopperisca alle mancanze di quella fisica creando una base per Tempo medio di esecuzione(s) Macchina Fisica 6257 Macchina Virtuale 9309 Tempo medio di Rapporto risolurisoluzione(s) zione/esecuzione 5166 82.65% 6827 73.36% Tabella 6.1: Tempi di calcolo del job 113 sperimentazioni future. Difatti si potrebbero creare algoritmi per migliorare la gestione delle risorse. Ad esempio algoritmi che migrino da macchine fisiche ad altre in modo da riempire completamente un server fisico e poter cos`ı spegnere i server inutilizzati, con conseguente risparmio sui costi del consumo. Si potrebbe studiare il comportamento delle VMs sotto differenti tipi di carico. Provare a utilizzare job di tipo I/O oppure job che presentino sia parti di CPU intensive che di I/O. Monitorare i parametri di affidabilit`a per capire se il Cloud migliora l’affidabilit`a complessiva e dove bisogna agire per migliorarla. 114 Appendice A Installazione Openstack In questa appendice si evidenzieranno brevemente i passi per l’installazione di Openstack componente per componente. A.1 Installazione e configurazione di Keystone Per installare l’Identity Service si `e eseguito da root: 1 apt - get install keystone Di default viene creato un database sqlite e perci`o vanno cambiate le configurazioni affinch`e il servizio punti a un database Mysql. Perci`o rimuoviamo : 1 rm / var / lib / keystone / keystone . db A questo punto `e necessario creare il database in mysql e l’utente a cui verr`o assegnato il pieno controllo: 1 2 3 4 mysql -u root -p mysql > CREATE DATABASE keystone ; mysql > GRANT ALL ON keystone .* TO ’ keystone ’@ ’% ’ IDENTIFIED ,→ BY ’[ Y O U R _ K E Y S T O N E D B _ P A S S W O R D ] ’; mysql > GRANT ALL ON keystone .* TO ’ keystone ’@ ’ localhost ’ ,→ IDENTIFIED BY ’[ Y O U R _ K E Y S T O N E D B _ P A S S W O R D ] ’; 5 115 Fatto questo bisogna cambiare nel file di configurazione /etc/keystone/keystone.conf il data store da sqlite a mysql in questo modo: connection = mysql :// keystone :[ Y O U R _ K E Y S T O N E D B _ P A S S W O R D ] @143 ,→ .225.20.189/ keystone 1 L’ip 143.225.20.189 `e quello della macchina fisica che far`a da controller. Bisogna far attenzione anche che il token del servizio corretto sia usato in keystone.conf 1 admin \ _token = 012345 S E C RE T 9 9T O K EN 0 1 23 4 5 A questo punto dopo aver riavviato keystone 1 service keystone restart Bisogna creare i progetti gli utenti e i ruoli. Solitamente per autentificarsi nell’Identity Service vengono usate username e password. Ma questo punto dell’installazione non esiste ancora un user perci`o verr`a utilizzato il service token per l’autentificazione. Ogni volta che bisogner`a eseguire un comando bisogner`a strutturarlo in questo modo: 1 2 keystone -- token 012345 SE C R ET 9 9 TO K E N0 1 2 34 5 -- endpoint http ,→ : / / 1 4 3 . 2 2 5 . 2 0 . 1 8 9 : 3 5 3 5 7 / v2 .0 ’ command parameters ’ per ovviare a ci`o basta creare un file keystonerc assegnargli i privilegi di esecuzione ed eseguirlo in modo da esportare ogni volta i valori che servono: $ export OS_SERVICE_TOKEN =012345 S E C RE T 9 9T O K EN 0 1 23 4 5 $ export O S _S E R VI C E _ EN D P OI N T = http : / / 1 4 3 . 2 2 5 . 2 0 . 1 8 9 : 3 5 3 5 7 / v2 .0 Il primo passo `e quello di creare un progetto che chiamiamo ’demo’. Bisogna fare attenzione in quanto tenant in Openstack sta ad indicare proprio un progetto. 116 1 2 1 keystone tenant - create -- name demo -- description Default ,→ Tenant Creiamo un utente admin keystone user - create -- tenant - id IDPROGETTO -- name admin -,→ pass secrete } 1 2 Ora creiamo un ruolo admin 1 keystone role - create -- name admin E assegniamo all’utente admin il ruolo di admin: 1 keystone user - role - add ? user - id IDUTENTE ? tenant \ - id ,→ IDPROGETTO -- role - id IDRUOLO } A questo punto creiamo un progetto ’service’ che conterr`a tutti i servizi che bisogna rendere noti nel catalogo dei servizi 1 keystone tenant - create -- name service -- description Service ,→ Tenant } Ora bisogna creare per ogni servizio (glance,nova, cinder,ec2,swift) un utente, assegnargli il ruolo di admin e attaccarlo logicamente al progetto service. 1 2 keystone user - create -- tenant - id IDSE RVICEC ATALOG O -- name ,→ glance -- pass glance 3 4 keystone user - role - add -- user - id IDUSERGLANCE ? tenant - id ,→ IDS ERVICE CATALO GO -- role - id IDRUOLOADMIN 117 Nell’immagine A.1 sono mostrati tutti gli utenti creati Figura A.1: Lista utenti e dei progetti Figura A.2: Lista dei tenant Keystone agisce anche come catalogo dei servizi. Esistono due modi per definire i servizi in keystone : 1. Usando un file template 2. Usando un database di backend In questo caso noi utilizziamo un database e per settare ci`o bisogna inserire nel file keystone.conf la seguente riga: [catalog] driver = keystone.catalog.backends.sql.Catalog Per ogni servizio nel catalogo, bisogna eseguire due operazioni di keystone. • usare keystone servicecreate per creare una entry nel database per il servizio con i seguenti attributi : – name: Nome del servizio 118 – type: tipo del servizio – description: Una breve descrizione del servizio • Usare keystone endpointcreate per creare una entry nel database che descrive differenti tipi di clienti che possono connettersi al servizio con i seguenti attributi: – region il nome della regione che si sta dando al Cloud Openstack – serviceid Il campo ID ritornato dal comando keystone servicecreate – publicurl L’url della faccia pubblica dell’enpoint per il servizio – internalurl l’url della faccia interna dell’endpoin per il servizio. Solitamente ha lo stesso valore di publicurl – adminurl l’url per l’endpoint admin per il servizio. Keystone ed EC2 usano adminurl e publicurl differenti mentre tutti per tutti gli altri coincidono A questo punto non rimane che creare i servizi a cominciare da keystone: $keystone service - create -- name = keystone -- type = identity -,→ description = Identity Service 1 2 3 4 5 6 7 8 % keystone endpoint - create \ -- region RegionOne \ -- service - id =15 c 1 1 a 2 3 6 6 7 e 4 2 7 e 9 1 b c 3 1 3 3 5 b 4 5 f 4 b d \ -- publicurl = http : / / 1 9 2 . 1 6 8 . 2 0 6 . 1 3 0 : 5 0 0 0 / v2 .0 \ -- internalurl = http : / / 1 9 2 . 1 6 8 . 2 0 6 . 1 3 0 : 5 0 0 0 / v2 .0 \ -- adminurl = http : / / 1 9 2 . 1 6 8 . 2 0 6 . 1 3 0 : 3 5 3 5 7 / v2 .0 \ Lo stesso verr`a fatto per tutti i servizi e alla fine avremmo una lista del genere: 119 Figura A.3: Lista dei servizi A.2 Installazione e configurazione di Image Service I primi passi sono identici all’installazione di keystone( installazione del servizio e configurazione del database di backend) $sudo apt \ - get install glance $mysql \ - u root \ - p mysql > GRANT ALL ON glance .* TO ’ glance ’@ ’% ’ IDENTIFIED BY ’[ ,→ Y O U R _ G L A N C E D B _ P A S S W O R D ] ’; mysql > GRANT ALL ON glance .* TO ’ glance ’@ ’ localhost ’% ’ ,→ IDENTIFIED BY ’[ YO U R _ G L A N C E D B _ P A S S W O R D ] ’; 1 2 3 4 5 Per configurare il database mysql bisogna, nel file /etc/glance/glanceapi.conf 1 sql_connection = mysql :// glance [ Y O U R _ G L A N C E D B _ P A S S W O R D ] @143 ,→ .225.20.189/ glance e inoltre va configurato in modo che usi come sistema di autentificazione keystone,modificando il file /etc/glance/glanceapi.conf Una volta configurato (come in appendice) bisogna sincronizzare e popolare il database con 1 glance - manage db_sync e ristartare tutti i servizi 1 2 # service glance - registry restart # service glance - api restart Nell’immagine A.4 `e mostrato l’utilizzo di glance 120 Figura A.4: Lista delle immagini di Glance A.3 Configurare l’hypervisor Prima di tutto `e stato necessario capire se la nostra macchina che far`a da compute supporta KVM perci`o abbiamo prima installato cpuchecker e poi controllato: 1 # apt - get install cpu - checker } se non fosse stato supportato il comando kvmok avrebbe dato un output del genere 1 2 INFO : Your CPU does not support KVM extensions KVM acceleration can NOT be used Per abilitare KVM esplicitamente `e stato necessario aggiungere la seguente opzione di configurazione a /etc/nova/nova.conf 1 2 compute_driver = libvirt . LibvirtDriver libvirt_type = kvm A.4 Installazione e configurazione NOVA Sia sul nodo controller che sui compute vanno installati i packages nova richiesti. Sul nodo controller bisogna installare : sudo apt - get install nova - novncproxy novnc nova - api nova - ajax ,→ - console \ - proxy nova - cert nova - conductor nova - consoleauth ,→ nova \ - doc nova - scheduler nova - network 121 1 mentre sui nodi compute: 1 sudo apt - get install nova - compute nova - network Inoltre sul nodo controller andr`a configurato il database come gi`a visto in precedenza $ mysql -u root -p } $ mysql > CREATE DATABASE nova ; $ mysql > GRANT ALL ON nova .* TO ’ nova ’@ ’% ’ IDENTIFIED BY ’ ,→ password ’; $ mysql : GRANT ALL ON nova .* TO ’ nova ’@ ’ localhost ’ IDENTIFIED ,→ BY ’ password ’ 1 2 3 4 Anche in questo caso si necessit`a la configurazione di mysql come database di backend andando ad aggiungere nel fille nova.conf la seguente linea di codice : 1 sql_connection = mysql :// nova [ Y O U R _ N O V A D B _ P A S S W O R D ] @143 ,→ .225.20.189/ nova } A questo punto non rimane che creare le tabelle nel database mysql tramite il comando 1 nova \ - manage db \ _sync Per tutte le altre modifiche al file di configurazione nova.conf conviene dare un occhiata al file nell’appendice. Nella figura A.5 c’`e la lista dei servizi nova presenti sui diversi host. Figura A.5: Servizi Nova Come si pu`o vedere tutti i servizi sono attivi eccetto quello di novanetwork sul nodo compute che `e stato fermato per problemi di conflitto con quello presente sul nodo Controller. 122 A.5 Installazione e configurazione Block Storage I passi sono gli stessi effettuali precedentemente per gli altri servizi. 1 $ sudo apt - get install cinder - api e poi configurare il database come gi`a visto per gli altri servizi e configurare cinder $ mysql -u root -p $ mysql > CREATE DATABASE cinder ; $ mysql > GRANT ALL ON cinder .* TO ’ cinder ’@ ’% ’ IDENTIFIED BY ,→ ’ password ’;} $ mysql : GRANT ALL ON nova .* TO ’ nova ’@ ’ localhost ’ IDENTIFIED ,→ BY ’ password ’; A.6 1 2 3 4 Installazione e configurazione Dashboard Per installare basta eseguire il comando : # apt - get install -y memcached libapache2 - mod - wsgi openstack ,→ dashboard Poi bisogna cambiare il valore della variabile CACHE BACKEND in /etc/openstackdashboard/local settings.py affinch`e sia uguale a quello in /etc/memcached.conf. Per la configurazione prendere in considerazione l’appendice C 123 1 Appendice B Installazione Ganglia In quest’appendice mostriamo come `e stato installato ganglia da lato server e lato client. B.1 Installazione server Il primo passo per installare Ganglia `e stato recuperare ed abilitare le repository epol e remy su Linux Scientific 6.3 tramite i comandi: 1 # wget http :// download . fedoraproject . org / pub / epel /6/ x86_64 / ,→ epel - release -6 -8. noarch . rpm rpm - ivh epel - release -6 -8. noarch . rpm # wget http :// rpms . famillecollet . com / enterprise / remi - release ,→ -6. rpm # rpm - Uvh remi - release -6*. rpm 2 3 4 Per abilitare la repository remi basta settare il campo enabled uguale a 1, nel file /etc/yum.repos.d/remi.repo: [ remi ] name = Les RPM de remi pour Enterprise Linux $releasever ,→ $basearch # baseurl = http :// rpms . famillecollet . com / enterprise / $releasever ,→ / remi / $basearch / mirrorlist = http :// rpms . famillecollet . com / enterprise / ,→ $releasever / remi / mirror enabled =1 124 1 2 3 4 5 6 gpgcheck =1 gpgkey = file :/// etc / pki / rpm - gpg / RPM - GPG - KEY - remi failovermethod = priority [ remi - test ] name = Les RPM de remi en test pour Enterprise Linux ,→ $releasever - $basearch # baseurl = http :// rpms . famillecollet . com / enterprise / $releasever ,→ / test / $basearch / mirrorlist = http :// rpms . famillecollet . com / enterprise / ,→ $releasever / test / mirror enabled =1 gpgcheck =1 gpgkey = file :/// etc / pki / rpm - gpg / RPM - GPG - KEY - remi 7 8 9 10 11 12 13 14 15 16 Fatto questo bisona installare alcuni prerequisiti: 1 # yum install gcc gcc - c ++ autoconf automake expat - devel ,→ libconfuse - devel rrdtool rrdtool - devel apr - devel ,→ libconfuse Poi scaricato e compilato pcre # wget ftp :// ftp . csx . cam . ac . uk / pub / software / programming / pcre / ,→ pcre -8.32. tar . gz # tar zxvf pcre -8.32. tar . gz # cd pcre -8.32 # ./ configure # make # make install 1 2 3 4 5 6 Ora viene scaricato e compilato ganglia. La macchina su cui gira gmetad deve essere compilato con l’opzione –with-gmetad abilitata. # wget http :// sourceforge . net / projects / ganglia / files / latest / ,→ download ? source = files # tar zxvf ganglia -3.6.0. tar . gz # cd ganglia -3.6.0 # ./ configure -- sysconfdir =/ etc / ganglia / -- sbindir =/ usr / sbin / ,→ -- with - gmetad -- enable - static - build # make # make install Per generare il file di configurazione gmond. 125 1 2 3 4 5 6 1 # gmond -- default \ _config > / etc / ganglia / gmond . conf Dar`a un errore del tipo : gmond : error while loading shared libraries : libpcre . so .1: ,→ cannot open shared object file : No such file or directory 1 Per risolvere si crea un symlink e si esegue di nuovo il comando. 1 2 # ln -s / lib64 / libpcre . so .0.0.1 / lib64 / libpcre . so .1 # gmond -- default_config > / etc / ganglia / gmond . conf Per configurare gmond bisogna cambiare il file /etc/ganglia/gmond.conf. Si cambia il campo cluster che dovr`a essere lo stesso in ogni file gmond.conf. Il file di configurazione utilizzato `e mostrato in appendice. 1 2 3 4 5 6 cluster { name = " UNINA - SCOPE - DATACENTER " owner = " unspecified " latlong = " unspecified " url = " unspecified " } Fatto questo si copia lo script di init e si starta il servizio gmond. # # # # # 1 2 3 4 5 cd ganglia -3.6.0/ gmond cp gmond . init / etc / init . d / gmond / etc / init . d / gmond start chkconfig -- add gmond chkconfig gmond on Ora bisogna creare la directory rrd, cambiare i permessi e copiare lo script di init gmetad e aprirlo in un editore qualsiasi. # # # # # 1 2 3 4 5 mkdir -p / var / lib / ganglia / rrds / chown nobody : nobody / var / lib / ganglia / rrds / cd ganglia -3.5.0/ gmetad cp gmetad . init / etc / init . d / gmetad vi / etc / init . d / gmetad A questo punto basta startare il processo gmetad. 1 2 # service gmetad restart # chkconfig ? add gmetad 126 3 # chkconfig gmetad on Per installare l’interfaccia web, bisogna installare i prerequisiti: 1 # yum install httpd php Scaricata l’interfaccia web e decompressa, bisogna copiarlo nel documento root del web server e alla fine installarlo. # wget http :// sourceforge . net / projects / ganglia / files / ganglia ,→ web /3.5.7/ ganglia - web -3.5.7. tar . gz / download # tar zxvf ganglia - web -3.5.7. tar . gz # mv ganglia - web -3.5.7 / var / www / html / ganglia # cd / var / www / html / ganglia # make install B.2 1 2 3 4 5 Installazione client Anche col client bisogna scaricare e abilitare le repository remi e epel. Fatto q uesto e reinstallati i prerequisiti, bisogna scaricare e compilare ganglia senza per`o abilitare l’opzione gmetad. # wget http :// sourceforge . net / projects / ganglia / files / latest / ,→ download ? source = files # tar zxvf ganglia -3.5.0. tar . gz # cd ganglia -3.5.0 # ./ configure -- sysconfdir =/ etc / ganglia / -- sbindir =/ usr / sbin / ,→ -- enable - static - build # make # make install 1 2 3 4 5 6 Generiamo il file gmond nello stesso modo fatto in precedenza Si copia il file di init di gmond e apriamo il file di configurazione di gmond.conf in modo che il campo cluster sia uguale a quello presente nel file di configurazione di gmond del server. 1 # gmond -- default_config > / etc / ganglia / gmond . conf A questo punto non rimane che far startare il servizio gmond. 1 # service gmond start 127 Ora dal browser basta andare all’indirizzo http://ipaddress-or-domainname/ganglia. Se non si riesce a caricare bisogna controllare il firewall delle macchine. Per gestire il firewall basta cambiare i valori nel file /etc/sysconfig/iptables. In appendice le regole del firewall che sono state utilizzate nel nostro server. 128 Appendice C Script creati In quest’appendice invece raccogliamo tutti gli script creati per estendere ganglia,e per effettuare la migrazione da archivi rra a database mysql. C.1 File per estendere Ganglia I file .pyconf sono i file che andranno inseriti nella cartella /etc/ganglia/conf.d, mentre i file .py nella cartella /usr/lib64/ganglia/python modules/. C.1.1 m600.pyconf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 modules { module { name = " m600 " language = " python " param poweredge { # ip : hostname value = ’ localhost ’ } } } #/* Collection groups for the # example python module */ collection_group { 129 16 17 18 19 20 21 22 23 collect_every = 20 time_threshold = 50 metric { name =" singlewatt " title = " Power Consumption " } } C.1.2 m600.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #!/ usr / bin / python import sys import os import re import time from pysnmp . entity . rfc3413 . oneliner import cmdgen NIPARAMS = {} # crea una lista di descrittori descriptors = list () # OID degli oggetti da interrogare oidDict = { ’ SingleWatts ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,1 ,600 ,30 ,1 ,6 ,1) , } def get_watt ( nomeMetrica ) : 19 20 21 22 23 24 25 26 27 28 global descriptors # ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’]) prova =( snmpTable [0][0][1]) return float ( prova ) 130 def runSnmp ( oidDict , ip ) : # Ritorna i risultati nell ’ ordine in cui sono stati ,→ interrogati errorIndication , errorStatus , errorIndex , varBindTable = ,→ cmdgen . CommandGenerator () . nextCmd ( # SNMP v2 # cmdgen . CommunityData ( ’ test - agent ’ , ’ public ’) , cmdgen . CommunityData ( ’2c ’ , ’ public ’) , cmdgen . U dp Tr an sp or tT ar ge t (( ip , 161) ) , oidDict [ ’ SingleWatts ’] , ) # Controlla se ci sono errori if errorIndication : print ( errorIndication ) else : if errorStatus : print ( ’% s at % s \n ’ % ( errorStatus . prettyPrint () , errorIndex and ,→ varBindTable [ -1][ int ( errorIndex ) -1] or ,→ ’? ’ )) else : 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 return ( varBindTable ) def metric_init ( params ) : global descriptors , Desc_WattSingle , _Worker_Thread , ,→ Debug , newdict 57 58 59 60 61 62 63 64 print ( ’[ poweredge ] Received the following parameters ’) print ( params ) for key in params : NIPARAMS [ key ] = params [ key ] 131 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 for para in params . keys () : if para . startswith ( ’ poweredge ’) : # ipaddr , namehost = params [ para ]. split ( ’: ’) Desc_WattSingle = { ’ name ’ : ’ singlewatt ’ , ’ call_back ’ : get_watt , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Watts ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Power Consumption ’ , ’ groups ’ : ’ NodeSingle ’ , # ’ spoof_host ’ : params [ para ] , } descriptors . append ( Desc_WattSingle ) # Ritorna il descrittore a Gmond return descriptors def metric_cleanup () : ’’’ Modulo di cleanup ’ ’ ’ pass # Per CLI Debuging : if __name__ == ’ __main__ ’: params = { ’ poweredge ’ : ’ localhost ’ } descriptors = metric_init ( params ) while True : for d in descriptors : v = d [ ’ call_back ’]( d [ ’ name ’]) 132 print ( ’ value for % s is %u ’ % ( params [ ’ poweredge ,→ ’] , v ) ) print ( ’ Sleeping 5 seconds ’) time . sleep (5) # exit (0) C.1.3 105 106 107 108 109 chassisX.pyconf Come detto nel [? ] si sono dovuti creare pi` u file di chassis. Perci`o alla X fa cambiato di volta in volta il valore che `e uguale all’ultimo byte dell’indirizzo IP. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 modules { module { name = " chassis21 " language = " python " param poweredge { # ip : hostname value = ’ indirizzioIP : hostname ’ } } } #/* Collection groups for the # example python module */ collection_group { collect_every = 20 time_threshold = 50 metric { name =" watt21 " title = " Watts Consumption " } # metric { # name = " amper21 " # title = " Amps Consumption " # } } 133 C.1.4 chassisX.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #!/ usr / bin / python import sys import os import re import time from pysnmp . entity . rfc3413 . oneliner import cmdgen NIPARAMS = {} # crea una lista di descrittori descriptors = list () # OID degli oggetti da interrogare oidDict = { ’ drsWattsReading ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,2 ,4 ,1 ,1 ,13) , ’ drsAmpsReading ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,2 ,4 ,1 ,1 ,14) , # ’ SingleWatts ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,1 ,600 ,30 ,1 ,6 ,1 ,1) , } def get_watt21 ( nomeMetrica ) : 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 global descriptors # ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’]) snmpTable = runSnmp ( oidDict , ip ) string = str ( snmpTable [0][0][1]) return float ( string ) def get_amper21 ( nomeMetrica ) : global descriptors # 134 ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’]) snmpTable = runSnmp ( oidDict , ip ) string = str ( snmpTable [0][1][1]) return float ( string ) def runSnmp ( oidDict , ip ) : # interrogati in the results errorIndication , errorStatus , errorIndex , varBindTable = ,→ cmdgen . CommandGenerator () . nextCmd ( # SNMP v2 # cmdgen . CommunityData ( ’ test - agent ’ , ’ public ’) , cmdgen . CommunityData ( ’2c ’ , ’ public ’) , cmdgen . U dp Tr an sp or tT ar ge t (( ip , 161) ) , oidDict [ ’ drsWattsReading ’] , # oidDict [ ’ ifName ’] , oidDict [ ’ drsAmpsReading ’] , ) # Check for SNMP errors if errorIndication : print ( errorIndication ) else : if errorStatus : print ( ’% s at % s \n ’ % ( errorStatus . prettyPrint () , errorIndex and ,→ varBindTable [ -1][ int ( errorIndex ) -1] or ,→ ’? ’ )) else : 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 return ( varBindTable ) def metric_init ( params ) : global descriptors , Desc_Watt21 , Desc_Amps21 , ,→ _Worker_Thread , Debug , newdict 135 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 print ( ’[ poweredge ] Received the following parameters ’) print ( params ) for key in params : NIPARAMS [ key ] = params [ key ] print (" NIPARAMS "+ str ( NIPARAMS ) ) # Find all the netiron ’ s passed in params for para in params . keys () : if para . startswith ( ’ poweredge ’) : ipaddr , namehost = params [ para ]. split ( ’: ’) Desc_Watt21 = { ’ name ’ : ’ watt21 ’ , ’ call_back ’ : get_watt21 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ power ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Watt Consumption ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_Amps21 = { ’ name ’ : ’ amper21 ’ , ’ call_back ’ : get_amper21 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ amper ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Amper Consumption ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } # print (" WAtt "+ str ( Desc_Watt ) ) # print (" AMps "+ str ( Desc_Amps ) ) descriptors . append ( Desc_Watt21 ) descriptors . append ( Desc_Amps21 ) 136 # Ritorna i descrittore a Gmond # print (" Descrittori "+ str ( descriptors ) ) return descriptors def metric_cleanup () : ’’’ Clean up the metric module . ’ ’ ’ pass # For CLI Debuging : if __name__ == ’ __main__ ’: params = { ’ poweredge ’ : ’ i nd ir iz zo IP ch as si s : chassis21 ’ , } descriptors = metric_init ( params ) while True : for d in descriptors : v = d [ ’ call_back ’]( d [ ’ name ’]) print ( ’ value for % s is %u ’ % ( params [ ’ poweredge ,→ ’] , v ) ) print ( ’ Sleeping 5 seconds ’) time . sleep (5) # exit (0) C.1.5 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 rackX.pyconf 1 2 3 4 5 6 7 8 9 modules { module { name = " rack3 " language = " python " param poweredge { # ip : hostname value = ’ indirizzoIPrack : rack3 ’ } 137 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 } } #/* Collection groups for the # example python module */ collection_group { collect_every = 20 time_threshold = 50 metric { name =" R A C K 3 t e m p e r a t u r e S e n s o r " title = " Temperature of sensor " # value_threshold = 0 } metric { name = " RA CK3coo lCapac ity " title = " Cooling Capacity " } metric { name = " RACK3rpm1 .1" title = " Spin Valve 1.1" } metric { name = " RACK3rpm1 .2" title = " Spin Valve 1.2" } metric { name = " RACK3rpm2 .1" title = " Spin Valve 2.1" } metric { name = " RACK3rpm2 .2" title = " Spin Valve 2.2" } metric { name = " RACK3rpm3 .1" title = " Spin Valve 3.1" } metric { 138 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 name = " RACK3rpm3 .2" title = " Spin Valve 3.2" } metric { name = " RACK3temp1 .1" title = " Temperature of } metric { name = " RACK3temp1 .2" title = " Temperature of } metric { name = " RACK3temp2 .1" title = " Temperature of } metric { name = " RACK3temp2 .2" title = " Temperature of } metric { name = " RACK3temp3 .1" title = " Temperature of } valve 1.1 Server - In " valve 1.2 Server - Out " valve 2.1 Server - In " valve 2.2 Server - Out " valve 3.1 Server - In " metric { name = " RACK3temp3 .2" title = " Temperature of valve 3.2 Server - Out " } metric { name = " RACK3nowtemp1 " title = " Actual Temperature 1" } metric { name = " RACK3nowtemp2 " title = " Actual Temperature 2" } metric { name = " RACK3watertemp1 " 139 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 title = " Water Temperature IN " } metric { name = " RACK3watertemp2 " title = " Water Temperature OUT " } metric { name = " RACK3flowrate " title = " Flow Rate " } metric { name = " RACK3fanspeed " title = " Fan speed " } } C.1.6 rackX.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import sys import os import re import time from pysnmp . entity . rfc3413 . oneliner import cmdgen NIPARAMS = {} # crea una lista di descrittori descriptors = list () # OID degli oggetti da interrogare oidDict = { ’ TemperatureSensor ’: ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,1) , 140 17 ’ CoolingCapacity ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,2) , # ’ AlarmMessage ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,3) , # ’ WarningMessage ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,4) , ’ RLCPrpm1 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,5) , ’ RLCPrpm1 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,6) , ’ RLCPrpm2 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,7) , ’ RLCPrpm2 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,8) , ’ RLCPrpm3 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,9) , ’ RLCPrpm3 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,10) , ’ RLCPtemp1 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,13) , ’ RLCPtemp1 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,14) , ’ RLCPtemp2 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,15) , ’ RLCPtemp2 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,16) , ’ RLCPtemp3 .1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,17) , ’ RLCPtemp3 .2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,18) , ’ RLCPActualTemp1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,21) , ’ RLCPActualTemp2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,22) , ’ RLCPWaterTemp1 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,23) , ’ RLCPWaterTemp2 ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,24) , ’ RLCPFlowRate ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,25) , 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 141 37 ’ RLCPFanSpeed ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,26) , ’ RLCPValve ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,27) , ’ RLCPStatus ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,2606 ,4 ,2 ,5 ,5 ,2 ,1 ,5 ,28) , # ’ drsWattsReading ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,2 ,4 ,1 ,1 ,13) , # ’ drsAmpsReading ’ : ,→ (1 ,3 ,6 ,1 ,4 ,1 ,674 ,10892 ,2 ,4 ,1 ,1 ,14) , 38 39 40 41 42 43 44 45 46 47 48 } def get_temSen_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ TemperatureSensor ’) snmpTable = runSnmp ( oidDict , ip , ’ TemperatureSensor ’) string = str ( snmpTable [0][1]) 49 50 51 52 53 54 55 56 57 58 return float ( string ) def get_cool_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ CoolingCapacity ’) snmpTable = runSnmp ( oidDict , ip , ’ CoolingCapacity ’) 59 60 61 62 63 64 65 66 67 68 69 string = str ( snmpTable [0][1]) return float ( string ) def get_rpm11_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) 142 70 # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm1 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm1 .1 ’) string = str ( snmpTable [0][1]) 71 72 73 74 75 76 77 78 79 80 81 return float ( string ) def get_rpm12_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm1 .2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm1 .2 ’) string = str ( snmpTable [0][1]) 82 83 84 85 86 87 88 89 90 91 92 return float ( string ) def get_rpm21_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm2 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm2 .1 ’) string = str ( snmpTable [0][1]) 93 94 95 96 97 98 99 100 101 102 103 return float ( string ) def get_rpm22_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm2 .2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm2 .2 ’) string = str ( snmpTable [0][1]) 104 105 106 143 107 108 109 110 111 112 113 return float ( string ) def get_rpm31_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm3 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm3 .1 ’) string = str ( snmpTable [0][1]) 114 115 116 117 118 119 120 121 122 123 return float ( string ) def get_rpm32_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPrpm3 .2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPrpm3 .2 ’) string = str ( snmpTable [0][1]) 124 125 126 127 128 129 130 131 132 133 return float ( string ) def get_temp11_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp1 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp1 .1 ’) string = str ( snmpTable [0][1]) 134 135 136 137 138 139 140 141 142 143 return float ( string ) def get_temp12_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp1 .2 ’) 144 144 145 146 147 148 149 150 151 152 153 154 snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp1 .2 ’) string = str ( snmpTable [0][1]) return float ( string ) def get_temp21_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp2 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp2 .1 ’) string = str ( snmpTable [0][1]) 155 156 157 158 159 160 161 162 163 164 165 return float ( string ) def get_temp22_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp2 .2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp2 .2 ’) string = str ( snmpTable [0][1]) 166 167 168 169 170 171 172 173 174 175 176 return float ( string ) def get_temp31_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp3 .1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp3 .1 ’) string = str ( snmpTable [0][1]) 177 178 179 180 181 return float ( string ) 145 182 183 184 185 186 187 def get_temp32_RACK3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPtemp3 .2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPtemp3 .2 ’) string = str ( snmpTable [0][1]) 188 189 190 191 192 193 194 195 196 197 198 return float ( string ) def ge t_ no wt em p1_ RA CK 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPActualTemp1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPActualTemp1 ’) string = str ( snmpTable [0][1]) 199 200 201 202 203 204 205 206 207 208 209 return float ( string ) def ge t_ no wt em p2_ RA CK 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPActualTemp2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPActualTemp2 ’) string = str ( snmpTable [0][1]) 210 211 212 213 214 215 216 217 218 219 return float ( string ) def g e t _ w a t e r t e m p 1 _ R A C K 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) 146 220 # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPWaterTemp1 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPWaterTemp1 ’) string = str ( snmpTable [0][1]) 221 222 223 224 225 226 227 228 229 230 231 return float ( string ) def g e t _ w a t e r t e m p 2 _ R A C K 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPWaterTemp2 ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPWaterTemp2 ’) string = str ( snmpTable [0][1]) 232 233 234 235 236 237 238 239 240 241 242 return float ( string ) def ge t_ fl ow ra te_ RA CK 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPFlowRate ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPFlowRate ’) string = str ( snmpTable [0][1]) 243 244 245 246 247 248 249 250 251 252 253 254 return float ( string ) def ge t_ fa ns pe ed_ RA CK 3 ( nomeMetrica ) : global descriptors ip , host = NIPARAMS [ ’ poweredge ’]. split ( ’: ’) # snmpTable = runSnmp ( oidDict , NIPARAMS [ ’ poweredge ’] , ’ ,→ RLCPFanSpeed ’) snmpTable = runSnmp ( oidDict , ip , ’ RLCPFanSpeed ’) string = str ( snmpTable [0][1]) 255 256 147 257 258 259 260 261 262 263 264 return float ( string ) def runSnmp ( oidDict , ip , parametro ) : cmdGen = cmdgen . CommandGenerator () errorIndication , errorStatus , errorIndex , varBinds = ,→ cmdGen . getCmd ( cmdgen . CommunityData ( ’ public ’ , mpModel =0) , cmdgen . U dp Tr an sp or tT ar ge t (( ip , 161) ) , cmdgen . MibVariable ( oidDict [ parametro ]) , ) 265 266 267 268 269 270 271 272 273 274 275 276 277 # Check for errors and print out results if errorIndication : print ( errorIndication ) else : if errorStatus : print ( ’% s at %s ’ % ( errorStatus . prettyPrint () , errorIndex and varBinds [ int ( errorIndex ) -1] or ,→ ’? ’ ) ) else : return varBinds def metric_init ( params ) : global descriptors , Desc_TS_RACK3 , Desc_Cool_RACK3 , ,→ Desc_rpm11_RACK3 , Desc_rpm12_RACK3 , Desc_rpm21_RACK3 , ,→ Desc_rpm22_RACK3 , Desc_rpm31_RACK3 , Desc_rpm32_RACK3 , ,→ Desc_temp11_RACK3 , Desc_temp12_RACK3 , Desc_temp21_RACK3 ,→ , Desc_temp22_RACK3 , Desc_temp31_RACK3 , ,→ Desc_temp32_RACK3 , Desc_NowTemp1_RACK3 , ,→ Desc_NowTemp2_RACK3 , Desc_WaterTemp1_RACK3 , ,→ Desc_WaterTemp2_RACK3 , Desc_FlowRate_RACK3 , ,→ Desc_FanSpeed_RACK3 , _Worker_Thread , Debug , newdict 278 279 280 281 282 283 284 285 286 287 print ( ’[ poweredge ] Received the following parameters ’) print ( params ) 148 for key in params : NIPARAMS [ key ] = params [ key ] for para in params . keys () : if para . startswith ( ’ poweredge ’) : # ipaddr , namehost = params [ para ]. split ( ’: ’) Desc_TS_RACK3 = { ’ name ’ : ’ RACK3temperatureSensor ’ , ’ call_back ’ : get_temSen_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature Sensor ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_Cool_RACK3 = { ’ name ’ : ’ RACK3coolCapacity ’ , ’ call_back ’ : get_cool_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ KWatts ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Cooling Capacity ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_rpm11_RACK3 = { ’ name ’ : ’ RACK3rpm1 .1 ’ , ’ call_back ’ : get_rpm11_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Revolution per minute ’ , ’ slope ’ : ’ both ’ , 149 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 ’ description ’ : ,→ valve 1.1 ’ , ’ groups ’ : ’ spoof_host ’ : } Desc_rpm12_RACK3 = { ’ name ’ : ’ call_back ’ : ’ time_max ’ : ’ value_type ’ : ’ format ’ : ’ units ’ : ’ slope ’ : ’ description ’ : ,→ valve 1.2 ’ , ’ groups ’ : ’ spoof_host ’ : } Desc_rpm21_RACK3 = { ’ name ’ : ’ call_back ’ : ’ time_max ’ : ’ value_type ’ : ’ format ’ : ’ units ’ : ’ slope ’ : ’ description ’ : ,→ valve 2.1 ’ , ’ groups ’ : ’ spoof_host ’ : } Desc_rpm22_RACK3 = { ’ name ’ : ’ call_back ’ : ’ time_max ’ : ’ value_type ’ : ’ format ’ : ’ units ’ : ’ slope ’ : ’ description ’ : ,→ valve 2.2 ’ , ’ Number of Revolution 328 of 329 330 331 332 333 334 335 336 337 338 339 340 ’ Poweredge ’ , params [ para ] , ’ RACK3rpm1 .2 ’ , get_rpm12_RACK3 , 60 , ’ float ’ , ’%0f ’ , ’ Revolution per minute ’ , ’ both ’ , ’ Number of Revolution of 341 342 343 344 345 346 347 348 349 350 351 352 ’ Poweredge ’ , params [ para ] , ’ RACK3rpm2 .1 ’ , get_rpm21_RACK3 , 60 , ’ float ’ , ’%0f ’ , ’ Revolution per minute ’ , ’ both ’ , ’ Number of Revolution of 353 354 355 356 357 358 359 360 361 362 363 364 ’ Poweredge ’ , params [ para ] , ’ RACK3rpm2 .2 ’ , get_rpm22_RACK3 , 60 , ’ float ’ , ’%0f ’ , ’ Revolution per minute ’ , ’ both ’ , ’ Number of Revolution of 150 ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_rpm31_RACK3 = { ’ name ’ : ’ RACK3rpm3 .1 ’ , ’ call_back ’ : get_rpm31_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Revolution per minute ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Number of Revolution of ,→ valve 3.1 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_rpm32_RACK3 = { ’ name ’ : ’ RACK3rpm3 .2 ’ , ’ call_back ’ : get_rpm32_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Revolution per minute ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Number of Revolution of ,→ valve 3.2 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Des c_temp 11_RAC K3 = { ’ name ’ : ’ RACK3temp1 .1 ’ , ’ call_back ’ : get_temp11_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 1.1 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } 151 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 Des c_temp 12_RAC K3 = { ’ name ’ : ’ RACK3temp1 .2 ’ , ’ call_back ’ : get_temp12_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 1.2 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Des c_temp 21_RAC K3 = { ’ name ’ : ’ RACK3temp2 .1 ’ , ’ call_back ’ : get_temp21_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 2.1 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Des c_temp 22_RAC K3 = { ’ name ’ : ’ RACK3temp2 .2 ’ , ’ call_back ’ : get_temp22_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 2.2 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Des c_temp 31_RAC K3 = { ’ name ’ : ’ RACK3temp3 .1 ’ , ’ call_back ’ : get_temp31_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , 152 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 3.1 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Des c_temp 32_RAC K3 = { ’ name ’ : ’ RACK3temp3 .2 ’ , ’ call_back ’ : get_temp32_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Temperature of valve 3.2 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } D e sc _ N ow T e mp 1 _ RA C K 3 = { ’ name ’ : ’ RACK3nowtemp1 ’ , ’ call_back ’ : get_nowtemp1_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Actual Temperature 1 ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } D e sc _ N ow T e mp 2 _ RA C K 3 = { ’ name ’ : ’ RACK3nowtemp2 ’ , ’ call_back ’ : get_nowtemp2_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Actual Temperature 2 ’ , ’ groups ’ : ’ Poweredge ’ , 153 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 ’ spoof_host ’ : params [ para ] , } Desc_WaterTemp1_RACK3 = { ’ name ’ : ’ RACK3watertemp1 ’ , ’ call_back ’ : get_watertemp1_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Water Temperature In ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } Desc_WaterTemp2_RACK3 = { ’ name ’ : ’ RACK3watertemp2 ’ , ’ call_back ’ : get_watertemp2_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ Temperature ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Water Temperature Out ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } D e sc _ F lo w R at e _ RA C K 3 = { ’ name ’ : ’ RACK3flowrate ’ , ’ call_back ’ : get_flowrate_RACK3 , ’ time_max ’ : 60 , ’ value_type ’ : ’ float ’ , ’ format ’ : ’%0f ’ , ’ units ’ : ’ rate ’ , ’ slope ’ : ’ both ’ , ’ description ’ : ’ Flow Rate ’ , ’ groups ’ : ’ Poweredge ’ , ’ spoof_host ’ : params [ para ] , } D e sc _ F an S p ee d _ RA C K 3 = { ’ name ’ : ’ RACK3fanspeed ’ , ’ call_back ’ : get_fanspeed_RACK3 , 154 ’ time_max ’ ’ value_type ’ ’ format ’ ’ units ’ ’ slope ’ ’ description ’ ’ groups ’ ’ spoof_host ’ } : : : : : : : : 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 60 , ’ float ’ , ’%0f ’ , ’ speedfans ’ , ’ both ’ , ’ Fan Speed ’ , ’ Poweredge ’ , params [ para ] , descriptors . append ( Desc_TS_RACK3 ) descriptors . append ( Desc_Cool_RACK3 ) descriptors . append ( Desc_rpm11_RACK3 ) descriptors . append ( Desc_rpm12_RACK3 ) descriptors . append ( Desc_rpm21_RACK3 ) descriptors . append ( Desc_rpm22_RACK3 ) descriptors . append ( Desc_rpm31_RACK3 ) descriptors . append ( Desc_rpm32_RACK3 ) descriptors . append ( Desc _temp1 1_RAC K3 ) descriptors . append ( Desc _temp1 2_RAC K3 ) descriptors . append ( Desc _temp2 1_RAC K3 ) descriptors . append ( Desc _temp2 2_RAC K3 ) descriptors . append ( Desc _temp3 1_RAC K3 ) descriptors . append ( Desc _temp3 2_RAC K3 ) descriptors . append ( De s c _N o w Te m p 1_ R A CK 3 ) descriptors . append ( De s c _N o w Te m p 2_ R A CK 3 ) descriptors . append ( D e s c _ W a t e r T e m p 1 _ R A C K 3 ) descriptors . append ( D e s c _ W a t e r T e m p 2 _ R A C K 3 ) descriptors . append ( De s c _F l o wR a t e_ R A CK 3 ) descriptors . append ( De s c _F a n Sp e e d_ R A CK 3 ) # Ritorna i descrittori return descriptors def metric_cleanup () : ’’’ Clean up the metric module . ’ ’ ’ pass # For CLI Debuging : 155 if __name__ == ’ __main__ ’: params = { ’ poweredge ’ : ’ IndirizzoIPrack : rack3 ’ , } descriptors = metric_init ( params ) while True : for d in descriptors : # ip , namehost = d [ ’ spoof_host ’]. split ( ’: ’) v = d [ ’ call_back ’]( d [ ’ name ’]) print ( ’ value for % s is %u ’ % ( params [ ’ poweredge ,→ ’] , v ) ) print ( ’ Sleeping 5 seconds ’) time . sleep (5) # exit (0) C.2 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 File per la migrazione dati In questa sezione presentiamo gli script utilizzati per migrare i dati dai file rrd a un database mysql. Inoltre ci sar`a uno script per l’analisi dei file di log di torque01 che raccoglier`a tutte le informazioni relative ai job in esecuzione sul Grid. C.2.1 import import import import Analisi log torque01 1 2 3 4 5 6 7 8 9 time datetime MySQLdb os filetoopen ="" user ="" job_name ="" queue ="" 156 cput ="" mem ="" vmem ="" wall_time ="" job_dequeuing ="" start_run ="" deleted ="" startTime = datetime . datetime . now () di ct io na ry _d el et ed ={} dict ionary _jobru n ={} dictionary_exit ={} dictionary_user ={} dictionary_cput ={} dictionary_mem ={} dictionary_vmem ={} d i c t i o n a r y _ d e q u e u i n g ={} dictionary_wall ={} di ct io na ry _j ob na me ={} dictionary_queue ={} dictionary_nodes ={} def r icerca _param etri ( jobid , file ) : global user , job_name , queue , cput , mem , vmem , wall_time , ,→ start_run , job_dequeuing , exit_status , deleted , ,→ nodes , filetoopen , count_parameters , ,→ dictionary_deleted , dictionary_jobrun , ,→ dictionary_exit , dictionary_user , dictionary_cput , ,→ dictionary_mem , dictionary_vmem , ,→ dictionary_dequeuing , dictionary_wall , ,→ dictionary_jobname , dictionary_queue , ,→ dictionary_nodes try : file2 = open ( file ," r ") for line in file2 : if (" Job Queued " in line ) : idnow = line . split (";") [4]. split (".") [0] if ( jobid == idnow ) : 157 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 dictionary_user [ jobid ] = user = line ,→ . split (";") [5]. split (" ,") [1]. ,→ split () [2] di ct io na ry _j ob na me [ jobid ] = job_name ,→ = line . split (";") [5]. split (" ,") ,→ [2]. split () [3] dictionary_queue [ jobid ] = queue = ,→ line . split (";") [5]. split (" ,") ,→ [3]. split () [2] else : dictionary_user [ idnow ]= line . split ,→ (";") [5]. split (" ,") [1]. split () ,→ [2] dictionary_queue [ idnow ]= line . split ,→ (";") [5]. split (" ,") [3]. split () ,→ [2] di ct io na ry _j ob na me [ idnow ]= line . ,→ split (";") [5]. split (" ,") [2]. ,→ split () [3] elif (" Exit_status " in line ) : idnow = line . split (";") [4]. split (".") [0] if ( jobid == idnow ) : dictionary_exit [ jobid ] = exit_status ,→ = line . split (";") [5]. split () [0]. ,→ split ("=") [1] dictionary_cput [ jobid ] = cput = line ,→ . split (";") [5]. split () [1]. split ,→ ("=") [1] dictionary_mem [ jobid ] = mem = line . ,→ split (";") [5]. split () [2]. split ,→ ("=") [1] dictionary_vmem [ jobid ] = vmem = line ,→ . split (";") [5]. split () [3]. split ,→ ("=") [1] dictionary_wall [ jobid ] = wall_time = ,→ line . split (";") [5]. split () [4]. ,→ split ("=") [1] 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 else : 158 dictionary_exit [ idnow ]= line . split ,→ (";") [5]. split () [0]. split ("=") ,→ [1] dictionary_cput [ idnow ]= line . split ,→ (";") [5]. split () [1]. split ("=") ,→ [1] dictionary_mem [ idnow ] = line . split ,→ (";") [5]. split () [2]. split ("=") ,→ [1] dictionary_vmem [ idnow ] = line . split ,→ (";") [5]. split () [3]. split ("=") ,→ [1] dictionary_wall [ idnow ] = line . split ,→ (";") [5]. split () [4]. split ("=") ,→ [1] elif (" dequeuing " in line ) : idnow = line . split (";") [4]. split (".") [0] if ( jobid == idnow ) : d i c t i o n a r y _ d e q u e u i n g [ jobid ]= ,→ job_dequeuing = line . split (";") ,→ [0] else : d i c t i o n a r y _ d e q u e u i n g [ idnow ]= line . ,→ split (";") [0] elif (" Job deleted " in line ) : idnow = line . split (";") [4]. split (".") [0] if ( jobid == idnow ) : di ct io na ry _d el et ed [ jobid ]= deleted = ,→ line . split (";") [0] else : di ct io na ry _d el et ed [ idnow ]= line . ,→ split (";") [0] elif (" Job Run " in line ) : idnow = line . split (";") [4]. split (".") [0] if ( jobid == idnow ) : dict ionar y_jobr un [ jobid ]= start_run = ,→ line . split (";") [0] 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 else : 159 dict ionar y_jobr un [ idnow ]= line . split ,→ (";") [0] if ( exit_status !="271" and exit_status !=" NaN ") : deleted =" NaN " d ict io na ry _d el et ed [ jobid ]= deleted for key in dictionary_exit . keys () : if ( dictionary_exit [ key ] !="271" and ,→ dictionary_exit [ key ] !=" NaN ") : di ct io na ry _d el et ed [ key ]=" NaN " for key2 in di ct io na ry _de le te d . keys () : if ( d ic ti on ar y_ de le te d [ key2 ]!=" NaN ") : try : if ( dictionary_exit [ key2 ]!="271") : pass except KeyError : dictionary_exit [ key2 ]=" NaN " dictionary_cput [ key2 ]= " NaN " dictionary_mem [ key2 ] = " NaN " dictionary_vmem [ key2 ] = " NaN " dictionary_wall [ key2 ] = " NaN " try : if ( di ctiona ry_job run [ key2 ]!=" NaN ") : pass except KeyError : dict ionary _jobru n [ key2 ]=" NaN " file2 . close () if ( job_dequeuing =="") : data = datetime . datetime . strptime ( file ,"% Y % m % d ,→ ") enddata = data + datetime . timedelta ( days =1) enddata2string = enddata . strftime ("% Y % m % d ") count_parameters = count_parameters +1 160 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ric erca_p aramet ri ( jobid , enddata2string ) else : if ( user =="") : user = " NaN " job_name = " NaN " queue =" NaN " dictionary_user [ jobid ]= user di ct io na ry _j ob na me [ jobid ]= job_name dictionary_queue [ jobid ]= queue if ( exit_status =="") : exit_status =" NaN " cput =" NaN " mem =" NaN " vmem =" NaN " wall_time =" NaN " dictionary_exit [ jobid ]= exit_status dictionary_cput [ jobid ]= cput dictionary_mem [ jobid ] = mem dictionary_vmem [ jobid ] = vmem dictionary_wall [ jobid ] = wall_time if ( deleted =="") : deleted =" NaN " di ct io na ry _d el et ed [ jobid ]= deleted if ( start_run =="") : start_run =" NaN " dict ionary _jobru n [ jobid ]= start_run except IOError : if ( count_parameters <30) : data = datetime . datetime . strptime ( file ,"% Y % m % d ,→ ") enddata = data + datetime . timedelta ( days =1) enddata2string = enddata . strftime ("% Y % m % d ") count_parameters = count_parameters +1 ric erca_p aramet ri ( jobid , enddata2string ) else : if ( user =="") : user = " NaN " job_name = " NaN " queue =" NaN " 161 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 dictionary_user [ jobid ]= user di ct io na ry _j ob na me [ jobid ]= job_name dictionary_queue [ jobid ]= queue if ( exit_status =="") : exit_status =" NaN " cput =" NaN " mem =" NaN " vmem =" NaN " wall_time =" NaN " dictionary_exit [ jobid ]= exit_status dictionary_cput [ jobid ]= cput dictionary_mem [ jobid ] = mem dictionary_vmem [ jobid ] = vmem dictionary_wall [ jobid ] = wall_time if ( job_dequeuing == "") : job_dequeuing =" NaN " d i c t i o n a r y _ d e q u e u i n g [ jobid ]= ,→ job_dequeuing if ( deleted =="") : deleted =" NaN " di ct io na ry _d el et ed [ jobid ]= deleted if ( start_run =="") : start_run =" NaN " dict ionary _jobru n [ jobid ]= start_run def takenodes ( jobid , file ) : try : global nodes , count_nodes , dictionary_nodes nodes_local ="" file2 = open (" nodi /"+ file ," r ") for line in file2 : if (" exec_host " in line and line . split ,→ (";") [1] == " S ") : idnow = line . split (";") [2]. split (".") ,→ [0] if ( line . split (";") [3]. split () [9]. ,→ split ("=") [0]==" exec_host ") : if ( jobid == idnow ) : 162 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 nodes = line . split (";") [3]. ,→ split () [9]. split ("=") [1] nodes_local = line . split (";") ,→ [3]. split () [9]. split ("=") ,→ [1] else : dictionary_nodes [ idnow ]= line ,→ . split (";") [3]. split () ,→ [9]. split ("=") [1] else : if ( jobid == idnow ) : nodes = line . split (";") [3]. ,→ split () [10]. split ("=") [1] nodes_local = line . split (";") ,→ [3]. split () [10]. split ,→ ("=") [1] else : dictionary_nodes [ idnow ]= line ,→ . split (";") [3]. split () ,→ [10]. split ("=") [1] if ( nodes_local =="") : nodes =" NaN " dictionary_nodes [ jobid ]= nodes else : dictionary_nodes [ jobid ]= nodes except IOError : nodes =" NaN " dictionary_nodes [ jobid ]= nodes def main () : global user , job_name , queue , cput , mem , vmem , wall_time , start_run ,→ , job_dequeuing , exit_status , deleted , nodes , filetoopen , ,→ count_parameters , dictionary_deleted , dictionary_jobrun , ,→ dictionary_exit , dictionary_user , dictionary_cput , ,→ dictionary_mem , dictionary_vmem , dictionary_dequeuing , ,→ dictionary_wall , dictionary_jobname , dictionary_queue , ,→ dictionary_nodes db = MySQLdb . connect ( host =" localhost " , # your host , usually ,→ localhost 163 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 user =" root " , # your username passwd =" tirocinioNAPPI " , # your password db =" dbjob ") # name of the data base cur = db . cursor () listafile = os . listdir ( ’. ’) listafile . sort () for line2 in listafile : if ( line2 . startswith ("2013") or line2 . startswith ("2014") ,→ ) : startJobTime = datetime . datetime . now () print (" Sto analizzando il file del giorno "+ str ( ,→ datetime . datetime . strptime ( line2 ,"% Y % m % d ") ) . split ,→ () [0]+" in data "+ str ( startJobTime ) ) filetoopen = line2 file = open ( filetoopen ," r ") try : cur . execute (" CREATE TABLE jobtable ( jobid varchar (20) ,→ primary key , jobname varchar (30) , user varchar ,→ (40) , queue varchar (20) , job_enqueuing varchar (40) ,→ , job_dequeuing varchar (40) , job_run varchar (30) , ,→ exit_status varchar (10) , cput varchar (30) , mem ,→ varchar (30) , vmem varchar (30) , wall_time varchar ,→ (30) , deleted varchar (30) , nodes varchar (6000) ) ") ; except MySQLdb . OperationalError : print (" Tabella esistente ") o =0 for line in file : # se metto enqueuing potrebbe capitare una situazione ,→ in cui jobrun e maggiore dell enqueing # questo perch ci sono casi di requeuing , per ovviare ,→ a cio basta mettere ; enqueuing if "; enqueuing " in line : try : startANALISI = datetime . datetime . now () job_enqueuing = line . split (";") [0] 164 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 jobid = line . split (";") [4]. split (".") [0] try : user = dictionary_user [ jobid ] job_name = d ic ti ona ry _j ob na me [ jobid ] queue = dictionary_queue [ jobid ] job_dequeuing = d i c t i o n a r y _ d e q u e u i n g [ jobid ] start_run = dicti onary_ jobrun [ jobid ] exit_status = dictionary_exit [ jobid ] cput = dictionary_cput [ jobid ] mem = dictionary_mem [ jobid ] vmem = dictionary_vmem [ jobid ] wall_time = dictionary_wall [ jobid ] deleted = di ct ion ar y_ de le te d [ jobid ] except KeyError : count_parameters =0 ric erca_p aramet ri ( jobid , filetoopen ) if ( start_run !=" NaN " and start_run !="") : passaggio = start_run . split () [0] passaggio2 = datetime . datetime . strptime ( ,→ passaggio ,"% m /% d /% Y ") . strftime ("% Y % m % d ") try : nodes = dictionary_nodes [ jobid ] except KeyError : count_nodes =0 takenodes ( jobid , passaggio2 ) else : nodes =" NaN " dictionary_nodes [ jobid ]= nodes # print (" Fine Analisi "+ str ( datetime . datetime . now ,→ () - startANALISI ) +" del job "+ jobid ) cur . execute (" INSERT INTO jobtable ( jobid ) VALUES ,→ ( ’"+ jobid +" ’) ") 165 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 # cur . execute (" INSERT INTO jobtable ( jobid , jobname ,→ , user , queue , job_enqueuing , job_dequeuing , ,→ job_run , exit_status , cput , mem , vmem , wall_time , ,→ deleted , nodes ) VALUES ( ’"+ jobid +" ’ , ’"+ ,→ job_name +" ’ , ’"+ user +" ’ , ’"+ queue +" ’ , ’"+ ,→ job_enqueuing +" ’ , ’"+ job_dequeuing +" ’ , ’"+ ,→ start_run +" ’ , ’"+ exit_status +" ’ , ’"+ cput ,→ +" ’ , ’"+ mem +" ’ , ’"+ vmem +" ’ , ’"+ wall_time +" ’ , ’"+ ,→ deleted +" ’ , ’"+ nodes +" ’) ") cur . execute (" UPDATE jobtable SET jobname = ’"+ ,→ job_name +" ’ , user = ’"+ user +" ’ , queue = ’"+ queue ,→ +" ’ , job_enqueuing = ’"+ job_enqueuing +" ’ , ,→ job_dequeuing = ’"+ job_dequeuing +" ’ , job_run ,→ = ’"+ start_run +" ’ , exit_status = ’"+ exit_status ,→ +" ’ , cput = ’"+ cput +" ’ , mem = ’"+ mem +" ’ , vmem = ’"+ ,→ vmem +" ’ , wall_time = ’"+ wall_time +" ’ , deleted ,→ = ’"+ deleted +" ’ , nodes = ’"+ nodes +" ’ WHERE jobid ,→ = ’"+ jobid +" ’") user ="" job_name ="" queue ="" exit_status ="" cput ="" mem ="" vmem ="" wall_time ="" job_dequeuing ="" start_run ="" deleted ="" except MySQLdb . IntegrityError : cur . execute (" UPDATE jobtable SET jobname = ’"+ ,→ job_name +" ’ , user = ’"+ user +" ’ , queue = ’"+ queue ,→ +" ’ , job_enqueuing = ’"+ job_enqueuing +" ’ , ,→ job_dequeuing = ’"+ job_dequeuing +" ’ , job_run = ’"+ ,→ start_run +" ’ , exit_status = ’"+ exit_status +" ’ , ,→ cput = ’"+ cput +" ’ , mem = ’"+ mem +" ’ , vmem = ’"+ vmem ,→ +" ’ , wall_time = ’"+ wall_time +" ’ , deleted = ’"+ ,→ deleted +" ’ , nodes = ’"+ nodes +" ’ WHERE jobid = ’"+ 166 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 ,→ jobid +" ’") user ="" job_name ="" queue ="" exit_status ="" cput ="" mem ="" vmem ="" wall_time ="" job_dequeuing ="" start_run ="" deleted ="" 310 311 312 313 314 315 316 317 318 319 320 321 322 print (" Tempo utilizzato per analizzare il file del "+ ,→ str ( datetime . datetime . strptime ( line2 ,"% Y % m % d ") ) . ,→ split () [0]) print ( datetime . datetime . now () - startJobTime ) 323 print 324 ,→ ( " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ,→ db . commit () 325 326 print ( len ( dictionary_user ) ) 327 print ( len ( d i c t i o n a r y _ d e q u e u i n g ) ) 328 file . close () 329 cur . close () 330 db . close () 331 332 print (" Tempo esecuzione :") 333 print ( datetime . datetime . now () - startTime ) 334 335 if __name__ == ’ __main__ ’: 336 main () 337 C.2.2 Migrazione da RRA a mysql I file rrd di ogni singolo nodo sono raccolti in una cartella col nome di quest’ultimo. A loro volta sono raccolte da una cartella che portar`a il nome del cluster di cui fanno parte. 167 copia.sh Copia in tutti le cartelle dei nodi il file avvio.sh e migrazione.py e avvia lo scipt avvio.sh in ogni cartella. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #!/ bin / sh listDir = ‘ ls -d */ ‘ # count =0 for line in $listDir do # count = count +1 # echo ’ Analisi della cartella ’ $line cp migrazione . py $line cp avvio . sh $line cd $line ./ avvio . sh cd .. wait done avvio.sh Il file avvio.sh crea i file xml di ogni file rrd e invoca lo script python migrazione.py 1 2 3 4 5 6 7 8 9 10 11 #!/ bin / sh RRD = ‘ ls -a | grep rrd ‘ rm * xml for line in $RRD do prova =( $ ( echo $ { line %. rrd }) ) 168 12 13 14 15 16 17 18 rrdtool dump $line >> $ { prova [0]}". xml " done rm parsingfile . txt ls -a | grep xml >> parsingfile . txt python migrazione . py migrazione.py Questo file si preoccupa di fare il parsing del file xml e di migrare tutto in un database mysql. 1 2 3 4 5 6 7 8 9 from xml . dom import minidom import xml . dom import MySQLdb from datetime import datetime from lxml import etree import time import os startTime = datetime . now () db = MySQLdb . connect ( host =" localhost " , # your host , usually ,→ localhost user =" root " , # your username passwd ="" , # your password db =" python ") # name of the data base 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 host = os . getcwd () stringahost = str ( host ) lista = stringahost . split ("/") prova = open (" parsingfile . txt " ," r ") filexml = list () for line in prova : filexml . append ( line . rstrip () ) prova . close () nomeHOST =( lista [ len ( lista ) -1]) 169 try : filexml . remove ( ’. xml ’) except ValueError : pass conto =0 size = len ( filexml ) cur = db . cursor () print (" Iniziata analisi dell ’ host "+ nomeHOST +" all ’ istante : ,→ "+ str ( datetime . now () ) ) nomeMODIFIED = nomeHOST if ("." in nomeMODIFIED ) : nomeMODIFIED = nomeMODIFIED . replace ("." ," _ ") print nomeMODIFIED try : cur . execute (" CREATE TABLE "+ nomeMODIFIED +"( data varchar (30) ,→ primary key ) ") except MySQLdb . OperationalError : print (" Tabella esistente ") while conto < size : start = datetime . now () Commenti = list () Valori = list () if ( filexml [ conto ]. split (".") [1]==" xml ") : nomeColonna = filexml [ conto ]. split (".") [0] else : nomeColonna =( filexml [ conto ]. split (".") [0]+ filexml [ ,→ conto ]. split (".") [1]) try : 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 if (" -" in nomeColonna ) : nomeColonna = nomeColonna . replace (" -" ," _ ") cur . execute (" ALTER TABLE "+ nomeMODIFIED +" ADD "+ ,→ nomeColonna +" varchar (30) ") except MySQLdb . OperationalError : 63 64 170 pass path = os . path . dirname ( os . path . abspath ( __file__ ) ) xmldoc = etree . parse ( path + ’/ ’+ filexml [ conto ]) os . system ( ’ rm dimensioneFile . txt ’) os . system ( ’ ls - sh ’+ filexml [ conto ]+ ’ >> dimensioneFile . txt ,→ ’) 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 S = open ( ’ dimensioneFile . txt ’ , ’r ’) size2 = S . readline () . split () [0] data = xmldoc . getroot () prova1 = data [9] prova2 = prova1 . find (" database ") for child in prova2 : if child . tag is etree . Comment : comment = child . text stringa = comment . split ("/") [0] stringa2 = stringa . split () stringa3 = stringa2 [0]+" "+ stringa2 [1] Commenti . append ( stringa3 ) else : value = child . find ( ’v ’) . text value = value [1:] Valori . append ( value ) indice =0 while indice < len ( Commenti ) : try : cur . execute (" INSERT INTO "+ nomeMODIFIED +"( data ,"+ ,→ nomeColonna +") VALUES ( ’"+ Commenti [ indice ,→ ]+" ’ , ’"+ Valori [ indice ]+" ’) ;") except MySQLdb . IntegrityError : cur . execute (" UPDATE "+ nomeMODIFIED +" SET "+ ,→ nomeColonna +"= ’"+ Valori [ indice ]+" ’ WHERE data ,→ = ’"+ Commenti [ indice ]+" ’") 171 98 99 100 101 102 103 104 105 106 107 108 109 110 indice = indice +1 db . commit () conto = conto +1 cur . close () db . close () print (" Tempo utilizzato per l ’ analisi dell ’ host "+ nomeHOST +": ,→ "+ str ( datetime . now () - startTime ) ) print 111 ,→ ( " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * " ) ,→ 172 Bibliografia [1] M. Cinque, D. Cotroneo, F. Frattini, and S. Russo Cost-Benefit Analysis of Virtualizing Batch Systems: Performance-Energy-Dependability Tradeoffs, Proc. of UCC ’13, IEEE, 2013. [2] Anjali D.Meshram A.S.Sambare S.D.Zade Fault Tolerance Model for Reliable Cloud Computing, IJRITCC,2013 [3] Jayant Baliga, Robert W. A. Ayre, Kerry Hinton, and Rodney S. Tucker, Green Cloud Computing: Balancing Energy in Processing,Storage, and Transport, Proceedings of the IEEE,2011 [4] Shin-ichi Kuribayashi Improving Quality of Service and Reducing Power Consumption with WAN accelerator in Cloud Computing Environments, IJCNC,2013 [5] Grid computing, P Plaszczak, R Wellner, 2005 [6] IBM Solutions Grid for Business Partners: Helping IBM Business Partners to Grid-enable applications for the next phase of e-business on demand [7] The Grid Caf`e , The place for everybody to learn about grid computing . CERN. Retrieved December 3,2008 [8] M. Dias de Assuncao, J.-P. Gelas, L. Lef`evre and A.-C. Orgerie,The Green Grid5000: Instrumenting a Grid with Energy Sensors, INGRID 2010, May 2010 [9] A. Iosup et al.,How are Real Grids Used? The Analysis of Four Grid Traces and Its Implications Grid Computing, 2007 173 [10] Paul Townend and Jie Xu, Fault Tolerance within a Grid Environment, In Proceedings of the UK e-Science All Hands Meeting 2003 [11] Peter Mell Timothy Grance The NIST Definition of Cloud Computing 2011 [12] http://www.andreabeggi.net/2007/03/22/server-consolidation-tramitevirtualizzazione/ [13] Ian Foster, Yong Zha, Ioan Raicu, Shiyong Lu, Cloud Computing and Grid Computing 360-Degree Compared 2008 [14] http://jncc.defra.gov.uk/page-2268 [15] http://www.cloudtalk.it/tipologie-di-virtualizzazione-e-differenzerispetto-al-cloud-compting/ [16] http://ganglia.sourceforge.net/ [17] http://www.wikipedia.org [18] Matt Massie, Bernard Li, Brad Nicholes, Vladimir Vuksan, Monitoring with Ganglia [19] http://www.mirantis.com/blog/openstack-networking-flatmanagerand-flatdhcpmanager/ [20] http://www.solinea.com/2013/06/15/openstack-grizzly-architecturerevisited/ [21] http://www.linuxforu.com/2011/06/ganglia-for-monitoring-clusters/ [22] http://linuxdrops.com/install-ganglia-monitoring-system-on-centosrhel/ [23] http://www.openstack.org/ [24] http://sourceforge.net/apps/trac/ganglia/wiki/Ganglia%203.1.x%20 Installation%20and%20Configuration 174 Ringraziamenti A fine di questo ciclo universitario e di questa esperienza voglio ringraziare in primis il prof. Marcello Cinque per l’opportunit`a che mi ha dato con questa tesi. Sono cresciuto molto sia come Ingegnere che come Uomo. Inoltre vorrei ringraziare enormemente l’Ing. Flavio Frattini per la costante presenza,i suoi consigli e la sua disponibilit`a, che ha saputo motivarmi quando ce ne era bisogno. Un sincero ringraziamento anche al nucleo operativo di S.Co.P.E. Davanti a tutti Davide che in alcune occasioni mi ha tirato fuori da grossi problemi con i suoi consigli e la sua esperienza, un grazie anche alle Dott.sse Vania Boccia e Luisa Carracciuolo che mi hanno aiutato nella gestione del Grid. Un grazie di cuore ai miei genitori che in questa anni non mi hanno mai fatto pressioni di nessun tipo e mi sono sempre stati vicini, vi voglio un gran bene. A Martina che `e riuscita a sopportarmi in tutti questi mesi e che non smetter`o mai di ringraziare per come mi `e stata vicina e per quello che ha fatto per me. Non lo dimenticher`o mai! Grazie amore :) Agli amici di una vita e a quelli di ”serie A” con cui ho passato tante serate spensierate, neanche la distanza(grande o piccola che sia) ci far`a perdere. A Tonino e Nello compagni di avventure in questi anni universitari, tutto `e stato pi` u facile affrontandolo insieme. Al BEST, iniziato a frequentare troppo tardi ma che mi ha regalato esperienze intense e in particolare ad Alberto e Milly compagni di panino. A tutti quelli che ho incontrato in questi anni e che mi hanno lasciato qualcosa. GRAZIE! 175
© Copyright 2024 Paperzz