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

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