1
2
3
4
5
6
7
8
9
10
11
12
13 import warnings
14 warnings.warn("SnmpSession is deprecated", DeprecationWarning)
15
16 __doc__="""snmp
17
18 snmp utility library to have a more sane interface than pysnmp
19
20 $Id: SnmpSession.py,v 1.16 2003/07/14 19:58:49 edahl Exp $"""
21
22 __version__ = "$Revision: 1.16 $"[11:-2]
23
24 import copy
25 from struct import unpack
26 import Globals
27
28 from pysnmp.compat.pysnmp2x import asn1, v1, asynrole
29 from pysnmp.proto import v2c
30 from pysnmp.mapping.udp import role
31 from pysnmp.proto.api import alpha
32
33 from Products.ZenUtils.Exceptions import ZentinelException
34
36
38
39 - def __init__(self, host, community='public', port=161,
40 version=1, timeout=2, retries=2, callback=None):
55
56
58 """collect snmp information from device
59 snmpmap is an SnmpAttMap object"""
60 oidmap = snmpmap.getOidMap()
61 oids = oidmap.keys()
62 snmpdata = self.get(oids)
63 retdata = {}
64 for oid, value in snmpdata.items():
65 if snmpmap.getPropertyType(oid) == 'oidmac':
66 retdata[oidmap[oid]] = self.asmac(value)
67 else:
68 retdata[oidmap[oid]] = value
69 return retdata
70
71
73 """collect and map snmp table data returns a list of dictionaries
74 which have attribute names as keys and snmp data as values
75 snmpmap is an SnmpTableMap object"""
76 tablemap = self.collectSnmpTable(snmpmap.tableOid)
77 datamaps = []
78 oidmap = snmpmap.getOidMap()
79 for row in tablemap.values():
80 nrow = {}
81 for col in row.keys():
82 if oidmap.has_key(col):
83 if snmpmap.getPropertyType(col) == 'oidmac':
84 nrow[oidmap[col]] = self.asmac(row[col])
85 elif snmpmap.getPropertyType(col) == 'oidfs':
86 nrow[oidmap[col]] = row[col].replace('/', '-')
87 else:
88 nrow[oidmap[col]] = row[col]
89 datamaps.append(nrow)
90 return datamaps
91
92
94 """optimized table collection we only get the columns in datamap"""
95 if bulk:
96 collector = self.getBulkTable
97 else:
98 collector = self.getTable
99 retdata = {}
100 tblen = len(tableOid)
101 for col in dataMap.keys():
102 snmpdata = collector(tableOid + col)
103 colname = dataMap[col]
104 for key, data in snmpdata.items():
105 rowcol = key[tblen:].split('.')
106 row = '.'.join(rowcol[2:])
107 if not retdata.has_key(row):
108 retdata[row] = {}
109 retdata[row][colname] = data
110 return retdata
111
112
113
115 """collect and snmp table based on its oid and return
116 a dict of dicts with row, col as keys"""
117 if bulk:
118 snmpdata = self.getBulkTable(tableOid)
119 else:
120 snmpdata = self.getTable(tableOid)
121 tblen = len(tableOid)
122 tablemap = {}
123 for oid, value in snmpdata.items():
124 rowcol = oid[tblen:].split('.')
125 col = '.'.join(rowcol[:2])
126 row = '.'.join(rowcol[2:])
127 if not tablemap.has_key(row):
128 tablemap[row] = {}
129 tablemap[row][col] = value
130 return tablemap
131
132
134 """convert a byte string to a mac address string"""
135 mac = []
136 for char in val:
137 tmp = unpack('B', char)[0]
138 tmp = str(hex(tmp))[2:]
139 if len(tmp) == 1: tmp = '0' + tmp
140 mac.append(tmp)
141 return ":".join(mac).upper()
142
143
144 - def asip(self, val):
145 ip = ""
146 for char in val:
147 tmp = unpack('B', char)[0]
148 ip = ip + str(tmp) + "."
149 return ip[:-1]
150
151
153 """map the results of a full table query (as returned from
154 collectSnmpTable) the oidmap should be in the same format
155 has descripbed by snmpRowMap below
156 """
157 datamaps = []
158 for row in tabledata.values():
159 nrow = self.snmpRowMap(row, oidmap)
160 datamaps.append(nrow)
161 return datamaps
162
163
165 """map the results of a single row from a table query
166 a row map has column numbers as keys (with the .)
167 and object attributes as the values.
168 {'.2' : 'id', '.3' : 'type',}"""
169 nrow = {}
170 for col in row.keys():
171 if oidmap.has_key(col):
172 nrow[oidmap[col]] = row[col]
173 return nrow
174
175
176 - def get(self, head_oids):
177 req = eval('v' + self.version).GETREQUEST()
178 return self._get(req, head_oids)
179
180
182 req = eval('v' + self.version).GETNEXTREQUEST()
183 return self._get(req, head_oids)
184
185
186 - def _get(self, req, head_oids):
187 """get a list of oids"""
188 if type(head_oids) == type(''):
189 head_oids = [head_oids,]
190 encoded_oids = map(asn1.OBJECTID().encode, head_oids)
191 (oids, vals, rsp) = self._perfreq(req, encoded_oids)
192 retval={}
193 for (oid, val) in map(None, oids, vals):
194 retval[oid] = val
195 return retval
196
197
199 """walk a list of table oids"""
200 if bulk:
201 return self.getBulkTable(head_oids)
202 if type(head_oids) == type(''):
203 head_oids = [head_oids,]
204 retval = {}
205 encoded_oids = map(asn1.OBJECTID().encode, head_oids)
206 req = eval('v' + self.version).GETNEXTREQUEST()
207 while 1:
208 (oids, vals, rsp) = self._perfreq(req, encoded_oids)
209 if rsp['error_status'] == 2:
210
211 for l in oids, vals, head_oids:
212 del l[rsp['error_index']-1]
213
214 while 1:
215 for idx in range(len(head_oids)):
216 if not asn1.OBJECTID(head_oids[idx]).isaprefix(oids[idx]):
217
218 for l in oids, vals, head_oids:
219 del l[idx]
220 break
221 else:
222 break
223
224 if not head_oids: return retval
225
226
227 for (oid, val) in map(None, oids, vals):
228 retval[oid] = val
229
230
231 encoded_oids = map(asn1.OBJECTID().encode, oids)
232
233
234 req['request_id'] = req['request_id'] + 1
235
236
237
239 """get a set of table oids using snmp bulk requests
240 if a list of oids is passed in they must have result
241 rows that are the same length (ie different columns
242 of the same table)"""
243 if type(head_oids) == type(''):
244 head_oids = [head_oids,]
245 retdata = {}
246 oids = copy.copy(head_oids)
247 req = v2c.GetBulkRequest()
248 req['community'].set(self.community)
249 req['pdu']['get_bulk_request']['variable_bindings'].extend(
250 map(lambda x: v2c.VarBind(name=v2c.ObjectName(x)), oids))
251 rsp = v2c.Response();
252 while 1:
253 vb = map(lambda x: v2c.VarBind(name=v2c.ObjectName(x)), oids)
254 req['pdu'].values()[0]['variable_bindings']=v2c.VarBindList(*vb)
255
256
257 (answer, src) = self.client.send_and_receive(req.encode())
258
259 rsp.decode(answer)
260
261 if not req.match(rsp):
262 raise ZenSnmpError('Unmatched response: %s vs %s' % (req, rsp))
263
264 oids = map(lambda x: x['name'].get(), \
265 rsp['pdu'].values()[0]['variable_bindings'])
266 vals = map(lambda x: x['value'], \
267 rsp['pdu'].values()[0]['variable_bindings'])
268
269 if rsp['pdu'].values()[0]['error_status']:
270 raise ZenSnmpError(str(rsp['pdu'].values()[0]['error_status'])+
271 ' at '+str(oids[rsp['pdu'].values()[0]['error_index'].get()-1]))
272
273
274 N = 0;
275 R = len(req['pdu'].values()[0]['variable_bindings']) - N
276 L = len(rsp['pdu'].values()[0]['variable_bindings'])
277 M = L / R
278 cut=(R*M)-L
279 if cut < 0:
280 oids=oids[:cut]
281 vals=vals[:cut]
282 for i in range(1, M+1):
283 for r in range(1, R+1):
284 idx = N + ((i-1)*R) + r
285 oid = oids[idx-1]
286 if oid.find(head_oids[r-1]) > -1:
287 retdata[oid] = \
288 vals[idx-1].apiAlphaGetTerminalValue().get()
289 else:
290 oids[idx-1]="None"
291 oids = oids[-R:]
292 vals = vals[-R:]
293 toids = copy.copy(oids)
294 for oid in toids:
295 if oid == 'None':
296 oids.remove(oid)
297 if not oids:
298 break
299 req['pdu'].values()[0]['request_id'] = \
300 req['pdu'].values()[0]['request_id'] + 1
301 return retdata
302
303
305 """perform a get based on req and a list of encoded_oids"""
306 rsp = eval('v' + self.version).GETRESPONSE()
307 myreq = req.encode(community=self.community, encoded_oids=encoded_oids)
308 (answer, src) = self.client.send_and_receive(myreq)
309 rsp.decode(answer)
310 if req != rsp:
311 raise ZenSnmpError('Unmatched response: %s vs %s' %
312 (str(req), str(rsp)))
313 if rsp['error_status']:
314 raise ZenSnmpError('SNMP error #' + str(rsp['error_status']) +
315 ' for OID #' + str(rsp['error_index']))
316 oids = map(lambda x: x[0], map(asn1.OBJECTID().decode,
317 rsp['encoded_oids']))
318 vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals']))
319 return (oids, vals, rsp)
320
321
322
323
324
325
326
327 if __name__ == '__main__':
328 s = SnmpSession('laser', community='public')
329
330
331
332
333
334 r = s.getTable(['.1.3.6.1.2.1.1',])
335
336
337
338
339 a = r.keys()
340 a.sort()
341 for k in a:
342 print k + "-->" + str(r[k])
343