| Trees | Indices | Help |
|
|---|
|
|
1 ###########################################################################
2 #
3 # This program is part of Zenoss Core, an open source monitoring platform.
4 # Copyright (C) 2007, Zenoss Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License version 2 or (at your
8 # option) any later version as published by the Free Software Foundation.
9 #
10 # For complete information please visit: http://www.zenoss.com/oss/
11 #
12 ###########################################################################
13
14 import sys
15 import logging
16 log = logging.getLogger("zen.SnmpClient")
17
18 from twisted.internet import reactor, error, defer
19 from twisted.python import failure
20 from twisted.internet.error import TimeoutError
21
22 from Products.ZenUtils.snmp import SnmpV1Config, SnmpV2cConfig
23 from Products.ZenUtils.snmp import SnmpAgentDiscoverer
24
25 from pynetsnmp.twistedsnmp import snmpprotocol, Snmpv3Error
26
27 import Globals
28
29 from Products.ZenUtils.Driver import drive
30
31 global defaultTries, defaultTimeout
32 defaultTries = 2
33 defaultTimeout = 1
34 defaultSnmpCommunity = 'public'
35
36 DEFAULT_MAX_OIDS_BACK = 40
37
38 from BaseClient import BaseClient
39
41
42 - def __init__(self, hostname, ipaddr, options=None, device=None,
43 datacollector=None, plugins=[]):
44 BaseClient.__init__(self, device, datacollector)
45 global defaultTries, defaultTimeout
46 self.hostname = hostname
47 self.device = device
48 self.options = options
49 self.datacollector = datacollector
50 self.plugins = plugins
51
52 self._getdata = {}
53 self._tabledata = {}
54
55 from Products.ZenHub.services.PerformanceConfig import SnmpConnInfo
56 self.connInfo = SnmpConnInfo(device)
57 self.proxy = None
58
60 if self.proxy is not None: self.proxy.close()
61 srcport = snmpprotocol.port()
62 self.proxy = self.connInfo.createSession(srcport.protocol)
63 self.proxy.open()
64
66 """Start snmp collection.
67 """
68 log.debug("Starting %s", self.connInfo.summary())
69 self.initSnmpProxy()
70 drive(self.doRun).addBoth(self.clientFinished)
71
72
73 # FIXME: cleanup --force option #2660
75 """Check to see if a cisco box has changed.
76 """
77 device = self.device
78 yield self.proxy.get(['.1.3.6.1.4.1.9.9.43.1.1.1.0'])
79 lastpolluptime = device.getLastPollSnmpUpTime()
80 log.debug("lastpolluptime = %s", lastpolluptime)
81 result = True
82 try:
83 lastchange = driver.next().values()[0]
84 log.debug("lastchange = %s", lastchange)
85 if lastchange <= lastpolluptime:
86 log.info("skipping cisco device %s no change detected",
87 device.id)
88 result = False
89 else:
90 device.setLastPollSnmpUpTime(lastchange)
91 except Exception:
92 pass
93 yield defer.succeed(result)
94
95
97 # test snmp connectivity
98 log.debug("Testing SNMP configuration")
99 yield self.proxy.walk('.1.3')
100 try:
101 driver.next()
102 except TimeoutError, ex:
103 log.info("Device timed out: " + self.connInfo.summary())
104 if self.options.discoverCommunity:
105 yield self.findSnmpCommunity()
106 snmp_config = driver.next()
107 if not snmp_config:
108 log.warn(
109 'Failed to rediscover the SNMP connection info for %s',
110 self.device.manageIp)
111 return
112 if snmp_config.version:
113 self.connInfo.zSnmpVer = snmp_config.version
114 if snmp_config.port:
115 self.connInfo.zSnmpPort = snmp_config.port
116 if snmp_config.community:
117 self.connInfo.zSnmpCommunity = snmp_config.community
118 self.connInfo.changed = True
119 self.initSnmpProxy()
120 else:
121 return
122 except Snmpv3Error, ex:
123 log.info("Cannot connect to SNMP agent: {0}".format(self.connInfo.summary()))
124 return
125 except Exception, ex:
126 log.exception("Unable to talk: " + self.connInfo.summary())
127 return
128
129 changed = True
130 # FIXME: cleanup --force option #2660
131 if not self.options.force and self.device.snmpOid.startswith(".1.3.6.1.4.1.9"):
132 yield drive(self.checkCiscoChange)
133 changed = driver.next()
134 if changed:
135 yield drive(self.collect)
136
138 def inner(driver):
139 """
140 Twisted driver class to iterate through devices
141
142 @param driver: Zenoss driver
143 @type driver: Zenoss driver
144 @return: successful result is a list of IPs that were added
145 @rtype: Twisted deferred
146 """
147 log.info("Rediscovering SNMP connection info for %s",
148 self.device.id)
149
150 communities = list(self.device.zSnmpCommunities)
151 communities.reverse()
152
153 configs = []
154 weight = 0
155 for community in communities:
156 for port in self.device.zSnmpPorts:
157 weight+=1
158 port = int(port)
159 configs.append(SnmpV1Config(
160 self.device.manageIp, weight=weight,
161 port=port,
162 timeout=self.connInfo.zSnmpTimeout,
163 retries=self.connInfo.zSnmpTries,
164 community=community))
165 configs.append(SnmpV2cConfig(
166 self.device.manageIp, weight=weight+1000, port=port,
167 timeout=self.connInfo.zSnmpTimeout,
168 retries=self.connInfo.zSnmpTries,
169 community=community))
170
171 yield SnmpAgentDiscoverer().findBestConfig(configs)
172 driver.next()
173 return drive(inner)
174
175
177 maxOidsPerRequest = getattr(self.device, 'zMaxOIDPerRequest', DEFAULT_MAX_OIDS_BACK)
178 log.debug("Using a max of %s OIDs per request", maxOidsPerRequest)
179 for plugin in self.plugins:
180 try:
181 log.debug('running %s', plugin)
182 pname = plugin.name()
183 self._tabledata[pname] = {}
184 log.debug("sending queries for plugin %s", pname)
185 if plugin.snmpGetMap:
186 results = {}
187 for oid in plugin.snmpGetMap.getoids():
188 yield self.proxy.get([oid])
189 results.update(driver.next())
190 self._getdata[pname] = results
191 for tmap in plugin.snmpGetTableMaps:
192 rowSize = len(tmap.getoids())
193 maxRepetitions = max(maxOidsPerRequest / rowSize, 1)
194 yield self.proxy.getTable(tmap.getoids(),
195 maxRepetitions=maxRepetitions,
196 limit=sys.maxint)
197 self._tabledata[pname][tmap] = driver.next()
198 except Exception, ex:
199 if not isinstance( ex, error.TimeoutError ):
200 log.exception("device %s plugin %s unexpected error",
201 self.hostname, pname)
202
203
205 """Return data for this client in the form
206 ((plugin, (getdata, tabledata),)
207 getdata = {'.1.2.4.5':"value",}
208 tabledata = {tableMap : {'.1.2.3.4' : {'.1.2.3.4.1': "value",...}}}
209 """
210 data = []
211 for plugin in self.plugins:
212 pname = plugin.name()
213 getdata = self._getdata.get(pname,{})
214 tabledata = self._tabledata.get(pname,{})
215 if getdata or tabledata:
216 data.append((plugin, (getdata, tabledata)))
217 return data
219 log.info("snmp client finished collection for %s" % self.hostname)
220 if isinstance(result, failure.Failure):
221 from twisted.internet import error
222 if isinstance(result.value, error.TimeoutError):
223 log.warning("Device %s timed out: are "
224 "your SNMP settings correct?", self.hostname)
225 elif isinstance(result.value, Snmpv3Error):
226 log.warning("Connection to device {0.hostname} failed: {1.value.message}".format(self, result))
227 else:
228 log.exception("Device %s had an error: %s",self.hostname,result)
229 self.proxy.close()
230 """tell the datacollector that we are all done"""
231 if self.datacollector:
232 self.datacollector.clientFinished(self)
233 else:
234 reactor.stop()
235
238
240 "build options list that both telnet and ssh use"
241 if not usage:
242 usage = "%prog [options] hostname[:port] oids"
243 if not parser:
244 from optparse import OptionParser
245 parser = OptionParser(usage=usage)
246
247 parser.add_option('--snmpCommunity',
248 dest='snmpCommunity',
249 default=defaultSnmpCommunity,
250 help='Snmp Community string')
251
252
253 if __name__ == "__main__":
254 import pprint
255 logging.basicConfig()
256 log = logging.getLogger()
257 log.setLevel(20)
258 import sys
259 sys.path.append("plugins")
260 from plugins.zenoss.snmp.InterfaceMap import InterfaceMap
261 ifmap = InterfaceMap()
262 sc = SnmpClient("gate.confmon.loc", community="zentinel", plugins=[ifmap,])
263 reactor.run()
264 pprint.pprint(sc.getResults())
265
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Tue Oct 11 12:51:58 2011 | http://epydoc.sourceforge.net |