Skip to content

Commit

Permalink
Implemented the abort_on_nonexistent parameter for sessions and disab…
Browse files Browse the repository at this point in the history
…led not found exceptions by default
  • Loading branch information
fgimian committed Jun 12, 2015
1 parent ad36f0c commit 49ea15e
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 12 deletions.
31 changes: 23 additions & 8 deletions easysnmp/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,18 @@ def validate_results(varlist):
"""

for variable in varlist:
# Create a printable variable string for the error
varstr = variable.oid
if variable.oid_index:
varstr += ' with index {0}'.format(variable.oid_index)

if variable.snmp_type == 'NOSUCHOBJECT':
raise EasySNMPNoSuchObjectError('no such object could be found')
if variable.value == 'NOSUCHINSTANCE':
raise EasySNMPNoSuchObjectError(
'no such object {0} could be found'.format(varstr)
)
if variable.snmp_type == 'NOSUCHINSTANCE':
raise EasySNMPNoSuchInstanceError(
'no such instance could be found'
'no such instance {0} could be found'.format(varstr)
)


Expand Down Expand Up @@ -149,6 +156,9 @@ class Session(object):
SNMP variables, when set to False this feature is
disabled and the entire get request will fail on
any NOSUCH error (applies to v1 only)
:param abort_on_nonexistent: raise an exception if no object or no
instance is found for the given oid and
oid index
"""

def __init__(
Expand All @@ -161,7 +171,7 @@ def __init__(
our_identity='', their_identity='', their_hostname='',
trust_cert='', use_long_names=False, use_numeric=False,
use_sprint_value=False, use_enums=False, best_guess=0,
retry_no_such=False
retry_no_such=False, abort_on_nonexistent=False
):
# Validate and extract the remote port
if ':' in hostname:
Expand Down Expand Up @@ -202,6 +212,7 @@ def __init__(
self.use_enums = use_enums
self.best_guess = best_guess
self.retry_no_such = retry_no_such
self.abort_on_nonexistent = abort_on_nonexistent

# The following variables are required for internal use as they are
# passed to the C interface
Expand Down Expand Up @@ -304,7 +315,8 @@ def get(self, oids):
interface.get(self, varlist)

# Validate the variable list returned
validate_results(varlist)
if self.abort_on_nonexistent:
validate_results(varlist)

# Return a list or single item depending on what was passed in
return list(varlist) if is_list else varlist[0]
Expand Down Expand Up @@ -392,7 +404,8 @@ def get_next(self, oids):
interface.getnext(self, varlist)

# Validate the variable list returned
validate_results(varlist)
if self.abort_on_nonexistent:
validate_results(varlist)

# Return a list or single item depending on what was passed in
return list(varlist) if is_list else varlist[0]
Expand Down Expand Up @@ -427,7 +440,8 @@ def get_bulk(self, oids, non_repeaters, max_repetitions):
interface.getbulk(self, non_repeaters, max_repetitions, varlist)

# Validate the variable list returned
validate_results(varlist)
if self.abort_on_nonexistent:
validate_results(varlist)

# Return a list of variables
return varlist
Expand All @@ -453,7 +467,8 @@ def walk(self, oids='.1.3.6.1.2.1'):
interface.walk(self, varlist)

# Validate the variable list returned
validate_results(varlist)
if self.abort_on_nonexistent:
validate_results(varlist)

# Return a list of variables
return list(varlist)
Expand Down
4 changes: 3 additions & 1 deletion easysnmp/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ class SNMPVariable(object):
:param value: the OID value
:param snmp_type: the snmp_type of data contained in val (please see
http://www.net-snmp.org/wiki/index.php/TUT:snmpset#Data_Types
for further information)
for further information); in the case that an object
or instance is not found, the type will be set to
NOSUCHOBJECT and NOSUCHINSTANCE respectively
"""

def __init__(self, oid=None, oid_index=None, value=None, snmp_type=None):
Expand Down
27 changes: 24 additions & 3 deletions tests/test_easy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,43 @@ def test_snmp_get_unknown(sess_args):
'sess_args', [sess_v1_args(), sess_v2_args(), sess_v3_args()]
)
def test_snmp_get_invalid_instance(sess_args):
# Sadly, SNMP v1 doesn't distuingish between an invalid instance and an
# invalid object ID, so it raises the same exception for both
res = snmp_get('sysContact.1', **sess_args)
if sess_args['version'] == 1:
res.snmp_type == 'NOSUCHOBJECT'
else:
res.snmp_type == 'NOSUCHINSTANCE'


@pytest.mark.parametrize(
'sess_args', [sess_v1_args(), sess_v2_args(), sess_v3_args()]
)
def test_snmp_get_invalid_instance_with_abort_enabled(sess_args):
# Sadly, SNMP v1 doesn't distuingish between an invalid instance and an
# invalid object ID, so it raises the same exception for both
if sess_args['version'] == 1:
with pytest.raises(EasySNMPNoSuchObjectError):
snmp_get('sysContact.1', **sess_args)
snmp_get('sysContact.1', abort_on_nonexistent=True, **sess_args)
else:
with pytest.raises(EasySNMPNoSuchInstanceError):
snmp_get('sysContact.1', **sess_args)
snmp_get('sysContact.1', abort_on_nonexistent=True, **sess_args)


@pytest.mark.parametrize(
'sess_args', [sess_v1_args(), sess_v2_args(), sess_v3_args()]
)
def test_snmp_get_invalid_object(sess_args):
res = snmp_get('iso', **sess_args)
assert res.snmp_type == 'NOSUCHOBJECT'


@pytest.mark.parametrize(
'sess_args', [sess_v1_args(), sess_v2_args(), sess_v3_args()]
)
def test_snmp_get_invalid_object_with_abort_enabled(sess_args):
with pytest.raises(EasySNMPNoSuchObjectError):
snmp_get('iso', **sess_args)
snmp_get('iso', abort_on_nonexistent=True, **sess_args)


@pytest.mark.parametrize(
Expand Down
19 changes: 19 additions & 0 deletions tests/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ def test_session_get_bulk(sess): # noqa
def test_session_get_invalid_instance(sess):
# Sadly, SNMP v1 doesn't distuingish between an invalid instance and an
# invalid object ID, so it raises the same exception for both
res = sess.get('sysDescr.100')
if sess.version == 1:
assert res.snmp_type == 'NOSUCHOBJECT'
else:
assert res.snmp_type == 'NOSUCHINSTANCE'


@pytest.mark.parametrize('sess', [sess_v1(), sess_v2(), sess_v3()])
def test_session_get_invalid_instance_with_abort_enabled(sess):
# Sadly, SNMP v1 doesn't distuingish between an invalid instance and an
# invalid object ID, so it raises the same exception for both
sess.abort_on_nonexistent = True
if sess.version == 1:
with pytest.raises(EasySNMPNoSuchObjectError):
sess.get('sysDescr.100')
Expand All @@ -274,6 +286,13 @@ def test_session_get_invalid_instance(sess):

@pytest.mark.parametrize('sess', [sess_v1(), sess_v2(), sess_v3()])
def test_session_get_invalid_object(sess):
res = sess.get('iso')
assert res.snmp_type == 'NOSUCHOBJECT'


@pytest.mark.parametrize('sess', [sess_v1(), sess_v2(), sess_v3()])
def test_session_get_invalid_object_with_abort_enabled(sess):
sess.abort_on_nonexistent = True
with pytest.raises(EasySNMPNoSuchObjectError):
sess.get('iso')

Expand Down

0 comments on commit 49ea15e

Please sign in to comment.