Package Products :: Package ZenUtils :: Module snmp
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.snmp

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2010, 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 logging 
 15  from twisted.internet import reactor 
 16  from twisted.internet.defer import Deferred 
 17  from pynetsnmp.twistedsnmp import AgentProxy 
 18   
 19  _LOG = logging.getLogger("zen.ZenUtils.snmp") 
20 21 -class SnmpConfig(object):
22 succeeded = None 23 sysName = None 24 25 @property
26 - def port(self):
27 return self._port
28 29 @property
30 - def community(self):
31 return self._community
32 33 @property
34 - def weight(self):
35 return self._weight is None and self.defaultWeight or self._weight
36 37
38 - def __init__(self, ip, weight=None, port=161, timeout=2.5, retries=2, 39 community='public'):
40 self._ip = ip 41 self._weight = weight 42 self._port = port 43 self._timeout = timeout 44 self._retries = retries 45 self._community = community
46 47
48 - def __str__(self):
49 return "(%s) %s:%s, SNMP%s, timeout=%ss, retries=%s, community=%s" % ( 50 self.weight, self._ip, self._port, self.version, self._timeout, 51 self._retries, self.community)
52 53
54 - def getAgentProxy(self):
55 return AgentProxy( 56 ip=self._ip, 57 port=self._port, 58 timeout=self._timeout, 59 tries=self._retries, 60 snmpVersion=self.version, 61 community=self._community)
62 63
64 - def test(self, oid='.1.3.6.1.2.1.1.5.0'):
65 _LOG.debug("SnmpConfig.test: oid=%s" % oid) 66 self._proxy = self.getAgentProxy() 67 self._proxy.open() 68 return self._proxy.get([oid]).addBoth(self.enrichResult)
69 70
71 - def enrichResult(self, result):
72 self._proxy.close() 73 if isinstance(result, dict) and bool(result): 74 # one and only one key/value pair _should_ be available in result, 75 # and we only need the value (the device name) 76 self.sysName = result.values()[0] 77 self.succeeded = True 78 else: 79 self.succeeded = False 80 81 return self
82
83 84 -class SnmpV1Config(SnmpConfig):
85 version = 'v1' 86 defaultWeight = 10
87
88 89 -class SnmpV2cConfig(SnmpConfig):
90 version = 'v2c' 91 defaultWeight = 20
92
93 94 -class SnmpV3Config(SnmpConfig):
95 version = 'v3' 96 defaultWeight = 30 97
98 - def __init__(self, ip, weight=None, port=161, timeout=2.5, retries=2, 99 community='public', securityName=None, authType=None, 100 authPassphrase=None, privType=None, privPassphrase=None):
101 super(SnmpV3Config, self).__init__( 102 ip, weight, port, timeout, retries, community) 103 104 self._securityName = securityName 105 self._authType = authType 106 self._authPassphrase = authPassphrase 107 self._privType = privType 108 self._privPassphrase = privPassphrase
109 110
111 - def __str__(self):
112 v3string = "securityName=%s" % self._securityName 113 if self._authType: 114 v3string += ", authType=%s, authPassphrase=%s" % ( 115 self._authType, self._authPassphrase) 116 117 if self._privType: 118 v3string += " privType=%s, privPassphrase=%s" % ( 119 self._privType, self._privPassphrase) 120 121 return "(%s) %s:%s, SNMP%s, timeout=%ss, retries=%s, %s" % ( 122 self.weight, self._ip, self._port, self.version, self._timeout, 123 self._retries, v3string)
124 125
126 - def getAgentProxy(self):
127 cmdLineArgs = ['-u', self._securityName] 128 129 if self._privType: 130 cmdLineArgs += [ 131 '-l', 'authPriv', 132 '-x', self._privType, 133 '-X', self._privPassphrase] 134 elif self._authType: 135 cmdLineArgs += [ 136 '-l', 'authNoPriv'] 137 else: 138 cmdLineArgs += [ 139 '-l', 'noAuthNoPriv'] 140 141 if self._authType: 142 cmdLineArgs += [ 143 '-a', self._authType, 144 '-A', self._authPassphrase] 145 146 return AgentProxy( 147 ip=self._ip, 148 port=self._port, 149 timeout=self._timeout, 150 tries=self._retries, 151 snmpVersion=self.version, 152 community=self._community, 153 cmdLineArgs=cmdLineArgs)
154 155
156 - def enrichResult(self, result):
157 self._proxy.close() 158 if isinstance(result, dict) \ 159 and len(result.keys()) > 0 \ 160 and not result.keys()[0].startswith('.1.3.6.1.6.3.15.1.1.'): 161 self.sysName = result.values()[0] 162 self.succeeded = True 163 else: 164 self.succeeded = False 165 166 return self
167
168 169 -class SnmpAgentDiscoverer(object):
170 _bestsofar = None 171
172 - def _handleResult(self, result):
173 if not hasattr(result, 'weight'): 174 # http://dev.zenoss.org/trac/ticket/6268 175 return 176 177 for i, p in enumerate(self._pending): 178 if p.weight == result.weight: 179 self._pending.pop(i) 180 181 if result.succeeded: 182 # Record this result as the best so far. 183 if self._bestsofar: 184 if result.weight > self._bestsofar.weight: 185 self._bestsofar = result 186 else: 187 self._bestsofar = result 188 189 # Short-circuit the rest of the tests if this result's weight is 190 # higher than any still pending. 191 for config in self._pending: 192 if config.weight >= self._bestsofar.weight: 193 break 194 else: 195 if not self._d.called: 196 self._d.callback(self._bestsofar) 197 198 return 199 200 # We got responses to all of our queries without being able to short- 201 # circuit the test. Return the best match or none. 202 if len(self._pending) < 1 and not self._d.called: 203 self._d.callback(self._bestsofar)
204 205
206 - def findBestConfig(self, configs):
207 """ 208 Returns the best SnmpConfig in the provided configs list. 209 """ 210 _LOG.debug("findBestConfig: configs=%s" % configs) 211 self._pending = configs 212 self._d = Deferred() 213 214 for c in configs: 215 c.test().addBoth(self._handleResult) 216 217 return self._d
218 219 220 if __name__ == '__main__': 221 """ 222 The following snmpd.conf is a good one to run the following tests on. 223 224 rocommunity zenosszenoss 225 rouser noauthtest noauth 226 createUser noauthtest MD5 "zenosszenoss" 227 rouser authtest 228 createUser authtest SHA "zenosszenoss" 229 rouser privtest 230 createUser privtest SHA "zenosszenoss" DES "zenosszenoss" 231 """
232 - def printAndExit(result):
233 print result 234 reactor.stop()
235 236 configs = [ 237 SnmpV3Config('127.0.0.1', weight=33, securityName='privtest', 238 authType='SHA', authPassphrase='zenosszenoss', 239 privType='DES', privPassphrase='zenosszenoss'), 240 241 SnmpV3Config('127.0.0.1', weight=32, securityName='authtest', 242 authType='SHA', authPassphrase='zenosszenoss'), 243 244 SnmpV3Config('127.0.0.1', weight=31, securityName='noauthtest'), 245 246 SnmpV2cConfig('127.0.0.1', weight=22, community='zenosszenoss'), 247 SnmpV2cConfig('127.0.0.1', weight=21, community='public'), 248 249 SnmpV1Config('127.0.0.1', weight=12, community='zenosszenoss'), 250 SnmpV1Config('127.0.0.1', weight=11, community='public'), 251 ] 252 253 sad = SnmpAgentDiscoverer() 254 sad.findBestConfig(configs).addBoth(printAndExit) 255 reactor.run() 256