#!/usr/bin/perl

# To check the DRBD status on a machine

use strict;
use vars qw($drbdadm $procdrbd);
use Data::Dumper;
use Hobbit;

my $procdrbd='/proc/drbd';
my $drbdadm='sudo /sbin/drbdadm';
my $status='clear';
my $msg='No message';
my %drbds;

# A hash of messages. 
my %messages=(green=>{'state'=>['Primary/Secondary','Secondary/Primary'],
                    'cstate'=>['Connected'],
                    'dstate'=>['UpToDate/UpToDate']},
            yellow=>{'state'=>['Primary/Primary','Secondary/Secondary'],
                     'cstate'=>['WFConnection','WFReportParams','SyncTarget','SyncSource']},
            ignore=>{'state'=>['Unconfigured']}
            );
my %status;
my $bb = new Hobbit('drbd');

if (! -f $procdrbd) {
 $status='red';
 $msg="$procdrbd not found: drbd module not loaded\n";
 &sendmsg($status,$msg);
 exit(1);
} else {
 my $fh;
 if (! open($fh,$procdrbd)) {
  $status='red';
  $msg="Unable to open $procdrbd: $!";
  &sendmsg($status,$msg);
  exit(1);
 };
 my $version=<$fh>;
 $bb->print($version);
 close ($fh);

 # Loop over all resources
 $|=0;
 my @resources=split(/ /,`$drbdadm sh-resources`);
 foreach my $resource (@resources) {
  chomp($resource);
  my $state=&drbdadm($resource,'state');
  my $cstate=&drbdadm($resource,'cstate');
  my $dstate=&drbdadm($resource,'dstate');
  my $device=&drbdadm($resource,'sh-dev');
  my $lldev=&drbdadm($resource,'sh-ll-dev');
  next if &msgmatch($state ,$messages{ignore}{state});
  if (&msgmatch($state ,$messages{green}{state} ) && 
      &msgmatch($cstate,$messages{green}{cstate}) && 
      &msgmatch($dstate,$messages{green}{dstate}) &&
      ( -b $device ) &&
      ( -b $lldev )) {
   $bb->color_line ('green',$resource.' ['.$device.'] is happy'."\n");
  } else {
   if (! (&msgmatch($cstate,$messages{green}{cstate}))) {
    if (  &msgmatch($cstate,$messages{yellow}{cstate})) {
     $bb->color_line('yellow',$resource.': Connection'.&msgtext($cstate,$messages{green}{cstate}));
    } else {
     $bb->color_line('red',$resource.': Connection'.&msgtext($cstate,$messages{green}{cstate},$messages{yellow}{cstate}));
    }
   }
   if (!(&msgmatch($state,$messages{green}{state}))) {
    if ( &msgmatch($state,$messages{yellow}{state})) {
     $bb->color_line('yellow',$resource.': State'.&msgtext($state,$messages{green}{state}));
    } else {
     $bb->color_line('red',$resource.': State'.&msgtext($state,$messages{green}{state},$messages{yellow}{state}));
    }
   }
   if (! -b $device) {
    $bb->color_line('red',$resource.': $device is not a block device! How can this be?!'."\n");
   }
   if (! -b $lldev) {
    $bb->color_line('red',$resource.': $lldev is not a block device! How can this be?!'."\n");
   }
  }
 }

 $bb->send();
}  # -f /proc/drbd

sub drbdadm($$) {
 my $resource=shift;
 my $command=shift;
 my $result;
 if ($command) {
  $result=`$drbdadm $command $resource`;
 }
 chomp($result);
 return $result;
}
  
sub msgmatch($,@)  {
 my $text=shift;
 my $matches=shift;
 my $matched=0;
 foreach my $match (@$matches) {
  #print "Testing $match and $text: ".($match eq $text)."\n";
  $matched = $matched || ($match eq $text);
 } 
 return $matched;
}

sub msgtext($,$) {
 my $text=shift;
 my $gmatches=shift; 
 my $ymatches=shift;
 my @matches=@$gmatches;
 if ($ymatches) {
  push(@matches,@$ymatches);
 }
 return " is '$text' not '".join("' or '",@matches)."'\n";
}

sub sendmsg($$) {
 $status=shift;
 $msg=shift;
 print "Status: $status - $msg\n";
}
