Skip to content

Instantly share code, notes, and snippets.

@jcurry
Created October 28, 2016 14:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcurry/cf2422b3fce6162960d416ab25616090 to your computer and use it in GitHub Desktop.
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
#!/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