Package Products :: Package DataCollector :: Module SnmpClient
[hide private]
[frames] | no frames]

Source Code for Module Products.DataCollector.SnmpClient

  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 as published by 
  8  # 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 pynetsnmp.twistedsnmp import snmpprotocol 
 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   
37 -class SnmpClient(BaseClient):
38
39 - def __init__(self, hostname, ipaddr, options=None, device=None, 40 datacollector=None, plugins=[]):
41 BaseClient.__init__(self, device, datacollector) 42 global defaultTries, defaultTimeout 43 self.hostname = hostname 44 self.device = device 45 self.options = options 46 self.datacollector = datacollector 47 self.plugins = plugins 48 49 self._getdata = {} 50 self._tabledata = {} 51 52 from Products.ZenHub.services.PerformanceConfig import SnmpConnInfo 53 self.connInfo = SnmpConnInfo(device) 54 srcport = snmpprotocol.port() 55 self.proxy = self.connInfo.createSession(srcport.protocol)
56 57
58 - def run(self):
59 """Start snmp collection. 60 """ 61 log.debug("Starting %s", self.connInfo.summary()) 62 self.proxy.open() 63 drive(self.doRun).addBoth(self.clientFinished)
64 65 66 # FIXME: cleanup --force option #2660
67 - def checkCiscoChange(self, driver):
68 """Check to see if a cisco box has changed. 69 """ 70 device = self.device 71 yield self.proxy.get(['.1.3.6.1.4.1.9.9.43.1.1.1.0']) 72 lastpolluptime = device.getLastPollSnmpUpTime() 73 log.debug("lastpolluptime = %s", lastpolluptime) 74 result = True 75 try: 76 lastchange = driver.next().values()[0] 77 log.debug("lastchange = %s", lastchange) 78 if lastchange <= lastpolluptime: 79 log.info("skipping cisco device %s no change detected", 80 device.id) 81 result = False 82 else: 83 device.setLastPollSnmpUpTime(lastchange) 84 except Exception: 85 pass 86 yield defer.succeed(result)
87 88
89 - def doRun(self, driver):
90 # test snmp connectivity 91 log.debug("Testing SNMP configuration") 92 yield self.proxy.walk('.1.3') 93 try: 94 driver.next() 95 except TimeoutError, ex: 96 log.info("Device timed out: " + self.connInfo.summary()) 97 return 98 except Exception, ex: 99 log.exception("Unable to talk: " + self.connInfo.summary()) 100 return 101 102 changed = True 103 # FIXME: cleanup --force option #2660 104 if not self.options.force and self.device.snmpOid.startswith(".1.3.6.1.4.1.9"): 105 yield drive(self.checkCiscoChange) 106 changed = driver.next() 107 if changed: 108 yield drive(self.collect)
109 110
111 - def collect(self, driver):
112 for plugin in self.plugins: 113 try: 114 log.debug('running %s', plugin) 115 pname = plugin.name() 116 self._tabledata[pname] = {} 117 log.debug("sending queries for plugin %s", pname) 118 if plugin.snmpGetMap: 119 results = {} 120 for oid in plugin.snmpGetMap.getoids(): 121 yield self.proxy.get([oid]) 122 results.update(driver.next()) 123 self._getdata[pname] = results 124 for tmap in plugin.snmpGetTableMaps: 125 rowSize = len(tmap.getoids()) 126 maxRepetitions = max(DEFAULT_MAX_OIDS_BACK / rowSize, 1) 127 yield self.proxy.getTable(tmap.getoids(), 128 maxRepetitions=maxRepetitions, 129 limit=sys.maxint) 130 self._tabledata[pname][tmap] = driver.next() 131 except Exception, ex: 132 if not isinstance( ex, error.TimeoutError ): 133 log.exception("device %s plugin %s unexpected error", 134 self.hostname, pname)
135 136
137 - def getResults(self):
138 """Return data for this client in the form 139 ((plugin, (getdata, tabledata),) 140 getdata = {'.1.2.4.5':"value",} 141 tabledata = {tableMap : {'.1.2.3.4' : {'.1.2.3.4.1': "value",...}}} 142 """ 143 data = [] 144 for plugin in self.plugins: 145 pname = plugin.name() 146 getdata = self._getdata.get(pname,{}) 147 tabledata = self._tabledata.get(pname,{}) 148 if getdata or tabledata: 149 data.append((plugin, (getdata, tabledata))) 150 return data
151
152 - def clientFinished(self, result):
153 log.info("snmp client finished collection for %s" % self.hostname) 154 if isinstance(result, failure.Failure): 155 from twisted.internet import error 156 if isinstance(result.value, error.TimeoutError): 157 log.warning("Device %s timed out: are " 158 "your SNMP settings correct?", self.hostname) 159 else: 160 log.error("Device %s had an error: %s", self.hostname, result) 161 self.proxy.close() 162 """tell the datacollector that we are all done""" 163 if self.datacollector: 164 self.datacollector.clientFinished(self) 165 else: 166 reactor.stop()
167 168
169 - def stop(self):
170 self.proxy.close()
171 172
173 -def buildOptions(parser=None, usage=None):
174 "build options list that both telnet and ssh use" 175 176 if not usage: 177 usage = "%prog [options] hostname[:port] oids" 178 179 if not parser: 180 from optparse import OptionParser 181 parser = OptionParser(usage=usage) 182 183 parser.add_option('--snmpCommunity', 184 dest='snmpCommunity', 185 default=defaultSnmpCommunity, 186 help='Snmp Community string')
187 188 189 if __name__ == "__main__": 190 import pprint 191 logging.basicConfig() 192 log = logging.getLogger() 193 log.setLevel(20) 194 import sys 195 sys.path.append("plugins") 196 from plugins.zenoss.snmp.InterfaceMap import InterfaceMap 197 ifmap = InterfaceMap() 198 sc = SnmpClient("gate.confmon.loc", community="zentinel", plugins=[ifmap,]) 199 reactor.run() 200 pprint.pprint(sc.getResults()) 201