Building a Perl Script for High Availability Monitoring in Centreon
Tags: monitoring, centreon, perl, linux
Published: 2023-09-05 15:43:36

In today's interconnected world, high availability is crucial for ensuring uninterrupted services. One way to achieve this is by monitoring the availability of hosts using tools like Centreon. In this blog post, we will explore how to create a Perl script that checks the high availability between two hosts in Centreon by monitoring their ping services.

## Why Ping Services?
![Why ?](https://media.tenor.com/tDQXUq-HakUAAAAM/why-just-why.gif)
Ping is a commonly used network diagnostic utility that sends ICMP echo request packets to a target host and waits for an ICMP echo reply. By monitoring the ping service of two hosts, we can determine if they are reachable and responsive.

### Requirements:
 To follow along with this tutorial, you will need:
- Perl installed on your system.
- A working installation of Centreon or any other compatible monitoring platform.
- Access privileges to configure monitors and execute scripts on the monitored hosts.

## Step 1: Setting Up Centreon Ping Services

Before diving into scripting, ensure that both hosts have ping services configured in Centreon as part of their monitoring templates or custom configurations. This ensures that the necessary checks are already running from within Centreon's infrastructure.

## Step 2: Creating the Perl Script

Open your favorite text editor and start creating your Perl script with these steps:

We start with the shebang (#!/usr/bin/perl) followed by some use statements that import necessary modules as strict, DBI (for database connectivity), Text::Diff and Pod::Text::Termcap.

``` perl
#!/usr/bin/perl

use strict;
use DBI;
use Text::Diff;

use Pod::Text::Termcap;

use Time::localtime;
```
Next, we need to define constant definitions for different states: OK, WARNING, CRITICAL, UNKNOWN.

```perl
use constant OK       => 0;
use constant WARNING  => 1;
use constant CRITICAL => 2;
use constant UNKNOWN  => 3;
```
We also need to check if the required Monitoring::Plugin module or Nagios::Plugin module is available. If not found, it prints an error message and exits with an UNKNOWN state.

```perl
my $pkg_monitoring_available = 0;
BEGIN {
    my $pkg_nagios_available = 0;
    eval {
        require Monitoring::Plugin;
        require Monitoring::Plugin::Functions;
        require Monitoring::Plugin::Threshold;
        $pkg_monitoring_available = 1;
    };
    if (!$pkg_monitoring_available) {
        eval {
            require Nagios::Plugin;
            require Nagios::Plugin::Functions;
            require Nagios::Plugin::Threshold;
            *Monitoring::Plugin:: = *Nagios::Plugin::;
            $pkg_nagios_available = 1;
        };
            }
    if (!$pkg_monitoring_available && !$pkg_nagios_available) {
        print("UNKNOWN - Unable to find module Monitoring::Plugin or Nagios::Plugin\n");
        exit UNKNOWN;
    }
}
```
Two arguments (firstHostServiceId and secondHostServiceId) are added using add_arg() method to define command-line options for specifying service IDs of the first host and second host respectively.

```perl
my $mp = Monitoring::Plugin->new(
    shortname => "High Availability of two hosts",
    usage => "",
    extra => $extra_doc_output
);

$mp->add_arg(
    spec    => 'firstHostServiceId|id1=s',
    help    => 'service id of the first host status',
    required => 1
);

$mp->add_arg(
    spec    => 'secondHostServiceId|id2=s',
    help    => 'service id of the second host status',
    required => 1
);
```
Connects to Centreon MySQL database using DBI->connect()
```perl
# Connect to Centreon MySQL database
my $dbh = DBI->connect("DBI:mysql:centreon_storage:localhost", $user, $password)
  or die wrap_exit(UNKNOWN, $$DBI::errstr) ;
```


We need to prepare and execute SQL query to retrieve the output and name of the service associated with $firstService_id from the services table. The results are stored in variables $firstHostStatusOutput and $firstHostStatusName.

```perl
my $sth = $dbh->prepare("
  SELECT t1.output, t2.name
  FROM services t1
  JOIN hosts t2
  ON t1.host_id=t2.host_id
  WHERE service_id = ?
  LIMIT 1
");
$sth->execute($firstService_id)
  or die "Cannot execute SQL statement: $DBI::errstr";
my ($firstHostStatusOutput, $firstHostStatusName) = $sth->fetchrow_array;

$sth->execute($secondService_id)
  or die "Cannot execute SQL statement: $DBI::errstr";
my ($secondHostStatusOutput, $secondHostStatusName) = $sth->fetchrow_array;
```

Now we need to add the important part that checks the status of two hosts. If both hosts have an "OK" status, it adds a message stating that both hosts are OK. If either host has a "CR" (Critical) status, it sets the check state as CRITICAL and determines which host is critical to add an appropriate message. If neither condition matches, indicating that both hosts are considered critical, it sets the check state as CRITICAL and adds a generic message indicating that both hosts are critical.

```perl
my $check_state = OK;

# Check if both strings have 'OK'
if ($firstHostStatusOutput =~ /OK/ && $secondHostStatusOutput =~ /OK/) {
    $mp->add_message(
        $check_state,
        sprintf(
            'Both Hosts are OK'
        )
    );
}
# Check if either host has 'CR'
elsif ($firstHostStatusOutput =~ /CR/ || $secondHostStatusOutput =~ /CR/) {
    my $result = ($firstHostStatusOutput =~ /CR/) ? "$firstHostStatusName host is CRITICAL" : "$secondHostStatusName host is CRITICAL";
    $check_state = CRITICAL;
    $mp->add_message(
        $check_state,
        sprintf(
            $result
        )
    );
}
else {
    $check_state = CRITICAL;
    $mp->add_message(
        $check_state,
        sprintf(
            'Both hosts are CRITICAL.'
        )
    );
}
```

## Step 3: Running the Script

Save the Perl script with a descriptive name like high_availability_check.pl, and make it executable by running chmod +x high_availability_check.pl

To run this script, open your terminal and navigate to its location. Then execute:

```console
./high_availability_check.pl id1=<id1number> id2=<id2number>
```

The output will indicate whether both hosts are reachable or if high availability has been compromised.

After implementing the script in a service, the result can be viewed in Centreon.


![Result in Centreon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dm9u7x9i3wua6wrcwf0l.png)



In this blog post, we explored how to create a Perl script that checks high availability between two hosts in Centreon by monitoring their ping services. By incorporating this custom script into your monitoring workflow, you can proactively identify potential downtime issues and take appropriate actions to ensure uninterrupted services.

Remember, while ping-based checks provide basic connectivity information, additional service-level checks may be necessary depending on your specific requirements. Feel free to customize this script further or explore other monitoring techniques provided by Centreon to enhance your high availability monitoring capabilities.

_Happy monitoring!_