From cce48368e33ac879bad181a915ace5ad0d872979 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 08:58:32 -0700 Subject: [PATCH 01/14] Fixing the test case. --- test_snmplient.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test_snmplient.py b/test_snmplient.py index 85c90ca..049a410 100644 --- a/test_snmplient.py +++ b/test_snmplient.py @@ -1,9 +1,11 @@ import snmpclient -router = '10.42.1.1' -authdata = {'community': 'public', 'version': snmpclient.V2C} +router = '10.100.184.62' +port = 161 +authdata = [{'community': 'public', 'version': snmpclient.V2C}, + {'community': 'private', 'version': snmpclient.V2C}] -client = snmpclient.SnmpClient(router, [authdata]) +client = snmpclient.SnmpClient(router, port, authdata) print client.alive print client.get('SNMPv2-MIB::sysName.0') print client.gettable('UDP-MIB::udpLocalAddress') From 25bad92c088121487927ea89bbc4b331d540b816 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 08:59:07 -0700 Subject: [PATCH 02/14] Renaming the test to the proper name. --- test_snmplient.py => test_snmpclient.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test_snmplient.py => test_snmpclient.py (100%) diff --git a/test_snmplient.py b/test_snmpclient.py similarity index 100% rename from test_snmplient.py rename to test_snmpclient.py From d275a583c5c677c904718ec7fcba5e15d2c4e326 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 09:03:09 -0700 Subject: [PATCH 03/14] Addressing PEP8 formatting and pysnmp 4.5.2 compatibility changes. --- snmpclient.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index 6ee5ae4..b678435 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -46,13 +46,17 @@ def load_mibs(*modules): raise # Load basic mibs that come with pysnmp -load_mibs('SNMPv2-MIB','IF-MIB','IP-MIB','HOST-RESOURCES-MIB','FIBRE-CHANNEL-FE-MIB') +load_mibs('SNMPv2-MIB', + 'IF-MIB', + 'IP-MIB', + 'HOST-RESOURCES-MIB', + 'FIBRE-CHANNEL-FE-MIB') def nodeinfo(oid): """Translate dotted-decimal oid to a tuple with symbolic info""" if isinstance(oid, basestring): oid = tuple([int(x) for x in oid.split('.') if x]) - return (__mibViewController.getNodeLocation(oid), + return (__mibViewController.getNodeLocation(oid), __mibViewController.getNodeName(oid)) def nodename(oid): @@ -63,7 +67,7 @@ def nodename(oid): if noid: name += '.' + noid return name - + def nodeid(oid): """Translate named oid to dotted-decimal format""" ids = oid.split('.') @@ -86,7 +90,10 @@ def __init__(self, host, port, authorizations): noid = nodeid('SNMPv2-MIB::sysName.0') for auth in authorizations: (errorIndication, errorStatus, errorIndex, varBinds) = \ - cmdgen.CommandGenerator().getCmd(auth, cmdgen.UdpTransportTarget((self.host, self.port)), noid) + cmdgen.CommandGenerator().getCmd( + cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.UdpTransportTarget((self.host, self.port)), + noid) if errorIndication == 'requestTimedOut': continue else: @@ -98,7 +105,10 @@ def get(self, oid): """Get a specific node in the tree""" noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ - cmdgen.CommandGenerator().getCmd(self.auth, cmdgen.UdpTransportTarget((self.host, self.port)), noid) + cmdgen.CommandGenerator().getCmd( + cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.UdpTransportTarget((self.host, self.port)), + noid) if errorIndication: raise RuntimeError("SNMPget of %s on %s failed" % (oid, self.host)) return varBinds[0][1] @@ -107,7 +117,10 @@ def gettable(self, oid): """Get a complete subtable""" noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ - cmdgen.CommandGenerator().nextCmd(self.auth, cmdgen.UdpTransportTarget((self.host, self.port)), noid) + cmdgen.CommandGenerator().nextCmd( + cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.UdpTransportTarget((self.host, self.port)), + noid) if errorIndication: raise RuntimeError("SNMPget of %s on %s failed" % (oid, self.host)) return [x[0] for x in varBinds] From 4e99051c8e882f8498783038dc9fa129f474bc60 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 09:04:12 -0700 Subject: [PATCH 04/14] Fixed issue from previous checkin with class variable. --- snmpclient.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index b678435..68bbf5b 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -106,7 +106,8 @@ def get(self, oid): noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( - cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.CommunityData(self.auth['community'], + self.auth['version']), cmdgen.UdpTransportTarget((self.host, self.port)), noid) if errorIndication: @@ -118,7 +119,8 @@ def gettable(self, oid): noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().nextCmd( - cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.CommunityData(self.auth['community'], + self.auth['version']), cmdgen.UdpTransportTarget((self.host, self.port)), noid) if errorIndication: From 372b88cee3f73368a92b9fdee4b6b4c2078c9855 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 09:07:03 -0700 Subject: [PATCH 05/14] Explicitly providing the mdModel named parameter. --- snmpclient.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index 68bbf5b..32520bf 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -91,7 +91,8 @@ def __init__(self, host, port, authorizations): for auth in authorizations: (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( - cmdgen.CommunityData(auth['community'], auth['version']), + cmdgen.CommunityData(auth['community'], + mpModel=auth['version']), cmdgen.UdpTransportTarget((self.host, self.port)), noid) if errorIndication == 'requestTimedOut': @@ -107,7 +108,7 @@ def get(self, oid): (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( cmdgen.CommunityData(self.auth['community'], - self.auth['version']), + mpModel=self.auth['version']), cmdgen.UdpTransportTarget((self.host, self.port)), noid) if errorIndication: @@ -120,7 +121,7 @@ def gettable(self, oid): (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().nextCmd( cmdgen.CommunityData(self.auth['community'], - self.auth['version']), + mpModel=self.auth['version']), cmdgen.UdpTransportTarget((self.host, self.port)), noid) if errorIndication: From 8dabefd1fc69d6fb9181ad2b1111579ce1ae4721 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 09:10:30 -0700 Subject: [PATCH 06/14] Minor refactoring of shared code. --- snmpclient.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index 32520bf..0b367ae 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -31,10 +31,12 @@ __mibBuilder = builder.MibBuilder() __mibViewController = view.MibViewController(__mibBuilder) + def add_mib_path(*path): """Add a directory to the MIB search path""" __mibBuilder.setMibPath(*(__mibBuilder.getMibPath() + path)) + def load_mibs(*modules): """Load one or more mibs""" for m in modules: @@ -45,12 +47,6 @@ def load_mibs(*modules): continue raise -# Load basic mibs that come with pysnmp -load_mibs('SNMPv2-MIB', - 'IF-MIB', - 'IP-MIB', - 'HOST-RESOURCES-MIB', - 'FIBRE-CHANNEL-FE-MIB') def nodeinfo(oid): """Translate dotted-decimal oid to a tuple with symbolic info""" @@ -59,6 +55,7 @@ def nodeinfo(oid): return (__mibViewController.getNodeLocation(oid), __mibViewController.getNodeName(oid)) + def nodename(oid): """Translate dotted-decimal oid or oid tuple to symbolic name""" oid = __mibViewController.getNodeLocation(oid) @@ -68,6 +65,7 @@ def nodename(oid): name += '.' + noid return name + def nodeid(oid): """Translate named oid to dotted-decimal format""" ids = oid.split('.') @@ -77,6 +75,15 @@ def nodeid(oid): oid = mibnode.getName() + ids return oid + +# Load basic mibs that come with pysnmp +load_mibs('SNMPv2-MIB', + 'IF-MIB', + 'IP-MIB', + 'HOST-RESOURCES-MIB', + 'FIBRE-CHANNEL-FE-MIB') + + class SnmpClient(object): """Easy access to an snmp deamon on a host""" @@ -85,6 +92,7 @@ def __init__(self, host, port, authorizations): self.host = host self.port = port self.alive = False + self.transport = cmdgen.UdpTransportTarget((self.host, self.port)) # Which community to use noid = nodeid('SNMPv2-MIB::sysName.0') @@ -93,7 +101,7 @@ def __init__(self, host, port, authorizations): cmdgen.CommandGenerator().getCmd( cmdgen.CommunityData(auth['community'], mpModel=auth['version']), - cmdgen.UdpTransportTarget((self.host, self.port)), + self.transport, noid) if errorIndication == 'requestTimedOut': continue @@ -107,9 +115,9 @@ def get(self, oid): noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( - cmdgen.CommunityData(self.auth['community'], - mpModel=self.auth['version']), - cmdgen.UdpTransportTarget((self.host, self.port)), + cmdgen.CommunityData(self.auth['community'], + mpModel=self.auth['version']), + self.transport, noid) if errorIndication: raise RuntimeError("SNMPget of %s on %s failed" % (oid, self.host)) @@ -120,9 +128,9 @@ def gettable(self, oid): noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().nextCmd( - cmdgen.CommunityData(self.auth['community'], - mpModel=self.auth['version']), - cmdgen.UdpTransportTarget((self.host, self.port)), + cmdgen.CommunityData(self.auth['community'], + mpModel=self.auth['version']), + self.transport, noid) if errorIndication: raise RuntimeError("SNMPget of %s on %s failed" % (oid, self.host)) From e8d1e3db738737fcfa7c505d23555e99117b0874 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 10:33:54 -0700 Subject: [PATCH 07/14] Adding the ability to set values to a specific tree node. --- snmpclient.py | 65 +++++++++++++++++++++++++++++++++++++++------- test_snmpclient.py | 6 ++--- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index 0b367ae..39c666e 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -19,11 +19,12 @@ import pysnmp.entity.rfc3413.oneliner.cmdgen as cmdgen from pysnmp.smi import builder, view from pysnmp.smi.error import SmiError +from pysnmp.proto import rfc1902 __all__ = ['V1', 'V2', 'V2C', 'add_mib_path', 'load_mibs', 'nodeinfo', 'nodename', 'nodeid', 'SnmpClient', 'cmdgen'] -# Snmp version constants +# SNMP version constants V1 = 0 V2 = V2C = 1 @@ -34,7 +35,8 @@ def add_mib_path(*path): """Add a directory to the MIB search path""" - __mibBuilder.setMibPath(*(__mibBuilder.getMibPath() + path)) + mibPath = __mibBuilder.getMibPath() + path + __mibBuilder.setMibPath(*mibPath) def load_mibs(*modules): @@ -87,16 +89,16 @@ def nodeid(oid): class SnmpClient(object): """Easy access to an snmp deamon on a host""" - def __init__(self, host, port, authorizations): + def __init__(self, host, port, read_authorizations, write_authorizations): """Set up the client and detect the community to use""" self.host = host self.port = port self.alive = False self.transport = cmdgen.UdpTransportTarget((self.host, self.port)) - # Which community to use + # Determine which community to use for reading values noid = nodeid('SNMPv2-MIB::sysName.0') - for auth in authorizations: + for auth in read_authorizations: (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( cmdgen.CommunityData(auth['community'], @@ -107,29 +109,72 @@ def __init__(self, host, port, authorizations): continue else: self.alive = True - self.auth = auth + self.readauth = cmdgen.CommunityData(auth['community'], + mpModel=auth['version']) break + # Don't determine the write authorization since there's no temporary + # location within SNMP to write to. Choose the first authorization. + for auth in write_authorizations: + self.writeauth = cmdgen.CommunityData(auth['community'], + mpModel=auth['version']) + break + def get(self, oid): """Get a specific node in the tree""" noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( - cmdgen.CommunityData(self.auth['community'], - mpModel=self.auth['version']), + self.readauth, self.transport, noid) if errorIndication: raise RuntimeError("SNMPget of %s on %s failed" % (oid, self.host)) return varBinds[0][1] + def set(self, oid, value): + """Set a specific value to a node in the tree""" + initial_value = self.get(oid) + + # Types from RFC-1902 + if isinstance(initial_value, rfc1902.Counter32): + set_value = rfc1902.Counter32(str(value)) + elif isinstance(initial_value, rfc1902.Counter64): + set_value = rfc1902.Counter64(str(value)) + elif isinstance(initial_value, rfc1902.Gauge32): + set_value = rfc1902.Gauge32(str(value)) + elif isinstance(initial_value, rfc1902.Integer): + set_value = rfc1902.Integer(str(value)) + elif isinstance(initial_value, rfc1902.Integer32): + set_value = rfc1902.Integer32(str(value)) + elif isinstance(initial_value, rfc1902.IpAddress): + set_value = rfc1902.IpAddress(str(value)) + elif isinstance(initial_value, rfc1902.OctetString): + set_value = rfc1902.OctetString(str(value)) + elif isinstance(initial_value, rfc1902.TimeTicks): + set_value = rfc1902.TimeTicks(str(value)) + elif isinstance(initial_value, rfc1902.Unsigned32): + set_value = rfc1902.Unsigned32(str(value)) + else: + raise RuntimeError("Unknown type %s" % type(initial_value)) + + noid = nodeid(oid) + (errorIndication, errorStatus, errorIndex, varBinds) = \ + cmdgen.CommandGenerator().setCmd( + self.writeauth, + self.transport, + (noid, set_value) + ) + if errorIndication: + raise RuntimeError("SNMPset of %s on %s failed" % (oid, self.host)) + return varBinds[0][1] + def gettable(self, oid): """Get a complete subtable""" noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().nextCmd( - cmdgen.CommunityData(self.auth['community'], - mpModel=self.auth['version']), + self.readauth, self.transport, noid) if errorIndication: diff --git a/test_snmpclient.py b/test_snmpclient.py index 049a410..ac9ec4d 100644 --- a/test_snmpclient.py +++ b/test_snmpclient.py @@ -2,10 +2,10 @@ router = '10.100.184.62' port = 161 -authdata = [{'community': 'public', 'version': snmpclient.V2C}, - {'community': 'private', 'version': snmpclient.V2C}] +public_auth = [{'community': 'public', 'version': snmpclient.V2C}] +priavte_auth = [{'community': 'private', 'version': snmpclient.V2C}] -client = snmpclient.SnmpClient(router, port, authdata) +client = snmpclient.SnmpClient(router, port, public_auth, priavte_auth) print client.alive print client.get('SNMPv2-MIB::sysName.0') print client.gettable('UDP-MIB::udpLocalAddress') From 7806aa260b5ba86d2e9ab0f85682ca6b7323796b Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 10:35:37 -0700 Subject: [PATCH 08/14] Fixing spelling mistake. --- test_snmpclient.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_snmpclient.py b/test_snmpclient.py index ac9ec4d..3d09780 100644 --- a/test_snmpclient.py +++ b/test_snmpclient.py @@ -3,9 +3,9 @@ router = '10.100.184.62' port = 161 public_auth = [{'community': 'public', 'version': snmpclient.V2C}] -priavte_auth = [{'community': 'private', 'version': snmpclient.V2C}] +private_auth = [{'community': 'private', 'version': snmpclient.V2C}] -client = snmpclient.SnmpClient(router, port, public_auth, priavte_auth) +client = snmpclient.SnmpClient(router, port, public_auth, private_auth) print client.alive print client.get('SNMPv2-MIB::sysName.0') print client.gettable('UDP-MIB::udpLocalAddress') From 3ed078436369267b8c5c0f8d78e5baa1494b1321 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 10:40:59 -0700 Subject: [PATCH 09/14] Adding test for use with APC PDU Model 8xxx. --- test_snmpclient_apcpdu.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test_snmpclient_apcpdu.py diff --git a/test_snmpclient_apcpdu.py b/test_snmpclient_apcpdu.py new file mode 100644 index 0000000..16c9ac9 --- /dev/null +++ b/test_snmpclient_apcpdu.py @@ -0,0 +1,38 @@ +from os import getcwd +import snmpclient + +router = '10.100.184.62' +port = 161 +public_auth = [{'community': 'public', 'version': snmpclient.V2C}] +private_auth = [{'community': 'private', 'version': snmpclient.V2C}] + +snmpclient.add_mib_path(getcwd()) + +# NOTE: In order to use this, download the APC PowerNet-MIB from: +# ftp://ftp.apc.com/apc/public/software/pnetmib/mib +# and run: +# build-pysnmp-mib -o PowerNet-MIB.py powernetZZZ.mib +# There appears to be a bug in either the MIB or build-pysnmp-mib whereby +# Unsigned32 is undefined. Despite this being an awful hack, modify the +# generated PowerNet-MIB.py running: +# sed -i '10 a ( Unsigned32, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Unsigned32")' PowerNet-MIB.py +snmpclient.load_mibs('PowerNet-MIB') +client = snmpclient.SnmpClient(router, port, public_auth, private_auth) + +print client.alive +print "APC Model Number: %s" % \ + client.get('PowerNet-MIB::rPDU2IdentModelNumber.1') +print "Outlet 5 status: %s" % \ + client.get('PowerNet-MIB::rPDU2OutletSwitchedStatusState.5') +print "Outlet 5 on: %s" % \ + client.set('PowerNet-MIB::rPDU2OutletSwitchedControlCommand.5', 1) +print "Outlet 5 command pending: %s" % \ + client.get('PowerNet-MIB::rPDU2OutletSwitchedStatusCommandPending.5') +print "Outlet 5 status: %s" % \ + client.get('PowerNet-MIB::rPDU2OutletSwitchedStatusState.5') +print "Outlet 5 off: %s" % \ + client.set('PowerNet-MIB::rPDU2OutletSwitchedControlCommand.5', 1) +print "Outlet 5 command pending: %s" % \ + client.get('PowerNet-MIB::rPDU2OutletSwitchedStatusCommandPending.5') +print "Outlet 5 status: %s" % \ + client.get('PowerNet-MIB::rPDU2OutletSwitchedStatusState.5') From 5dcb609461abb0a7a71ddfe23bb85e17d622b9fb Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 10:41:15 -0700 Subject: [PATCH 10/14] Fixing PEP8 violation. --- test_snmpclient.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test_snmpclient.py b/test_snmpclient.py index 3d09780..d45d780 100644 --- a/test_snmpclient.py +++ b/test_snmpclient.py @@ -9,4 +9,7 @@ print client.alive print client.get('SNMPv2-MIB::sysName.0') print client.gettable('UDP-MIB::udpLocalAddress') -print client.matchtables('IF-MIB::ifIndex', ('IF-MIB::ifDescr', 'IF-MIB::ifPhysAddress', 'IF-MIB::ifOperStatus')) +print client.matchtables('IF-MIB::ifIndex', + ('IF-MIB::ifDescr', + 'IF-MIB::ifPhysAddress', + 'IF-MIB::ifOperStatus')) From b8e57f60c340a53e0dde57fa79e581b4566c2ab9 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 24 Sep 2015 10:47:59 -0700 Subject: [PATCH 11/14] Adding AUTHORS file. --- AUTHORS | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..bda0415 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +snmpclient is written and maintained by Dennis Kaarsemaker and +various contributors: + +Development Lead +```````````````` + +- Dennis Kaarsemaker + +Patches and Suggestions +``````````````````````` + +- Robert Wlodarczyk From 1ca207e42246f52c4558226e609b748156c97df2 Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Thu, 1 Oct 2015 14:39:14 -0700 Subject: [PATCH 12/14] Fixing up setup.py to include pysnmp. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2eb65e6..b8704e7 100644 --- a/setup.py +++ b/setup.py @@ -15,5 +15,5 @@ "Topic :: System :: Monitoring", "Topic :: Software Development" ], - #install_requires='pysnmp', + install_requires=['pysnmp'], ) From 90d5b857b1aeb1e79026d2808d24aae694a5355a Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Tue, 12 Jan 2016 09:30:54 -0800 Subject: [PATCH 13/14] Adding timeout, retries, and returning if read/write auth is not set. --- snmpclient.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/snmpclient.py b/snmpclient.py index 39c666e..66eacab 100644 --- a/snmpclient.py +++ b/snmpclient.py @@ -89,12 +89,19 @@ def nodeid(oid): class SnmpClient(object): """Easy access to an snmp deamon on a host""" - def __init__(self, host, port, read_authorizations, write_authorizations): + def __init__(self, host, port, read_authorizations, write_authorizations, + timeout=1, retries=2): """Set up the client and detect the community to use""" self.host = host self.port = port + self.timeout = timeout + self.retries = retries self.alive = False - self.transport = cmdgen.UdpTransportTarget((self.host, self.port)) + self.transport = cmdgen.UdpTransportTarget((self.host, self.port), + timeout=self.timeout, + retries=self.retries,) + self.readauth = None + self.writeauth = None # Determine which community to use for reading values noid = nodeid('SNMPv2-MIB::sysName.0') @@ -122,6 +129,9 @@ def __init__(self, host, port, read_authorizations, write_authorizations): def get(self, oid): """Get a specific node in the tree""" + if not self.readauth: + return + noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().getCmd( @@ -134,6 +144,9 @@ def get(self, oid): def set(self, oid, value): """Set a specific value to a node in the tree""" + if not self.writeauth: + return + initial_value = self.get(oid) # Types from RFC-1902 @@ -171,6 +184,9 @@ def set(self, oid, value): def gettable(self, oid): """Get a complete subtable""" + if not self.readauth: + return + noid = nodeid(oid) (errorIndication, errorStatus, errorIndex, varBinds) = \ cmdgen.CommandGenerator().nextCmd( @@ -184,6 +200,9 @@ def gettable(self, oid): def matchtables(self, index, tables): """Match a list of tables using either a specific index table or the common tail of the OIDs in the tables""" + if not self.readauth: + return + oid_to_index = {} result = {} indexlen = 1 From f51531df750611bcdbde3c0721e162f24002a80c Mon Sep 17 00:00:00 2001 From: Robert Wlodarczyk Date: Tue, 12 Jan 2016 16:50:46 -0800 Subject: [PATCH 14/14] Updating README --- README.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 202d73b..a57d14c 100644 --- a/README.rst +++ b/README.rst @@ -34,10 +34,11 @@ The SnmpClient class This class wraps arround pysnmp's cmdgen.CommandGenerator to make it easier to address an snmp daemon. -snmpclient.SnmpClient(host, port, authorizations) ----------------------------------------- -The constructor takes a hostname/ip address, UDP port and a list of -authorization objects. +snmpclient.SnmpClient(host, port, read_authorizations, write_authorizations, timeout, retries) +---------------------------------------------------------------------------------------------- +The constructor takes a hostname/ip address, UDP port, and a list of +read authorization objects. Optionally, a list of write authorization objects, +timeout, and number of retries may be provided as well. These objects are created as follows: @@ -60,6 +61,11 @@ snmpclient.SnmpClient.get(oid) Takes a named oid, queries the server and returns the value of that oid on the server. +snmpclient.SnmpClient.set(oid, value) +------------------------------ +Takes a named oid and value, queries the server to determine its type, and +subsequently sets value to the newly provided one. + snmpclient.SnmpClient.gettable(oid) ----------------------------------- Takes a named oid, walks that table and returns a list of (oid, value) pairs in