3. Configurazione dei dati

È giunto il momento di dire a Nagios cosa controllare. Dobbiamo quindi dirgli:

Tutte queste informazioni sono rappresentate per mezzo di oggetti, definiti da un insieme di dichiarazioni "define", racchiuse fra parentesi graffe e contenenti un numero variabile di direttive, una per riga, in forma chiave/valore. Le chiavi sono separate dai valori per mezzo di spazi ed è possibile specificare più valori separandoli con delle virgole; l'indentazione, all'interno delle dichiarazioni, è ammessa.

Ricapitolando, la sintassi della dichiarazione di un oggetto può essere rappresentata così:

define oggetto {
    chiave-1     valore-1
    chiave-2     valore-2,valore-3,...
    [...]
    chiave-n     valore-n
}

Le definizioni degli oggetti possono essere suddivise in un numero arbitrario di file: basta ricordarsi di elencarli tutti nel file di configurazione principale usando le direttive cfg_file e/o cfg_dir.

3.1 Definizione dei timeperiod

La dichiarazione timeperiod consente di specificare, per ogni giorno della settimana, uno o più intervalli di tempo in cui eseguire determinati controlli e/o notificare determinate persone. Gli intervalli di tempo non possono superare la mezzanotte e i giorni esclusi vanno semplicemente saltati.

In questo esempio, tutte le definizioni di timeperiod sono raggruppate in un file chiamato timeperiods.cfg all'interno della directory /var/www/etc/nagios/.

/var/www/etc/nagios/timeperiods.cfg
# La seguente definizione di timeperiod comprende le normali ore lavorative. Le
# direttive 'timeperiod_name' e 'alias' sono obbligatorie. Si noti che i giorni
# del weekend sono semplicemente omessi
define timeperiod {
    timeperiod_name    workhours
    alias              Work Hours
    monday             09:00-18:00
    tuesday            09:00-18:00
    wednesday          09:00-18:00
    thursday           09:00-18:00
    friday             09:00-18:00
}

# Il seguente timeperiod comprende tutto il tempo fuori dalle normali ore
# lavorative. Gli intervalli di tempo fra le 18 e le 9 devono essere spezzati
# in due intervalli per non essere a cavallo di mezzanotte
define timeperiod {
    timeperiod_name    nonworkhours
    alias              Non-Work Hours
    sunday             00:00-24:00
    monday             00:00-09:00,18:00-24:00
    tuesday            00:00-09:00,18:00-24:00
    wednesday          00:00-09:00,18:00-24:00
    thursday           00:00-09:00,18:00-24:00
    friday             00:00-09:00,18:00-24:00
    saturday           00:00-24:00
}

# La maggior parte dei controlli girera' continuamente
define timeperiod {
    timeperiod_name    always
    alias              Every Hour Every Day
    sunday             00:00-24:00
    monday             00:00-24:00
    tuesday            00:00-24:00
    wednesday          00:00-24:00
    thursday           00:00-24:00
    friday             00:00-24:00
    saturday           00:00-24:00
}

# Il timeperiod perfetto per quando non si vuole essere seccati dalle notifiche
# (ad es. durante i test)
define timeperiod {
    timeperiod_name    never
    alias              No Time is a Good Time
}

# Alcune eccezioni alle normali schedulazioni settimanali (vd. la documentazione
# per ulteriori esempi)
define timeperiod {
    timeperiod_name    exceptions
    alias              Some random dates
    2008-12-15         00:00-24:00        ; 15 Dicembre 2008
    friday 3           00:00-24:00        ; Terzo venerdì di ogni mese
    february -1        00:00-24:00        ; Ultimo giorno di Febbraio ogni anno
    march 20 - june 21 00:00-24:00        ; Primavera
    day 1 - 15         00:00-24:00        ; Prima metà di ogni mese
    2008-01-01 / 7     00:00-24:00        ; Ogni 7 giorni a partire dal 1/1/2008
}

3.2 Definizione dei comandi

Il passo successivo è dire a Nagios come effettuare i vari controlli e le notifiche; lo facciamo definendo una serie di oggetti command che specificano i comandi che Nagios dovrà eseguire.

Le definizioni dei comandi sono formate da coppie di nomi e righe di comando (entrambi obbligatori) e possono contenere delle macro. Come detto prima, le macro sono variabili, racchiuse fra "$", che verranno sostituite con il rispettivo valore subito prima dell'esecuzione del comando; le macro consentono di mantenere le definizioni dei comandi generiche e leggibili. Un piccolo esempio renderà tutto più chiaro.

Si supponga di voler monitorare un web server con indirizzo IP "1.2.3.4"; si potrebbe definire un comando come il seguente:

define command {
    command_name    check-http
    command_line    /usr/local/libexec/nagios/check_http -I 1.2.3.4
}

Questa definizione è corretta e raggiungerà perfettamente il suo scopo. Ma cosa succede se si decide in un secondo tempo di monitorare un altro server web? Sarebbe una buona idea definire un nuovo comando, quasi identico? Pare decisamente più efficiente approfittare delle macro e scrivere un comando generico come:

define command {
    command_name    check-http
    command_line    $USER1$/check_http -I $HOSTADDRESS$
}

e lasciare a Nagios la responsbilità di sostituire la macro $HOSTADDRESS$ con l'indirizzo IP corretto, ricavato dalla definizione dell'host (vd. sotto). Come si ricorderà dal capitolo precedente, la macro $USER1$ contiene il percorso della directory dei plugin.

E ora complichiamo ancora un po' le cose! Cosa succede se vogliamo che Nagios verifichi la disponibilità di una certa URL su ogni server web? Questa URL può variare da server a server, quindi ora dobbiamo definire un comando che sia ancora generico, ma allo stesso tempo specifico per ogni server! Può sembrare contraddittorio, eppure, ancora una volta, Nagios risolve questo problema per mezzo delle macro: infatti le macro $ARGn$ (dove n è un numero fra 1 e 32 compresi) fungono da segnaposto per argomenti (specifici per ogni servizio) che verranno indicati più avanti, all'interno delle definizioni dei servizi (vd. sotto per ulteriori dettagli). Quindi, la definizione del comando diventerebbe:

define command {
    command_name    check-http
    command_line    $USER1$/check_http -I $HOSTADDRESS$ -u $ARG1$
}

Oltre a quelle appena viste, Nagios fornisce parecchie altre macro utilissime; la documentazione le elenca tutte, insieme al loro contesto di validità. Di seguito, un esempio di definizioni di comandi.

/var/www/etc/nagios/commands.cfg
################################################################################
# Comandi di notifica                                                          #
# Non ci sono plugin di notifica standard; quindi i comandi di notifica sono   #
# generalmente script personali o semplici righe di comando                    #
################################################################################
define command {
    command_name    host-notify-by-email
    command_line    $USER1$/host_notify_by_email.sh $CONTACTEMAIL$
}

define command {
    command_name    notify-by-email
    command_line    $USER1$/notify_by_email.sh $CONTACTEMAIL$
}

define command {
    command_name    host-notify-by-SMS
    command_line    /usr/local/bin/sendsms $ADDRESS1$ "Nagios: Host $HOSTNAME$ ($HOSTADDRESS$)is in state: $HOSTSTATE$"
}

define command {
    command_name    notify-by-SMS
    command_line    /usr/local/bin/sendsms $ADDRESS1$ "Nagios: Service $SERVICEDESC$ on $HOSTALIAS$ is in state: $SERVICESTATE$"
}

################################################################################
# Comandi di controllo                                                         #
# I plugin ufficiali di Nagios dovrebbero soddisfare le esigenze piu' comuni   #
# per il monitoraggio di host e servizi. Comunque, se non dovessero bastare,   #
# vedremo a breve come scrivere plugin personali                               #
################################################################################
define command {
    command_name    check-host-alive
    command_line    $USER1$/check_ping -H $HOSTADDRESS$ -w 3000.0,80% -c 5000.0,100% -p 1
}

define command {
    command_name    check-ssh
    command_line    $USER1$/check_ssh $HOSTADDRESS$
}

define command {
    command_name    check-http
    command_line    $USER1$/check_http -I $HOSTADDRESS$ -u $ARG1$
}

define command {
    command_name    check-smtp
    command_line    $USER1$/check_smtp -H $HOSTADDRESS$
}

define command {
    command_name    check-imap
    command_line    $USER1$/check_imap -H $HOSTADDRESS$
}

define command {
    command_name    check-dns
    command_line    $USER1$/check_dns -s $HOSTADDRESS$ -H $ARG1$ -a $ARG2$
}

define command {
    command_name    check-mysql
    command_line    $USER1$/check_mysql -H $HOSTADDRESS -u $USER2$ -p $USER3$
}

[...]

3.3 Definizione dei contatti

Gli oggetti contact consentono di specificare le persone che devono essere avvisate automaticamente al verificarsi delle condizioni di allarme. I contatti vengono prima definiti individualmente e poi raggruppati in oggetti contactgroup, per semplificarne la gestione.

Per la prima volta, nelle prossime definizioni, si farà riferimento a oggetti definiti in precedenza. In particolare, i valori delle direttive host_notification_period e service_notification_period devono essere oggetti timeperiod; e i valori delle direttive host_notification_command e service_notification_command devono essere oggetti command.

/var/www/etc/nagios/contacts.cfg
define contact {
# Nome breve per identificare il contatto
    contact_name                    john
# Nome esteso o descrizione
    alias                           John Doe

# Abilita le notifiche per questo contatto
    host_notifications_enabled      1
    service_notifications_enabled   1

# Timeperiod durante i quali il contatto puo' essere notificato in caso di
# problemi o di recovery di un host o un servizio
    host_notification_period        always
    service_notification_period     always

# Stati degli host per i quali questo contatto vuole essere notificato
# (d=down, u=unreachable, r=recovery, f=flapping, n=none)
    host_notification_options       d,u,r

# Stati dei servizi per i quali questo contatto vuole essere notificato
# (w=warning, c=critical, u=unknown, r=recovery, f=flapping, n=none)
    service_notification_options    w,u,c,r

# Comandi usati per notificare questo contatto in caso di problemi o recovery
# di host o servizi
    host_notification_commands      host-notify-by-email,host-notify-by-SMS
    service_notification_commands   notify-by-email,notify-by-SMS

# Indirizzo email di questo contatto
    email                           jdoe@kernel-panic.it

# Nagios fornisce 6 direttive 'address' (da address1 a address6) per
# specificare altri 'indirizzi' per il contatto (ad es. il numero di cellulare
# per le notifiche via SMS)
    address1                        xxx-xxx-xxxx

# Consenti a questo contatto di passare comandi esterni a Nagios dai CGI
    can_submit_commands             1
}

# Il prossimo contatto e' diviso in due, per consentire diverse opzioni di
# notifica a seconda del timeperiod
define contact {
    contact_name                    danix@work
    alias                           Daniele Mazzocchio
    host_notifications_enabled      1
    service_notifications_enabled   1
    host_notification_period        workhours
    service_notification_period     workhours
    host_notification_options       d,u,r
    service_notification_options    w,u,c,r
    host_notification_commands      host-notify-by-email
    service_notification_commands   notify-by-email
    email                           danix@kernel-panic.it
    can_submit_commands             1
}

define contact {
    contact_name                    danix@home
    alias                           Daniele Mazzocchio
    host_notifications_enabled      1
    service_notifications_enabled   1
    host_notification_period        nonworkhours
    service_notification_period     nonworkhours
    host_notification_options       d,u
    service_notification_options    c
    host_notification_commands      host-notify-by-email,host-notify-by-SMS
    service_notification_commands   notify-by-email,notify-by-SMS
    email                           danix@kernel-panic.it
    address1                        xxx-xxx-xxxx
    can_submit_commands             1
}

[...]

# Tutti i contatti amministrativi sono raggruppati nel contactgroup 'Admins'
define contactgroup {
    contactgroup_name               Admins
    alias                           Nagios Administrators
    members                         danix@work,danix@home,john
}

[...]

3.4 Definizione degli host

Siamo finalmente giunti a uno degli aspetti più importanti della configurazione di Nagios; la definizione degli host (server, workstation, dispositivi di rete, ecc.) che vogliamo monitorare. Questo ci porterà a parlare di una delle funzionalità più potenti della configurazione di Nagios: l'ereditarietà degli oggetti. Si noti che, anche se ne parliamo ora per la prima volta, l'ereditarietà si applica a tutti gli oggetti di Nagios; tuttavia, è proprio nella definizione di host e servizi che offre i maggiori vantaggi.

In effetti, configurare un host richiede l'impostazione di un sacco di parametri; e il valore di questi parametri sarà normalmente lo stesso per la maggior parte degli host. Senza ereditarietà, questo significherebbe sprecare un sacco di tempo scrivendo e riscrivendo gli stessi parametri per poi ritrovarsi dei file di configurazione confusi, sovrappeso e ingestibili.

Ma per fortuna Nagios è abbastanza furbo da risparmiarci un sacco di fatica, consentendo di definire speciali oggetti template, le cui proprietà possono essere "ereditate" da altri oggetti senza doverle riscrivere. Di seguito un breve esempio di come viene creato un template:

define host {
    name                            generic-host-template  # Nome del template

    check_command                   check-host-alive
    check_period                    always
    max_check_attempts              5
    notification_options            d,u,r

    register                        0                      # Non registrarlo!
}

Come si vede, la definizione di un template è praticamente identica alla definizione di un normale oggetto. Le uniche differenze sono:

Per creare un host effettivo a partire da un template, occorre semplicemente specificare il nome del template come valore della direttiva use e assicurarsi che tutti i campi obbligatori siano ereditati o impostati esplicitamente:

define host {
    host_name                       hostname
    use                             generic-host-template
    alias                           alias
    address                         x.x.x.x
}

Bene, adesso passiamo dalla teoria alla pratica e definiamo un paio di template per i nostri server. Si noti che il secondo eredita dal primo; Nagios consente infatti più livelli di template.

/var/www/etc/nagios/generic-hosts.cfg
# Questo e' il template per tutti gli host in LAN
define host {
# Nome del template
    name                            generic-lan-host

# Comando da usare per controllare lo stato dell'host
    check_command                   check-host-alive

# Contactgroup da notificare in caso di problemi (o recovery) di questo host
    contact_groups                  Admins

# Abilita i check attivi
    active_checks_enabled           1
# Timeperiod durante il quale effettuare i check attivi per questo host
    check_period                    always
# Numero di volte che Nagios ripetera' un controllo che ritorna uno stato non OK
    max_check_attempts              3

# Abilita il gestore degli eventi
    event_handler_enabled           1

# Abilita il calcolo dei dati di performance
    process_perf_data               1

# Abilita il salvataggio delle informazioni di stato fra restart del programma
    retain_status_information       1
# Abilita il salvataggio delle informazioni non di stato fra restart del programma
    retain_nonstatus_information    1

# Abilita le notifiche
    notifications_enabled           1

# Intervallo di tempo (in minuti) fra notifiche consecutive che il server e'
# ancora giu' o non raggiungibile
    notification_interval           120
# Timeperiod durante il quale le notifiche riguardanti questo host vanno spedite
    notification_period             always
# Stati dell'host per i quali le notifiche dovrebbero essere spedite (d=down,
# u=unreachable, r=recovery, f=flapping, n=none)
    notification_options            d,u,r

# Non registrare questa definizione: e' solo un template, non un host effettivo
    register                        0
}

# GLi host in DMZ ereditano tutti gli attributi dal generic-lan-host per mezzo
# della direttiva 'use'. L'unica differenza e' che Nagios deve passare dai
# firewall interni (CARP) per raggiungere i server in DMZ, rendendo quindi
# necessaria la direttiva 'parents'
define host {
    name                            generic-dmz-host

# La direttiva 'use' specifica il nome di un oggetto template da cui questo host
# eredita le proprieta'
    use                             generic-lan-host

# Questa direttiva specifica gli host lungo la strada fra il server di
# monitoraggio e l'host remoto (maggiori dettagli qui)
    parents                         fw-int

# Anche questo e' un template
    register                        0
}

Ora possiamo approfittare dei nostri template per definire gli host in poche righe.

/var/www/etc/nagios/hosts/servers.cfg
# Configurazione per l'host dns1.lan.kernel-panic.it
define host {
    use                             generic-lan-host
    host_name                       dns1
    alias                           LAN primary master name server
    address                         172.16.0.161

# Informazioni estese (totalmente facoltative)
    notes                           This is the internal primary master name server (Bind 9.3.4)
# URL con maggiori informazioni su questo host
    notes_url                       http://www.kernel-panic.it/openbsd/dns/
# Immagine associata a questo host nello status CGI; le immagini devono essere in
# /var/www/nagios/images/logos/
    icon_image                      dns.png
# Stringa usata nel tag 'alt' della icon_image
    icon_image_alt                  [dns]
# Immagine associata a questo host nel CGI statusmap
    statusmap_image                 dns.gd2
}

# Configurazione per l'host mail.kernel-panic.it
define host {
    use                             generic-dmz-host
    host_name                       mail
    alias                           Mail server
    address                         172.16.240.150
    notes                           This is the Postfix mail server (with IMAP(S) and web access)
    notes_url                       http://www.kernel-panic.it/openbsd/mail/
    icon_image                      mail.png
    icon_image_alt                  [Mail]
    statusmap_image                 mail.gd2
}

# Configurazione per l'host proxy.kernel-panic.it
define host {
    use                             generic-dmz-host
    host_name                       proxy
    alias                           Proxy server
    address                         172.16.240.151
    notes                           This is the Squid proxy server
    notes_url                       http://www.kernel-panic.it/openbsd/proxy/
    icon_image                      proxy.png
    icon_image_alt                  [Proxy]
    statusmap_image                 proxy.gd2
}

[...]
/var/www/etc/nagios/hosts/firewalls.cfg
# Configurazione per l'host fw-int.kernel-panic.it
define host {
    use                             generic-lan-host
    host_name                       fw-int
    alias                           Internal firewalls' CARP address
    address                         172.16.0.202
    notes                           Virtual CARP address of the internal firewalls
    notes_url                       http://www.kernel-panic.it/openbsd/carp/
    icon_image                      fw.png
    icon_image_alt                  [FW]
    statusmap_image                 fw.gd2
}

# Configurazione per l'host mickey.kernel-panic.it
define host {
    use                             generic-lan-host
    host_name                       mickey
    alias                           Internal Firewall #1
    address                         172.16.0.200
    notes                           Internal firewall (first node of a two-nodes CARP cluster)
    notes_url                       http://www.kernel-panic.it/openbsd/carp/
    icon_image                      fw.png
    icon_image_alt                  [FW]
    statusmap_image                 fw.gd2
}

[...]

Gli host possono essere raggruppati con la dichiarazione hostgroup, che non ha effetto sul monitoraggio, ma semplicemente consente di visualizzare gli host a gruppi nei CGI.

/var/www/etc/nagios/hosts/hostgroups.cfg
# Server DNS
define hostgroup {
    hostgroup_name                  DNS
    alias                           Domain Name Servers
    members                         dns1,dns2,dns3,dns4
    notes                           Our internal Domain Name Servers, running Bind 9.4.2-P2
}

# Firewall
define hostgroup {
    hostgroup_name                  firewalls
    alias                           CARP Firewalls
    members                         mickey,minnie,donald,daisy,fw-int,fw-ext
    notes                           Our CARP-enabled firewalls (both virtual and physical addresses)
}

# Server web
define hostgroup {
    hostgroup_name                  WWW
    alias                           Web Servers
    members                         www1,www2
    notes                           Our corporate web servers, running Apache 1.3
}

3.5 Definizione dei servizi

La configurare dei servizi da monitorare è molto simile a quella degli host: l'ereditarietà può farci risparmiare un sacco di tempo ed è possibile raggruppare i servizi con la dichiarazione (facoltativa) servicegroup. Di seguito la definizione del nostro servizio template:

/var/www/etc/nagios/generic-services.cfg
define service {
# Nome del template
    name                            generic-service

# Normalmente i servizi non sono volatili
    is_volatile                     0

# Contactgroup da notificare in caso di problemi (o recovery) di questo servizio
    contact_groups                  Admins

# Abilita i check attivi
    active_checks_enabled           1
# Timeperiod durante il quale effettuare i check attivi per questo servizio
    check_period                    always
# Intervallo di tempo (in minuti) fra check "regolari", cioe' check che
# avvengono quando il servizio e' in stato OK o quando e' in stato non OK ma
# e' gia' stato controllato max_check_attempts volte
    normal_check_interval           5
# Intervallo di tempo (in minuti) fra controlli non regolari
    retry_check_interval            1
# Numero di volte che Nagios ripetera' un controllo che ritorna uno stato non OK
    max_check_attempts              3
# Abilita la parallelizzazione dei controlli per migliorare le performance
    parallelize_check               1
# Abilita i check passivi
    passive_checks_enabled          1

# Abilita il gestore degli eventi
    event_handler_enabled           1

# Abilita il calcolo dei dati di performance
    process_perf_data               1

# Abilita il salvataggio delle informazioni di stato fra restart del programma
    retain_status_information       1
# Abilita il salvataggio delle informazioni non di stato fra restart del programma
    retain_nonstatus_information    1

# Abilita le notifiche
    notifications_enabled           1
# Intervallo di tempo (in minuti) fra notifiche consecutive che il servizio e'
# ancora in stato non-OK
    notification_interval           120
# Timeperiod durante il quale le notifiche per questo servizio vanno spedite
    notification_period             always
# Stati del servizio per i quali le notifiche dovrebbero essere spedite (c=critical,
# w=warning, u=unknown, r=recovery, f=flapping, n=none)
    notification_options            w,u,c,r

    register                        0
}

Ora, prima di passare alla definizione dei servizi, dobbiamo terminare la nostra discussione su come passare ai comandi argomenti specifici per servizio, tramite le macro $ARGn$. Come si ricorderà, queste macro fungono da segnaposto: vengono sostituite con l'ennesimo argomento passato al comando nella definizione del servizio; ad esempio, una definizione di comando come la seguente si aspetta di ricevere due argomenti:

define command {
    command_name                    some-command
    command_line                    $USER1$/check_something $ARG1$ $ARG2$
}

Di conseguenza, per controllare un servizio tramite questo comando, dovremo assegnare alla variabile check_command una stringa contenente lo short name del comando, seguito dagli argomenti, il tutto separato da caratteri "!". Ad es.:

define service {
    service_description             some-service
    check_command                   some-command!arg-1!arg-2
    [...]
}

Procediamo quindi alla definizione dei servizi effettivi:

/var/www/etc/nagios/services/services.cfg
# Servizio di secure shell
define service {
    use                             generic-service
    service_description             SSH
# Short name degli host che eseguono questo servizio. Se un servizio gira su
# tutti gli host, si puo' usare il carattere jolly '*'
    host_name                       *
    check_command                   check-ssh
# Questa direttiva e' una possibile alternativa all'uso della direttiva members
# nelle definizioni dei service group
    servicegroups                   ssh-services
# Informazioni estese
    notes                           Availability of the SSH daemon
    notes_url                       http://www.openssh.org/
    icon_image                      ssh.png
    icon_image_alt                  [SSH]
}

# Servizi web
define service {
    use                             generic-service
    service_description             WWW
    host_name                       www1,www2
    check_command                   check-http!/index.html
    notes                           Availability of the corporate web sites
    notes_url                       http://www.apache.org/
    icon_image                      www.png
    icon_image_alt                  [WWW]
}

define service {
    use                             generic-service
    service_description             WWW
    host_name                       mail
    check_command                   check-http!/webmail/index.html
    notes                           Availability of the web access to the mail server
    notes_url                       http://www.squirrelmail.org/
    icon_image                      www.png
    icon_image_alt                  [WWW]
}

[...]

Come gli host, anche i servizi possono essere raggruppati per mezzo della direttiva servicegroup:

/var/www/etc/nagios/services/servicegroups.cfg
define servicegroup {
    servicegroup_name               www-services
    alias                           Web Services
# La direttiva 'members' richiede una lista, separata da virgole, di coppie
# di host e servizi, ad es. 'host1,servizio1,host2,servizio2,...'
    members                         www1,WWW,www2,WWW,mail,WWW
}

define servicegroup {
    servicegroup_name               dns-services
    alias                           Domain Name Service
    members                         dns1,DNS,dns2,DNS,dns3,DNS,dns4,DNS
}

# I membri del seguente servicegroup sono specificati dalla direttiva
# 'serviecegroups' nella definizione del servizio 'SSH'
define servicegroup {
    servicegroup_name               ssh-services
    alias                           Secure Shell Service
}

[...]

Bene, il grosso del lavoro è fatto: l'ultimo passo è la configurazione dell'interfaccia web e poi saremo finalmente in grado di mettere Nagios al lavoro!