Skip to main content

Hi,
It is possible to develop a plugin for Microsens G7 please, G6 Plugin is not compatible and i have to monitor more than 450 devices of this kind.

Thanks.

 

NewNeeds Votes

@lordvader this is a pretty specific request. If this is a vital need for you, I advise you talk to your Centreon sales representative to check options for this custom development to be performed.


Hi Guys,

Finally i develop my own script:

 

#!/usr/bin/env perl
use strict;
use warnings;
use Net::SNMP;
use Getopt::Long;

Getopt::Long::Configure("bundling");

# --- OIDs spécifiques Microsens G7 ---
my %OID = (
  uptime                => '1.3.6.1.4.1.3181.10.7.1.1.30.101.0',
  # Temp sensors
  temp_system           => '1.3.6.1.4.1.3181.10.7.1.1.30.104.0',
  temp_switch           => '1.3.6.1.4.1.3181.10.7.1.1.30.105.0',
  temp_1gphy            => '1.3.6.1.4.1.3181.10.7.1.1.30.106.0',
  temp_5gphy            => '1.3.6.1.4.1.3181.10.7.1.1.30.107.0',
  # Ports
  port_status_table     => '1.3.6.1.4.1.3181.10.7.1.1.81.102',
  port_status_linkup    => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.2',
  port_status_linkstate => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.4',
  port_status_speed     => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.8',
  port_up        => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.2',
  # PoE
  poe_total             => '1.3.6.1.4.1.3181.10.7.1.1.33.100.0',
  poe_perport_power     => '1.3.6.1.4.1.3181.10.7.1.1.33.101.1.6',
  # G.8032 Ring status
  g8032_ring_status     => '1.3.6.1.4.1.3181.10.7.1.2.43.7.1.2',
  firmware_version     => '1.3.6.1.4.1.3181.10.7.1.1.30.109.1.0',
  system_mem    => '1.3.6.1.4.1.3181.10.7.1.1.30.108.0',
  mac_address   => '1.3.6.1.4.1.3181.10.7.1.1.30.102.0',
  operating_temp => '1.3.6.1.4.1.3181.10.7.1.1.30.104.0',
  system_util    => '1.3.6.1.4.1.3181.10.7.1.1.30.4.0',
  serial_number  => '1.3.6.1.4.1.3181.10.7.1.1.32.2.0',
  mac_address    => '1.3.6.1.4.1.3181.10.7.1.1.30.102.0',

);

# --- CLI ---
my ($host,$community,$version,$port,$timeout,$mode,$warn,$crit,$help);
my ($username,$authproto,$authpass,$privproto,$privpass);
my $debug=0;
$community='public'; $version='2c'; $port=161; $timeout=5;

GetOptions(
  "H|host=s"       => \$host,
  "C|community=s"  => \$community,
  "v|version=s"    => \$version,
  "p|port=i"       => \$port,
  "t|timeout=i"    => \$timeout,
  "m|mode=s"       => \$mode,
  "w|warning=s"    => \$warn,
  "c|critical=s"   => \$crit,
  "u|username=s"   => \$username,
  "authproto=s"    => \$authproto,
  "authpass=s"     => \$authpass,
  "privproto=s"    => \$privproto,
  "privpass=s"     => \$privpass,
  "debug!"         => \$debug,
  "h|help"         => \$help,
) or usage();

usage() if $help || !$host || !$mode;

# --- SNMP Session ---
my ($session,$error);
if ($version =~ /^3$/i) {
  my %params = (
    -hostname  => $host,
    -version   => '3',
    -port      => $port,
    -timeout   => $timeout,
    -username  => $username,
  );
  if ($authproto && $authpass) {
    $params{-authprotocol} = uc($authproto);
    $params{-authpassword} = $authpass;
  }
  if ($privproto && $privpass) {
    $params{-privprotocol} = uc($privproto);
    $params{-privpassword} = $privpass;
  }
  ($session,$error) = Net::SNMP->session(%params);
} else {
  ($session,$error) = Net::SNMP->session(
    -hostname  => $host,
    -community => $community,
    -version   => $version,
    -port      => $port,
    -timeout   => $timeout,
  );
}
if (!defined $session) { print "UNKNOWN - SNMP session error: $error\n"; exit 3; }

# --- Mode dispatcher ---
if    ($mode eq 'uptime')      { check_uptime(); }
elsif ($mode eq 'temperature') { check_temperature(); }
elsif ($mode eq 'ports')       { check_ports(); }
elsif ($mode eq 'poe')         { check_poe(); }
elsif ($mode eq 'g8032')       { check_g8032(); }
elsif ($mode eq 'firmware')    { check_firmware(); }
elsif ($mode eq 'system')      { check_system(); }
elsif ($mode eq 'info')        { check_info(); }
else { print "UNKNOWN - Mode $mode not supported\n"; exit 3; }

$session->close();
exit 0;

# --- Usage ---
sub usage {
  print <<"USAGE";
Usage: $0 -H <host> -m <mode> [options]

SNMPv2:
  -C <community> -v 2c

SNMPv3:
  -v 3 -u <user> --authproto <MD5|SHA> --authpass <authpass> [--privproto <DES|AES>] [--privpass <privpass>]

Modes:
  uptime        - uptime du switch
  temperature   - max des 4 capteurs (system/switch/1G/5G)
  ports         - état détaillé par port
  poe           - consommation PoE total + par port
  g8032         - état du Ring 1 G.8032
  firmware    - version du firmware actuel
  system    - cpu, mem, temp, serial num, mac address 
USAGE
  exit 3;
}

my %port_state = (
    0 => 'linkDown',
    1 => 'blocking',
    2 => 'learning',
    3 => 'forwarding',
    4 => 'unauthVlan',
  );

# --- Checks ---

sub check_system {
    my $resp = $session->get_request(
        -varbindlist => [
            $OID{operating_temp},
            $OID{system_util},
            $OID{serial_number},
            $OID{mac_address},
        ]
    );

    unless (defined $resp) {
        print "UNKNOWN - Erreur SNMP : " . $session->error() . "\n";
        exit 3;
    }

    # Température
    my $temp = $resp->{$OID{operating_temp}} // 0;

    # Utilisation CPU/Mem
    my $util_raw = $resp->{$OID{system_util}} // "";
    my ($cpu, $mem);
    if ($util_raw =~ /CPU:\s*([\d.]+)%.*, Mem:\s*([\d.]+)%/i) {
        $cpu = $1;
        $mem = $2;
    } else {
        $cpu = 0;
        $mem = 0;
    }

    # Serial & MAC
    my $serial = $resp->{$OID{serial_number}} // "N/A";
    my $mac    = $resp->{$OID{mac_address}}  // "N/A";

    # Statut
    my $status = "OK";
    my $exitcode = 0;

    print "$status - CPU=${cpu}%, MEM=${mem}%, TEMP=${temp}°C, Serial=$serial, MAC=$mac ".
          "| temp=$temp mem=$mem cpu=$cpu serial=\"$serial\" mac=\"$mac\"\n";
    exit $exitcode;
}

sub check_uptime {
  my $resp = $session->get_request($OID{uptime});
  if (!defined $resp) {
    print "UNKNOWN - ".$session->error()."\n";
    exit 3;
  }
  my $val = $resp->{$OID{uptime}};

  # Nettoyage des espaces
  $val =~ s/^\s+|\s+$//g;

  my $sec;
  if ($val =~ /^\d+$/) {
    # déjà en ticks bruts
    $sec = int($val/100);
  }
  elsif ($val =~ /\((\d+)\)/) {
    # format "Timeticks: (60080600) ..."
    $sec = int($1/100);
  }
  elsif ($val =~ /(?:(\d+)\s+days?,\s*)?(\d+):(\d+):(\d+)/) {
    # format "6 days, 22:56:30.00"
    my ($d,$h,$m,$s) = ($1||0,$2,$3,$4);
    $sec = $d*86400 + $h*3600 + $m*60 + $s;
  }
  else {
    print "UNKNOWN - unexpected uptime format: '$val'\n";
    exit 3;
  }

  my $days = int($sec/86400);
  my $hours = int(($sec%86400)/3600);
  my $mins = int(($sec%3600)/60);

  print "OK - Uptime ${days}d ${hours}h ${mins}m | uptime=${sec}s\n";
  exit 0;
}

sub check_temperature {
  my $resp = $session->get_request(
    -varbindlist => [$OID{temp_system},$OID{temp_switch},$OID{temp_1gphy},$OID{temp_5gphy}]
  );
  my @vals = map { int($resp->{$_}) } grep { defined $resp->{$_} } keys %$resp;
  my $max = 0;
  for my $val (@vals) {
    $max = $val if $val > $max;
  }
  my ($code,$state) = (0,"OK");
  if (defined $crit && $max >= $crit) { ($code,$state)=(2,"CRITICAL"); }
  elsif (defined $warn && $max >= $warn) { ($code,$state)=(1,"WARNING"); }
  print "$state - Max temperature ${max}C | temp=$max;$warn;$crit\n";
  exit $code;
}

sub check_ports {
    my $oid_state = $OID{port_status_linkstate};
    my $oid_link  = $OID{port_status_linkup};
    my $port_count = 7;

    my %port_state = (
        0 => 'linkDown',
        1 => 'blocking',
        2 => 'learning',
        3 => 'forwarding',
        4 => 'unauthVlan',
    );

    # Récupération des deux tables
    my $table_state = $session->get_table(-baseoid => $oid_state);
    my $table_link  = $session->get_table(-baseoid => $oid_link);

    unless (defined $table_state && defined $table_link) {
        print "UNKNOWN - Erreur SNMP : " . $session->error() . "\n";
        exit 3;
    }

    # Debug
    if ($debug) {
        print "DEBUG - Port state table:\n";
        foreach my $k (sort keys %$table_state) { print "$k => $table_state->{$k}\n"; }
        print "DEBUG - Port linkUp table:\n";
        foreach my $k (sort keys %$table_link)  { print "$k => $table_link->{$k}\n"; }
    }

    my %port_status;
    my @crit;
    my @warn;
    my @info;
    my @ok;

    foreach my $port (1..$port_count) {
        my $s_oid = "$oid_state.$port";
        my $l_oid = "$oid_link.$port";

        my $status   = $table_state->{$s_oid};
        my $link_val = $table_link->{$l_oid};

        my $state_label = defined $status ? $port_state{$status} // 'unknown' : 'unknown';
        my $link_label  = defined $link_val ? ($link_val==1 ? "up" : "down") : "unknown";

        $port_status{$port} = "$state_label/$link_label";

        if ($port == 5 || $port == 6) {   # ports critiques
            if (!defined $link_val || $link_val == 0) {
                push @crit, "P$port=linkDown/$state_label";
            }
            else {
                if ($status == 0 || $status == 1) { push @crit, "P$port=$state_label/$link_label"; }
                elsif ($status == 2 || $status == 4) { push @warn, "P$port=$state_label/$link_label"; }
                elsif ($status == 3) { push @ok, "P$port=$state_label/$link_label"; }
                else { push @crit, "P$port=unknown"; }
            }
        }
        else { # ports non critiques
            push @info, "P$port=$state_label/$link_label";
        }
    }

    # état global
    my $code  = 0;
    my $state = "OK";
    if (@crit) { $code=2; $state="CRITICAL"; }
    elsif (@warn) { $code=1; $state="WARNING"; }

    my $summary = sprintf(
        "%d critiques, %d warnings, %d ok, %d info",
        scalar(@crit), scalar(@warn), scalar(@ok), scalar(@info)
    );

    my @msg = (@crit, @warn, @ok, @info);

    # sortie
    print "$state - $summary : " . join(", ", @msg) . " | ";
    foreach my $port (1..$port_count) {
        my $val = $port_status{$port} // 'unknown';
        my $code_val;
        if    ($val =~ /^linkDown/)   { $code_val = 0; }
        elsif ($val =~ /^blocking/)   { $code_val = 1; }
        elsif ($val =~ /^learning/)   { $code_val = 2; }
        elsif ($val =~ /^forwarding/) { $code_val = 3; }
        elsif ($val =~ /^unauthVlan/) { $code_val = 4; }
        else                          { $code_val = -1; }
        print "port_${port}=$code_val ";
    }
    print "\n";

    exit $code;
}

sub check_poe {
  my $resp = $session->get_request($OID{poe_total});
  my $total = $resp->{$OID{poe_total}};
  my $table = $session->get_table($OID{poe_perport_power});
  my $perf="total=$total "; my $out="Total=$total W; ";
  for my $oid (keys %$table) {
    if ($oid =~ /\.(\d+)$/) {
      my $idx=$1; my $val=$table->{$oid};
      $perf.="poe$idx=$val ";
      $out.="P$idx=${val}W ";
    }
  }
  my ($code,$state)=(0,"OK");
  if (defined $crit && $total >= $crit) {($code,$state)=(2,"CRITICAL");}
  elsif (defined $warn && $total >= $warn) {($code,$state)=(1,"WARNING");}
  print "$state - $out | $perf\n";
  exit $code;
}

sub check_firmware {
    my $oid = $OID{firmware_version};  # à définir
    my $resp = $session->get_request(-varbindlist => [$oid]);

    if (!defined $resp || !exists $resp->{$oid}) {
        print "UNKNOWN - SNMP error: " . $session->error() . "\n";
        exit 3;
    }

    my $version = $resp->{$oid};
    print "OK - Firmware version: $version | firmware=\"$version\"\n";
    exit 0;
}

sub check_g8032 {
  my $base = $OID{g8032_ring_status};         # colonne g8032
  my $oid1 = $base . ".1";                    # ring index 1

  # 1) essai direct sur l'instance .1
  my $resp = $session->get_request(-varbindlist => [$oid1]);

  my $val;
  if (defined $resp && exists $resp->{$oid1}) {
    $val = $resp->{$oid1};
    print "DEBUG: got $oid1 => '$val'\n" if $debug;
  } else {
    # 2) fallback : récupération de la table entière
    my $table = $session->get_table(-baseoid => $base);
    if (!defined $table) {
      print "UNKNOWN - ".$session->error()."\n";
      exit 3;
    }
    if ($debug) {
      print "DEBUG - g8032 table contents:\n";
      for my $k (sort keys %$table) { print "  $k => ".$table->{$k}."\n"; }
    }

    # Prefer explicit .1 if present
    my $candidate_oid = $base . ".1";
    if (exists $table->{$candidate_oid}) {
      $val = $table->{$candidate_oid};
    } else {
      # prendre le premier index dispo
      my ($first_oid) = sort keys %$table;
      $val = $table->{$first_oid};
      print "DEBUG - using $first_oid => '$val'\n" if $debug;
    }
  }

  # Normalisation / extraction numérique
  $val = '' unless defined $val;
  $val =~ s/^\s+|\s+$//g;
  my $numeric;
  if ($val =~ /^-?\d+$/) {
    $numeric = int($val);
  } elsif ($val =~ /(-?\d+)/) {
    $numeric = int($1);
  } else {
    my $lc = lc($val);
    if ($lc =~ /idle/)        { $numeric = 3; }
    elsif ($lc =~ /protect/)  { $numeric = 2; }
    elsif ($lc =~ /fail/)     { $numeric = 5; }
    elsif ($lc =~ /unknown/)  { $numeric = 0; }
    else {
      print "UNKNOWN - unrecognized g8032 value: '$val'\n";
      exit 3;
    }
  }

  # --- Mapping corrigé ---
  my ($code,$state,$label);
  if (!defined $numeric || $numeric == 0) {
    ($code,$state,$label) = (3,"UNKNOWN","unknown");
  }
  elsif ($numeric == 1 || $numeric == 3) {
    ($code,$state,$label) = (0,"OK","ok");
  }
  elsif ($numeric == 2 || $numeric == 4) {
    ($code,$state,$label) = (1,"WARNING","warning");
  }
  elsif ($numeric == 5) {
    ($code,$state,$label) = (2,"CRITICAL","critical");
  }
  else {
    ($code,$state,$label) = (3,"UNKNOWN","value=$numeric");
  }

  print "DEBUG: raw='$val' numeric=$numeric -> mapping $state\n" if $debug;
  print "$state - Ring1=$label | ring1=$numeric\n";
  exit $code;
}

 

 

 


Last version,

The uptime management is optimized and add the option configuration to display (DNS, NTP, TACACS config with alerts in case of missing config):

#!/usr/bin/env perl
use strict;
use warnings;
use Net::SNMP;
use Getopt::Long;

Getopt::Long::Configure("bundling");

# --- OIDs Microsens G7 ---
my %OID = (
  uptime                => '1.3.6.1.4.1.3181.10.7.1.1.30.101.0',
  # Temp sensors
  temp_system           => '1.3.6.1.4.1.3181.10.7.1.1.30.104.0',
  # System
  hostname              => '1.3.6.1.4.1.3181.10.7.1.1.22.5.0',
  serial                => '1.3.6.1.4.1.3181.10.7.1.1.32.2.0',
  mac                   => '1.3.6.1.4.1.3181.10.7.1.1.30.102.0',
  cpu_mem               => '1.3.6.1.4.1.3181.10.7.1.1.30.4.0',
  # Ports
  port_status_linkup    => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.2',
  port_status_linkstate => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.4',
  # PoE
  poe_total             => '1.3.6.1.4.1.3181.10.7.1.1.33.100.0',
  poe_perport_power     => '1.3.6.1.4.1.3181.10.7.1.1.33.101.1.6',
  # G.8032 Ring
  g8032_ring_status     => '1.3.6.1.4.1.3181.10.7.1.2.43.7.1.2',
  # Firmware
  firmware_version      => '1.3.6.1.4.1.3181.10.7.1.1.30.109.1.0',
  # Config
  dns1                  => '1.3.6.1.4.1.3181.10.7.1.1.22.100.5.0',
  dns2                  => '1.3.6.1.4.1.3181.10.7.1.1.22.100.6.0',
  ntp_server            => '1.3.6.1.4.1.3181.10.7.1.3.73.4.0',
  ntp_server_backup     => '1.3.6.1.4.1.3181.10.7.1.3.73.5.0',
  access_auth_mode      => '1.3.6.1.4.1.3181.10.7.1.3.76.1.1.0',
  tacacs_primary        => '1.3.6.1.4.1.3181.10.7.1.3.76.1.6.0',
  tacacs_fallback       => '1.3.6.1.4.1.3181.10.7.1.3.76.1.7.0',
);

# --- CLI ---
my ($host,$community,$version,$port,$timeout,$mode,$warn,$crit,$help);
my ($username,$authproto,$authpass,$privproto,$privpass);
my $debug=0;
$community='public'; $version='2c'; $port=161; $timeout=5;

GetOptions(
  "H|host=s"       => \$host,
  "C|community=s"  => \$community,
  "v|version=s"    => \$version,
  "p|port=i"       => \$port,
  "t|timeout=i"    => \$timeout,
  "m|mode=s"       => \$mode,
  "w|warning=s"    => \$warn,
  "c|critical=s"   => \$crit,
  "u|username=s"   => \$username,
  "authproto=s"    => \$authproto,
  "authpass=s"     => \$authpass,
  "privproto=s"    => \$privproto,
  "privpass=s"     => \$privpass,
  "debug!"         => \$debug,
  "h|help"         => \$help,
) or usage();

usage() if $help || !$host || !$mode;

# --- SNMP Session ---
my ($session,$error);
if ($version =~ /^3$/i) {
  my %params = (
    -hostname  => $host,
    -version   => '3',
    -port      => $port,
    -timeout   => $timeout,
    -username  => $username,
  );
  if ($authproto && $authpass) {
    $params{-authprotocol} = uc($authproto);
    $params{-authpassword} = $authpass;
  }
  if ($privproto && $privpass) {
    $params{-privprotocol} = uc($privproto);
    $params{-privpassword} = $privpass;
  }
  ($session,$error) = Net::SNMP->session(%params);
} else {
  ($session,$error) = Net::SNMP->session(
    -hostname  => $host,
    -community => $community,
    -version   => $version,
    -port      => $port,
    -timeout   => $timeout,
  );
}
if (!defined $session) {
  print "CRITICAL - SNMP unreachable on $host ($error)\n";
  exit 2;
}

# --- Mode dispatcher ---
if    ($mode eq 'uptime')      { check_uptime(); }
elsif ($mode eq 'temperature') { check_temperature(); }
elsif ($mode eq 'ports')       { check_ports(); }
elsif ($mode eq 'poe')         { check_poe(); }
elsif ($mode eq 'g8032')       { check_g8032(); }
elsif ($mode eq 'firmware')    { check_firmware(); }
elsif ($mode eq 'system')      { check_system(); }
elsif ($mode eq 'config')      { check_config(); }
else { print "UNKNOWN - Mode $mode not supported\n"; exit 3; }

$session->close();
exit 0;

# --- Usage ---
sub usage {
  print <<"USAGE";
Usage: $0 -H <host> -m <mode> [options]

Modes:
  uptime        - uptime du switch
  temperature   - température système
  ports         - état des ports (linkstate + linkup)
  poe           - consommation PoE
  g8032         - état du Ring 1 G.8032
  firmware      - version du firmware
  system        - hostname, serial, MAC, CPU/MEM/temp
  config        - config DNS/NTP/TACACS/auth
USAGE
  exit 3;
}

# --- Checks ---

sub check_uptime {
  my $resp = $session->get_request($OID{uptime});
  if (!defined $resp) {
    print "UNKNOWN - ".$session->error()."\n";
    exit 3;
  }
  my $val = $resp->{$OID{uptime}};
  $val =~ s/^\s+|\s+$//g;

  my $sec;
  if ($val =~ /^\d+$/) {
    $sec = int($val/100);
  }
  elsif ($val =~ /\((\d+)\)/) {
    $sec = int($1/100);
  }
  elsif ($val =~ /(?:(\d+)\s+days?,\s*)?(\d+):(\d+):(\d+)/) {
    my ($d,$h,$m,$s) = ($1||0,$2,$3,$4);
    $sec = $d*86400 + $h*3600 + $m*60 + $s;
  }
  elsif ($val =~ /(\d+)\s+minutes?,\s*(\d+)\.(\d+)/) {
    my ($m,$s) = ($1,$2);
    $sec = $m*60 + $s;
  }
  elsif ($val =~ /(\d+)\s+hours?,\s*(\d+):(\d+)\.(\d+)/) {
    my ($h,$m,$s) = ($1,$2,$3);
    $sec = $h*3600 + $m*60 + $s;
  }
  else {
    print "UNKNOWN - unexpected uptime format: '$val'\n";
    exit 3;
  }

  my $days  = int($sec/86400);
  my $hours = int(($sec%86400)/3600);
  my $mins  = int(($sec%3600)/60);

  print "OK - Uptime ${days}d ${hours}h ${mins}m | uptime=${sec}s\n";
  exit 0;
}

sub check_temperature {
  my $resp = $session->get_request($OID{temp_system});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $temp = int($resp->{$OID{temp_system}});
  my ($code,$state)=(0,"OK");
  if (defined $crit && $temp >= $crit) {($code,$state)=(2,"CRITICAL");}
  elsif (defined $warn && $temp >= $warn) {($code,$state)=(1,"WARNING");}
  print "$state - Température $temp C | temp=$temp;$warn;$crit\n";
  exit $code;
}

sub check_ports {
  my $base_up    = $OID{port_status_linkup};
  my $base_state = $OID{port_status_linkstate};
  my $port_count = 7;
  my $table = $session->get_table(-baseoid => $base_up);
  if (!defined $table) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }

  my %status;
  foreach my $i (1..$port_count) {
    my $up = $table->{"$base_up.$i"};
    my $st = $table->{"$base_state.$i"} // "";
    $status{$i} = ($up eq "1") ? "up/$st" : "down/$st";
  }

  print "OK - Ports status | ";
  foreach my $i (1..$port_count) {
    print "port_$i=\"$status{$i}\" ";
  }
  print "\n";
  exit 0;
}

sub check_poe {
  my $resp = $session->get_request($OID{poe_total});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $total = $resp->{$OID{poe_total}};
  my $table = $session->get_table($OID{poe_perport_power});
  my $perf="total=$total "; my $out="Total=$total W; ";
  for my $oid (keys %$table) {
    if ($oid =~ /\.(\d+)$/) {
      my $idx=$1; my $val=$table->{$oid};
      $perf.="poe$idx=$val ";
      $out.="P$idx=${val}W ";
    }
  }
  my ($code,$state)=(0,"OK");
  if (defined $crit && $total >= $crit) {($code,$state)=(2,"CRITICAL");}
  elsif (defined $warn && $total >= $warn) {($code,$state)=(1,"WARNING");}
  print "$state - $out | $perf\n";
  exit $code;
}

sub check_firmware {
  my $resp = $session->get_request($OID{firmware_version});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $version = $resp->{$OID{firmware_version}};
  print "OK - Firmware version: $version | firmware=\"$version\"\n";
  exit 0;
}

sub check_system {
  my $resp = $session->get_request(
    -varbindlist => [$OID{hostname},$OID{serial},$OID{mac},$OID{cpu_mem},$OID{temp_system}]
  );
  unless (defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }

  my $host = $resp->{$OID{hostname}} // "";
  my $serial = $resp->{$OID{serial}} // "";
  my $mac = $resp->{$OID{mac}} // "";
  my $util = $resp->{$OID{cpu_mem}} // "";
  my $temp = $resp->{$OID{temp_system}} // "";

  my ($cpu,$mem) = (0,0);
  if ($util =~ /CPU:\s*(\d+)%.*, Mem:\s*([\d\.]+)%/) {
    ($cpu,$mem) = ($1,$2);
  }

  print "OK - Host=$host Serial=$serial MAC=$mac CPU=${cpu}% MEM=${mem}% TEMP=${temp}C ".
        "| cpu=$cpu mem=$mem temp=$temp\n";
  exit 0;
}

sub check_config {
  my $resp = $session->get_request(
    -varbindlist => [$OID{dns1},$OID{dns2},$OID{ntp_server},$OID{ntp_server_backup},
                     $OID{access_auth_mode},$OID{tacacs_primary},$OID{tacacs_fallback}]
  );
  unless (defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }

  my $dns1 = $resp->{$OID{dns1}} // "";
  my $dns2 = $resp->{$OID{dns2}} // "";
  my $ntp  = $resp->{$OID{ntp_server}} // "";
  my $ntp2 = $resp->{$OID{ntp_server_backup}} // "";
  my $auth = $resp->{$OID{access_auth_mode}} // "";
  my $tac1 = $resp->{$OID{tacacs_primary}} // "";
  my $tac2 = $resp->{$OID{tacacs_fallback}} // "";

  my %auth_map = (0=>"local",1=>"radius",2=>"tacacs+",3=>"ldap");
  my $auth_text = exists $auth_map{$auth} ? $auth_map{$auth} : $auth;

  my $code=0; my $state="OK"; my @issues;
  if ($dns1 eq "" && $dns2 eq "") { ($code,$state)=(2,"CRITICAL"); push @issues,"aucun DNS"; }
  elsif ($dns1 eq "" || $dns2 eq "") { ($code,$state)=(1,"WARNING") if $code<2; push @issues,"un seul DNS"; }
  if ($ntp eq "" && $ntp2 eq "") { ($code,$state)=(1,"WARNING") if $code<2; push @issues,"aucun NTP"; }
  if ($auth_text eq "tacacs+") {
    if ($tac1 eq "" && $tac2 eq "") { ($code,$state)=(2,"CRITICAL"); push @issues,"aucun TACACS+"; }
    elsif ($tac1 eq "" || $tac2 eq "") { ($code,$state)=(1,"WARNING") if $code<2; push @issues,"un seul TACACS+"; }
  }

  my $msg = @issues ? join(", ",@issues) : "Config OK";
  print "$state - $msg | dns1=\"$dns1\" dns2=\"$dns2\" ntp=\"$ntp\" ntp_backup=\"$ntp2\" auth=\"$auth_text\" tacacs1=\"$tac1\" tacacs2=\"$tac2\"\n";
  exit $code;
}

sub check_g8032 {
  my $base = $OID{g8032_ring_status};
  my $oid1 = $base.".1";
  my $resp = $session->get_request(-varbindlist => [$oid1]);
  my $val;
  if (defined $resp && exists $resp->{$oid1}) { $val=$resp->{$oid1}; }
  else {
    my $table = $session->get_table(-baseoid => $base);
    if (!defined $table) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
    my ($first_oid) = sort keys %$table;
    $val = $table->{$first_oid};
  }
  my $numeric=int($val);
  my ($code,$state,$label);
  if ($numeric==1 || $numeric==3) { ($code,$state,$label)=(0,"OK","ok"); }
  elsif ($numeric==2 || $numeric==4) { ($code,$state,$label)=(1,"WARNING","warning"); }
  elsif ($numeric==5) { ($code,$state,$label)=(2,"CRITICAL","critical"); }
  else { ($code,$state,$label)=(3,"UNKNOWN","value=$numeric"); }
  print "$state - Ring1=$label | ring1=$numeric\n";
  exit $code;
}

 


For exemple i use this commands below:

Uptime

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m uptime

ERP Ring 1 Status:

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m g8032

POE utilization per port:

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m poe

Firmware version:

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m firmware

Check CPU, Memory, temp + display mac address & serial:

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m system

Ports Status UP/Down (Critical ports 5 & 6 only)

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m ports

Check config (DNS, NTP, TACACS servers:

/usr/lib/centreon/plugins//check_microsens_G7_v3.pl -H 192.168.60.50 -v3 -u 'snmp' --authproto MD5 --authpass '*********' -m config

 

 

 

 

 

 


Final version of the script:

#!/usr/bin/env perl
use strict;
use warnings;
use Net::SNMP;
use Getopt::Long;

Getopt::Long::Configure("bundling");

# --- OIDs spécifiques Microsens G7 ---
my %OID = (
  hostname              => '1.3.6.1.4.1.3181.10.7.1.1.22.5.0',
  uptime                => '1.3.6.1.4.1.3181.10.7.1.1.30.101.0',
  # Temp sensors
  temp_system           => '1.3.6.1.4.1.3181.10.7.1.1.30.104.0',
  temp_switch           => '1.3.6.1.4.1.3181.10.7.1.1.30.105.0',
  temp_1gphy            => '1.3.6.1.4.1.3181.10.7.1.1.30.106.0',
  temp_5gphy            => '1.3.6.1.4.1.3181.10.7.1.1.30.107.0',
  # Ports
  port_status_linkup    => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.2',
  port_status_linkstate => '1.3.6.1.4.1.3181.10.7.1.1.81.102.1.4',
  # PoE
  poe_total             => '1.3.6.1.4.1.3181.10.7.1.1.33.100.0',
  poe_perport_power     => '1.3.6.1.4.1.3181.10.7.1.1.33.101.1.6',
  # G.8032 Ring status
  g8032_ring_status     => '1.3.6.1.4.1.3181.10.7.1.2.43.7.1.2',
  # Firmware / infos système
  firmware_version      => '1.3.6.1.4.1.3181.10.7.1.1.30.109.1.0',
  serial_number         => '1.3.6.1.4.1.3181.10.7.1.1.32.2.0',
  mac_address           => '1.3.6.1.4.1.3181.10.7.1.1.30.102.0',
  cpu_usage             => '1.3.6.1.4.1.3181.10.7.1.1.30.4.0',
  mem_usage             => '1.3.6.1.4.1.3181.10.7.1.1.30.108.0',
  dns1              => '1.3.6.1.4.1.3181.10.7.1.1.22.100.5.0',
  dns2              => '1.3.6.1.4.1.3181.10.7.1.1.22.100.6.0',
  ntp1              => '1.3.6.1.4.1.3181.10.7.1.3.73.4.0',
  ntp2              => '1.3.6.1.4.1.3181.10.7.1.3.73.5.0',
  tacacs1           => '1.3.6.1.4.1.3181.10.7.1.3.76.1.6.0',
  tacacs2           => '1.3.6.1.4.1.3181.10.7.1.3.76.1.7.0',
  auth_mode         => '1.3.6.1.4.1.3181.10.7.1.3.76.1.1.0',
);

# Mapping linkstate
my %port_state = (
    0 => 'linkDown',
    1 => 'blocking',
    2 => 'learning',
    3 => 'forwarding',
    4 => 'unauthVlan',
);

# --- CLI ---
my ($host,$community,$version,$port,$timeout,$mode,$warn,$crit,$help);
my ($username,$authproto,$authpass,$privproto,$privpass);
my $debug=0;
$community='public'; $version='2c'; $port=161; $timeout=5;

GetOptions(
  "H|host=s"       => \$host,
  "C|community=s"  => \$community,
  "v|version=s"    => \$version,
  "p|port=i"       => \$port,
  "t|timeout=i"    => \$timeout,
  "m|mode=s"       => \$mode,
  "w|warning=s"    => \$warn,
  "c|critical=s"   => \$crit,
  "u|username=s"   => \$username,
  "authproto=s"    => \$authproto,
  "authpass=s"     => \$authpass,
  "privproto=s"    => \$privproto,
  "privpass=s"     => \$privpass,
  "debug!"         => \$debug,
  "h|help"         => \$help,
) or usage();

usage() if $help || !$host || !$mode;

# --- SNMP Session ---
my ($session,$error);
if ($version =~ /^3$/i) {
  my %params = (
    -hostname  => $host,
    -version   => '3',
    -port      => $port,
    -timeout   => $timeout,
    -username  => $username,
  );
  if ($authproto && $authpass) {
    $params{-authprotocol} = uc($authproto);
    $params{-authpassword} = $authpass;
  }
  if ($privproto && $privpass) {
    $params{-privprotocol} = uc($privproto);
    $params{-privpassword} = $privpass;
  }
  ($session,$error) = Net::SNMP->session(%params);
} else {
  ($session,$error) = Net::SNMP->session(
    -hostname  => $host,
    -community => $community,
    -version   => $version,
    -port      => $port,
    -timeout   => $timeout,
  );
}
if (!defined $session) { print "UNKNOWN - SNMP session error: $error\n"; exit 3; }

# --- Dispatcher ---
if    ($mode eq 'ports')       { check_ports(); }
elsif ($mode eq 'uptime')      { check_uptime(); }
elsif ($mode eq 'temperature') { check_temperature(); }
elsif ($mode eq 'poe')         { check_poe(); }
elsif ($mode eq 'g8032')       { check_g8032(); }
elsif ($mode eq 'firmware')    { check_firmware(); }
elsif ($mode eq 'system')      { check_system(); }
elsif ($mode eq 'config')      { check_config(); }
else { print "UNKNOWN - Mode $mode not supported\n"; exit 3; }

$session->close();
exit 0;

# --- Usage ---
sub usage {
  print <<"USAGE";
Usage: $0 -H <host> -m <mode> [options]
Modes: uptime | temperature | ports | poe | g8032 | firmware | system
USAGE
  exit 3;
}

# --- Checks ---

sub check_ports {
    my $port_count = 7;
    my $table = $session->get_table(-baseoid => $OID{port_status_linkstate});
    my $table2 = $session->get_table(-baseoid => $OID{port_status_linkup});
    unless (defined $table && defined $table2) {
        print "UNKNOWN - Erreur SNMP : " . $session->error() . "\n";
        exit 3;
    }

    my %port_status;
    foreach my $port (1..$port_count) {
        my $oid_linkup   = "$OID{port_status_linkup}.$port";
        my $oid_linkstat = "$OID{port_status_linkstate}.$port";

        my $linkup_val    = $table2->{$oid_linkup};
        my $linkstate_val = $table->{$oid_linkstat};

        my $linkup    = defined $linkup_val    ? ($linkup_val == 1 ? "up" : "down") : "unknown";
        my $linkstate = defined $linkstate_val ? ($port_state{$linkstate_val} // "unknown") : "unknown";

        $port_status{$port} = "$linkup/$linkstate";
    }

    print "OK - Statut des ports | ";
    foreach my $port (1..$port_count) {
        print "port_${port}=\"$port_status{$port}\" ";
    }
    print "\n";
    exit 0;
}

sub check_uptime {
  my $resp = $session->get_request($OID{uptime});
  if (!defined $resp) {
    print "UNKNOWN - ".$session->error()."\n";
    exit 3;
  }
  my $val = $resp->{$OID{uptime}};
  $val =~ s/^\s+|\s+$//g;

  my $sec;
  if ($val =~ /^\d+$/) {
    $sec = int($val/100);
  }
  elsif ($val =~ /\((\d+)\)/) {
    $sec = int($1/100);
  }
  elsif ($val =~ /(?:(\d+)\s+days?,\s*)?(\d+):(\d+):(\d+)/) {
    my ($d,$h,$m,$s) = ($1||0,$2,$3,$4);
    $sec = $d*86400 + $h*3600 + $m*60 + $s;
  }
  elsif ($val =~ /(\d+)\s+minutes?,\s*(\d+)\.(\d+)/) {
    my ($m,$s) = ($1,$2);
    $sec = $m*60 + $s;
  }
  elsif ($val =~ /(\d+)\s+hours?,\s*(\d+):(\d+)\.(\d+)/) {
    my ($h,$m,$s) = ($1,$2,$3);
    $sec = $h*3600 + $m*60 + $s;
  }
  else {
    print "UNKNOWN - unexpected uptime format: '$val'\n";
    exit 3;
  }

  my $days  = int($sec/86400);
  my $hours = int(($sec%86400)/3600);
  my $mins  = int(($sec%3600)/60);

  print "OK - Uptime ${days}d ${hours}h ${mins}m | uptime=${sec}s\n";
  exit 0;
}

sub check_temperature {
  my $resp = $session->get_request($OID{temp_system});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $temp = int($resp->{$OID{temp_system}});
  my ($code,$state)=(0,"OK");
  if (defined $crit && $temp >= $crit) {($code,$state)=(2,"CRITICAL");}
  elsif (defined $warn && $temp >= $warn) {($code,$state)=(1,"WARNING");}
  print "$state - Température $temp C | temp=$temp;$warn;$crit\n";
  exit $code;
}

sub check_poe {
  my $resp = $session->get_request($OID{poe_total});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $total = $resp->{$OID{poe_total}};
  my $table = $session->get_table($OID{poe_perport_power});
  my $perf="total=$total "; my $out="Total=$total W; ";
  for my $oid (keys %$table) {
    if ($oid =~ /\.(\d+)$/) {
      my $idx=$1; my $val=$table->{$oid};
      $perf.="poe$idx=$val ";
      $out.="P$idx=${val}W ";
    }
  }
  my ($code,$state)=(0,"OK");
  if (defined $crit && $total >= $crit) {($code,$state)=(2,"CRITICAL");}
  elsif (defined $warn && $total >= $warn) {($code,$state)=(1,"WARNING");}
  print "$state - $out | $perf\n";
  exit $code;
}

sub check_firmware {
  my $resp = $session->get_request($OID{firmware_version});
  if (!defined $resp) { print "UNKNOWN - ".$session->error()."\n"; exit 3; }
  my $version = $resp->{$OID{firmware_version}};
  print "OK - Firmware version: $version | firmware=\"$version\"\n";
  exit 0;
}

sub check_config {
    my @wanted = qw(dns1 dns2 ntp1 ntp2 tacacs1 tacacs2 auth_mode);
    my @oids;
    my %key_by_oid;
    for my $k (@wanted) {
        next unless defined $OID{$k} && $OID{$k} ne '';
        push @oids, $OID{$k};
        $key_by_oid{$OID{$k}} = $k;
    }

    unless (@oids) {
        print "UNKNOWN - aucun OID configuré pour check_config\n";
        exit 3;
    }

    my $resp = $session->get_request(-varbindlist => \@oids);
    unless (defined $resp) {
        print "UNKNOWN - ".$session->error()."\n";
        exit 3;
    }

    my %res;
    for my $oid (@oids) {
        my $k = $key_by_oid{$oid};
        $res{$k} = $resp->{$oid} // '';
    }

    # --- logique de vérification ---
    my ($code,$state,$msg) = (0,"OK","Config correcte");

    # DNS
    my $dns_missing = 0;
    $dns_missing++ unless $res{dns1};
    $dns_missing++ unless $res{dns2};
    if ($dns_missing == 1) { ($code,$state,$msg) = (1,"WARNING","Un seul DNS configuré"); }
    elsif ($dns_missing == 2) { ($code,$state,$msg) = (2,"CRITICAL","Aucun DNS configuré"); }

    # NTP
    unless ($res{ntp1} || $res{ntp2}) {
        ($code,$state,$msg) = (1,"WARNING","Aucun serveur NTP configuré") if $code < 1;
    }

    # TACACS
    my $tacacs_missing = 0;
    $tacacs_missing++ unless $res{tacacs1};
    $tacacs_missing++ unless $res{tacacs2};
    if ($tacacs_missing == 2) { ($code,$state,$msg) = (2,"CRITICAL","Aucun serveur TACACS configuré"); }
    elsif ($tacacs_missing == 1 && $code < 2) { ($code,$state,$msg) = (1,"WARNING","Un seul serveur TACACS configuré"); }

    print "$state - $msg | dns1=\"$res{dns1}\" dns2=\"$res{dns2}\" ntp1=\"$res{ntp1}\" ntp2=\"$res{ntp2}\" tacacs1=\"$res{tacacs1}\" tacacs2=\"$res{tacacs2}\" auth_mode=\"$res{auth_mode}\"\n";
    exit $code;
}

sub check_system {
    my $resp = $session->get_request(
        -varbindlist => [
            $OID{hostname},
            $OID{serial_number},
            $OID{mac_address},
            $OID{cpu_usage},
            $OID{mem_usage},
            $OID{temp_system}
        ]
    );

    unless (defined $resp) {
        print "UNKNOWN - ".$session->error()."\n";
        exit 3;
    }

    my $host   = $resp->{$OID{hostname}}       // "";
    my $serial = $resp->{$OID{serial_number}}  // "";
    my $mac    = $resp->{$OID{mac_address}}    // "";
    my $cpu    = $resp->{$OID{cpu_usage}}      // 0;
    my $mem    = $resp->{$OID{mem_usage}}      // 0;
    my $temp   = $resp->{$OID{temp_system}}    // 0;

    print "OK - Host=$host Serial=$serial MAC=$mac CPU=${cpu}% MEM=${mem}% TEMP=${temp}C ".
          "| cpu=$cpu mem=$mem temp=$temp\n";
    exit 0;
}

sub check_g8032 {
    my $base = $OID{g8032_ring_status};
    my $oid1 = $base.".1";
    my $resp = $session->get_request(-varbindlist => [$oid1]);

    my $val;
    if (defined $resp && exists $resp->{$oid1}) {
        $val = $resp->{$oid1};
    } else {
        my $table = $session->get_table(-baseoid => $base);
        if (!defined $table) {
            print "UNKNOWN - ".$session->error()."\n";
            exit 3;
        }
        my ($first_oid) = sort keys %$table;
        $val = $table->{$first_oid};
    }

    my $numeric = int($val);
    my ($code,$state,$label);

    if ($numeric == 1 || $numeric == 3) {
        ($code,$state,$label) = (0,"OK","ok");
    }
    elsif ($numeric == 2 || $numeric == 4) {
        ($code,$state,$label) = (1,"WARNING","warning");
    }
    elsif ($numeric == 5) {
        ($code,$state,$label) = (2,"CRITICAL","critical");
    }
    else {
        ($code,$state,$label) = (3,"UNKNOWN","value=$numeric");
    }

    print "$state - Ring1=$label | ring1=$numeric\n";
    exit $code;
}

 


Hello :)

Thank you for sharing this solution with us. Do you think you could make a PR on GitHub (it would be more suitable for sharing large segments of code)?

Kind regards.

 


Hi,

PR sent :)

BR