Grid on Cloud : Implementazione e Monitoraggio

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