-
Notifications
You must be signed in to change notification settings - Fork 10
/
device.py
155 lines (132 loc) · 5.32 KB
/
device.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python
import snmp
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
class Device:
__doc__ = "Networked device"
info = {}
def __init__(self, hostname):
self.hostname = hostname
def snmpConfig(self, oid, version=2, community="public", test=False):
self.snmp = snmp.Connection(host=self.hostname, version=version, community=community)
self.oid = oid
if test:
return self.snmpTest()
def snmpTest(self, oid=".1.3.6.1.2.1.1.5.0"):
result = self.snmp.get(oid)
if not result:
logger.warning("Cannot get OID %s on host %s" % oid, self.hostname)
return result
#
# returns real interface name (LLDP OIDs use only numbers while the device might use letters).
#
def getInterfaceName(self, interface):
snmp = self.snmp
oid = self.oid
# <interface names OID><interface number> is what we're looking for
name = snmp.get(oid['if']['ifname'] + str(interface))
if name:
interface = name
logger.info("Returning interface name %s", interface)
return interface
#
# returns interface description
#
def getInterfaceDesc(self, interface):
snmp = self.snmp
oid = self.oid
# <interface descriptions OID><interface number> is what we're looking for
desc = snmp.get(oid['if']['ifdesc'] + str(interface))
logger.info("Returning interface description %s", desc)
return desc
#
# returns interface ID
#
# def getInterfaceByName(self, interfacename):
#
# given subinterface name as input, finds and returns parent interface ID.
#
def getParentInterface(self, interface, subname):
parentname = subname.split('.')[0]
logger.debug("Searching for interface name %s", parentname)
originalinterface = interface
while True:
interface = int(interface) - 1
name = self.getInterfaceName(interface)
if name == parentname:
logger.debug("Found name %s on interface number %s", name, interface)
return interface
if parentname not in name:
logger.debug("Encountered name %s. Giving up.", name)
# Give up
return originalinterface
#
# returns interface speed
#
def getInterfaceSpeed(self, interface, format='M'):
snmp = self.snmp
oid = self.oid
speed = None
divide = {'G': 1000000000, 'M': 1000000, 'K': 1000, 'B': 1}
if format.upper() not in divide:
format = 'M'
# <interface speeds OID><interface number> is what we're looking for
speed = snmp.get(oid['if']['ifspeed'] + str(interface))
if speed:
speedInBits = int(speed)
speed = speedInBits / divide[format.upper()]
logger.info("Returning interface speed %s", speed)
return speed
#
# Collects LLDP neighbours from SMTP information, returns dict of oid:neighbour pairs.
#
def getNeighbours(self):
oid = self.oid
lldp = self.snmp.walk(oid['lldp']['remotesysname'])
if not lldp:
return None
logger.debug(lldp)
return lldp
#
# Returns list of dicts with interface number, name, speed and neighbour.
#
def getNeighbourInterfaceInfo(self, neighbours=None):
iflist = []
if not isinstance(neighbours, dict):
# neighbours is not a dict. Let's get us something to work with.
neighbours = self.getNeighbours()
if not neighbours:
return None
for n in neighbours.keys():
# Take the OID's second to last dot separated number. That's our local interface.
ifnumber = n.split('.')[-2]
logger.debug("From OID %s interface is %s", n, ifnumber)
ifname = self.getInterfaceName(ifnumber)
if '.' in str(ifname):
# Do we have a subinterface?
ifnumber = self.getParentInterface(ifnumber, ifname)
ifspeed = self.getInterfaceSpeed(ifnumber)
logger.info("%s interface %s has neighbour %s, speed %s", self.hostname, ifname, neighbours[n], ifspeed)
iflist.append({'number': ifnumber, 'name': ifname, 'speed': ifspeed, 'neighbour': neighbours[n]})
return iflist
def getDeviceInfo(self):
snmp = self.snmp
oid = self.oid
# Let's start collecting info
deviceFamily = None
# First we poll standard OIDs
deviceinfo = snmp.populateDict(oid['standard'])
if 'sysdesc' in deviceinfo:
# Split into words (space separated), take the first one and lowercase it
deviceFamily = deviceinfo['sysdesc'].split(' ')[0].lower()
logger.info("Found device family %s", deviceFamily)
# If we have a device family identified, let's look for a matching set of OIDs
if deviceFamily in oid['device']:
familyinfo = snmp.populateDict(oid['device'][deviceFamily])
# Add the information to the deviceinfo dict
deviceinfo.update(familyinfo)
self.deviceFamily = deviceFamily
deviceinfo['if'] = self.getNeighbourInterfaceInfo()
self.info.update(deviceinfo)
return deviceinfo