easysnmp停止使用单个IP地址

时间:2019-03-16 14:37:25

标签: python easysnmp

我有一个脚本,该脚本使用easysnmp get和bulkwalk模块来收集设备上所有IP地址的列表,并将它们添加到字典中以进行进一步处理。该问题发生在特定的IP地址上,而问题似乎与最终主机本身无关。

从python shell的全新开始,我可以对其中一个有问题的IP进行批量遍历:

>>> from easysnmp import snmp_bulkwalk
>>> snmp_ips = snmp_bulkwalk('ipAdEntIfIndex', hostname='x.x.x.80', version=3, security_username=snmp_user, security_level='auth_with_privacy', auth_protocol='SHA', auth_password=snmp_auth, privacy_protocol='AES128', privacy_password=snmp_priv)     
>>> snmp_ips
[<SNMPVariable value='4010' (oid='ipAdEntIfIndex', oid_index='x.x.x.179', snmp_type='INTEGER')>, <SNMPVariable value='4011' (oid='ipAdEntIfIndex', oid_index='x.x.x.186', snmp_type='INTEGER')>, <SNMPVariable value='20567' (oid='ipAdEntIfIndex', oid_index='x.x.x.80', snmp_type='INTEGER')>, <SNMPVariable value='808' (oid='ipAdEntIfIndex', oid_index='x.x.x.133', snmp_type='INTEGER')>]

如果仅对单个节点运行我的函数,它将起作用。这是函数:

def get_ints():
    addrs = {}
    for h in nodes['results']:
        # Update all nodes in the dictionary to their FQDN
        if 'foo.com' not in h['SysName']:
            h['SysName'] = h['SysName'] + '.foo.com'
        # Fix random hostname issues
        if '-re' in h['SysName']:
            # This is probably way more complicated than it needs to be. Split the hostname at '-' and combine the two results
            # starting at index 3 of the second half of the split.
            h['SysName'] = h['SysName'].split('-'[::])[0] + h['SysName'].split('-'[::])[1][3:]
        host = h['SysName']
        # Use SNMP to get IP and interface information because screen scraping is slow and painful to reformat.
        # This walks the IF-MIB table and gets the IPs assigned to each interface. 
        print(f'Getting interface info from {host}')
        try:
            snmp_ips = snmp_bulkwalk('ipAdEntIfIndex', hostname=host, version=3, security_username=snmp_user, security_level='auth_with_privacy', auth_protocol='SHA', auth_password=snmp_auth, privacy_protocol='AES128', privacy_password=snmp_priv)
        except:
            print(f'Could not get data from {host}')
        # Iterate through SNMP GET objects and update the addrs table with: { IP : { PTR record : RR value }}
        for x in snmp_ips:
            # We only want to process IPs that fall within specific network ranges
            for n in my_nets:
                if ip_address(x.oid_index) in n:
                    try:
                        addrs[x.oid_index] = gen_rev(x.oid_index, snmp_get('ifName' + '.' + x.value, hostname=host, version=3, security_username=snmp_user, security_level='auth_with_privacy', auth_protocol='SHA', auth_password=snmp_auth, privacy_protocol='AES128', privacy_password=snmp_priv).value.lower(), host)
                    except:
                        pass
    return addrs

以下是针对字典中的单个主机运行的函数:

>>> nodes['results'] = [ {'NodeID': 571, 'SysName': 'host80.foo.com', 'IPAddress': 'x.x.x.80' } ]
>>> my_addrs = get_ints()
>>> Getting interface info from host80.foo.com
>>> my_addrs
[<SNMPVariable value='4010' (oid='ipAdEntIfIndex', oid_index='x.x.x.179', snmp_type='INTEGER')>, <SNMPVariable value='4011' (oid='ipAdEntIfIndex', oid_index='x.x.x.186', snmp_type='INTEGER')>, <SNMPVariable value='20567' (oid='ipAdEntIfIndex', oid_index='x.x.x.80', snmp_type='INTEGER')>, <SNMPVariable value='808' (oid='ipAdEntIfIndex', oid_index='x.x.x.133', snmp_type='INTEGER')>]

这是词典中的一整套节点,并且针对该函数运行该函数时,“ host80.foo.com”将失败:

>>> nodes['results'] = [{'NodeID': 14, 'SysName': 'host13.foo.com', 'IPAddress': 'x.x.x.13'}, {'NodeID': 15, 'SysName': 'host14.foo.com', 'IPAddress': 'x.x.x.14'}, {'NodeID': 17, 'SysName': 'hhost16.foo.com', 'IPAddress': 'x.x.x.16'}, {'NodeID': 18, 'SysName': 'host17.foo.com', 'IPAddress': 'x.x.x.17'}, {'NodeID': 571, 'SysName': 'host80.foo.com', 'IPAddress': 'x.x.x.80'}, {'NodeID': 20, 'SysName': 'host19.foo.com', 'IPAddress': 'x.x.x.19'}]
>>> my_addrs = get_ints()
Getting interface info from host13.foo.com
Getting interface info from host14.foo.com
Getting interface info from host16.foo.com
Getting interface info from host17.foo.com
Getting interface info from host19.foo.com
Getting interface info from host80.foo.com
Could not get data from host80.foo.com
...

现在,如果我尝试仅自行运行bulkwalk请求,它将不再起作用:

>>> snmp_bulkwalk('ipAdEntIfIndex', hostname='x.x.x.80',version=3, security_username=snmp_user, security_level='auth_with_privacy', auth_protocol='SHA', auth_password=snmp_auth, privacy_protocol='AES128', privacy_password=snmp_priv)    
easysnmp.exceptions.EasySNMPTimeoutError: timed out while connecting to remote host

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/logging/__init__.py", line 1293, in debug
    if self.isEnabledFor(DEBUG):
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/logging/__init__.py", line 1548, in isEnabledFor
    return level >= self.getEffectiveLevel()
SystemError: PyEval_EvalFrameEx returned a result with an error set

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/site-packages/easysnmp/easy.py", line 147, in snmp_bulkwalk
    return session.bulkwalk(oids, non_repeaters, max_repetitions)
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/site-packages/easysnmp/session.py", line 498, in bulkwalk
    interface.bulkwalk(self, non_repeaters, max_repetitions, varlist)
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/logging/__init__.py", line 1293, in debug
    if self.isEnabledFor(DEBUG):
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/logging/__init__.py", line 1548, in isEnabledFor
    return level >= self.getEffectiveLevel()
SystemError: PyEval_EvalFrameEx returned a result with an error set

如果我退出解释器并重新进行一次,则结果始终相同。我还可以在另一个python shell中运行独立的bulkrequest,它工作正常。

我的防火墙上的数据包捕获显示了正在发送到设备的请求,但是设备没有获取响应,而是发送了报告响应。在有效的会话和无效的会话之间,get请求和getbulkrequest之间似乎没有任何区别。我愿意接受这个问题可能与防火墙有关,但又是什么,特别是由于bulkrequest同时在另一个Shell中可以正常工作吗?另外,为什么每次单独对表中的所有主机运行该功能时,为什么它只能自己工作而不是呢?

我曾经尝试一次添加导入的模块,以查看在这方面是否发生了什么,但是直到该功能针对字典中的其余主机运行,并且没有发生过任何故障,之后在同一外壳中根本无法工作。

0 个答案:

没有答案