Commit d1f77b80 by JR Dalrymple

Got the billing period logic all working it seems

Corrected path issue (better) for interfaces with '/'
parent 0a6b29b0
...@@ -11,17 +11,14 @@ ...@@ -11,17 +11,14 @@
# go CRITICAL when you've actually surpassed your allotment. Will use # go CRITICAL when you've actually surpassed your allotment. Will use
# command line SNMP so no extra Python libraries are required. # command line SNMP so no extra Python libraries are required.
# #
# TODO: - Everything # TODO:
# - As an added feature I'll someday make it work on daily caps and
# additionally make it so you can adjust the day of the month to reset
# - Add in the ability to use perfdata as a simple bandwidth
# method to create graphs in Nagios
# - SNMP v3? # - SNMP v3?
# - Still don't have the logic for when the period rolls - I have about # - Make the usage/documentation better
# 29 days to figure this out :)
# #
# #
# Release Hitory: # Release History:
#
# 0.1 - basic functionality
# #
################################################################################# #################################################################################
...@@ -34,7 +31,9 @@ import subprocess ...@@ -34,7 +31,9 @@ import subprocess
import datetime import datetime
host = '' host = ''
billingPeriodArg = 'm1'
debug = 0 debug = 0
rotate = False
communityString = 'public' communityString = 'public'
OIDDateTime = '.1.3.6.1.2.1.25.1.2.0' OIDDateTime = '.1.3.6.1.2.1.25.1.2.0'
OIDIfDescr = '.1.3.6.1.2.1.2.2.1.2' OIDIfDescr = '.1.3.6.1.2.1.2.2.1.2'
...@@ -92,7 +91,7 @@ def getInterfaces(): ...@@ -92,7 +91,7 @@ def getInterfaces():
def usage(): def usage():
print('Usage: check_snmp_usage.py -H hostname -i interface -b bandwidth limit (bytes) -c community string \n') print('Usage: check_snmp_usage.py -H hostname -i interface -b bandwidth limit (bytes) -c community string \n')
try: try:
opts, args = getopt.getopt(sys.argv[1:], 'H:i:b:cdp') opts, args = getopt.getopt(sys.argv[1:], 'H:i:b:cdp:')
except getopt.GetoptError as err: except getopt.GetoptError as err:
print(err) print(err)
usage() usage()
...@@ -137,6 +136,8 @@ else: ...@@ -137,6 +136,8 @@ else:
multiplier = limitMatch.search(bytesLimit).group(2) multiplier = limitMatch.search(bytesLimit).group(2)
if multiplier: if multiplier:
bytesLimit = int(scalar) * int(unitMultipliers[multiplier]) bytesLimit = int(scalar) * int(unitMultipliers[multiplier])
# validate billing period data # validate billing period data
if not 'billingPeriodArg' in locals(): if not 'billingPeriodArg' in locals():
billingPeriod = 0 billingPeriod = 0
...@@ -157,8 +158,8 @@ else: ...@@ -157,8 +158,8 @@ else:
print('When using monthly billing cycle it is necessary to specify a day between 1 and 31 inclusive.') print('When using monthly billing cycle it is necessary to specify a day between 1 and 31 inclusive.')
sys.exit(3) sys.exit(3)
elif billingPeriod == 'd': elif billingPeriod == 'd':
if int(billTime) < 0 or int(billTime) > 24: if int(billTime) < 0 or int(billTime) > 23:
print('When using daily billing cycle it is necessary to specify an hour between 0 and 24 inclusive.') print('When using daily billing cycle it is necessary to specify an hour between 0 and 23 inclusive.')
# Not optimized - we'll be getting all of the interfaces from the remote system and match up the indexes # Not optimized - we'll be getting all of the interfaces from the remote system and match up the indexes
...@@ -210,10 +211,8 @@ current['outbytes'] = stdout.rstrip().split()[-1] ...@@ -210,10 +211,8 @@ current['outbytes'] = stdout.rstrip().split()[-1]
# Time to see if we have a temp file in place or not and read it if we do # Time to see if we have a temp file in place or not and read it if we do
tmpFile = '/tmp/check_snmp_usage_' + host + '_' + interface + '.tmp' interfacePath = interface.replace('/', '_')
tmpFile = '/tmp/check_snmp_usage_' + host + '_' + interfacePath + '.tmp'
# If the interface name has forward slashes (Cisco) they need to be replaced
tmpFile = tmpFile.replace('/', '_')
if os.path.isfile(tmpFile): if os.path.isfile(tmpFile):
...@@ -249,6 +248,71 @@ currentDateStr = current['year'] + ' ' + current['month'] + ' ' + current['day'] ...@@ -249,6 +248,71 @@ currentDateStr = current['year'] + ' ' + current['month'] + ' ' + current['day']
lastDateTime = datetime.datetime.strptime(lastDateStr, format) lastDateTime = datetime.datetime.strptime(lastDateStr, format)
currentDateTime = datetime.datetime.strptime(currentDateStr, format) currentDateTime = datetime.datetime.strptime(currentDateStr, format)
# Before we go any farther - we will identify if we rotated from one period to the next
# and adjust the file as appropriate - then throw out this iteration of the check
# for all other purposes
# Identify the datetimes to test for:
interestingPeriodEnds = []
# Daily periods:
if billingPeriod == 'd':
todayPeriodEndStr = current['year'] + ' ' + current['month'] + ' ' + current['day'] + ' ' + billTime + ' 00 00'
thisPeriodEndDateTime = datetime.datetime.strptime(todayPeriodEndStr, format)
yesterdayPeriodEndDateTime = thisPeriodEndDateTime - datetime.timedelta(days=1)
interestingPeriodEnds.append(yesterdayPeriodEndDateTime)
interestingPeriodEnds.append(thisPeriodEndDateTime)
# Monthly periods:
# This is actually the number of days in the prior month - it's the right way
if billingPeriod == 'm':
monthDays = {
'1' : 31,
'2' : 31,
'3' : 28,
'4' : 31,
'5' : 30,
'6' : 31,
'7' : 30,
'8' : 31,
'9' : 31,
'10' : 30,
'11' : 31,
'12' : 30,
}
thisMonthPeriodEndStr = current['year'] + ' ' + current['month'] + ' ' + billTime + ' 00 00 00'
thisPeriodEndDateTime = datetime.datetime.strptime(thisMonthPeriodEndStr, format)
lastMonthPeriodEndDateTime = thisPeriodEndDateTime - datetime.timedelta(days=monthDays[current['month']])
interestingPeriodEnds.append(lastMonthPeriodEndDateTime)
interestingPeriodEnds.append(thisPeriodEndDateTime)
for date in interestingPeriodEnds:
# This check iteration is crossing a billing period boundary
if lastDateTime < date and currentDateTime > date and not rotate:
fileLines.append(fileLines[-1] + os.linesep)
fileLines[-2] = '**ARCHIVE** ' + fileLines[-2]
startOfBillingPeriod = date
if billingPeriod == 'm':
endOfBillingPeriod = thisPeriodEndDateTime + datetime.timedelta(days=monthDays[str(int(current['month'])+1)])
if billingPeriod == 'd':
endOfBillingPeriod = thisPeriodEndDateTime + datetime.timedelta(days=1)
rotate = True
elif lastDateTime > date:
startOfBillingPeriod = date
endOfBillingPeriod = thisPeriodEndDateTime
if endOfBillingPeriod < currentDateTime:
if billingPeriod == 'm':
endOfBillingPeriod = thisPeriodEndDateTime + datetime.timedelta(days=monthDays[str(int(current['month'])+1)])
if billingPeriod == 'd':
endOfBillingPeriod = thisPeriodEndDateTime + datetime.timedelta(days=1)
timeDifference = currentDateTime - lastDateTime timeDifference = currentDateTime - lastDateTime
if int(current['inbytes']) > int(last['inbytes']) and int(current['outbytes']) > int(last['outbytes']): if int(current['inbytes']) > int(last['inbytes']) and int(current['outbytes']) > int(last['outbytes']):
...@@ -261,7 +325,8 @@ if int(current['inbytes']) > int(last['inbytes']) and int(current['outbytes']) > ...@@ -261,7 +325,8 @@ if int(current['inbytes']) > int(last['inbytes']) and int(current['outbytes']) >
outLine = current['year'] + '|' + current['month'] + '|' + current['day'] + '|' + current['hour'] + '|' + current['minute'] + '|' + current['second'] + '|' + current['inbytes'] + '|' + current['outbytes'] + '|' + str(inBytesTotal) + '|' + str(outBytesTotal) outLine = current['year'] + '|' + current['month'] + '|' + current['day'] + '|' + current['hour'] + '|' + current['minute'] + '|' + current['second'] + '|' + current['inbytes'] + '|' + current['outbytes'] + '|' + str(inBytesTotal) + '|' + str(outBytesTotal)
fileLines[-1] = outLine fileLines[-1] = outLine
f = open(tmpFile, 'w') f = open(tmpFile, 'w')
f.write(outLine) for line in fileLines:
f.write(line)
f.close() f.close()
else: else:
print('Seems the counter went whacky, we need to reset things') print('Seems the counter went whacky, we need to reset things')
...@@ -270,32 +335,26 @@ else: ...@@ -270,32 +335,26 @@ else:
outLine = current['year'] + '|' + current['month'] + '|' + current['day'] + '|' + current['hour'] + '|' + current['minute'] + '|' + current['second'] + '|' + current['inbytes'] + '|' + current['outbytes'] + '|' + last['inbytestotal'] + '|' + last['outbytestotal'] outLine = current['year'] + '|' + current['month'] + '|' + current['day'] + '|' + current['hour'] + '|' + current['minute'] + '|' + current['second'] + '|' + current['inbytes'] + '|' + current['outbytes'] + '|' + last['inbytestotal'] + '|' + last['outbytestotal']
fileLines[-1] = outLine fileLines[-1] = outLine
f = open(tmpFile, 'w') f = open(tmpFile, 'w')
f.write(outLine) for line in fileLines:
f.write(line)
f.close() f.close()
sys.exit(3) sys.exit(3)
# Files should be done, time to do Nagios logic # Files should be done, time to do Nagios logic
# Calculate number of seconds into month so far
beginningOfMonthStr = current['year'] + ' ' + current['month'] + ' 1 00 00 00'
beginningOfMonthDateTime = datetime.datetime.strptime(beginningOfMonthStr, format)
secondsIntoMonth = currentDateTime - beginningOfMonthDateTime
# Calculate number of seconds in the current month # billingPeriod = m or d
if current['month'] == '12': # billTime = 0-31 or 0-23
nextMonth = '1' # startOfBillingPeriod = datetime object
nextYear = int(current['year']) + 1 # endOfBillingPeriod = datetime object
else:
nextMonth = int(current['month']) + 1 periodLength = endOfBillingPeriod - startOfBillingPeriod
nextYear = current['year'] secondsIntoPeriod = currentDateTime - startOfBillingPeriod
beginningOfNextMonthStr = str(nextYear) + ' ' + str(nextMonth) + ' 1 00 00 00'
beginningOfNextMonthDateTime = datetime.datetime.strptime(beginningOfNextMonthStr, format)
secondsInMonth = beginningOfNextMonthDateTime - beginningOfMonthDateTime
# Percentage of month complete # Percentage of period complete
monthComplete = ( float(secondsIntoMonth.total_seconds()) / float(secondsInMonth.total_seconds()) ) * 100 periodComplete = ( float(secondsIntoPeriod.total_seconds()) / float(periodLength.total_seconds()) ) * 100
# Percentage of data used # Percentage of data used
...@@ -313,22 +372,29 @@ perfdata = '|\'BytesInRate\'=' + str(inBytesPerSec) +'bytes/sec;;;;\'BytesOutRat ...@@ -313,22 +372,29 @@ perfdata = '|\'BytesInRate\'=' + str(inBytesPerSec) +'bytes/sec;;;;\'BytesOutRat
if totalDataUsed > bytesLimit: if totalDataUsed > bytesLimit:
print('CRITICAL - You have exceeded your alloted data usage for this period' + perfdata) print('CRITICAL - You have exceeded your alloted data usage for this period' + perfdata)
print('You are alloted ' + str(bytesLimit) + ' bytes for the month but have already used ' + str(totalDataUsed) + ' bytes.') print('You are alloted ' + str(bytesLimit) + ' bytes for the period but have already used ' + str(totalDataUsed) + ' bytes.')
print('The current billing period started on ' + str(startOfBillingPeriod))
print('The current billing period ends on ' + str(endOfBillingPeriod))
sys.exit(2) sys.exit(2)
elif percentageDataUsed > monthComplete: elif percentageDataUsed > periodComplete:
print('WARNING - You are using data at a rate that will cause you to exceed usage allotment for this period' + perfdata) print('WARNING - You are using data at a rate that will cause you to exceed usage allotment for this period' + perfdata)
print('The month is ' + str(round(monthComplete,2)) + '% complete.') print('The period is ' + str(round(periodComplete,2)) + '% complete.')
print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.') print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.')
print('The current billing period started on ' + str(startOfBillingPeriod))
print('The current billing period ends on ' + str(endOfBillingPeriod))
sys.exit(1) sys.exit(1)
else: else:
print('OK - You will not use all of your alloted data for this period at the current rate' + perfdata) print('OK - You will not use all of your alloted data for this period at the current rate' + perfdata)
print('The month is ' + str(round(monthComplete,2)) + '% complete.') print('The period is ' + str(round(periodComplete,2)) + '% complete.')
print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.') print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.')
print('The current billing period started on ' + str(startOfBillingPeriod))
print('The current billing period ends on ' + str(endOfBillingPeriod))
sys.exit(0) sys.exit(0)
if debug == 1: if debug == 1:
print('The month is ' + str(round(monthComplete,2)) + '% complete.') print('The period is ' + str(round(periodComplete,2)) + '% complete.')
print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.') print('The data allotment on interface ' + interface + ' is ' + str(round(percentageDataUsed,2)) +'% used.')
print('The current incoming rate is ' + str(inBytesPerSec) + ' bytes/second.') print('The current incoming rate is ' + str(inBytesPerSec) + ' bytes/second.')
print('The current outgoing rate is ' + str(outBytesPerSec) + ' bytes/second.') print('The current outgoing rate is ' + str(outBytesPerSec) + ' bytes/second.')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment