#!/usr/bin/perl

# /******************************************************************************
# *
# * CHECK_ORACLE_ASM_DISK_GROUPS
# *
# * Program: Linux plugin for Nagios
# * License: GPL
# * Copyright (c) 2013- Victor Ruiz (vruiz@adif.es)
# *
# * Description:
# *
# * This software checks the used space for disk_groups
# * managed by Oracle ASM (Automatic Storage Management)
# * against a threshold provided in command line
# *
# * License Information:
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# *
# * $Id: check_oracle_ASM_disk_groups ,v 0.9 2012/11/17 17:39:45 savirziur Exp $
# *
# *****************************************************************************/

use Getopt::Long qw(:config no_ignore_case);
use DBI;
use DBD::Oracle qw(:ora_session_modes);


my $sid = '';
my $ora_home = '';
my %disk_groups_thresholds = ();
my %nagios_exit_codes = ( 'UNKNOWN', 3, 'OK', 0, 'WARNING', 1, 'CRITICAL', 2 );
my $output_msg = '';
my $status = 'OK';

&usage unless GetOptions ('sid=s' => \$sid, 'ora_home=s' => \$ora_home, 'threshold=s' => \%disk_groups_thresholds);


$dsn = "dbi:Oracle:";
$ENV{ORACLE_SID} = $sid;
$ENV{ORACLE_HOME} = $ora_home;
delete $ENV{TWO_TASK};

$dbh = DBI->connect($dsn, "", "", { ora_session_mode => ORA_SYSDBA });
if ( ! defined $dbh ) { print "$DBI::errstr\n"; exit $nagios_exit_codes{'CRITICAL'}; }

$dbh->{RaiseError} = 1;
$sth = $dbh->prepare(qq{select name, free_mb, total_mb from v\$asm_diskgroup}) or die $dbh->errstr;


if ( $sth->execute ) {

	$output_msg .= "USED SPACE: ";
	# Traverse all disk groups in ASM
	while ( @disk_group = $sth->fetchrow_array()) {
		my $used_space = 0;
		my $rounded_used_space = 0;
		chomp @disk_group;
		# If the disk group in ASM has threshold defined in command line let's check it  
		if ( $disk_groups_thresholds{$disk_group[0]} ){
			if ( $disk_group[2] != 0 ) {
				$used_space = (  ($disk_group[2] - $disk_group[1]) / $disk_group[2] ) * 100;
				$rounded_used_space = sprintf("%.2f", $used_space);
			}
			if ( $rounded_used_space > $disk_groups_thresholds{$disk_group[0]} ) {
				$status = 'CRITICAL';
				$output_msg .= "  [<blink><b>$disk_group[0]: $rounded_used_space%<\/b><\/blink>]";
			}else{
				$output_msg .= "[$disk_group[0]: $rounded_used_space%]   ";
			}
			# Once processed, we drop command line disk group and threshold
			delete($disk_groups_thresholds{$disk_group[0]});
		} # end if
	} # end while
	$output_msg .= "\n";
} else {
	$status = 'CRITICAL';
	print $dbh->errstr;
}

# Free DBI resources
$sth->finish();
$dbh->disconnect();


# Let's check if any disk group remains in command line, not being present in ASM 
if ( scalar keys %disk_groups_thresholds ) {
	$status = 'CRITICAL';
	foreach ( keys(%disk_groups_thresholds) ) {
	$output_msg = "[<blink><b>$_ is not in $sid<\/b><\/blink>] " . $output_msg;	
	}
}

print $output_msg;
exit $nagios_exit_codes{ $status };


########################## SUBROUTINES #######################

sub usage {
   print "\nUsage: $0 --sid <SID> --ora_home <ORACLE_HOME for SID> --threshold <GROUP_DISK=integer> [[--threshold <GROUP_DISK=integer>] ... ]\n\n";
   print "--sid:		SID name of ASM instance\n";
   print "--ora_home:		ORACLE_HOME for SID\n";
   print "--threshold:	GROUP_DISK_NAME=percentage threshold for used space (range [0..100])\n\n";
   exit $nagios_exit_codes{'WARNING'};
}
