#!/usr/bin/perl -w

use strict;
use File::Which;
use Getopt::Long;
use JSON;

my $json;
@{$json->{data}} = ();

my $gluster = which('gluster');
my $lock = '/var/lock/gluster-zabbix.lock';

unless($gluster){
  # Gluster is not installed, just return an empty JSON object
  print to_json($json);
  exit(0);
}

# Get an exclusive lock
open(LOCK, ">$lock") || die "Can't open $lock";
flock(LOCK, 2);

my $what = 'volumes';
GetOptions(
  "what=s" => \$what,
);

sub usage (){
  print <<"EOF";

Usage: $0 --what=[volumes|peers]

EOF
}

sub gluster($){
  my $cmd = shift;
  my $code = 256;
  my @result = ();
  # Loop to run gluster cmd as it can fail if two run at the same time
  for (my $i = 0; ($code != 0 && $i < 10); $i++){
    open (RES, "$cmd |")
          || die "error: Could not execute $cmd";
    @result = <RES>;
    close RES;
    $code = $?;
    sleep(1) unless ($code == 0);
  }
  die "error: Could not execute $cmd" unless ($code == 0);
  return @result;
}

if ($what eq 'volumes'){
  foreach my $line (gluster("$gluster vol info all")){
    if ($line =~ m/^Volume\ Name:\ (\w+)$/){
      my $vol = $1;
      my ($type,$bricks,$uuid,$status,$transport) = ('unknown');
      open (VOLUMEINFO, "$gluster vol info $vol |")
          || die "error: Could not execute gluster vol info $vol";
      foreach my $info (<VOLUMEINFO>){
        if ($info =~ m/^Type:\ (.*)$/){
          $type = $1;
        }
        elsif ($info =~ m/^Volume\ ID:\ ([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})$/){
          $uuid = $1;
        }
        elsif ($info =~ m/^Status:\ (\w+)$/){
          $status = $1;
        }
        elsif ($info =~ m/^Transport-type:\ (\w+)$/){
          $transport = $1;
        }
        elsif ($info =~ m/^Number\ of\ Bricks:\ \d+\ x\ \d+\ =\ (\d+)$/){
          $bricks = $1;
        }
      }
      push @{$json->{data}}, {
        "{#GLUSTER_VOL_NAME}"      => $vol,
        "{#GLUSTER_VOL_TYPE}"      => $type,
        "{#GLUSTER_VOL_UUID}"      => $uuid,
        "{#GLUSTER_VOL_STATUS}"    => $status,
        "{#GLUSTER_VOL_TRANSPORT}" => $transport,
        "{#GLUSTER_VOL_BRICKS}"    => $bricks
      };
    }
  }
}

elsif ($what eq 'peers'){
  my $peerno = 0;
  my ($host,$uuid,$status) = ('unknown');
  foreach my $line (gluster("$gluster peer status")){
    if ($line =~ m/^Number of Peers:\ (\d+)$/){
      $peerno = $1;
    }
    elsif ($line =~ m/^Hostname:\ ([\w\.]+)$/){
      $host = $1;
    }
    elsif ($line =~ m/Uuid:\ ([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})$/){
      $uuid = $1;
    }
    elsif ($line =~ m/State:\ [\w\s]+\((\w+)\)$/){
      $status = $1;
      push @{$json->{data}}, {
        "{#GLUSTER_PEER_HOST}"   => $host,
        "{#GLUSTER_PEER_UUID}"   => $uuid,
        "{#GLUSTER_PEER_STATUS}" => $status
      };
    }
  }
}
else{
  usage();
  exit(1);
}

close(LOCK);
print to_json($json);
exit(0);

