Checkmk
to checkmk.com
Important

This is a machine translation based on the English version of the article. It might or might not have already been subject to text preparation. If you find errors, please file a GitHub issue that states the paragraph that has to be improved.

1. Introduzione

I plug-in di controllo sono moduli software scritti in Python che vengono eseguiti su un sito Checkmk e che creano e valutano i servizi su un host.

Checkmk include oltre 2000 plug-in di controllo già pronti per ogni tipo di hardware e software immaginabile. Questi plug-in sono gestiti dal team di Checkmk e ogni settimana ne vengono aggiunti di nuovi. Inoltre, su Checkmk Exchange ci sono altri plug-in forniti dai nostri utenti.

Eppure può sempre capitare che un dispositivo, un’applicazione o semplicemente una certa metrica, importante per te, non sia ancora coperta da nessuno di questi plug-in esistenti — magari semplicemente perché si tratta di qualcosa sviluppato nella tua organizzazione e quindi nessun altro potrebbe averlo. Nell’articolo sull’introduzione allo sviluppo di estensioni per Checkmk, puoi scoprire quali opzioni hai a disposizione.

Questo articolo ti mostra come sviluppare veri e propri plug-in di controllo per l’agente Checkmk — compreso tutto ciò che ne consegue. C’è un articolo a parte per i plug-in di controllo basati su SNMP.

Tip

Quando sviluppi un plug-in di controllo basato su agente, in genere hai bisogno di due plug-in: il plug-in agente sull'host monitorato, che fornisce i dati, e il plug-in di controllo sul server Checkmk, che valuta questi dati. Entrambi devono essere scritti insieme e ottimizzati l'uno per l'altro. Solo così funzioneranno senza intoppi in seguito.

1.1. La documentazione dell'API di controllo

A partire dalla versione 2.0.0 di Checkmk, è stata sviluppata una nuova Check API per la programmazione dei plug-in di controllo. Nella versione 2.4.0 di Checkmk, la Check API V2 è la versione attuale. In questo articolo ti mostreremo come utilizzare la Check API versione 2 per la programmazione dei plug-in. Puoi trovare informazioni sulla migrazione alla Check API versione 2 alla fine di questo articolo nel capitolo Migrazione.

Puoi accedere alla documentazione della Check API in qualsiasi momento tramite l'interfaccia utente di Checkmk: Help > Developer resources > Plug-in API references. Nella nuova finestra del browser, seleziona "Agent based ("Check API") > Version 2" nella barra di navigazione a sinistra:

“Page to access the Check API version 2 documentation.”

Qui troverai non solo la documentazione per l'API Check in tutte le versioni supportate, ma anche la documentazione di tutte le altre API rilevanti per la creazione di plug-in di controllo. In questo articolo, non utilizziamo solo l'API Check, ma anche l'API Rulesets V1 quando creiamo un set di regole e l'API Graphing V1 quando creiamo definizioni metriche.

Tip

Anche senza un sito Checkmk attivo, puoi visualizzare una copia della documentazione dell'API dei plugin all'indirizzo docs.checkmk.com/plugin-api.

1.2. Prerequisiti

Se sei interessato alla programmazione di plug-in di controllo, avrai bisogno di quanto segue:

  • Conoscenza del linguaggio di programmazione Python.

  • Esperienza con Checkmk, in particolare per quanto riguarda gli agenti e i controlli.

  • Esperienza nell'uso di Linux dalla riga di comando.

2. Scrivere un plug-in agente

Se sei interessato a programmare plug-in per Checkmk, è molto probabile che tu abbia già configurato un server Checkmk. Se l'hai fatto, probabilmente hai anche monitorato il tuo server Checkmk stesso come host.

Qui creeremo uno scenario in cui è utile che il server Checkmk e l'host monitorato siano identici. Questo ci permette di utilizzare le query Livestatus dall'host per ottenere informazioni sui gruppi di host forniti dal server Checkmk.

Nell'esempio descritto, ipotizzeremo un'organizzazione con diverse sedi:

  • Ciascuna di queste sedi è rappresentata in Checkmk da un gruppo di host.

  • Ogni sede ha il proprio team di assistenza.

Per garantire che il team di assistenza corretto possa essere avvisato in caso di problemi, ogni host deve essere assegnato a una sede, ovvero anche a un gruppo di host. Lo scopo di questo esempio è impostare un controllo per assicurarsi che nessun host abbia dimenticato di assegnare un gruppo di host.

L'intero processo comprende due passaggi:

  1. Leggere le informazioni per il monitoraggio dall'host. Questo è l'argomento di questo capitolo.

  2. Scrivere un plug-in di controllo nel sito Checkmk che valuti questi dati. Te lo mostreremo nel prossimo capitolo.

Allora, cominciamo…​

2.1. Recupero e filtraggio delle informazioni

Il primo passo prima di scrivere qualsiasi programma plug-in è la ricerca! Questo significa che devi capire come ottenere le informazioni necessarie per il monitoraggio.

Per l'esempio scelto, sfruttiamo il fatto che il server Checkmk è anche l'host. Ciò significa che inizialmente è sufficiente recuperare i dati di stato tramite Livestatus, ovvero i dati organizzati in tabelle che Checkmk conserva nella memoria volatile riguardo agli host e ai servizi monitorati.

Accedi come utente del sito e richiedi le informazioni sui gruppi di host con il seguente comando:

OMD[mysite]:~$ lq "GET hostgroups"
action_url;alias;members;members_with_state;name;notes;notes_url;num_hosts;num_hosts_down;num_hosts_handled_problems;num_hosts_pending;num_hosts_unhandled_problems;num_hosts_unreach;num_hosts_up;num_services;num_services_crit;num_services_handled_problems;num_services_hard_crit;num_services_hard_ok;num_services_hard_unknown;num_services_hard_warn;num_services_ok;num_services_pending;num_services_unhandled_problems;num_services_unknown;num_services_warn;worst_host_state;worst_service_hard_state;worst_service_state
;Hamburg;myhost11,myhost22,myhost33;myhost11|0|1,myhost22|0|1,myhost33|0|1;Hamburg;;;3;0;0;0;0;0;3;123;10;0;10;99;0;14;99;0;24;0;14;0;2;2
;Munich;myhost1,myhost2,myhost3;myhost1|0|1,myhost2|0|1,myhost3|0|1;Munich;;;3;0;0;0;0;0;3;123;10;0;10;99;0;14;99;0;24;0;14;0;2;2
;check_mk;localhost;localhost|0|1;check_mk;;;1;0;0;0;0;0;1;66;0;0;0;4;0;1;4;61;1;0;1;0;1;1
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

La prima riga dell'output contiene i nomi delle colonne della tabella hostgroups interrogata. Il punto e virgola funge da separatore. Le righe successive contengono quindi il contenuto di tutte le colonne, anch'esse separate da punti e virgola.

L'output è già relativamente confuso in questo piccolo esempio e contiene informazioni che non sono rilevanti per il nostro caso. In generale, dovresti lasciare l'interpretazione dei dati a Checkmk. Tuttavia, un pre-filtraggio sull'host può ridurre il volume dei dati da trasferire se non tutti sono effettivamente necessari. Quindi, in questo caso, limita la query alle colonne rilevanti (Columns), ai nomi dei gruppi di host (name) e agli host in quei gruppi (members):

OMD[mysite]:~$ lq "GET hostgroups\nColumns: name members"
Hamburg;myhost11,myhost22,myhost33
Munich;myhost1,myhost2,myhost3
check_mk;localhost
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

L'interfaccia Livestatus si aspetta di ricevere tutti i comandi e le intestazioni su righe separate. Le interruzioni di riga necessarie sono indicate da \n.

In questo esempio, ci sono attualmente tre gruppi di host: due gruppi per le località e uno per il gruppo check_mk. Questo contiene un host chiamato localhost.

Il gruppo di host check_mk è una funzionalità speciale all'interno dei gruppi di host. Non l'hai creato tu. E non puoi aggiungere attivamente un host a questo gruppo. Allora da dove viene questo gruppo di host? Poiché per definizione ogni host in Checkmk deve appartenere a un gruppo, Checkmk assegna ogni host che non assegni specificatamente a un gruppo al gruppo "speciale" check_mk come impostazione predefinita. Non appena avrai assegnato un host a uno dei tuoi gruppi di host, verrà rimosso da Checkmk dal gruppo check_mk. Non c'è nemmeno modo di riassegnare un host al gruppo di host check_mk.

Sono proprio queste proprietà del gruppo check_mk a essere utilizzate nel nostro esempio: Poiché ogni host deve essere assegnato a una posizione, il gruppo di host check_mk deve essere vuoto. Se non è vuoto, è necessario intervenire, ovvero gli host in esso contenuti devono essere assegnati ai gruppi di host e quindi alle posizioni appropriate.

2.2. Inserisci il comando nell'agente

Finora, come utente del sito, hai utilizzato il comando lq per visualizzare le informazioni. Questo è utile per comprendere i dati.

Tuttavia, per recuperare questi dati dal server Checkmk, il nuovo comando deve diventare parte dell'agente Checkmk sull'host monitorato. In teoria, potresti ora modificare direttamente l'agente Checkmk nel file /usr/bin/check_mk_agent e includere questa parte. Questo metodo avrebbe però lo svantaggio che il tuo nuovo comando scomparirebbe di nuovo quando il software dell'agente viene aggiornato, poiché questo file verrà sovrascritto durante l'aggiornamento.

È quindi meglio creare un plug-in dell'agente. Tutto ciò che ti serve è un file eseguibile che contenga il comando e che si trovi nella directory /usr/lib/check_mk_agent/plugins/.

E c'è un'altra cosa importante: I dati non possono essere semplicemente visualizzati. Avrai comunque bisogno di un'intestazione di sezione. Si tratta di una riga formattata in modo speciale che contiene il nome del nuovo plug-in dell'agente. Questa intestazione di sezione permette a Checkmk di riconoscere in seguito dove iniziano i dati del nuovo plug-in dell'agente e dove finiscono quelli del plug-in precedente. È più semplice se il plug-in dell'agente, l'intestazione di sezione e il plug-in di controllo hanno lo stesso nome, anche se questo non è obbligatorio.

Quindi, prima di tutto, ti servirà un nome significativo per il tuo nuovo plug-in di controllo. Questo nome può contenere solo lettere minuscole (solo a-z, senza dieresi né accenti), trattini bassi e cifre e deve essere unico. Evita conflitti di nomi con i plug-in di controllo esistenti. Se sei curioso di sapere quali nomi esistono già, in un sito Checkmk dalla riga di comando puoi elencarli con cmk -L:

OMD[mysite]:~$ cmk -L
3par_capacity               agent      HPE 3PAR: Capacity
3par_cpgs                   agent      HPE 3PAR: CPGs
3par_cpgs_usage             agent      HPE 3PAR: CPGs Usage
3par_hosts                  agent      HPE 3PAR: Hosts
3par_ports                  agent      HPE 3PAR: Ports
3par_remotecopy             agent      HPE 3PAR: Remote Copy
3par_system                 agent      HPE 3PAR: System
3par_volumes                agent      HPE 3PAR: Volumes
3ware_disks                 agent      3ware ATA RAID Controller: State of Disks
3ware_info                  agent      3ware ATA RAID Controller: General Information
3ware_units                 agent      3ware ATA RAID Controller: State of Units
acme_agent_sessions         snmp       ACME Devices: Agent Sessions
acme_certificates           snmp       ACME Devices: Certificates
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

L'output qui mostra solo le prime righe di un elenco molto lungo. Utilizzando i prefissi, l'assegnazione di molti plug-in di controllo può già essere facilmente riconosciuta qui. L'uso dei prefissi è quindi consigliato anche per i tuoi plug-in di controllo. Per inciso, la seconda colonna mostra come il rispettivo plug-in di controllo ottiene i propri dati.

Un nome adatto per il nuovo plug-in di controllo del nostro esempio è myhostgroups.

Ora hai tutte le informazioni necessarie per creare lo script per il plug-in dell'agente. Crea un nuovo file myhostgroups come utente root nella directory /usr/lib/check_mk_agent/plugins/:

/usr/lib/check_mk_agent/plugins/myhostgroups
#!/bin/bash

columns="name members"
site="mysite"

echo '<<<myhostgroups:sep(59)>>>'
su - ${site} lq "GET hostgroups\nColumns: ${columns}"
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Cosa significa questo in dettaglio?

La prima riga contiene lo "shebang" (abbreviazione di sharp e bang, dove quest'ultimo è l'abbreviazione del punto esclamativo), grazie al quale Linux riconosce che deve eseguire lo script con la shell specificata.

Per mantenere lo script adattabile, vengono introdotte due variabili:

  • la variabile columns, che attualmente contiene i nomi dei gruppi e i membri associati,

  • la variabile site, che contiene il nome del sito Checkmk.

Usa il comando echo per visualizzare l'intestazione della sezione. Poiché le colonne della tabella sono separate da un punto e virgola, usa l'aggiunta sep(59) per specificare che il punto e virgola venga utilizzato come separatore per i dati nell'output dell'agente. Il 59 sta per il codice carattere ASCII 59, il punto e virgola. Senza questa aggiunta, il carattere spazio (carattere ASCII 32) verrebbe utilizzato come separatore per impostazione predefinita.

Per poter utilizzare il comando lq, a tua disposizione come utente del sito, in uno script eseguito dall'utente root, anteponigli su.

Tip

È possibile che l'accesso a lq tramite su possa causare problemi. In alternativa, come utente root, puoi anche accedere a Livestatus direttamente nella shell con printf o echo -e tramite un socket Unix. L'articolo su Livestatus spiega come farlo.

Un altro punto importante una volta creato il file: rendi il file eseguibile:

root@linux# chmod +x /usr/lib/check_mk_agent/plugins/myhostgroups
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Puoi provare il plug-in dell'agente direttamente a mano inserendo il percorso completo come comando:

root@linux# /usr/lib/check_mk_agent/plugins/myhostgroups
<<<myhostgroups:sep(59)>>>
Hamburg;myhost11,myhost22,myhost33
Munich;myhost1,myhost2,myhost3
check_mk;localhost
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

I gruppi di host che non contengono alcun host non vengono elencati qui.

Tip

Il nostro esempio utilizza uno script di shell molto semplice come plug-in dell'agente. In molti casi, vorrai utilizzare un linguaggio di scripting o file binari che sono più facili da mantenere. È consentito qualsiasi file eseguibile sul sistema di destinazione. Quando si utilizza Python, c'è un piccolo dettaglio da notare: Se nel nome del file non è presente il suffisso .py, lo "shebang" viene valutato come con tutti gli altri linguaggi di scripting. Se il suffisso .py è presente, lo shebang viene ignorato e l'agente Checkmk cercherà invece l'interprete Python. Puoi anche specificarne il percorso assoluto nel file di configurazione $MK_CONFDIR/python_path.cfg come variabile PYTHON3, che differisce dal Python di sistema. Questo è utile se un plug-in richiede moduli Python specifici e, di conseguenza, dipende da un ambiente virtuale Python (venv).

2.3. Test dell'agente

Il test e la risoluzione dei problemi sono le attività più importanti quando si crea un plug-in agente funzionante. È meglio procedere in tre passaggi:

  1. Prova il plug-in dell'agente "in modalità standalone". L'hai appena fatto nella sezione precedente.

  2. Testa l'agente nel suo complesso a livello locale.

  3. Recupera l'agente dal server Checkmk.

Testare l'agent localmente è molto semplice. Come utenroot, esegui il comando check_mk_agent:

root@linux# check_mk_agent
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

La nuova sezione dovrebbe apparire da qualche parte nell'output molto lungo. I plug-in dell'agente vengono generati dall'agente al termine dell'elaborazione.

Puoi scorrere l'output aggiungendo less (premi Spacebar per scorrere, / per cercare e Q per uscire):

root@linux# check_mk_agent | less
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Oppure puoi cercare le righe che ti interessano nell'output. Ad esempio, grep con -A offre la possibilità di visualizzare qualche riga in più dopo ogni risultato. Questo ti permette di cercare e visualizzare comodamente la sezione:

root@linux# check_mk_agent | grep -A3 '^<<<myhostgroups'
<<<myhostgroups:sep(59)>>>
Hamburg;myhost11,myhost22,myhost33
Munich;myhost1,myhost2,myhost3
check_mk;localhost
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il terzo e ultimo test viene quindi eseguito direttamente dal sito Checkmk. Includi l'host nel monitoraggio (ad esempio come localhost), accedi come utente del sito e poi recupera i dati dell'agente con cmk -d:

OMD[mysite]:~$ cmk -d localhost | grep -A3 '^<<<myhostgroups'
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Questo dovrebbe produrre lo stesso output del comando precedente.

Se funziona, il tuo agente è pronto. E cosa hai fatto per questo? Hai creato un breve script nel percorso /usr/lib/check_mk_agent/plugins/myhostgroups e l'hai reso eseguibile.

Tutto ciò che segue ora avviene solo sul server Checkmk: Lì scrivi il plug-in di controllo.

3. Scrivere un semplice plug-in di controllo

Preparare l'agente è solo metà del divertimento. Ora devi insegnare a Checkmk come gestire le informazioni provenienti dalla nuova sezione dell'agente, quali servizi deve generare, quando devono essere indirizzati a WARN o CRIT, ecc. Puoi fare tutto questo programmando un plug-in di controllo usando Python.

3.1. Preparazione del file

Per i tuoi plug-in di controllo troverai la directory di base già pronta nella gerarchia local della directory del sito. Si tratta di ~/local/lib/python3/cmk_addons/plugins/. La directory appartiene all’utente del sito ed è quindi scrivibile per te.

In questa directory, i plug-in sono organizzati in famiglie di plug-in, i cui nomi di directory possono essere definiti liberamente. Ad esempio, tutti i plug-in relativi ai dispositivi Cisco sono memorizzati nella cartella cisco, allo stesso modo tutti i plug-in relativi ai tuoi gruppi di host sono memorizzati nella cartella myhostgroups. Questa convenzione permette a tutti i plug-in appartenenti alla stessa famiglia di condividere il codice — ed è utilizzata esattamente allo stesso modo dai plug-in forniti con Checkmk.

In questa sottodirectory <plug-in_family> vengono poi create ulteriori sottodirectory con nomi predefiniti, a seconda delle diverse API, ad esempio agent_based per l’API Check dei plug-in di controllo basati su agent. A sua volta, introdurremo in seguito ulteriori sottodirectory per l’API Rulesets e l’API Graphing.

Crea le due sottodirectory per il nuovo plug-in di controllo basato su agente e poi passa a esse per lavorare:

OMD[mysite]:~$ mkdir -p ~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based
OMD[mysite]:~$ cd ~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Puoi modificare il tuo plug-in di controllo con qualsiasi editor di testo installato sul sistema Linux.

Crea qui il file myhostgroups.py per il plug-in di controllo. La convenzione prevede che il nome del file rifletta il nome della sezione dell'agente. È obbligatorio che il file finisca con .py, perché a partire dalla versione 2.0.0 di Checkmk i plug-in di controllo sono sempre veri e propri moduli Python.

Un framework di base eseguibile (scaricabile da GitHub), che amplierai passo dopo passo di seguito, ha questo aspetto:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
#!/usr/bin/env python3

from cmk.agent_based.v2 import AgentSection, CheckPlugin, Service, Result, State, Metric, check_levels

def parse_myhostgroups(string_table):
    parsed = {}
    return parsed

def discover_myhostgroups(section):
    yield Service()

def check_myhostgroups(section):
    yield Result(state=State.OK, summary="Everything is fine")

agent_section_myhostgroups = AgentSection(
    name = "myhostgroups",
    parse_function = parse_myhostgroups,
)

check_plugin_myhostgroups = CheckPlugin(
    name = "myhostgroups",
    service_name = "Host group check_mk",
    discovery_function = discover_myhostgroups,
    check_function = check_myhostgroups,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per prima cosa, devi importare le funzioni e le classi necessarie per i plug-in di controllo dai moduli Python. Per il nostro esempio, importeremo solo ciò che sarà necessario o potrebbe essere utile nel resto di questo articolo. Qui, si usa `cmk.agent_based.v2` per specificare che vengono importati i moduli dall'API Check V2:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
from cmk.agent_based.v2 import AgentSection, CheckPlugin, Service, Result, State, Metric, check_levels
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

3.2. Scrivere la funzione parse

La funzione di analisi ha il compito di "analizzare" i dati "grezzi" dell'agente, ovvero analizzarli e suddividerli, e inserirli in una forma strutturata logicamente che sia facile da elaborare per tutti i passaggi successivi.

Come mostrato nella sezione dedicata al test dell'agente, la sezione fornita dal plug-in dell'agente ha la seguente struttura:

<<<myhostgroups:sep(59)>>>
Hamburg;myhost11,myhost22,myhost33
Munich;myhost1,myhost2,myhost3
check_mk;localhost

Checkmk suddivide già le righe della sezione fornita dal plug-in dell'agente in un elenco di righe in base al separatore nell'intestazione della sezione (nell'esempio ;); queste righe sono a loro volta elenchi di parole. In Checkmk è quindi disponibile la seguente struttura di dati al posto dei dati grezzi provenienti dal plug-in dell'agente:

[
    ['Hamburg', 'myhost11,myhost22,myhost33'],
    ['Munich', 'myhost1,myhost2,myhost3'],
    ['check_mk', 'localhost']
]
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Nell'elenco interno, il primo elemento contiene il nome del gruppo di host e il secondo i nomi degli host appartenenti al gruppo.

Puoi accedere a tutte queste informazioni, ma solo tramite la loro posizione nel set di dati. Dovresti quindi specificare sempre il numero di parentesi quadre e il numero "sequenziale" dei contenuti desiderati all'interno di ciascuna parentesi. Con volumi di dati più grandi, questo diventa sempre più complesso ed è sempre più difficile mantenere una visione d'insieme.

A questo punto, una funzione di analisi sintattica offre chiari vantaggi grazie alla struttura che crea. Rende il codice più leggibile, gli accessi sono più performanti ed è molto più facile mantenere una visione d'insieme. Trasforma la struttura dei dati fornita da Checkmk in modo tale da poter accedere a ciascuno dei singoli valori per nome (o chiave) a piacimento, senza dover cercare ripetutamente nell'array per trovare ciò che stai cercando:

{
    'Hamburg': {'members': 'myhost11,myhost22,myhost33'},
    'Munich': {'members': 'myhost1,myhost2,myhost3'},
    'check_mk': {'members': 'localhost'}
}
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

La convenzione prevede che la funzione di analisi prenda il nome dalla sezione dell'agente e inizi con parse_. Riceve string_table come unico argomento. Nota che qui non sei libero di scegliere l'argomento: deve essere chiamato esattamente così.

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def parse_myhostgroups(string_table):
    # print(string_table)
    parsed = {}
    for line in string_table:
        parsed[line[0]] = {"members": line[1]}
    # print(parsed)
    return parsed
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Con def si specifica in Python che una funzione deve essere definita di seguito. parsed = {} crea il dizionario con la struttura dati migliorata. Nel nostro esempio, esamineremo ogni riga, elemento per elemento. Il gruppo di host seguito dai membri del gruppo di host viene prelevato da ogni riga e assemblato in una voce per il dizionario.

Il dizionario viene quindi restituito con return parsed.

Tip

Nell'esempio mostrato sopra, troverai due righe commentate. Se le commenti in seguito durante il test del plug-in di controllo, i dati prima e dopo l'esecuzione della funzione di analisi verranno visualizzati sulla riga di comando. Questo ti permette di verificare se la funzione fa davvero quello che dovrebbe fare.

3.3. Creazione della sezione agente

Affinché l'intera procedura abbia effetto, devi creare la nuova sezione agente con la nuova funzione di analisi. Questo è l'unico modo in cui verrà riconosciuta e presa in considerazione da Checkmk. Per farlo, crea la sezione agente come istanza della classe AgentSection:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
agent_section_myhostgroups = AgentSection(
    name = "myhostgroups",
    parse_function = parse_myhostgroups,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Qui è importante che il nome della sezione corrisponda esattamente all'intestazione della sezione nell'output dell'agente. Da questo momento in poi, ogni plug-in di controllo che utilizza la sezione myhostgroups riceve il valore di ritorno dalla funzione parse. Di norma, si tratterà del plug-in di controllo con lo stesso nome. Ma anche altri plug-in di controllo possono iscriversi a questa sezione, come mostreremo nell'estensione del plug-in di controllo.

A proposito: se vuoi saperne di più, puoi dare un'occhiata alla documentazione dell'API Check a questo punto. Lì troverai una descrizione dettagliata di questa classe, nonché delle classi, delle funzioni e degli oggetti che verranno utilizzati più avanti in questo articolo.

“Check API documentation for the ‘AgentSection’ class.”

3.4. Creazione di un plug-in di controllo

Affinché Checkmk riconosca la presenza di un nuovo plug-in di controllo, è necessario crearlo. Ciò avviene creando un'istanza della classe CheckPlugin.

Devi sempre specificare almeno quattro cose:

  1. name: Il nome del plug-in di controllo. Il modo più semplice per farlo è usare lo stesso nome della tua nuova sezione agente. In questo modo, il controllo definito più avanti nella funzione di controllo sa automaticamente quale sezione deve valutare.

  2. service_name: Il nome del servizio così come dovrebbe poi apparire nel monitoraggio.

  3. discovery_function: La funzione per individuare i servizi di questo tipo (ne parleremo meglio tra un attimo).

  4. check_function: La funzione per eseguire il controllo vero e proprio (ne parleremo meglio tra un attimo).

Il nome dell'istanza deve iniziare con check_plugin_. Il risultato sarà quindi simile a questo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
check_plugin_myhostgroups = CheckPlugin(
    name = "myhostgroups",
    service_name = "Host group check_mk",
    discovery_function = discover_myhostgroups,
    check_function = check_myhostgroups,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

È meglio non provarlo ancora, poiché devi prima scrivere le funzioni discover_myhostgroups e check_myhostgroups. Queste devono apparire nel codice sorgente prima della creazione della sezione agente e del plug-in di controllo, come descritto sopra.

Important

Se si utilizza il core Nagios (sempre nella Checkmk Community), i seguenti caratteri speciali non sono consentiti nel nome del servizio :
`;~!$%^&*|\'"<>?,()=
Se questi caratteri compaiono comunque nei nomi dei servizi, vengono semplicemente rimossi in Checkmk.
Nelle edizioni commerciali con Checkmk Micro Core (CMC), il punto e virgola (; ) non è consentito nel nome. Il simbolo del dollaro ($ ) viene visualizzato solo se preceduto da una barra rovesciata (\ ). Per tutte le edizioni
vale quanto segue: Se nel nome del servizio compaiono virgolette singole, il servizio non verrà trovato dal riconoscimento dei servizi!

3.5. Scrivere la funzione di rilevamento

Una caratteristica speciale di Checkmk è il rilevamento automatico dei servizi da monitorare. Affinché ciò funzioni, ogni plug-in di controllo deve definire una funzione che utilizzi l'output dell'agente per riconoscere se un servizio di questo tipo o quali servizi di questo tipo debbano essere creati per l'host in questione.

La funzione di rilevamento viene sempre chiamata quando viene eseguito un rilevamento dei servizi per un host. Essa decide quindi se e quali servizi devono essere creati. Nel caso standard, riceve esattamente un argomento con il nome section. Questo contiene i dati della sezione dell'agente in un formato preparato dalla funzione parse.

Pertanto, implementa la seguente semplice logica: se esiste la sezione dell'agente myhostgroups, crea anche un servizio adeguato. Questo apparirà automaticamente su tutti gli host su cui è distribuito il plug-in dell'agente.

Per i plug-in di controllo che creano un solo servizio per host, non sono necessarie ulteriori informazioni:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def discover_myhostgroups(section):
    yield Service()
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

La funzione di rilevamento deve restituire un oggetto di tipo service per ogni servizio da creare utilizzando yield (non con return). In Python, yield ha la stessa funzione di return: entrambe restituiscono un valore alla funzione chiamante. La differenza fondamentale è che yield ricorda a che punto è arrivata la funzione nell'elaborazione dei dati. La chiamata successiva prosegue dopo l'ultima istruzione yield e non ricomincia dall'inizio. Questo significa che non viene letto solo il primo risultato (come accadrebbe con return), ma tutti i risultati in sequenza (questo vantaggio diventerà rilevante più avanti nel nostro esempio con il service discovery).

3.6. Scrivere la funzione di controllo

Ora puoi passare alla funzione di controllo vera e propria, che utilizza l'output corrente dell'agente per decidere quale stato deve assumere il servizio e può fornire ulteriori informazioni.

Lo scopo della funzione di controllo è impostare un controllo che possa essere utilizzato per verificare se a un host è stato assegnato un gruppo di host. Per farlo, controlla se il gruppo di host check_mk contiene host. Se è così, il servizio dovrebbe ricevere lo stato CRIT. In caso contrario, tutto è OK e lo stesso vale per lo stato del servizio.

Ecco l'implementazione:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups(section):
    attr = section.get("check_mk")
    hosts = attr["members"] if attr else ""
    if hosts:
        yield Result(state=State.CRIT, summary=f"Default group is not empty; Current member list: {hosts}")
    else:
        yield Result(state=State.OK, summary="Everything is fine")
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

E ora la spiegazione: La funzione check_myhostgroups() recupera prima il valore associato alla chiave check_mk e lo assegna alla variabile attr. Poi la variabile hosts viene collegata al valore members, se esiste. Se non ci sono members, hosts rimane vuota.

Segue poi una query if per la valutazione effettiva:

  • Se la variabile hosts ha un contenuto, cioè il gruppo di host check_mk non è vuoto, lo stato del servizio passa a CRIT e viene visualizzato un testo di avviso. Questo testo contiene anche un elenco dei nomi di tutti gli host che fanno parte del gruppo di host check_mk. Per visualizzare il testo con le espressioni si usa la stringa F di Python, chiamata così perché la stringa è preceduta dalla lettera f.

  • Se la variabile hosts è vuota, cioè non ci sono host nel gruppo di host check_mk, lo stato del servizio passa invece a OK. In questo caso viene visualizzato anche un messaggio appropriato.

Una volta creata la funzione di controllo, il plug-in di controllo è pronto.

Il plug-in di controllo e il plug-in dell'agente sono stati resi disponibili su GitHub.

3.7. Testare e attivare il plug-in di controllo

Per prima cosa, assicurati che il tuo plug-in sia sintatticamente corretto:

OMD[mysite]:~$ cmk-validate-plugins
Agent based plugins loading succeeded, Active checks loading succeeded, Special agents
loading succeeded, Rule specs loading succeeded, Rule specs forms creation succeeded,
Referenced rule specs validation succeeded, Loaded rule specs usage succeeded
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Ulteriori test e l'attivazione del plug-in vengono eseguiti dalla riga di comando utilizzando il comando `cmk`. Per prima cosa, prova il rilevamento dei servizi con l'opzione `-I`. Aggiungendo l'opzione `v` (per la modalità verbosa) otterrai un output dettagliato. L'opzione `--detect-plugins` limita l'esecuzione del comando a questo plug-in di controllo e `localhost` a questo specifico host:

OMD[mysite]:~$ cmk -vI --detect-plugins=myhostgroups localhost
Discovering services and host labels on: localhost
localhost:
+ FETCHING DATA
No piggyback files for 'localhost'. Skip processing.
Get piggybacked data
+ ANALYSE DISCOVERED HOST LABELS
SUCCESS - Found no new host labels
+ ANALYSE DISCOVERED SERVICES
+ EXECUTING DISCOVERY PLUGINS (1)
  1 myhostgroups
SUCCESS - Found 1 services
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Come previsto, il servizio di rilevamento riconosce un nuovo servizio nel plug-in di controllo myhostgroups.

Ora puoi provare il controllo contenuto nel plug-in di controllo:

OMD[mysite]:~$ cmk --detect-plugins=myhostgroups -v localhost
+ FETCHING DATA
No piggyback files for 'localhost'. Skip processing.
Get piggybacked data
Host group check_mk  Default group is not empty; Current member list: localhost
No piggyback files for 'localhost'. Skip processing.
[agent] Success, [piggyback] Success (but no data found for this host), execution time 1.8 sec | execution_time=1.800 user_time=0.030 system_time=0.000 children_user_time=0.000 children_system_time=0.000 cmk_time_agent=1.780
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Eseguendo il controllo, verrà determinato lo stato del servizio trovato in precedenza.

Se tutto è andato come previsto, puoi attivare le modifiche. In caso contrario, troverai informazioni utili nel capitolo dedicato alla risoluzione dei problemi.

Infine, genera una configurazione aggiornata del core di monitoraggio e riavvialo:

OMD[mysite]:~$ cmk -R
Generating configuration for core (type nagios)...
Precompiling host checks...OK
Validating Nagios configuration...OK
Restarting monitoring core...OK
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Nel monitoraggio Checkmk troverai ora il nuovo servizio Host group check_mk sull'host localhost:

The new service created in the monitoring by the check plug-in.
Poiché il gruppo di hostcheck_mk non è vuoto, il servizio èCRIT

Congratulazioni per aver creato con successo il tuo primo plug-in di controllo!

4. Estensione del plug-in di controllo

4.1. Lavori preparatori

Il primo plug-in di controllo, completato di recente, verrà ora ampliato passo dopo passo. Finora, il plug-in dell'agente ha fornito solo informazioni sui nomi e sui membri all'interno dei gruppi di host. Per poter valutare lo stato degli host e dei servizi in esecuzione su di essi, ad esempio, sono necessari ulteriori dati.

Estensione del plug-in dell'agente

Per prima cosa estenderai una volta il plug-in agente per raccogliere tutte le informazioni necessarie per estendere il plug-in di controllo nelle sezioni seguenti.

Per scoprire quali informazioni fornisce Checkmk per i gruppi di host, puoi interrogare tutte le colonne disponibili della tabella dei gruppi di host con il seguente comando come utente del sito:

OMD[mysite]:~$ lq "GET columns\nFilter: table = hostgroups\nColumns: name"
action_url
alias
members
members_with_state
name
notes
notes_url
num_hosts
...
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

L'output va ancora oltre. La tabella ha quasi 30 colonne - e la maggior parte delle colonne ha persino nomi significativi. Le colonne seguenti sono di interesse in questo contesto: Numero di host per gruppo (colonna num_hosts), numero di host nello stato "UP" (num_hosts_up), numero di servizi di tutti gli host nel gruppo (num_services) e numero di servizi nello stato "OK" (num_services_ok).

Ora queste nuove colonne devono solo essere fornite dall'agente. Puoi farlo estendendo il plug-in dell'agente creato nel capitolo precedente.

Come utente root, modifica lo script del plug-in dell'agente. Dato che lo script ha già inserito i valori configurabili nelle variabili, basta cambiare solo la riga che inizia con columns e inserire le quattro colonne aggiuntive recuperate lì:

/usr/lib/check_mk_agent/plugins/myhostgroups
#!/bin/bash

columns="name members num_hosts num_hosts_up num_services num_services_ok"
site="mysite"

echo '<<<myhostgroups:sep(59)>>>'
su - ${site} lq "GET hostgroups\nColumns: ${columns}"
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Esegui lo script per verificarlo:

root@linux# /usr/lib/check_mk_agent/plugins/myhostgroups
<<<myhostgroups:sep(59)>>>
Munich;myhost3,myhost2,myhost1;3;3;180;144
Hamburg;myhost22,myhost33,myhost11;3;2;132;105
check_mk;localhost;1;1;62;45
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

I quattro nuovi valori — separati da un punto e virgola — ora compaiono alla fine di ogni riga.

Con questa modifica, il plug-in dell'agente ora fornisce dati diversi rispetto a prima. A questo punto, è importante assicurarsi che, con i dati modificati, il plug-in di controllo continui a fare ciò che dovrebbe.

Estensione della funzione di analisi

In un plug-in di controllo, la funzione di analisi è responsabile della conversione dei dati forniti dal plug-in agente. Quando hai scritto la funzione di analisi, hai considerato solo due colonne della tabella del gruppo di host. Ora vengono fornite sei colonne invece di due. La funzione di analisi deve quindi essere personalizzata per elaborare le quattro colonne aggiuntive.

Come utente del sito, modifica la funzione di analisi nel file myhostgroups.py, che contiene il plug-in di controllo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def parse_myhostgroups(string_table):
    parsed = {}
    column_names = [
        "name",
        "members",
        "num_hosts",
        "num_hosts_up",
        "num_services",
        "num_services_ok",
    ]
    for line in string_table:
        parsed[line[0]] = {}
        for n in range(1, len(column_names)):
            parsed[line[0]][column_names[n]] = line[n]
    return parsed
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Qui è stato modificato tutto ciò che si trova tra parsed = {} e return parsed. Innanzitutto, le colonne da elaborare vengono definite sotto i loro nomi come un elenco column_names. Viene quindi creato un dizionario nel ciclo for generando le coppie chiave-valore in ogni riga dal nome della colonna e dal valore letto.

Questa estensione non è fondamentale per la funzione di controllo esistente, poiché la struttura dei dati nelle prime due colonne rimane invariata. Vengono fornite solo colonne aggiuntive, che non vengono (ancora) valutate nella funzione di controllo.

Ora che i nuovi dati possono essere elaborati, utilizzerai anche questi dati.

4.2. Rilevamento dei servizi

Nel capitolo precedente hai creato un controllo molto semplice che crea un servizio su un host. Tuttavia, è anche molto comune che ci siano diversi servizi da un singolo controllo su un host.

L'esempio più comune è un servizio per un file system su un host. Il plug-in di controllo denominato df crea un servizio per ogni file system presente sull'host. Per distinguere questi servizi, il punto di montaggio del file system (ad esempio /var) o la lettera dell'unità (ad esempio C:) viene incorporato nel nome del servizio. Ciò porta a nomi di servizio come Filesystem /var o Filesystem C:. La parola /var o C: viene qui definita come elemento. Stiamo quindi parlando anche di un controllo con elementi.

Se vuoi creare un controllo con elementi, devi implementare le seguenti funzioni:

  • La funzione di discovery deve generare un servizio per ciascuna delle voci che devono essere monitorate sull'host.

  • Devi includere l'elemento nel nome del servizio utilizzando il segnaposto %s (ad es. "Filesystem %s").

  • La funzione di controllo viene chiamata una volta, separatamente per ogni elemento, e la riceve come argomento. Dai dati dell'agente deve quindi estrarre i dati rilevanti per quell'elemento.

Per testarlo nella pratica, creerai un servizio separato per ogni gruppo di host esistente.

Poiché il plug-in di controllo myhostgroups creato nel capitolo precedente per controllare il gruppo standard check_mk dovrebbe continuare a funzionare, questo plug-in di controllo rimane così com'è. Per l'estensione, crea il nuovo plug-in di controllo myhostgroups_advanced nel file esistente myhostgroups.py. — nel primo passo come in precedenza creando un'istanza della classe CheckPlugin.

Qui puoi trovare il codice vecchio e quello nuovo evidenziati:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
check_plugin_myhostgroups = CheckPlugin(
    name = "myhostgroups",
    service_name = "Host group check_mk",
    discovery_function = discover_myhostgroups,
    check_function = check_myhostgroups,
)

check_plugin_myhostgroups_advanced = CheckPlugin(
    name = "myhostgroups_advanced",
    sections = [ "myhostgroups" ],
    service_name = "Host group %s",
    discovery_function = discover_myhostgroups_advanced,
    check_function = check_myhostgroups_advanced,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per poter distinguere il nuovo plug-in di controllo da quello vecchio, gli viene assegnato un nome univoco con myhostgroups_advanced. Il parametro sections determina le sezioni dell'output dell'agente a cui il plug-in di controllo si abbona. Qui, myhostgroups viene utilizzato per specificare che il nuovo plug-in di controllo utilizza gli stessi dati di quello vecchio: la sezione del plug-in dell'agente preparata dalla funzione parse. Il nome del servizio ora contiene il segnaposto %s. Il nome dell'elemento verrà inserito in seguito in questo punto da Checkmk. Nelle ultime due righe vengono definiti i nomi della nuova funzione di discovery e della nuova funzione di controllo, che devono ancora essere scritte.

Iniziamo dalla funzione di rilevamento, che ora ha il compito di determinare gli elementi da monitorare: anche questa va inserita in aggiunta a quella esistente:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def discover_myhostgroups_advanced(section):
    for group in section:
        if group != "check_mk":
            yield Service(item=group)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Come in precedenza, la funzione di rilevamento riceve l'argomento section. I singoli gruppi di host vengono elaborati in un ciclo. Qui sono di interesse tutti i gruppi di host, ad eccezione di check_mk, poiché questo gruppo di host speciale è già stato gestito dal plug-in di controllo esistente myhostgroups. Ogni volta che viene trovato un elemento, viene restituito con yield, che crea un oggetto del tipo Service, il quale a sua volta riceve il nome del gruppo di host come elemento.

Se l'host viene monitorato in un secondo momento, la funzione di controllo viene chiamata separatamente per ogni servizio — e quindi per ogni elemento. Questo ti porta alla definizione della funzione di controllo per il nuovo plug-in di controllo myhostgroups_advanced. La funzione di controllo riceve l'argomento item oltre alla sezione. La prima riga della funzione appare quindi così:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, section):
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

L'algoritmo per la funzione di controllo è semplice: Se il gruppo di host esiste, il servizio viene impostato su OK e vengono elencati il numero e i nomi degli host nel gruppo. La funzione completa per questo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, section):
    attr = section.get(item)
    if attr:
        yield Result(state=State.OK, summary=f"{attr['num_hosts']} hosts in this group: {attr['members']}")
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il risultato del controllo viene fornito restituendo un oggetto della classe Result tramite yield. Ciò richiede i parametri state e summary. Qui, state definisce lo stato del servizio (nell'esempio OK) e summary il testo che viene visualizzato nell'Summarye del servizio. Questo è puramente informativo e non viene valutato ulteriormente da Checkmk. Puoi trovare ulteriori informazioni al riguardo nella prossima sezione.

Fin qui tutto bene. Ma cosa succede se l’elemento che stai cercando non viene trovato? Questo può accadere se in passato è già stato creato un servizio per un gruppo di host, ma questo gruppo di host ora è scomparso — sia perché il gruppo di host esiste ancora in Checkmk ma non contiene più alcun host, sia perché è stato cancellato completamente. In entrambi i casi, questo gruppo di host non sarà più presente nell’output dell’agente.

La buona notizia: Checkmk se ne occupa! Se un elemento cercato non viene trovato, Checkmk genera automaticamente il risultato UNKNOWN - Item not found in monitoring data per il servizio. Questo è intenzionale ed è una cosa positiva. Se un elemento cercato non viene trovato, puoi semplicemente eseguire Python dalla funzione e lasciare che Checkmk faccia il suo lavoro.

Checkmk sa solo che l'elemento che prima era presente ora non c'è più. Checkmk non conosce il motivo di ciò, ma tu sì. È quindi opportuno non tenere questa informazione per te, ma intercettare questa condizione nella funzione di controllo e visualizzare un messaggio utile.

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, section):
    attr = section.get(item)
    if not attr:
        yield Result(state=State.CRIT, summary="Group is empty or has been deleted")
        return

    yield Result(state=State.OK, summary=f"{attr['num_hosts']} hosts in this group: {attr['members']}")
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Cosa è cambiato? Ora la condizione di errore viene gestita per prima. Pertanto, controlla nel ramo if se l’elemento non esiste davvero, imposta lo stato su CRIT ed esci dalla funzione con return. In tutti gli altri casi, restituisci OK come prima.

Ciò significa che hai integrato la situazione dei gruppi di host che scompaiono nella funzione di controllo. Invece di UNKNOWN, il servizio associato sarà ora CRIT e conterrà informazioni sulla causa dello stato critico.

Questo completa il nuovo plug-in di controllo come estensione di quello vecchio. Il plug-in dell'agente esteso e il file esteso per i plug-in di controllo si trovano nuovamente su GitHub. Quest'ultimo contiene il semplice plug-in di controllo myhostgroups del capitolo precedente, la funzione di analisi avanzata e i componenti del nuovo plug-in di controllo myhostgroups_advanced con la creazione del plug-in di controllo, la funzione di rilevamento e la funzione di controllo. Tieni presente che le funzioni devono sempre essere definite prima della creazione dei plug-in di controllo o delle sezioni dell'agente, in modo che non si verifichino errori dovuti a nomi di funzioni non definiti.

Poiché il nuovo plug-in di controllo myhostgroups_advanced fornisce nuovi servizi, devi eseguire un rilevamento dei servizi per questo plug-in di controllo e attivare le modifiche per poter visualizzare questi servizi nel monitoraggio:

The two new services created by the advanced check plug-in in the monitoring.
Due nuovi servizi nel monitoraggio:

Procedi come descritto nel capitolo dedicato ai plug-in di controllo semplici. Non eseguire i primi due comandi per myhostgroups, ma eseguili invece per il nuovo plug-in di controllo myhostgroups_advanced.

4.3. Riepilogo e dettagli

Nel monitoraggio di Checkmk, ogni servizio ha uno stato — OK, WARN, ecc. — oltre a una riga di testo. Questo testo si trova nella colonna Summary — come si può vedere nella schermata precedente — e ha quindi il compito di fornire un breve riassunto dello stato del servizio. L'idea è che questo testo non superi i 60 caratteri. Questo garantisce una visualizzazione concisa della tabella senza fastidiose interruzioni di riga.

C'è anche il campo "Details", in cui vengono visualizzati tutti i dettagli sullo stato del servizio, incluse tutte le informazioni del riepilogo. Cliccando sul servizio si apre la pagina del servizio, in cui si possono vedere i due campi "Summary" e "Details" insieme a molti altri.

Quando chiami yield Result(...), puoi decidere quali informazioni sono così importanti da dover essere visualizzate nel riepilogo e per quali è sufficiente che compaiano nei dettagli.

Nel nostro esempio, hai sempre utilizzato una chiamata del seguente tipo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield Result(state=State.OK, summary=f"{attr['num_hosts']} hosts in this group: {attr['members']}")
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Ciò significa che il testo definito come "summary" appare sempre nell'Summary — e anche nell'Details. Dovresti quindi utilizzarlo solo per informazioni importanti. Se un gruppo di host contiene molti host, l'elenco di riepilogo può diventare molto lungo — più lungo dei 60 caratteri raccomandati. Se un'informazione è di secondaria importanza, puoi utilizzare "details" per specificare che il suo testo appaia solo nei dettagli:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield Result(
        state = State.OK,
        summary = f"{attr['num_hosts']} hosts in this group",
        details = f"{attr['num_hosts']} hosts in this group: {attr['members']}",
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Nell'esempio sopra, l'elenco degli host viene quindi visualizzato solo nell'Details. L'Summary mostra quindi solo il numero di host nel gruppo:

'Summary' and 'Details' shown in the service details.
Contenuti diversi per il riepilogo e i dettagli nel monitoraggio

Oltre a summary e details, c'è un terzo parametro. Con notice specifichi che un testo relativo a un servizio nell'OKe venga visualizzato solo nei dettagli, ma anche nel riepilogo per tutti gli altri stati. In questo modo, dal riepilogo risulta immediatamente chiaro perché il servizio non è OK. Il parametro notice non è particolarmente utile se i testi sono associati in modo permanente agli stati, come nel nostro esempio finora.

In sintesi, questo significa:

  • Il testo totale del riepilogo non dovrebbe superare i 60 caratteri per i servizi che sono OK.

  • Usa sempre o summary o notice — almeno uno dei due, ma non entrambi.

  • Se necessario, aggiungi details se il testo dei dettagli deve essere un'alternativa.

4.4. Risultati parziali multipli per servizio

Per evitare che il numero di servizi su un host aumenti eccessivamente, spesso si combinano diversi risultati parziali in un unico servizio. Ad esempio, il servizio Memory su Linux non solo controlla l'utilizzo della RAM e dello swap, ma anche la memoria condivisa, le tabelle di pagina e ogni sorta di altre cose.

L'API Check offre un'interfaccia molto comoda per questo. Una funzione di controllo può semplicemente generare un risultato con yield tutte le volte che serve. Lo stato complessivo del servizio si basa poi sul risultato parziale peggiore nell'ordine OKWARNUNKNOWNCRIT.

Nell'esempio, usa questa opzione per definire due risultati aggiuntivi per ogni servizio dei gruppi di host oltre al risultato esistente. Questi valutano la percentuale di host nello stato UP e dei servizi nello stato OK. Usa le colonne aggiuntive della tabella dei gruppi di host precedentemente definita nell'output dell'agente e nella funzione di analisi.

Ora espandi la funzione di controllo in più fasi dall'alto verso il basso:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, section):
    attr = section.get(item)
    if not attr:
        yield Result(state=State.CRIT, summary="Group is empty or has been deleted")
        return

    members = attr["members"]
    num_hosts = int(attr["num_hosts"])
    num_hosts_up = int(attr["num_hosts_up"])
    num_services = int(attr["num_services"])
    num_services_ok = int(attr["num_services_ok"])
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il ramo "if" rimane invariato, ovvero i nuovi risultati parziali si applicano solo ai gruppi di host che esistono già. Definisci quindi cinque variabili per le colonne della tabella dei gruppi di host contenuta nella sezione. Da un lato, questo aumenta la leggibilità e, dall'altro, puoi convertire le stringhe lette in numeri con "int()" per le quattro colonne che devono ancora essere utilizzate per il calcolo.

L'unico risultato esistente rimane (quasi) invariato:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield Result(
        state = State.OK,
        summary = f"{num_hosts} hosts in this group",
        details = f"{num_hosts} hosts in this group: {members}",
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Ora è più facile che in precedenza solo l'accesso nella "F-String" di Python all'espressione che restituisce il valore, poiché l'attr è già presente nelle definizioni delle variabili.

Passiamo ora al vero e proprio cuore dell'estensione, ovvero la definizione di un risultato che implementa la seguente affermazione: "Il servizio del gruppo di host è WARN quando il 90% degli host è UP, e CRIT quando l'80% degli host è UP." La convenzione qui è che il controllo passi a WARN o CRIT non appena viene raggiunta la soglia, e non solo quando viene superata. L'API Check fornisce la funzione ausiliaria check_levels per confrontare un valore determinato con i valori di soglia.

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    hosts_up_perc = 100.0 * num_hosts_up / num_hosts
    yield from check_levels(
        hosts_up_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        label = "UP hosts",
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Nella prima riga, la percentuale viene calcolata dal numero totale e dal numero di host nello stato "UP" e memorizzata nella variabile "hosts_up_perc". La singola barra (/) esegue una divisione in virgola mobile, il che garantisce che il risultato sia un valore float. Questo è utile perché alcune delle funzioni utilizzate in seguito richiedono un float come input.

Nella seconda riga, il risultato della funzione check_levels viene quindi restituito come oggetto di tipo Result, che puoi trovare nella documentazione dell'API. Questa funzione viene alimentata con la percentuale appena calcolata come valore (hosts_up_perc), i due valori di soglia inferiori (levels_lower), un'etichetta che precede l'output (label) e infine con notice_only=True.

L'ultimo parametro utilizza il parametro notice già introdotto nella sezione precedente per l'oggetto Result(). Con notice_only=True specifichi che il testo relativo al servizio viene visualizzato nel Summary solo se lo stato non è OK. Tuttavia, i risultati parziali che portano a un WARN o a un CRIT saranno in ogni caso sempre visibili nel riepilogo, indipendentemente dal valore di notice_only.

Infine, definisci il terzo risultato allo stesso modo del secondo, che calcola la percentuale di servizi nello stato OK:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    services_ok_perc = 100.0 * num_services_ok / num_services
    yield from check_levels(
        services_ok_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        label = "OK services",
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Questo completa la funzione di controllo.

Il servizio per un gruppo di host ora valuta tre risultati e visualizza lo stato peggiore tra questi nel monitoraggio, come nell'esempio seguente:

The summary shows the text for the critical state.
Il riepilogo mostra il testo relativo allo stato critico

4.5. Metriche

Non sempre, ma spesso, i controlli hanno a che fare con numeri — e questi numeri sono molto spesso valori misurati o calcolati. Nel nostro esempio, il numero di host nel gruppo di host (num_hosts) e il numero di host nello stato "UP" (num_hosts_up) sono i valori misurati. La percentuale di host nello stato "UP" (hosts_up_perc) è un valore calcolato a partire da questi valori. Se un valore del genere può poi essere visualizzato su un intervallo di tempo, viene chiamato anche metrica.

Con il suo sistema di grafici integrato, Checkmk dispone di un componente per memorizzare, valutare e visualizzare tali valori. Questo è completamente indipendente dal calcolo degli stati OK, WARN e CRIT.

In questo esempio, definirai i due valori calcolati, hosts_up_perc e services_ok_perc, come metriche. Le metriche saranno immediatamente visibili nell'interfaccia grafica di Checkmk senza che tu debba fare nulla. Per ogni metrica viene generato automaticamente un grafico.

Le metriche sono determinate dalla funzione di controllo e restituite come risultato aggiuntivo. Il modo più semplice è aggiungere le informazioni sulle metriche alla funzione check_levels() nella chiamata.

Come promemoria, ecco le righe con la chiamata alla funzione check_levels() della sezione precedente:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield from check_levels(
        hosts_up_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        label = "UP hosts",
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

I due nuovi argomenti per la metrica sono metric_name e boundaries:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield from check_levels(
        hosts_up_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        metric_name = "hosts_up_perc",
        label = "UP hosts",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per mantenere le cose semplici e significative, per il nome della metrica usa il nome della variabile in cui è memorizzata la percentuale come valore.

Puoi usare boundaries per fornire al sistema di grafici informazioni sull'intervallo dei valori possibili. Questo si riferisce al valore minimo e massimo possibile. Nel caso di una percentuale, i limiti di 0.0 e 100.0 non sono troppo difficili da determinare. Sono ammessi sia i numeri in virgola mobile che i numeri interi (che vengono convertiti internamente in numeri in virgola mobile), ma non le stringhe. Se viene definito solo un limite dell'intervallo di valori, inserisci semplicemente None per l'altro, ad esempio boundaries = (0.0, None).

Con questa estensione, la funzione check_levels ora restituisce anche un oggetto di tipo Metric tramite yield oltre a Result.

Ora puoi definire la metrica services_ok_perc allo stesso modo. Le ultime righe della funzione di controllo saranno quindi simili a queste:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    hosts_up_perc = 100.0 * num_hosts_up / num_hosts
    yield from check_levels(
        hosts_up_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        metric_name = "hosts_up_perc",
        label = "UP hosts",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
    services_ok_perc = 100.0 * num_services_ok / num_services
    yield from check_levels(
        services_ok_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        metric_name = "services_ok_perc",
        label = "OK services",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Con la funzione di controllo estesa, entrambi i grafici sono visibili nel monitoraggio. Nell'elenco dei servizi, l'icona "Icon for displaying the graphs for a service." ora indica che sono disponibili dei grafici per il servizio. Se passi il mouse sull'icona, i grafici verranno visualizzati in anteprima.

The service list with 2 graphs as a preview.
I nomi delle metriche vengono utilizzati come titoli per i grafici

Una panoramica di tutti i grafici, comprese le loro legende e altro ancora, è disponibile nei dettagli del servizio.

Ma cosa fare se il valore della metrica desiderata non è stato definito con la funzione check_levels()? Puoi, ovviamente, definire una metrica indipendentemente da una chiamata di funzione. A questo scopo viene utilizzato l'oggetto Metric(), che puoi anche creare direttamente tramite il suo costruttore. La definizione alternativa di una metrica per il valore hosts_up_perc è la seguente:

    yield Metric(
        name = "hosts_up_perc",
        value = hosts_up_perc,
        levels = (80.0, 90.0),
        boundaries = (0.0, 100.0),
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Gli argomenti in Metric() sono molto simili a quelli nella chiamata di funzione mostrata sopra: I primi due argomenti per il nome della metrica e il valore sono obbligatori. Inoltre, ci sono due argomenti opzionali: levels per i valori di soglia WARN e CRIT e boundaries per l'intervallo di valori.

Tip

La specifica di levels viene utilizzata qui solo come informazione per la visualizzazione del grafico. Nel grafico, i valori di soglia vengono solitamente rappresentati come linee gialle e rosse. La funzione check_levels con i valori di soglia specificati è responsabile del controllo effettivo.

Ora usa l'opzione di definire non solo i due valori calcolati, ma tutti i valori misurati come metriche usando Metric() — nel nostro esempio, i quattro valori misurati dalla tabella del gruppo di host. Limitati alle due specifiche obbligatorie del nome e del valore della metrica. Le quattro nuove righe completano l'estensione della funzione di controllo per le metriche:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    hosts_up_perc = 100.0 * num_hosts_up / num_hosts
    yield from check_levels(
        hosts_up_perc,
        levels_lower = (90.0, 80.0),
        metric_name = "hosts_up_perc",
        label = "UP hosts",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
    services_ok_perc = 100.0 * num_services_ok / num_services
    yield from check_levels(
        services_ok_perc,
        levels_lower = (90.0, 80.0),
        metric_name = "services_ok_perc",
        label = "OK services",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )

    yield Metric(name="num_hosts", value=num_hosts)
    yield Metric(name="num_hosts_up", value=num_hosts_up)
    yield Metric(name="num_services", value=num_services)
    yield Metric(name="num_services_ok", value=num_services_ok)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Questo aumenta il numero di grafici per servizio, ma ti offre anche la possibilità di combinare più metriche in un unico grafico, ad esempio. Mostriamo queste e altre opzioni nella sezione Personalizzazione della visualizzazione delle metriche qui sotto.

Nel file di esempio su GitHub puoi trovare nuovamente l'intera funzione di controllo.

5. Set di regole per i parametri di controllo

Nel plug-in di controllo esteso myhostgroups_advanced avrai generato lo stato WARN se solo il 90% degli host è UP, e CRIT per l'80%. In questo caso, i numeri 90 e 80 sono definiti esplicitamente nella funzione di controllo, o, come direbbero i programmatori, hard-coded. In Checkmk, tuttavia, gli utenti sono abituati a poter configurare tali valori di soglia e altri parametri di controllo tramite regole. Ad esempio, se un gruppo di host ha solo quattro membri, i due valori di soglia del 90% e dell'80% non sono proprio adatti, poiché la percentuale scenderà al 75% non appena il primo host fallirà e lo stato passerà direttamente a "CRIT" — senza uno stato intermedio "WARN".

Pertanto, il plug-in di controllo dovrebbe ora essere modificato in modo da poter essere configurato tramite l'interfaccia Setup. Per farlo, avrai bisogno di un set di regole.

Per creare un set di regole per un plug-in di controllo, esci dallo sviluppo del plug-in e cambia directory, file e API. Da Checkmk 2.3.0 l'API Rulesets ti aiuta a creare tali set di regole per i plug-in di controllo. La documentazione dell'API per i set di regole si trova nel tuo sito Checkmk sulla stessa pagina dell'API Check all'indirizzo Rulesets > Version 1.

5.1. Definizione di un nuovo set di regole

Per creare un nuovo set di regole, crea prima una nuova sottodirectory nella directory della famiglia di plug-in ~/local/lib/python3/cmk_addons/plugins/myhostgroups/. Il nome rulesets è predefinito per questa sottodirectory:

OMD[mysite]:~$ mkdir -p ~/local/lib/python3/cmk_addons/plugins/myhostgroups/rulesets
OMD[mysite]:~$ cd ~/local/lib/python3/cmk_addons/plugins/myhostgroups/rulesets
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

In questa directory, crea quindi un file per la definizione del set di regole. Il nome del file deve basarsi su quello del plug-in di controllo e, come tutti i file dei plug-in, deve avere l'estensione py. Per il nostro esempio, il nome del file ruleset_myhostgroups.py è adatto.

Diamo un'occhiata passo dopo passo alla struttura di questo file. Per prima cosa ci sono alcuni comandi di importazione:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/rulesets/ruleset_myhostgroups.py
#!/usr/bin/env python3

from cmk.rulesets.v1 import Label, Title
from cmk.rulesets.v1.form_specs import BooleanChoice, DefaultValue, DictElement, Dictionary, Float, LevelDirection, SimpleLevels
from cmk.rulesets.v1.rule_specs import CheckParameters, HostAndItemCondition, Topic
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per prima cosa vengono importate le classi per i testi.

La seconda riga effettua una selezione dalle specifiche del modulo, ovvero gli elementi di base per la GUI utilizzati nel set di regole, ad esempio la selezione binaria (BooleanChoice), la selezione multipla (Dictionary, DictElement), la definizione dei valori di soglia (SimpleLevel, LevelDirection, DefaultValue) e l'inserimento di numeri in virgola mobile (Float). Qui richiedi solo gli elementi logici del modulo e lasci la progettazione della GUI a Checkmk.

L'ultima riga importa le specifiche della regola, che determinano l'ambito di applicazione della regola in Checkmk, ovvero in questo caso la definizione dei parametri di controllo, l'assegnazione a host e item e l'archiviazione sotto un argomento. Poiché il tuo plug-in di controllo myhostgroups_advanced genera diversi servizi, importa qui HostAndItemCondition. Se il tuo controllo non genera un servizio, in altre parole non ha un item, importa invece HostCondition.

Ora passiamo alle definizioni effettive del modulo per l'inserimento dei parametri di controllo. L'utente dovrebbe poter definire separatamente i due valori di soglia per WARN e CRIT sia per il numero di host nello stato UP che per il numero di servizi nello stato OK:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/rulesets/ruleset_myhostgroups.py
def _parameter_form():
    return Dictionary(
        elements = {
            "hosts_up_lower": DictElement(
                parameter_form = SimpleLevels(
                    title = Title("Lower percentage threshold for host in UP status"),
                    form_spec_template = Float(),
                    level_direction = LevelDirection.LOWER,
                    prefill_fixed_levels = DefaultValue(value=(90.0, 80.0)),
                ),
                required = True,
            ),
            "services_ok_lower": DictElement(
                parameter_form = SimpleLevels(
                    title = Title("Lower percentage threshold for services in OK status"),
                    form_spec_template = Float(),
                    level_direction = LevelDirection.LOWER,
                    prefill_fixed_levels = DefaultValue(value=(90.0, 80.0)),
                ),
                required = True,
            ),
        }
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per farlo, crea una funzione che generi il dizionario. Puoi scegliere liberamente il nome della funzione; è richiesto solo quando crei la regola qui sotto. Il nome dovrebbe iniziare con un trattino basso in modo che la funzione non sia visibile al di fuori del modulo.

L'return Dictionary() è obbligatorio. Al suo interno, usa elements={} per creare gli elementi del dizionario, nell'esempio hosts_up_lower e services_ok_lower. Il modulo del parametro SimpleLevels viene utilizzato per inserire valori di soglia fissi. Nel modulo, definisci prima l'titlee e i numeri in virgola mobile per i valori da inserire (form_spec_template). Usa LevelDirection.LOWER per specificare che lo stato cambierà se i valori scendono al di sotto di questo livello.

Infine, puoi usare prefill_fixed_levels per fornire agli utenti del set di regole dei valori invece di campi di immissione vuoti. Tieni presente che questi valori visualizzati nella GUI non sono i valori predefiniti impostati più avanti nella creazione del plug-in di controllo tramite check_default_parameters. Se vuoi visualizzare nella GUI gli stessi valori predefiniti che si applicano anche alla funzione di controllo, devi mantenere i valori coerenti in entrambi i posti.

Infine, crea il nuovo set di regole utilizzando gli elementi importati e quelli definiti autonomamente. Questo si ottiene creando una nuova istanza della classe CheckParameters. Il nome di questa istanza deve iniziare con rule_spec_:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/rulesets/ruleset_myhostgroups.py
rule_spec_myhostgroups = CheckParameters(
    name = "myhostgroups_advanced",
    title = Title("Host group status"),
    topic = Topic.GENERAL,
    parameter_form = _parameter_form,
    condition = HostAndItemCondition(item_title=Title("Host group name")),
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Si applicano le seguenti spiegazioni:

  • L'namee del set di regole stabilisce la sua connessione ai plug-in di controllo. Un plug-in di controllo che vuole utilizzare questo set di regole deve usare questo nome come check_ruleset_namee al momento della creazione. Per tenere traccia di una serie di nuovi set di regole, è consigliabile utilizzare un prefisso nel nome.

  • title definisce il titolo del set di regole così come appare nell'interfaccia grafica di Checkmk.

  • L'topic determina dove il set di regole dovrebbe apparire nell'Setup. Con il valore selezionato nell'esempio, troverai il set di regole sotto Setup > Services > Service monitoring rules nella casella Various, dove di solito è in buone mani.

  • Inserisci il nome della funzione creata in precedenza come "parameter_form".

  • Se il tuo controllo non utilizza un elemento, la condizione è HostCondition e non HostAndItemCondition, come nell'esempio sopra. Con il titolo "Host group name" dell'elemento, definisci l'etichetta nella GUI con cui puoi limitare la regola a determinati gruppi di host.

5.2. Testare un set di regole

Una volta creato il file per il set di regole, dovresti verificare se finora tutto funziona — ancora senza una connessione al plug-in di controllo. L'esecuzione di cmk-validate-plugins confermerà ora che il set di regole stesso è valido, ma avviserà che non ha ancora alcun effetto.

Per rendere visibile il set di regole, devi riavviare i processi Python che forniscono l'interfaccia grafica. Questo si ottiene riavviando il server web Apache:

OMD[mysite]:~$ omd restart apache
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Dopodiché, il set di regole sarà visibile in Setup nella pagina sopra menzionata. Tuttavia, potrai trovare il valore predefinito utilizzando la funzione di ricerca in Setup solo dopo aver riavviato Redis:

OMD[mysite]:~$ omd restart redis
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il set di regole che hai appena definito apparirà così nella GUI:

“The newly created rule set in the setup.”

Nella casella "Conditions" troverai il campo di immissione "Host group name" definito tramite l'HostAndItemCondition per limitare la regola ai gruppi di host.

Crea una regola e prova diversi valori, come mostrato nella schermata qui sopra. Se funziona senza errori, ora puoi utilizzare i parametri di controllo nella funzione di controllo.

5.3. Collegamento del set di regole con il plug-in di controllo

Il set di regole appena creato è ora collegato al plug-in di controllo completato in via provvisoria nel capitolo precedente. Affinché la regola abbia effetto, devi consentire al plug-in di controllo di accettare i parametri di controllo e indicargli quale regola deve essere utilizzata. Per farlo, aggiungi due nuove righe al file del plug-in di controllo quando crei il plug-in di controllo myhostgroups_advanced:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
check_plugin_myhostgroups_advanced = CheckPlugin(
    name = "myhostgroups_advanced",
    sections = [ "myhostgroups" ],
    service_name = "Host group %s",
    discovery_function = discover_myhostgroups_advanced,
    check_function = check_myhostgroups_advanced,
    check_default_parameters = {},
    check_ruleset_name = "myhostgroups_advanced",
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Con la voce "check_default_parameters" puoi definire i valori predefiniti che si applicano finché non è stata effettivamente creata alcuna regola. Quando converti il plug-in di controllo per i parametri di controllo, questa riga deve essere presente. Nel caso più semplice, passa un dizionario vuoto {}.

In secondo luogo, inserisci check_ruleset_name, ovvero il nome del set di regole. In questo modo Checkmk sa da quale set di regole devono essere determinati i parametri.

Ora Checkmk proverà a passare i parametri alla funzione di controllo. Affinché funzioni, devi estendere la funzione di controllo in modo che si aspetti l'argomento params, che va inserito tra item e section:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, params, section):
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se stai creando un controllo senza un elemento, l'item viene omesso e params si trova all'inizio.

Si consiglia vivamente di far sì che il contenuto della variabile params venga visualizzato con print come primo test:

def check_myhostgroups_advanced(item, params, section):
    print(params)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Quando viene eseguito il plug-in di controllo, le righe stampate (una per ogni servizio) con i valori definiti da una regola appariranno più o meno così:

OMD[mysite]:~$ cmk --detect-plugins=myhostgroups_advanced -v localhost
Parameters({'hosts_up_lower': ('fixed', (75.0, 60.0)), 'services_ok_lower': ('fixed', (75.0, 60.0))})
Parameters({'hosts_up_lower': ('fixed', (75.0, 60.0)), 'services_ok_lower': ('fixed', (75.0, 60.0))})
Parameters({'hosts_up_lower': ('fixed', (75.0, 60.0)), 'services_ok_lower': ('fixed', (75.0, 60.0))})
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!
Important

Quando tutto è pronto e funziona correttamente, rimuovi le chiamate print, poiché queste possono compromettere la comunicazione interna all'interno di Checkmk. In alternativa, puoi limitare l'output delle informazioni di debug a una richiesta esplicita.

Ora personalizza ulteriormente la tua funzione di controllo in modo che i parametri passati possano avere effetto. Recupera i due elementi del dizionario definiti nella regola con il nome selezionato lì dai parametri:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
def check_myhostgroups_advanced(item, params, section):
    hosts_up_lower = params["hosts_up_lower"]
    services_ok_lower = params["services_ok_lower"]
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Più avanti nella funzione di controllo, i valori di soglia precedentemente hardcoded "fixed", (90.0, 80.0) vengono quindi sostituiti dalle variabili hosts_up_lower e services_ok_lower:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    hosts_up_perc = 100.0 * num_hosts_up / num_hosts
    yield from check_levels(
        hosts_up_perc,
        levels_lower = (hosts_up_lower),
        metric_name = "hosts_up_perc",
        label = "UP hosts",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
    services_ok_perc = 100.0 * num_services_ok / num_services
    yield from check_levels(
        services_ok_perc,
        levels_lower = (services_ok_lower),
        metric_name = "services_ok_perc",
        label = "OK services",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se è stata configurata una regola, ora puoi monitorare i gruppi di host dell'esempio con i valori di soglia impostati tramite la GUI. Tuttavia, se non è stata definita alcuna regola, questa funzione di controllo andrà in crash, poiché i parametri predefiniti nel plug-in di controllo non saranno stati compilati e il plug-in genererà un errore "KeyError" in assenza di una regola.

Tuttavia, questo problema può essere risolto se i valori predefiniti vengono definiti al momento della creazione del plug-in di controllo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
check_plugin_myhostgroups_advanced = CheckPlugin(
    name = "myhostgroups_advanced",
    sections = [ "myhostgroups" ],
    service_name = "Host group %s",
    discovery_function = discover_myhostgroups_advanced,
    check_function = check_myhostgroups_advanced,
    check_default_parameters = {"hosts_up_lower": ("fixed", (90, 80)), "services_ok_lower": ("fixed", (90, 80))},
    check_ruleset_name = "myhostgroups_advanced",
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Dovresti sempre passare i valori predefiniti in questo modo (e non intercettare il caso di parametri mancanti nel plug-in di controllo), poiché questi valori predefiniti possono essere visualizzati anche nell'interfaccia Setup. Ad esempio, nel rilevamento dei servizi di un host, nella pagina Services of host, nel menu Display, c'è l'opzione Show check parameters.

Tip

Su GitHub puoi trovare sia il file con il set di regole sia il plug-in di controllo esteso dal set di regole.

5.4. Testare e abilitare il plug-in di controllo esteso

Le modifiche apportate nel capitolo precedente interessano sia il nucleo di monitoraggio che l'interfaccia grafica, nonché i relativi processi di supporto. Pertanto, dopo aver eseguito l'cmk-validate-plugins, devi prima rigenerare la configurazione e poi riavviare il sito:

OMD[mysite]:~$ cmk -U
OMD[mysite]:~$ omd restart
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!
Riavvio più veloce per esperti

Se hai una conoscenza approfondita della struttura dei processi di Checkmk e sai esattamente quali componenti saranno interessati dalle modifiche al tuo plug-in, puoi limitare il riavvio a servizi specifici. Per una panoramica, consulta l'articolo Servizi del sito.

6. Personalizzazione della visualizzazione delle metriche

Nell'esempio sopra, hai fatto in modo che il plug-in di controllo myhostgroups_advanced generasse metriche per tutti i valori misurati e calcolati. Ti abbiamo mostrato due modi per farlo. In primo luogo, le metriche dei valori calcolati sono state create come parte della funzione check_levels() con l'argomento metric_name, ad esempio in questo modo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield from check_levels(
        services_ok_perc,
        levels_lower = ("fixed", (90.0, 80.0)),
        metric_name = "services_ok_perc",
        label = "OK services",
        boundaries = (0.0, 100.0),
        notice_only = True,
    )
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Quindi hai generato le metriche misurate direttamente con l'oggetto Metric() — per il numero di servizi nello stato OK, ad esempio, in questo modo:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py
    yield Metric(name="num_services_ok", value=num_services_ok)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Le metriche saranno immediatamente visibili nell'interfaccia grafica di Checkmk senza che tu debba fare nulla. Ci sono, tuttavia, alcune limitazioni:

  • Le metriche corrispondenti non vengono combinate automaticamente in un grafico, ma appaiono singolarmente.

  • La metrica non avrà un titolo corretto, ma verrà visualizzato il nome della variabile interna della metrica.

  • Non viene utilizzata alcuna unità che consenta una rappresentazione significativa (ad es. GB invece dei singoli byte).

  • Il colore viene selezionato a caso.

  • Un "Perf-O-Meter", ovvero l'anteprima grafica della metrica sotto forma di barra, non appare automaticamente nell'elenco dei servizi (ad esempio nella vista che mostra tutti i servizi di un host).

Per completare la visualizzazione delle tue metriche con tali dettagli, avrai bisogno delle definizioni delle metriche.

Proprio come per i set di regole, a partire da Checkmk 2.3.0 esiste anche un'API separata per metriche, grafici e Perf-O-Meter con la Graphing API. La documentazione per la Graphing API si trova nel tuo sito Checkmk sulla stessa pagina dell'API Check, sotto Graphing > Version 1.

6.1. Creazione di nuove definizioni di metriche

Le procedure per creare insiemi di regole e definizioni di metriche sono molto simili. Per prima cosa crea una nuova sottodirectory con il nome predefinito graphing nella directory della tua famiglia di plug-in ~/local/lib/python3/cmk_addons/plugins/myhostgroups/.

OMD[mysite]:~$ mkdir -p ~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing
OMD[mysite]:~$ cd ~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Quindi crea un file grafico in questa directory, ad esempio graphing_myhostgroups.py.

Per prima cosa ci sono di nuovo alcuni comandi di importazione:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing/graphing_myhostgroups.py
#!/usr/bin/env python3

from cmk.graphing.v1 import Title
from cmk.graphing.v1.graphs import Graph, MinimalRange
from cmk.graphing.v1.metrics import Color, DecimalNotation, Metric, Unit
from cmk.graphing.v1.perfometers import Closed, FocusRange, Open, Perfometer
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Per il nostro esempio, ora definisci la tua metrica per la percentuale di servizi nello stato "OK". Questo si ottiene creando un'istanza della classe Metric. Il nome di questa istanza deve iniziare con metric_

~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing/graphing_myhostgroups.py
metric_myhostgroups_services_ok_perc = Metric(
    name = "services_ok_perc",
    title = Title("Percentage of services in OK state"),
    unit = Unit(DecimalNotation("%")),
    color = Color.ORANGE,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Ecco la spiegazione:

  • Il nome della metrica (in questo caso services_ok_perc) deve corrispondere a ciò che viene restituito dalla funzione di controllo.

  • title è l'intestazione nel grafico della metrica e sostituisce il nome della variabile interna usata in precedenza.

  • Le unità disponibili (unit) si trovano nella documentazione API; terminano tutte con Notation, ad esempio DecimalNotation, EngineeringScientificNotation o TimeNotation.

  • I nomi dei colori utilizzati in Checkmk per la definizione dell'colore sono disponibili su GitHub.

Questa definizione nel file di grafici garantisce ora che il titolo, l'unità e il colore della metrica vengano visualizzati correttamente.

Come per la creazione di un file di regole, il file di grafici deve essere letto prima che la modifica sia visibile nell'interfaccia grafica. Questo si ottiene riavviando Apache sul sito:

OMD[mysite]:~$ omd restart apache
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il grafico della metrica apparirà quindi più o meno così nell'interfaccia grafica di Checkmk:

“The new metric definition in the service details.”

6.2. Grafici con più metriche

Se vuoi combinare diverse metriche in un unico grafico (cosa spesso molto utile), avrai bisogno di una definizione di grafico da aggiungere al file di grafici creato nella sezione precedente.

Nel nostro esempio, le due metriche num_services e num_services_ok devono essere visualizzate in un unico grafico. Le definizioni delle metriche per questo vengono create allo stesso modo della sezione precedente per services_ok_perc e hanno il seguente aspetto:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing/graphing_myhostgroups.py
metric_myhostgroups_services = Metric(
    name = "num_services",
    title = Title("Number of services in group"),
    unit = Unit(DecimalNotation("")),
    color = Color.PINK,
)

metric_myhostgroups_services_ok = Metric(
    name = "num_services_ok",
    title = Title("Number of services in OK state"),
    unit = Unit(DecimalNotation("")),
    color = Color.BLUE,
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Ora aggiungi un grafico che disegni queste due metriche come linee. Questo si fa tramite un'istanza della classe Graph, dove il nome dell'istanza deve iniziare di nuovo con un prefisso predefinito (graph_):

~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing/graphing_myhostgroups.py
graph_myhostgroups_combined = Graph(
    name = "services_ok_comparison",
    title = Title("Services in OK state out of total"),
    simple_lines=[ "num_services", "num_services_ok" ],
    minimal_range=MinimalRange(0, 50),
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Il parametro minimal_range descrive l'intervallo minimo coperto dall'asse verticale del grafico, indipendentemente dai valori effettivi della metrica. L'asse verticale verrà esteso se i valori superano l'intervallo minimo, ma non sarà mai più piccolo.

Il risultato è il grafico combinato nella GUI di Checkmk:

“The graph shows both metrics in the service details.”

6.3. Metriche nel Perf-O-Meter

Vuoi visualizzare un Perf-O-Meter per una metrica nella riga dell'elenco dei servizi? Potrebbe apparire così, ad esempio:

“The Perf-O-Meter shows the percentage of services in ‘OK’ state.”
Il Perf-O-Meter mostra la percentuale di servizi in uno stato OK

Per creare un Perf-O-Meter di questo tipo, avrai bisogno di un'altra istanza, questa volta della classe Perfometer, il cui nome inizia con il prefisso perfometer_:

~/local/lib/python3/cmk_addons/plugins/myhostgroups/graphing/graphing_myhostgroups.py
perfometer_myhostgroups_advanced = Perfometer(
    name = "myhostgroups_advanced",
    focus_range = FocusRange(Closed(0), Closed(100)),
    segments = [ "services_ok_perc" ],
)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

I Perf-O-Meter sono un po' più complicati dei grafici, poiché non hanno una legenda. È quindi difficile visualizzare un intervallo di valori, specialmente quando vengono visualizzati valori assoluti. È più facile visualizzare una percentuale. Questo vale anche per l'esempio sopra riportato:

  • I nomi delle metriche vengono inseriti in segments; in questo esempio, la percentuale di servizi nello stato OK.

  • I limiti inferiore e superiore vengono inseriti in focus_range. I limiti Closedsono pensati per le metriche che possono accettare solo valori compresi tra i limiti specificati (in questo caso 0 e 100).

Inoltre, nella documentazione dell'API Graphing puoi trovare opzioni ancora più sofisticate per implementare le metriche in Perf-O-Meters, ad esempio con le classi Bidirectional e Stacked, che permettono di visualizzare più Perf-O-Meters in uno solo.

Il file di grafici per questo capitolo è disponibile su GitHub. Tra le altre cose, questo file contiene le definizioni delle metriche per i quattro valori misurati e i due valori calcolati.

7. Formattazione dei numeri

I numeri vengono spesso visualizzati nell'Summarye e nell'Detailse di un servizio. Per rendere la formattazione pulita e corretta il più semplice possibile per te, e anche per standardizzare l'output di tutti i plug-in di controllo, ci sono funzioni di supporto per visualizzare i vari tipi di grandezze. Tutte queste sono sottofunzioni del modulo render e vengono quindi chiamate con render.. Ad esempio, render.bytes(2000) produce il testo 1.95 KiB.

Ciò che accomuna tutte queste funzioni è che il loro valore viene mostrato in una cosiddetta unità canonica o naturale. Questo significa che non devi mai pensarci e non ci sono difficoltà o errori durante la conversione. Ad esempio, i tempi sono sempre indicati in secondi, e le dimensioni di hard disk, file, ecc. sono sempre indicate in byte e non in kilobyte, kibibyte, blocchi o altre unità che potrebbero creare confusione.

Usa queste funzioni anche se la visualizzazione non ti piace molto. In ogni caso, sarà standardizzata per l’utente. Le versioni future di Checkmk potrebbero essere in grado di modificare la visualizzazione o addirittura renderla configurabile dall’utente, come già avviene, ad esempio, con la visualizzazione della temperatura. Anche il tuo plug-in di controllo ne trarrà vantaggio.

Prima di poter utilizzare la funzione render nel tuo plug-in di controllo, devi anche importarla:

from cmk.agent_based.v2 import render
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Dopo questa descrizione dettagliata di tutte le funzioni di visualizzazione (funzioni di rendering), troverai un riepilogo sotto forma di una tabella di facile lettura.

7.1. Orari, intervalli di tempo, frequenze

Le specifiche temporali assolute (timestamp) sono formattate con render.date() o render.datetime(). Le informazioni sono sempre fornite come tempo Unix, ovvero in secondi a partire dal 1° gennaio 1970, 00:00:00 UTC — l'inizio dell'epoca Unix. Questo è anche il formato utilizzato dalla funzione Python time.time().

Il vantaggio di questa rappresentazione è che è molto facile da calcolare, ad esempio per determinare un intervallo di tempo, quando si conoscono l'ora di inizio e quella di fine. La formula è semplicemente duration = end - start. Questi calcoli funzionano indipendentemente dal fuso orario, dai cambiamenti dell'ora legale o dagli anni bisestili.

render.date() restituisce solo la data, mentre render.datetime() aggiunge l'ora. Il risultato dipende dal fuso orario corrente in cui si trova il server Checkmk che sta eseguendo il controllo. Esempi:

Chiama Risultato

render.date(0)

1970-01-01

render.datetime(0)

1970-01-01 01:00:00

render.date(1700000000)

2023-11-14

render.datetime(1700000000)

2023-11-14 23:13:20

Non stupirti se render.datetime(0) non restituisce 00:00 come ora, ma 01:00. Questo perché stiamo scrivendo questa Guida utente nel fuso orario della Germania, che è un'ora avanti rispetto all'ora UTC standard (almeno durante l'ora solare, perché il 1° gennaio non è in ora legale).

Per gli intervalli di tempo (o periodi di tempo) c'è anche la funzione render.timespan(). A questa viene fornita una durata in secondi e la restituisce in un formato leggibile. Per periodi di tempo più lunghi, i secondi o i minuti vengono omessi. Se hai un intervallo di tempo in un oggetto TimeDelta, usa la funzione total_seconds() per leggere il numero di secondi come numero in virgola mobile.

Chiama Output

render.timespan(1)

1 second

render.timespan(123)

2 minutes 3 seconds

render.timespan(12345)

3 hours 25 minutes

render.timespan(1234567)

14 days 6 hours

Una frequenza è in pratica il reciproco del tempo. L'unità canonica è l'Hz, che equivale a 1 / sec (il reciproco di un secondo). Un esempio del suo utilizzo è la frequenza di clock di una CPU:

Chiama Output

render.frequency(111222333444)

111 GHz

7.2. Byte

Quando si parla di memoria di lavoro, file, dischi rigidi, file system e simili, l'unità canonica è il byte. Dato che i computer di solito organizzano queste cose in potenze di due, per esempio in unità da 512, 1024 o 65.536 byte, si è stabilito fin dall'inizio che un kilobyte non è 1000, e quindi mille volte l'unità, ma 1024 (2 alla potenza di 10) byte. Questo è certamente illogico, ma molto pratico perché di solito si ottengono numeri tondi. Il leggendario Commodore C64 aveva 64 kilobyte di memoria e non 65.536.

Purtroppo, a un certo punto i produttori di hard disk hanno avuto l'idea di specificare le dimensioni dei loro dischi in unità da 1000. Dato che la differenza tra 1000 e 1024 è del 2,4% per ciascuna dimensione, e queste vengono moltiplicate, un disco da 1 GB (1024 per 1024 per 1024) diventa improvvisamente 1,07 GB. Questo vende meglio.

Questa fastidiosa confusione esiste ancora oggi e continua a generare errori. Per ovviare a questo problema, la Commissione Elettrotecnica Internazionale (IEC) ha definito nuovi prefissi basati sul sistema binario. Di conseguenza, oggi un kilobyte è ufficialmente 1000 byte e un kibibyte è 1024 byte (2 alla potenza di 10). Inoltre, si dovrebbe dire mebibyte, gibibyte e tebibyte. Le abbreviazioni sono quindi KiB, MiB, GiB e TiB.

Checkmk si attiene a questo standard e ti aiuta con una serie di funzioni di rendering personalizzate per assicurarti di ottenere sempre il risultato corretto. Ad esempio, c'è la funzione "render.disksize()" pensata appositamente per i dischi rigidi e i file system, che produce il suo output in potenze di 1000.

Chiama Output

render.disksize(1000)

1.00 kB

render.disksize(1024)

1.02 kB

render.disksize(2000000)

2.00 MB

Quando si parla delle dimensioni dei file, spesso si usa specificare la dimensione esatta in byte senza arrotondamenti. Questo ha il vantaggio di permetterti di vedere molto rapidamente se un file è cambiato anche minimamente o se due file sono (probabilmente) uguali. Per questo si usa la funzione render.filesize():

Chiamata Output

render.filesize(1000)

1,000 B

render.filesize(1024)

1,024 B

render.filesize(2000000)

2,000,000 B

Se vuoi visualizzare un valore che non sia la dimensione di un disco rigido o di un file, usa semplicemente la funzione generica render.bytes(). In questo modo otterrai il risultato nella "classica" notazione ufficiale a potenze di 1024:

Chiama Output

render.bytes(1000)

1000 B

render.bytes(1024)

1.00 KiB

render.bytes(2000000)

1.91 MiB

7.3. Larghezze di banda, velocità di trasmissione

I networker hanno i loro termini e modi di esprimersi. E come sempre, Checkmk fa di tutto per adottare il modo convenzionale di comunicare in ogni ambito. Ecco perché ci sono tre diverse funzioni di rendering per le velocità di trasmissione dati. Ciò che tutte hanno in comune è che le velocità sono espresse in byte al secondo, anche se l'output effettivo è in bit!

render.nicspeed() rappresenta la velocità massima di una scheda di rete o di una porta di uno switch. Poiché non si tratta di valori misurati, non è necessario arrotondare. Sebbene nessuna porta possa inviare singoli bit, i dati sono espressi in bit per ragioni storiche.

Importante: Tuttavia, anche qui devi passare i byte al secondo!

Chiama Output

render.nicspeed(12500000)

100 MBit/s

render.nicspeed(100000000)

800 MBit/s

render.networkbandwidth() è destinato a una velocità di trasmissione effettivamente misurata nella rete. Il valore di input è di nuovo in byte al secondo:

Chiama Output

render.networkbandwidth(123)

984 Bit/s

render.networkbandwidth(123456)

988 kBit/s

render.networkbandwidth(123456789)

988 MBit/s

Quando non c'è una rete coinvolta ma vengono comunque visualizzate velocità di trasmissione dati, si usa di nuovo l'unità byte. Il caso più comune è la velocità di I/O dei dischi rigidi. Per questo si usa la funzione "render.iobandwidth()", che in Checkmk funziona con potenze di 1000:

Chiama Output

render.iobandwidth(123)

123 B/s

render.iobandwidth(123456)

123 kB/s

render.iobandwidth(123456789)

123 MB/s

7.4. Percentuali

La funzione render.percent() rappresenta una percentuale, arrotondata a due cifre decimali. È un'eccezione rispetto alle altre funzioni in quanto non restituisce il valore naturale effettivo, cioè il rapporto, ma la percentuale reale. Ad esempio, se qualcosa è pieno per metà, non devi passare 0.5 ma 50.

Poiché a volte può essere interessante sapere se un valore è quasi zero o esattamente zero, i valori vengono contrassegnati aggiungendo il carattere ‘<’, per i valori che sono maggiori di zero ma inferiori allo 0,01%.

Chiama Output

render.percent(0.004)

<0.01%

render.percent(18.5)

18.50%

render.percent(123)

123.00%

7.5. Riepilogo

In conclusione, ecco una panoramica di tutte le funzioni di rendering:

Funzione Input Descrizione Esempio di output

date()

Tempo Unix

Data

2023-11-14

datetime()

Tempo Unix

Data e ora

2023-11-14 23:13:20

timespan()

Secondi

Durata / età

3 hours 25 minutes

frequency()

Hz

Frequenza (ad es. frequenza di clock)

111 GHz

disksize()

Byte

Dimensione di un disco rigido, base 1000

1.234 GB

filesize()

Byte

Dimensione di un file, precisione totale

1,334,560 B

bytes()

Byte

Dimensione, base 1024

23.4 KiB

nicspeed()

Byte al secondo

Velocità della scheda di rete

100 MBit/s

networkbandwidth()

Byte al secondo

Velocità di trasmissione

23.50 GBit/s

iobandwidth()

Byte al secondo

Larghezze di banda I/O

124 MB/s

percent()

Valore percentuale

Percentuale, arrotondata in modo significativo

99.997%

8. Risoluzione dei problemi

La corretta gestione degli errori (purtroppo) occupa gran parte del lavoro di programmazione. La buona notizia è che l'API Check ti solleva già da gran parte del lavoro di gestione degli errori. Per alcuni tipi di errori, quindi, è meglio non gestirli affatto da solo.

Se Python si imbatte in una situazione in qualche modo inaspettata, reagisce con una cosiddetta eccezione. Ecco alcuni esempi:

  • Converti una stringa in un numero con int(), ma la stringa non contiene un numero, ad esempio int("foo").

  • Usi bar[4] per accedere al quinto elemento di bar, ma questa contiene solo quattro elementi.

  • Stai chiamando una funzione che non esiste.

Per decidere come gestire gli errori, è importante innanzitutto conoscere il punto esatto del codice in cui si verifica l'errore. Puoi utilizzare sia la GUI che la riga di comando per farlo, a seconda di dove stai lavorando al momento.

8.1. Eccezioni e rapporti di crash nell'interfaccia grafica

Se si verifica un'eccezione durante il monitoraggio o durante il rilevamento dei servizi nell'Setup, l'Summary contiene i riferimenti al rapporto di crash appena creato. Ad esempio, apparirà così:

A service whose check plug-in has crashed.

Cliccando sull'icona dell'Icon for a crashed check plug-in. si apre una pagina con i dettagli in cui puoi:

  • puoi vedere il file in cui si è verificato il crash,

  • ricevere tutte le informazioni relative al crash, come l'elenco degli errori verificatisi nel programma (traceback), i valori attuali delle variabili locali, l'output dell'agente e molto altro ancora, e

  • inviarci (Checkmk GmbH) il rapporto come feedback.

Il traceback ti aiuta, in qualità di sviluppatore, a decidere se c'è un errore nel programma (ad es. la chiamata di una funzione inesistente) o se i dati dell'agente non sono stati elaborati come previsto. Nel primo caso vorrai correggere l'errore, nel secondo caso spesso ha senso non fare nulla.

L'invio del rapporto è ovviamente utile solo per i plug-in di controllo che fanno ufficialmente parte di Checkmk. Se metti a disposizione di terzi i tuoi plug-in, puoi chiedere ai tuoi utenti di inviarti i dati.

8.2. Visualizzazione delle eccezioni dalla riga di comando

Se esegui il tuo plug-in di controllo dalla riga di comando, non riceverai alcuna indicazione dell'ID di eventuali rapporti di crash generati. Vedrai solo il messaggio di errore riassuntivo:

OMD[mysite]:~$ cmk --detect-plugins=myhostgroups_advanced localhost
Error in agent based plugin myhostgroups: invalid syntax (myhostgroups.py, line 11)
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se aggiungi l'opzione --debug come parametro di chiamata aggiuntivo, riceverai il traceback dall'interprete Python:

OMD[mysite]:~$ cmk --debug --detect-plugins=myhostgroups_advanced localhost
Traceback (most recent call last):
  File "/omd/sites/mysite/lib/python3/cmk/discover_plugins/_python_plugins.py", line 195, in add_from_module
    module = importer(mod_name, raise_errors=True)
             ^^^^^^^^^^^^^
  File "/omd/sites/mysite/lib/python3/cmk/discover_plugins/_python_plugins.py", line 156, in _import_optionally
    return importlib.import_module(module_name)
           ^^^^^^^^^^^^
  File "/omd/sites/mysite/lib/python3.12/importlib/init.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/omd/sites/mysite/local/lib/python3/cmk_addons/plugins/myhostgroups/agent_based/myhostgroups.py", line 110, in <module>
    agent_section_myhostgroups == AgentSection(
    ^^^^^^^^^^
NameError: name 'agent_section_myhostgroups' is not defined
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se l'errore non si verifica nuovamente la prossima volta che chiami --debug, ad esempio perché è disponibile un nuovo output dell'agente, puoi anche visualizzare gli ultimi rapporti di crash nel file system:

OMD[mysite]:~$ ls -lhtr ~/var/check_mk/crashes/check/ | tail -n 5
drwxrwxr-x 2 mysite mysite 4.0K Aug  6 17:56 7b59a49e-540c-11ef-9595-7574c603ce8d/
drwxrwxr-x 2 mysite mysite 4.0K Aug  6 17:56 7c8870c0-540c-11ef-9595-7574c603ce8d/
drwxrwxr-x 2 mysite mysite 4.0K Aug  6 17:56 7cf9626c-540c-11ef-9595-7574c603ce8d/
drwxrwxr-x 2 mysite mysite 4.0K Aug  6 17:56 7d192d68-540c-11ef-9595-7574c603ce8d/
drwxrwxr-x 2 mysite mysite 4.0K Aug  6 17:56 7e2d5ec2-540c-11ef-9595-7574c603ce8d/
Copia i comandi negli appunti
Comandi copiati con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

In ciascuna di queste cartelle ci sono due file:

  1. crash.info contiene un dizionario Python con il traceback e molte altre informazioni. Spesso basta dare un'occhiata al file con il Pager.

  2. agent_output contiene l'output completo dell'agente che era attivo al momento del crash.

8.3. Output di debug personalizzato

Negli esempi mostrati sopra, usiamo la funzione print() per visualizzare il contenuto delle variabili o la struttura degli oggetti per te come sviluppatore. Queste funzioni per l'output di debug devono essere rimosse dal plug-in di controllo finito.

In alternativa alla rimozione, puoi anche far visualizzare l'output di debug solo quando il plug-in di controllo viene richiamato dalla console in modalità debug. Per farlo, importa l'oggetto debug dalla toolbox di Checkmk e, se necessario, l'aiuto alla formattazione pprint(). Ora puoi generare l'output di debug in base al valore dell'oggetto debug:

Tip

L'oggetto debug ha cambiato percorso tra Checkmk 2.3.0 e 2.4.0. Invece della precedente posizione cmk.utils ora si trova in cmk.ccc. Il codice portatile tenta prima di importare dal nuovo percorso per poi ripiegare su quello vecchio in caso di errore.

try:
    from cmk.ccc import debug
except ImportError:
    from cmk.utils import debug

from pprint import pprint

def check_mystuff(section):
    if debug.enabled():
        pprint(section)
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Tieni presente che qualsiasi output di debug rimanente dovrebbe essere usato con parsimonia e limitato a suggerimenti che aiutino gli utenti successivi con il debug. Gli errori utente ovvi e prevedibili (ad esempio, che il contenuto della sezione agente indichi che il plug-in dell'agente è stato configurato in modo errato) dovrebbero ricevere come risposta lo stato UNKNOWN e includere note esplicative nel riepilogo.

8.4. Output dell'agente non valido

La domanda è: come dovresti reagire se l'output dell'agente non è nella forma che ti aspetti, sia che provenga dall'agente Checkmk o che sia ricevuto tramite SNMP. Supponiamo che ti aspetti sempre tre parole per riga, cosa dovresti fare se ne ricevi solo due?

Beh, se questo è un comportamento consentito e noto dell'agente, allora ovviamente devi intercettarlo e lavorare con una distinzione di casi. Tuttavia, se questo non è effettivamente consentito, allora è meglio comportarsi come se la riga fosse sempre composta da tre parole, ad esempio con la seguente funzione di analisi:

def parse_foobar(string_table):
    for foo, bar, baz in string_table:
        # ...
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se c'è una riga che non è composta esattamente da tre parole, viene generata un'eccezione e ricevi l'utilissimo rapporto di crash appena menzionato.

Se accedi a chiavi in un dizionario che potrebbero occasionalmente mancare, può ovviamente avere senso reagire di conseguenza. Questo può essere fatto impostando il servizio su CRIT o UNKNOWN e inserendo una nota nel riepilogo riguardo all'output dell'agente che non può essere valutato. In ogni caso, è meglio usare la funzione get() del dizionario per questo piuttosto che intercettare l'eccezione KeyError. Questo perché get() restituisce un oggetto di tipo None o una sostituzione opzionale da passare come secondo parametro se la chiave non è disponibile:

def check_foobar(section):
    foo = section.get("bar")
    if not foo:
        yield Result(state=State.CRIT, summary="Missing key in section: bar")
        return
    # ...
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

8.5. Elementi mancanti

Cosa succede se l'agente restituisce dati corretti, ma l'elemento da controllare manca? Come in questo caso, ad esempio:

def check_foobar(item, section):
    # Try to access the item as key in the section:
    foo = section.get(item)
    if foo:
        yield Result(state=State.OK, summary="Item found in monitoring data")
    # If foo is None, nothing is yielded here
Copia il contenuto del file negli appunti
Contenuto del file copiato con successo negli appunti!
L'accesso in scrittura agli appunti è stato negato!

Se l'elemento che stai cercando non è presente, il ciclo viene eseguito e Python semplicemente esce alla fine della funzione senza restituire un risultato tramite yield. Ed è proprio questo l'approccio corretto! Perché Checkmk riconosce che l'elemento da monitorare manca e genera lo stato corretto e un testo standard appropriato con UNKNOWN.

8.6. Test con i file di spool

Se vuoi simulare particolari output dell'agente, i file nella directory spool sono molto utili. Puoi usarli per testare casi limite che altrimenti sarebbero difficili da ricreare. Oppure puoi usare direttamente l'output dell'agente che ha portato a un rapporto di crash per testare le modifiche a un plug-in di controllo.

Per prima cosa disattiva il tuo plug-in dell'agente normale, ad esempio revocandone l'autorizzazione all'esecuzione. Quindi crea un file nella directory /var/lib/check_mk_agent/spool/ che contenga la sezione dell'agente (o le sezioni dell'agente previste) che il tuo plug-in di controllo si aspetta, inclusa l'intestazione della sezione, e che termini con un carattere di nuova riga. La prossima volta che l'agente verrà chiamato, verrà trasferito il contenuto del file di spool invece dell'output del plug-in dell'agente.

8.7. I vecchi plug-in di controllo diventano lenti per molti servizi

Con alcuni plug-in di controllo che utilizzano elementi, è possibile che su server di grandi dimensioni vengano generati diverse centinaia di servizi. Se non viene utilizzata una funzione di analisi separata, ciò significa che l'intero elenco di centinaia di righe deve essere elaborato per ciascuno dei centinaia di elementi. Il tempo necessario per la ricerca aumenta quindi in proporzione al quadrato del numero di elementi elencati, il che significa decine di migliaia di confronti per centinaia di servizi. Se, invece, l'elenco annidato viene trasferito in un dizionario, il tempo necessario per cercare un elemento aumenta solo in modo lineare con la dimensione del dizionario.

Nel wiki di Python troverai una panoramica dei costi di ricerca in diversi tipi di dati, compresa una spiegazione e la notazione O. L'uso della funzione parse riduce la complessità della ricerca da O(n) a O(1).

Poiché le versioni precedenti di questo articolo non utilizzavano la funzione parse, dovresti identificare tali plug-in di controllo e riscriverli in modo da utilizzare la funzione parse.

9. Migrazione

L'API Check V1 introdotta nella versione 2.0.0 di Checkmk è stata supportata fino alla versione 2.3.0, ma non lo è più nella versione attuale 2.4.0. Per continuare a utilizzare i tuoi plugin di controllo, devi migrarli alle nuove API mentre sei ancora su 2.3.0.

Le seguenti informazioni ti aiuteranno nella migrazione dei plugin di controllo dall'API Check V1 alla V2:

  • La nuova struttura delle directory e la convenzione di denominazione per l'archiviazione dei file per tutte le API dei plugin sono disponibili nella documentazione API sulla pagina principale Checkmk’s Plug-in APIs.

  • Il riepilogo delle modifiche nell'API Check V2 è disponibile anche nella documentazione API all'indirizzo Checkmk’s Plug-in APIs > Agent based ('Check API') > Version 2 > New in this version. Lì troverai anche il link a un commit GitHub che migra il plugin di controllo esistente apt all'API Check V2.

  • Su GitHub troverai degli script nella directory treasures di Checkmk che ti aiuteranno a migrare alle nuove API.

Important

Forniamo i file nella directory treasures perché potrebbero essere utili alla nostra community. Tuttavia, non fanno parte del prodotto Checkmk stesso. Gli script in treasures sono esclusi dal supporto. Usa questi script a tuo rischio e pericolo.

10. File e cartelle

Percorso del file Descrizione

~/local/lib/python3/cmk_addons/plugins/

Directory di base per l'archiviazione dei file dei plug-in.

~/local/lib/python3/cmk_addons/plugins/<plug-in_family>/agent_based/

Posizione di archiviazione per i plug-in di controllo scritti secondo l'API Check V2.

~/local/lib/python3/cmk_addons/plugins/<plug-in_family>/rulesets/

Percorso di archiviazione per i file dei set di regole creati secondo l'API Rulesets.

~/local/lib/python3/cmk_addons/plugins/<plug-in_family>/graphing/

Percorso di archiviazione per i file di grafici creati secondo la Graphing API.

/usr/lib/check_mk_agent/plugins/

Questa directory si trova su un host Linux monitorato. L'agente Checkmk per Linux si aspetta di trovare qui le estensioni dell'agente (plug-in dell'agente).


Last modified: Wed, 01 Apr 2026 14:11:35 GMT via commit e942b8dca
In questa pagina