12. 06. 2017 Davide Bizzarri Development, NetEye

How-To: NetEye APIs erweitern und ändern

NetEye API

Einleitung

Die NetEye APIs bieten einen einfachen Weg um gängige Prozesse in NetEye zu automatisieren. Die APIs stellen über 150 in Perl geschriebene Objekte zur Verfügung, diese können frei verwendet und auch ziemlich einfach verändert bzw. erweitert werden. Die wohl gebräuchlichsten Aktionen sind dabei: das Hinzufügen/Ändern/Entfernen von Hosts, Diensten oder Business Services von Nagios und die Berechnung der Verfügbarkeit für bestimmte Zeiträume.
Die NetEye APIs sind open-source, der Perl Code wird in /var/lib/neteye/API installiert. Verändern wir diesen Code, werden die Änderungen leider beim ersten Update der APIs wieder überschrieben und gehen somit verloren. Aber natürlich gibt es auch dafür eine Lösung: In diesem Artikel werde ich Ihnen zeigen, wie Sie dauerhafte Änderungen an den NetEye APIs machen können.  

Voraussetzungen

  • Perl-Kenntnisse
  • NetEye-Kenntnisse und Kentnisse zu dessen Funktionen
  • eine NetEye-Installation

Wir haben dieses Vorgehen auf NetEye 3.9 getestet, es ist möglich, dass diese Herangehensweise auch auf älteren bzw. neueren Versionen funktioniert, dafür können wir aber nicht garantieren.

Ein einfaches Skript

Unser Ausgangspunkt ist dieses Skript, das alle Services des Hosts neteye  und den jeweiligen, auszuführenden Befehl auflistet.

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;

Wenn wir dieses Skript ausführen, erhalten wir folgendes Ergebnis:

$ 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'

Wie Sie sehen, müssen die NetEye APIs nicht extra erfasst werden da sie automatisch eingeschlossen werden. Das ist so, weil die Variablen der PERL5LIB Umgebung den absoluten Path zu den NetEye APIs beinhalten. Um dies zu kontrollieren, reicht es den Befehl env in einem Linux Shell auf NetEye auszuführen.

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

Hinzufügen einer neuen Methode im Objekt Host

Wie oben erwähnt, können wir das Objekt Host in /var/lib/neteye/API/perl/NetEye/Monitoring/Host.pm nicht direkt ändern, da die Änderungen vom nächsten Update überschrieben werden würden. Wir müssen also ein neues File in /var/lib/neteye/API/perl/Extend/Monitoring/Host.pm erstellen. Wenn es die Ordner Extend und Monitoring noch nicht gibt, müssen wir auch diese neu erstellen.
Nun fügen wir im File Host.pm folgenden Inhalt hinzu:

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;

In der ersten Zeile haben wir geschrieben package NetEye::Monitoring::Host obwohl sich das File in Extend/Monitoring/Host.pm befindet. Damit sagen wir Perl, dass alle Funktionen in Extend/Monitoring/Host.pm zum Modul NetEye::Monitoring::Host gehören.
Wir erstellen also ein neues, sehr ähnliches Skript mit diesem Inhalt:

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;

Überschreiben wir eine Methode des Objekts Host

Nehmen wir an, wir möchten, dass die Methode getServices() in Host, nur jene Services ausgibt die einen Befehl haben (Param command_line). Um das zu erreichen, erstellen wir eine neue Methode die die Services herausfiltert welche von getServices() ausgegeben werden. Wir können aber auch die Methode getServices() überschreiben damit sie uns nur jene gefilterten Services ausgibt. Diese zweite Option ist nicht zu empfehlen, allerdings gibt es Situationen in denen diese Herangehensweise notwendig ist.
Um dies zu tun kehren wir zum File Extend/Monitoring/Host.pm zurück und änder es wie folgt:

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;

Nun gehen wir zum ersten Skript zurück und ergänzen das Modul Extend::Monitoring::Host. Das Ergebnis sieht dann so aus:

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;

Und wir führen es erneut aus. Das neue Ergebnis sieht ungefähr so aus:

$ 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'

Wir können sehen, dass im Gegensatz zur ersten Ausführung nun nur jene Services ausgegeben werden die einen Befehl haben.

Es gibt verschiedene Möglichkeiten um das selbe Ergebnis zu erzielen, in diesem Artikel wollten wir Ihnen einfachsten davon erklären.

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