1
2
3
4
5
6
7
8
9
10
11 import sys
12 import logging
13 log = logging.getLogger("zen.SnmpClient")
14
15 from twisted.internet import reactor, error, defer
16 from twisted.python import failure
17 from twisted.internet.error import TimeoutError
18
19 from Products.ZenUtils.snmp import SnmpV1Config, SnmpV2cConfig
20 from Products.ZenUtils.snmp import SnmpAgentDiscoverer
21
22 from pynetsnmp.twistedsnmp import snmpprotocol, Snmpv3Error
23
24 import Globals
25
26 from Products.ZenUtils.Driver import drive
27
28 global defaultTries, defaultTimeout
29 defaultTries = 2
30 defaultTimeout = 1
31 defaultSnmpCommunity = 'public'
32
33 DEFAULT_MAX_OIDS_BACK = 40
34
35 from BaseClient import BaseClient
36
38
39 - def __init__(self, hostname, ipaddr, options=None, device=None,
40 datacollector=None, plugins=[]):
55
61
68
69
70
91
92
133
135 def inner(driver):
136 """
137 Twisted driver class to iterate through devices
138
139 @param driver: Zenoss driver
140 @type driver: Zenoss driver
141 @return: successful result is a list of IPs that were added
142 @rtype: Twisted deferred
143 """
144 log.info("Rediscovering SNMP connection info for %s",
145 self.device.id)
146
147 communities = list(self.device.zSnmpCommunities)
148 communities.reverse()
149
150 configs = []
151 weight = 0
152 port = int(self.device.zSnmpPort)
153 for community in communities:
154 weight+=1
155 configs.append(SnmpV1Config(
156 self.device.manageIp, weight=weight,
157 port=port,
158 timeout=self.connInfo.zSnmpTimeout,
159 retries=self.connInfo.zSnmpTries,
160 community=community))
161 configs.append(SnmpV2cConfig(
162 self.device.manageIp, weight=weight+1000, port=port,
163 timeout=self.connInfo.zSnmpTimeout,
164 retries=self.connInfo.zSnmpTries,
165 community=community))
166
167 yield SnmpAgentDiscoverer().findBestConfig(configs)
168 driver.next()
169 return drive(inner)
170
171
173 maxOidsPerRequest = getattr(self.device, 'zMaxOIDPerRequest', DEFAULT_MAX_OIDS_BACK)
174 log.debug("Using a max of %s OIDs per request", maxOidsPerRequest)
175 for plugin in self.plugins:
176 try:
177 log.debug('running %s', plugin)
178 pname = plugin.name()
179 self._tabledata[pname] = {}
180 log.debug("sending queries for plugin %s", pname)
181 if plugin.snmpGetMap:
182 results = {}
183 for oid in plugin.snmpGetMap.getoids():
184 yield self.proxy.get([oid])
185 results.update(driver.next())
186 self._getdata[pname] = results
187 for tmap in plugin.snmpGetTableMaps:
188 rowSize = len(tmap.getoids())
189 maxRepetitions = max(maxOidsPerRequest / rowSize, 1)
190 yield self.proxy.getTable(tmap.getoids(),
191 maxRepetitions=maxRepetitions,
192 limit=sys.maxint)
193 self._tabledata[pname][tmap] = driver.next()
194 except Exception, ex:
195 if not isinstance( ex, error.TimeoutError ):
196 log.exception("device %s plugin %s unexpected error",
197 self.hostname, pname)
198
199
201 """Return data for this client in the form
202 ((plugin, (getdata, tabledata),)
203 getdata = {'.1.2.4.5':"value",}
204 tabledata = {tableMap : {'.1.2.3.4' : {'.1.2.3.4.1': "value",...}}}
205 """
206 data = []
207 for plugin in self.plugins:
208 pname = plugin.name()
209 getdata = self._getdata.get(pname,{})
210 tabledata = self._tabledata.get(pname,{})
211 if getdata or tabledata:
212 data.append((plugin, (getdata, tabledata)))
213 return data
231
234
236 "build options list that both telnet and ssh use"
237 if not usage:
238 usage = "%prog [options] hostname[:port] oids"
239 if not parser:
240 from optparse import OptionParser
241 parser = OptionParser(usage=usage)
242
243 parser.add_option('--snmpCommunity',
244 dest='snmpCommunity',
245 default=defaultSnmpCommunity,
246 help='Snmp Community string')
247
248
249 if __name__ == "__main__":
250 import pprint
251 logging.basicConfig()
252 log = logging.getLogger()
253 log.setLevel(20)
254 import sys
255 sys.path.append("plugins")
256 from plugins.zenoss.snmp.InterfaceMap import InterfaceMap
257 ifmap = InterfaceMap()
258 sc = SnmpClient("gate.confmon.loc", community="zentinel", plugins=[ifmap,])
259 reactor.run()
260 pprint.pprint(sc.getResults())
261