#!/usr/bin/python
##########################################################################
# Copyright (C) 2018  Igor Castro
#
# 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 3 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, see <http://www.gnu.org/licenses/>
###########################################################################
###########################################################################
# Version = 1.0
# Organisation = IATA
# Author = I.CASTRO
# Description = File monitoring for backup
#
#
##########################################################################
import os, sys, time, argparse, datetime
from datetime import date

# Hardcoded parameters to debug
my_command="ls -qalt"


# exit statuses recognized by Nagios
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3

# Create a Parser to get value from command arguments

parser = argparse.ArgumentParser(description="Nagios check to validate if there is new backup received within defined threshold and optionally validate corruption via checksum can be run like ./check_file_monitoring -d '/home/user/' -f '*.crt' can be also executed remotely via check_by_ssh")

parser.add_argument('-c', default=30, dest='critical', type=int, help='critical threshold in day for nagios (default: 30) is number of days without newer backup received')
parser.add_argument('-w', default=15, dest='warning', type=int, help='warning threshold in day for nagios for nagios (default: 15) is number of days without newer backup received')
parser.add_argument('-f', dest='file_check', help='file pattern to be found in backup file name')
parser.add_argument('-d', dest='dir_check', help='directory to look for the files')
parser.add_argument('-s', default='none', dest='crc', help='Optionally looks for latest file name with checksum to validate transfer integrity currently only default none or md5 are implemented file.md5 must be available')

args = parser.parse_args()


warning_arg=args.warning
critical_arg=args.critical
file_check=args.file_check
dir_check=args.dir_check
crc=args.crc

#

# Create the actual command with all parameters

full_command="%s %s%s" % (my_command,dir_check,file_check)


# Send the command to the OS

result_command=os.popen(full_command)

# Save result in a proper array
result=result_command.readlines()

# Save number of lines detected in result
nb_lines= int(len(result))


# If there are no lines something is wrong`
if nb_lines > 0 :
	# Get latest modified file matching pattern and extract corresponding date
	# Format is permission,user id, user, group, size, month, day, year, file
	last=result[0].split()
	
	#Check if ls output is displaying hour instead of year we must replace it by current year
        if (last[7].find(':') != -1): 
                last[7]= datetime.datetime.today().year 

        #print "last %s" % (last)
	# Create a date with values extracted and converted in integer
	last_date=date(int(last[7]),datetime.datetime.strptime(last[5], '%b').month,int(last[6]))

	#calculate current today value in days
        today = date.today()
        remaining_day = today - last_date 

	#print"last date %s today date %s remaining days %s" % (last_date,today,remaining_day)
	# Check if the size of the file is not null 
	if last[4] < 1 :
		print "CRITICAL - Last file found %s was updated on %s but has an anbormal size of %s KiBs " %(last[8],last_date,last[4])
                sys.exit(CRITICAL)
	else :
		# Check if the remaining number of days is more than critical threshold
		if remaining_day.days > critical_arg :
			print "CRITICAL - Last file found %s was updated on %s which is more than critical threshold of %d days old" %(last[8],last_date,critical_arg)
			sys.exit(CRITICAL)
		else :
			# Check if the remaining number of days is more than warning threshold
     			if remaining_day.days > warning_arg :
        			print "WARNING - Last file found %s was updated on %s which is more than warning threshold of %d days old" %(last[8],last_date,warning_arg)
                		sys.exit(WARNING)
        		else :
                		# Check if CRC option was used
				if crc.find('md5') != -1:
					#CRC option md5 is used
					check_crc_file= last[8] + "." + crc
					my_command="md5sum"
					
					#Execute md5sum remotely 
					result_command=os.popen(my_command + " " + last[8])

					# Save result first line
					result_crc=result_command.readline()
					result_crc=result_crc.split()
					
					#Read checksum more received checksum file
					result_command=os.popen("cat " + check_crc_file)

					# Save result first line
					received_crc =result_command.readline()	
					received_crc = received_crc.split()
					
					#Validate that checksum calculated is inside of crc file received
					if result_crc[0].find(received_crc[0]) != -1:
						print "OK -  Last file found %s was updated on %s , has a size of %s KiBs and has a valid %s calculated of %s wich matches  the one received in %s" % (last[8],last_date,last[4],crc,result_crc[0],check_crc_file)
						sys.exit(OK)
					else :
						print "CRITICAL -  Last file found %s has %s of %s which is different than the one received in % of %s" % (last[8],crc,result_crc[0],check_crc_file,received_crc[0])
						sys.exit(CRITICAL)

				else :
					print "OK - Last file found %s was updated on %s and has a size of %s KiBs " % (last[8],last_date,last[4])
                			sys.exit(OK)
else :
	sys.exit(UNKNOWN)
