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 @@
# go CRITICAL when you've actually surpassed your allotment. Will use
# command line SNMP so no extra Python libraries are required.
#
# TODO: - Everything
# - 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
# TODO:
# - SNMP v3?
# - Still don't have the logic for when the period rolls - I have about
# 29 days to figure this out :)
# - Make the usage/documentation better
#
#
# Release Hitory:
# Release History:
#
# 0.1 - basic functionality
#
#################################################################################
......@@ -34,7 +31,9 @@ import subprocess
import datetime
host = ''
billingPeriodArg = 'm1'
debug = 0
rotate = False
communityString = 'public'
OIDDateTime = '.1.3.6.1.2.1.25.1.2.0'
OIDIfDescr = '.1.3.6.1.2.1.2.2.1.2'
......@@ -92,7 +91,7 @@ def getInterfaces():
def usage():
print('Usage: check_snmp_usage.py -H hostname -i interface -b bandwidth limit (bytes) -c community string \n')
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:
print(err)
usage()
......@@ -137,6 +136,8 @@ else:
multiplier = limitMatch.search(bytesLimit).group(2)
if multiplier:
bytesLimit = int(scalar) * int(unitMultipliers[multiplier])
# validate billing period data
if not 'billingPeriodArg' in locals():
billingPeriod = 0
......@@ -157,8 +158,8 @@ else:
print('When using monthly billing cycle it is necessary to specify a day between 1 and 31 inclusive.')
sys.exit(3)
elif billingPeriod == 'd':
if int(billTime) < 0 or int(billTime) > 24:
print('When using daily billing cycle it is necessary to specify an hour between 0 and 24 inclusive.')
if int(billTime) < 0 or int(billTime) > 23:
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
......@@ -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
tmpFile = '/tmp/check_snmp_usage_' + host + '_' + interface + '.tmp'
# If the interface name has forward slashes (Cisco) they need to be replaced
tmpFile = tmpFile.replace('/', '_')
interfacePath = interface.replace('/', '_')
tmpFile = '/tmp/check_snmp_usage_' + host + '_' + interfacePath + '.tmp'
if os.path.isfile(tmpFile):
......@@ -249,6 +248,71 @@ currentDateStr = current['year'] + ' ' + current['month'] + ' ' + current['day']
lastDateTime = datetime.datetime.strptime(lastDateStr, 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
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']) >
outLine = current['year'] + '|' + current['month'] + '|' + current['day'] + '|' + current['hour'] + '|' + current['minute'] + '|' + current['second'] + '|' + current['inbytes'] + '|' + current['outbytes'] + '|' + str(inBytesTotal) + '|' + str(outBytesTotal)
fileLines[-1] = outLine
f = open(tmpFile, 'w')
f.write(outLine)
for line in fileLines:
f.write(line)
f.close()
else:
print('Seems the counter went whacky, we need to reset things')
......@@ -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']
fileLines[-1] = outLine
f = open(tmpFile, 'w')
f.write(outLine)
for line in fileLines:
f.write(line)
f.close()
sys.exit(3)
# 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
if current['month'] == '12':
nextMonth = '1'
nextYear = int(current['year']) + 1
else:
nextMonth = int(current['month']) + 1
nextYear = current['year']
# billingPeriod = m or d
# billTime = 0-31 or 0-23
# startOfBillingPeriod = datetime object
# endOfBillingPeriod = datetime object
periodLength = endOfBillingPeriod - startOfBillingPeriod
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
monthComplete = ( float(secondsIntoMonth.total_seconds()) / float(secondsInMonth.total_seconds()) ) * 100
# Percentage of period complete
periodComplete = ( float(secondsIntoPeriod.total_seconds()) / float(periodLength.total_seconds()) ) * 100
# Percentage of data used
......@@ -313,22 +372,29 @@ perfdata = '|\'BytesInRate\'=' + str(inBytesPerSec) +'bytes/sec;;;;\'BytesOutRat
if totalDataUsed > bytesLimit:
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)
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('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 current billing period started on ' + str(startOfBillingPeriod))
print('The current billing period ends on ' + str(endOfBillingPeriod))
sys.exit(1)
else:
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 current billing period started on ' + str(startOfBillingPeriod))
print('The current billing period ends on ' + str(endOfBillingPeriod))
sys.exit(0)
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 current incoming rate is ' + str(inBytesPerSec) + ' 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