Created
October 28, 2016 14:39
-
-
Save jcurry/cf2422b3fce6162960d416ab25616090 to your computer and use it in GitHub Desktop.
Uses SNMP to search for processes, returning processes plus cpu and memory used
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Author: Jane Curry | |
# Date: May 1st 2013 | |
# Description: Uses twisted SNMP to get process data from Host Resources MIB | |
# searching for supplied string (currently in attributes). | |
# Delivers process count, total mem used and total cpu used | |
# Requires parameters: | |
# -H <IP addr> -V <snmp ver> -c <community> -p <string in Path> -a <string in attrs> -v (for verbose} | |
# eg. -H 10.0.0.125 -V v2c -c public -p "/var/run/vmnet-netifup" | |
# Updated: April 14th, 2014 | |
# Returns system exit 1 on failure callback | |
import sys | |
import os | |
from optparse import OptionParser | |
from twisted.internet import reactor | |
from twisted.python.failure import Failure | |
from pynetsnmp.twistedsnmp import AgentProxy | |
def get_cli_options(): | |
"""Get command line options. Return them in a usable form.""" | |
parser = OptionParser() | |
parser.add_option( | |
'-H', '--host', | |
dest='host', | |
help='IP address of NetBotz device') | |
parser.add_option( | |
'-V', '--version', | |
dest='version', default='v1', | |
help='SNMP version to be used') | |
parser.add_option( | |
'-c', '--community', | |
dest='community', default='public', | |
help='SNMP community string') | |
parser.add_option( | |
'-a', '--attribprocess', | |
dest='aprocess', default='', | |
help='attribute process parameter string to match') | |
parser.add_option( | |
'-p', '--pathprocess', | |
dest='pprocess', default='', | |
help='path process parameter string to match') | |
parser.add_option( | |
'-v', '--verbose', | |
dest='verbose', | |
action="store_true", | |
default='False', | |
help='verbose output') | |
options, args = parser.parse_args() | |
return options | |
def get_snmp_proxy(host, version, community): | |
"""Return an SNMP proxy given host, version and community.""" | |
snmp_proxy = AgentProxy( | |
ip=host, | |
community=community, | |
snmpVersion=version) | |
try: | |
snmp_proxy.open() | |
return snmp_proxy | |
except: | |
return | |
class hrSWRunMIB: | |
"""Host Resources SW Run Table MIB""" | |
tempSensorEntry = '1.3.6.1.4.1.5528.100.4.1.1.1' | |
hrSWRunEntry = '1.3.6.1.2.1.25.4.2.1' | |
hrSWindex = '1.3.6.1.2.1.25.4.2.1.1' | |
hrSWname = '1.3.6.1.2.1.25.4.2.1.2' | |
hrSWPath = '1.3.6.1.2.1.25.4.2.1.4' | |
hrSWParam = '1.3.6.1.2.1.25.4.2.1.5' | |
hrSWCpu = '1.3.6.1.2.1.25.5.1.1.1' | |
hrSWMem = '1.3.6.1.2.1.25.5.1.1.2' | |
tempSensorId = '1.3.6.1.4.1.5528.100.4.1.1.1.1' | |
tempSensorValueStr = '1.3.6.1.4.1.5528.100.4.1.1.1.7' | |
def get_matching_processes(snmp_proxy, aprocess, pprocess, verbose): | |
def process_response(result): | |
cpuSum = 0 | |
memSum = 0 | |
procSum = 0 | |
pathList = [] | |
# Get dictionaries containing the CPU amd memory tables | |
cpudata = result.get(hrSWRunMIB.hrSWCpu, {}) | |
memdata = result.get(hrSWRunMIB.hrSWMem, {}) | |
# For verbose, also want process path and params | |
procParams = result.get(hrSWRunMIB.hrSWParam, {}) | |
procPath = result.get(hrSWRunMIB.hrSWPath, {}) | |
if aprocess: | |
# Check against attributes - hrSWParam | |
for oid, hrSWParam in result.get(hrSWRunMIB.hrSWParam, {}).items(): | |
snmpindex = oid.split('.')[-1] | |
#print 'oid is %s and hrSWParam is %s and snmpindex is %s' % (oid, hrSWParam, snmpindex) | |
cpuOID = '.' + hrSWRunMIB.hrSWCpu + '.' + snmpindex | |
memOID = '.' + hrSWRunMIB.hrSWMem + '.' + snmpindex | |
pathOID = '.' + hrSWRunMIB.hrSWPath + '.' + snmpindex | |
paramsOID = '.' + hrSWRunMIB.hrSWParam + '.' + snmpindex | |
# print 'param %s snmpindex %s cpuOID %s memOID %s' % (hrSWParam, snmpindex, cpuOID, memOID) | |
#print 'pathOID is %s and paramsOID is %s ' % (pathOID, paramsOID) | |
# Ignore processes that do not match our search string | |
if hrSWParam.find(aprocess) == -1: | |
continue | |
cpuSum += cpudata[cpuOID] | |
memSum += memdata[memOID] | |
procSum += 1 | |
procPathParams = procPath[pathOID] + ' ' + procParams[paramsOID] + ' ' | |
pathList.append(procPathParams) | |
# No need to modify CPU as it is treated as a counter anyway | |
# memSum is in KB - change to bytes | |
memSum = memSum * 1000 | |
if verbose != True: | |
pathList = [] | |
return { 'processes': procSum, 'cpu': cpuSum, 'mem': memSum, 'processPaths': pathList } | |
else: | |
if pprocess: | |
# Check against attributes - hrSWPath | |
for oid, hrSWPath in result.get(hrSWRunMIB.hrSWPath, {}).items(): | |
snmpindex = oid.split('.')[-1] | |
#print 'oid is %s and hrSWPath is %s and snmpindex is %s' % (oid, hrSWPath, snmpindex) | |
cpuOID = '.' + hrSWRunMIB.hrSWCpu + '.' + snmpindex | |
memOID = '.' + hrSWRunMIB.hrSWMem + '.' + snmpindex | |
pathOID = '.' + hrSWRunMIB.hrSWPath + '.' + snmpindex | |
paramsOID = '.' + hrSWRunMIB.hrSWParam + '.' + snmpindex | |
# print 'param %s snmpindex %s cpuOID %s memOID %s' % (hrSWPath, snmpindex, cpuOID, memOID) | |
# Ignore processes that do not match our search string | |
if hrSWPath.find(pprocess) == -1: | |
continue | |
cpuSum += cpudata[cpuOID] | |
memSum += memdata[memOID] | |
procSum += 1 | |
procPathParams = procPath[pathOID] + ' ' + procParams[paramsOID] + ' ' | |
pathList.append(procPathParams) | |
# No need to modify CPU as it is treated as a counter anyway | |
# memSum is in KB - change to bytes | |
memSum = memSum * 1000 | |
if verbose != True: | |
pathList = [] | |
return { 'processes': procSum, 'cpu': cpuSum, 'mem': memSum, 'processPaths': pathList } | |
d = snmp_proxy.getTable(( | |
hrSWRunMIB.hrSWParam, | |
hrSWRunMIB.hrSWPath, | |
hrSWRunMIB.hrSWCpu, | |
hrSWRunMIB.hrSWMem, | |
), maxRepetitions=1, limit=sys.maxint) | |
d.addCallback(process_response) | |
return d | |
def main(): | |
options = get_cli_options() | |
if not options.host: | |
print 'Incorrect parameters supplied, please use --help for usage' | |
return | |
snmp_proxy = get_snmp_proxy( | |
options.host, options.version, options.community) | |
# New code .... | |
if not snmp_proxy: | |
print 'Failed to get SNMP connection' | |
sys.exit('Failed to get SNMP connection') | |
return | |
def cmdsuccess(result): | |
if result['processPaths']: | |
print '%s processes running,%s, total mem is %s total cpu is %s status OK | processes=%s mem=%s cpu=%s ' % (result['processes'] , result['processPaths'], result['mem'] , result['cpu'],result['processes'] , result['mem'] , result['cpu']) | |
else: | |
print '%s processes running, total mem is %s total cpu is %s status OK | processes=%s mem=%s cpu=%s ' % (result['processes'] , result['mem'] , result['cpu'],result['processes'] , result['mem'] , result['cpu']) | |
def exit1(): | |
os._exit(1) | |
def failure(result): | |
msg = None | |
if isinstance(result, Failure): | |
msg = result.getErrorMessage() + 'Trying to access ' + options.host | |
else: | |
msg = str(result) + 'Trying to access ' + options.host | |
print 'Failure in running script %s' % (msg) | |
sys.stdout.flush() | |
reactor.addSystemEventTrigger('after', 'shutdown', exit1()) | |
def cleanup(result): | |
"""Called after success or failure.""" | |
snmp_proxy.close() | |
reactor.stop() | |
d = get_matching_processes(snmp_proxy, options.aprocess, options.pprocess, options.verbose) | |
d.addCallback(cmdsuccess) | |
d.addErrback(failure) | |
d.addBoth(cleanup) | |
reactor.run() | |
# If we're being called as a stand-alone script. Not imported. | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment