12. 06. 2017 Davide Bizzarri Development, NetEye

Come estendere o modificare le NetEye API

NetEye API

Introduzione

Le NetEye API offrono un metodo semplice per automatizzare e scriptare i processi più comuni su NetEye. Le NetEye API offrono oltre 150 oggetti scritti in Perl che possono essere facilmente utilizzati e estesi a proprio piacimento. Le azioni più comuni che possiamo compiere con le NetEye API sono: aggiungere/modificare/rimuovere un host, servizio o businessprocess da Nagios e anche calcolare l’availability di essi in qualsiasi range di tempo.
Le NetEye API sono Open Source e il codice Perl viene installato in /var/lib/neteye/API se pero’ modifichiamo questo codice Perl al primo aggiornamento delle API le nostre modifiche verranno sovrascritte. Ecco che quindi in questa guida andremo a spiegare come apportare delle modifiche permanenti alle NetEye API.

Prerequisiti

  • Conoscere Perl
  • Conoscere NetEye e i sui funzionamenti di base
  • Avere un’installazione di NetEye

Qusta guida e’ stata testata sulla versione 3.9 di NetEye e’ possibile che anche versioni piu’ vecchie o piu’ nuove di NetEye siano compatibili con questa guida ma non e’ garantito.

Un semplice script

Partiremo da questo script che lista tutti Servizi dell’Host neteye e il comando che viene eseguito per ogni servizio da Nagios.

use warnings;
use strict;

use NetEye::Config;
use NetEye::Monitoring::Host;

# Create the NetEye Config Object
# this object manage the entire configuration of NetEye and for
# for this reason it is required by many other objects
my $ConfigObject = NetEye::Config->new(
        AutoPersist => 0
);

# Search for the host with the name 'neteye' and return the object representing the host
my $NetEyeHost = NetEye::Monitoring::Host->;new(
        ConfigObject => $ConfigObject 
)->searchForObject(
        Properties => { name => 'neteye' }
);

# Retrive all services of the host neteye
# services is an array of service objects
my $Services = $NetEyeHost->getServices();

# Loop inside all services
for my $Service ( @{$Services} ) {

        # Retrive the ServiceName object of the actual Service
        my $ServiceName = $Service->getServiceName();

        # Prin in a line the name of the Host, the name of the Service and the command of the Service
        printf("Host: %s, Service: %s, Command: '%s'\n", $NetEyeHost->get('name'), $ServiceName->get('name'), $Service->get('command_line') // '');
}

1;

Eseguiamo quindi lo script e il risultato assomiglierà a questo:

$ perl ListHostServices.pl
Host: neteye, Service: Local_NetEye_Hardware_Status, Command: ''
Host: neteye, Service: Local_NetEye_Service_Status, Command: ''
Host: neteye, Service: Local_PerfData_Freschness, Command: 'check_perfdata!-c 500 -R -C'
Host: neteye, Service: Local_Total_Processes, Command: 'check_local_procs!150!200!RSZDT'
Host: neteye, Service: SMSD_Fileage, Command: 'check_file_age!30!180!/var/log/smstools.log'
Host: neteye, Service: SMSD_Process_running, Command: 'check_procs_process!2:2!2:2!smsd'
Host: neteye, Service: SMSD_SMS_QUEUE, Command: ''
Host: neteye, Service: SMSD_Modem_Status, Command: 'check_modem_smst! '
Host: neteye, Service: OCSNG_Duplicate_Hosts, Command: 'check_ocs_inventory!duplicates -x "localhost"'
Host: neteye, Service: OCSNG_Outdated_Items, Command: 'check_ocs_inventory!age -w 30 -c 90'

Come potete vedere dall’esempio appena mostrato le NetEye API non devono essere incluse poichè esse vengono incluse automaticamente. Questo succede perché la variabile d’ambiente PERL5LIB include la path assoluta alle NetEye API. Per verificare questo basta eseguire il comando env in una shell linux su NetEye.

$ env
HOSTNAME=host
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
PERL5LIB=/var/lib/neteye/API/perl
...

Aggingiamo un nuovo metodo all’oggetto Host

Come accennato prima non possiamo modificare direttamente l’oggetto Host che si trova in /var/lib/neteye/API/perl/NetEye/Monitoring/Host.pm poiché al primo update esso verrà sovrascritto. Per fare questo quindi andremo a creare una nuova file in /var/lib/neteye/API/perl/Extend/Monitoring/Host.pm. Se le directory Extend e Monitoring non esistono dobbiamo crearle.
Ora inseriamo all’interno del file Host.pm il seguente contenuto:

package NetEye::Monitoring::Host;

sub getServiceNames {
        my ( $Self ) = @_;

        my @ServiceNames;
        my $Services = $Self->getServices();

        for my $Service ( @{$Services} ) {
                push @ServiceNames, $Service->getServiceName();
        }

        return \@ServiceNames;
}

1;

Nella prima righa abbiamo scritto package NetEye::Monitoring::Host anche se il file si trova in Extend/Monitoring/Host.pm. In questo modo diciamo a Perl che tutte le funzioni in Extend/Monitoring/Host.pm fanno parte del modulo NetEye::Monitoring::Host.
Creiamo quindi un nuovo script molto simile a quello precedente con il seguente contenuto:

use warnings;
use strict;

use NetEye::Config;
use NetEye::Monitoring::Host;

# Include the file Extend/Host.pm to extend NetEye::Monitoring::Host
use Extend::Monitoring::Host;

my $Config = NetEye::Config->new(
        AutoPersist => 0
);

my $NetEyeHost = NetEye::Monitoring::Host->new(
        ConfigObject => $Config
)->searchForObject(
        Properties => { name => 'neteye' }
);

my $ServiceNames = $NetEyeHost->getServiceNames();

for my $ServiceName ( @{$ServiceNames} ) {

        printf("Host: %s, Service: %s\n", $NetEyeHost->get('name'), $ServiceName->get('name'));
}

1;

Sovrascriviamo un metodo dell’oggetto Host

Ipotizziamo che ora vogliamo che il metodo getServices() in Host restituisca solo i servizi che hanno un comando (Param command_line). Per fare questo possiamo creare una nuovo metodo che filtra i servizi restituiti da getServices() ma possiamo anche sovrascrivere il metodo getServices() in modo che ci restituisca solo i servizi filtrati. La seconda opzione è sconsigliata ma può essere che vi siamo dei casi in cui è necessaria.
Per fare ciò torniamo nel file Extend/Monitoring/Host.pm e modifichiamolo in questo modo:

package NetEye::Monitoring::Host;

sub getServices {
    my ( $Self, %Param ) = @_;

        my $ServiceHelper = NetEye::Monitoring::Service->new(
                ConfigObject => NetEye::Config->new( AutoPersist => 0 ),
        );

        my @Services = $ServiceHelper->searchFor(
                Properties => { 'host_id' => $Self->getId(), },
        );

        my @FilteredServices;
        for my $Service ( @Services ) {
                if ( $Service->get('command_line') ) {
                        push @FilteredServices, $Service;
                }
        }

        return \@FilteredServices;
}

1;

Ora torniamo al primo script che avevamo fatto e aggiungiamo il modulo Extend::Monitoring::Host. Il risultato sarà questo:

use warnings;
use strict;

use NetEye::Config;
use NetEye::Monitoring::Host;
use Extend::Monitoring::Host;

my $Config = NetEye::Config->new(
        AutoPersist => 0
);

my $NetEyeHost = NetEye::Monitoring::Host->new(
        ConfigObject => $Config
)->searchForObject(
        Properties => { name => 'neteye' }
);

my $Services = $NetEyeHost->getServices();

for my $Service ( @{$Services} ) {

        my $ServiceName = $Service->getServiceName();

        printf("Host: %s, Service: %s, Command: '%s'\n", $NetEyeHost->get('name'), $ServiceName->get('name'), $Service->get('command_line') // '');
}

1;

Ed eseguiamolo di nuovo. Il nuovo risultato ottenuto sara simile a questo:

$ perl ListHostServices.pl
Host: neteye, Service: HTTP, Command: 'check_http!-a $USER3$'
Host: neteye, Service: Local Disks Free Space, Command: 'check_local_disk!20%!10%'
Host: neteye, Service: PING, Command: 'check_ping!100.0,20%!500.0,60%'
Host: neteye, Service: MYSQL, Command: 'check_mysql!-uroot'
Host: neteye, Service: Local LOAD, Command: 'check_local_load!8,7,6!12,11,10'
Host: neteye, Service: Local Uptime, Command: 'check_local_uptime!15! '
Host: neteye, Service: Local_LoggedIn_Users, Command: 'check_local_users!10!20'

Potremmo notare che a differenza della prima volta che l’abbiamo eseguito ora vengono solo stampati i servizi che hanno un comando e non vengono piu’ visualizzati quelli che non ne hanno uno.

Conclusioni

Esistono molti altri metodi per raggiungere lo stesso risultato ma in questo tutorial abbiamo voluto mostrare il più semplice.

Davide Bizzarri

Davide Bizzarri

R&D Software Engineer at Würth Phoenix
Hi, I'm Davide! I’m a full stack developer at Würth Phoenix. I started to use a PC at the age of ten when my parents bought our first family PC: an old Windows 98. Then, in high school, my professor introduced me to the world of software development by teaching me my first programming language, C. Since then I began to study IT and programming languages alone. After one year, I started to develop my first website that reached over one thousand views per day. Once I finished high school, I changed my job twice, until Würth Phoenix has hired me. Here I have learned many interesting things, one of the most important once is the agile development methodology which we living every day.

Author

Davide Bizzarri

Hi, I'm Davide! I’m a full stack developer at Würth Phoenix. I started to use a PC at the age of ten when my parents bought our first family PC: an old Windows 98. Then, in high school, my professor introduced me to the world of software development by teaching me my first programming language, C. Since then I began to study IT and programming languages alone. After one year, I started to develop my first website that reached over one thousand views per day. Once I finished high school, I changed my job twice, until Würth Phoenix has hired me. Here I have learned many interesting things, one of the most important once is the agile development methodology which we living every day.

Leave a Reply

Your email address will not be published. Required fields are marked *

Archive