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

Source Code for Module DataCollector.zendisc

  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 re 
 16  import socket 
 17   
 18  import Globals 
 19   
 20  import transaction 
 21   
 22  from Products.ZenUtils.Exceptions import ZentinelException 
 23  from Products.ZenUtils.IpUtil import isip 
 24  from Products.ZenEvents.ZenEventClasses import Status_Ping, Status_Snmp 
 25  from Products.ZenEvents.Event import Event, Info 
 26  from Products.ZenStatus.Ping import Ping 
 27  from Products.ZenModel.Device import manage_createDevice 
 28   
 29  from zenmodeler import ZenModeler 
 30   
 31  DEFAULT_PING_THRESH = 168 
 32   
33 -class ZenDisc(ZenModeler):
34 35
36 - def __init__(self,noopts=0,app=None,single=True, 37 threaded=False,keeproot=True):
38 ZenModeler.__init__(self, noopts, app, single, threaded, keeproot)
39 40
41 - def discoverRouters(self, rootdev, seenips=[]):
42 """Discover all default routers based on dmd configuration. 43 """ 44 for ip in rootdev.followNextHopIps(): 45 if ip in seenips: continue 46 self.log.info("device '%s' next hop '%s'", rootdev.id, ip) 47 seenips.append(ip) 48 router = self.discoverDevice(ip,devicepath="/Network/Router") 49 if not router: continue 50 self.discoverRouters(router, seenips)
51 52
53 - def discoverIps(self, nets=None):
54 """Ping all ips create if nessesary and perform reverse lookup. 55 """ 56 ips = [] 57 sock = None 58 if self.options.useFileDescriptor: 59 sock = int(self.options.useFileDescriptor) 60 ping = Ping(tries=self.options.tries, 61 timeout=self.options.timeout, 62 chunkSize=self.options.chunkSize, 63 fileDescriptor=sock) 64 if not nets: 65 nets = self.dmd.Networks.getSubNetworks() 66 goodCount = 0 67 for net in nets: 68 if self.options.subnets and len(net.children()) > 0: continue 69 if not getattr(net, "zAutoDiscover", False): 70 self.log.warn("skipping network %s zAutoDiscover is False" 71 % net.id) 72 continue 73 self.log.info("discover network '%s'", net.id) 74 pingthresh = getattr(net, "zPingFailThresh", DEFAULT_PING_THRESH) 75 goodips, badips = ping.ping(net.fullIpList()) 76 goodCount += len(goodips) 77 for ip in goodips: 78 ipobj = net.createIp(ip) 79 if self.options.resetPtr: 80 ipobj.setPtrName() 81 transaction.commit() 82 if not ipobj.device(): 83 ips.append(ip) 84 if ipobj.getStatus(Status_Ping) > 0: 85 self.sendIpStatusEvent(ipobj, sev=0) 86 for ip in badips: 87 ipobj = self.dmd.Networks.findIp(ip) 88 if not ipobj and self.options.addInactive: 89 ipobj = net.createIp(ip) 90 if ipobj: 91 if self.options.resetPtr: 92 ipobj.setPtrName() 93 elif ipobj.getStatus(Status_Ping) > pingthresh: 94 net.ipaddresses.removeRelation(ipobj) 95 transaction.commit() 96 if ipobj: 97 self.sendIpStatusEvent(ipobj) 98 self.log.info("discovered %s active ips", goodCount) 99 return ips
100 101
102 - def sendIpStatusEvent(self, ipobj, sev=2):
103 """Send an ip down event. These are used to cleanup unused ips. 104 """ 105 ip = ipobj.id 106 dev = ipobj.device() 107 if sev == 0: 108 msg = "ip %s is up" % ip 109 else: 110 msg = "ip %s is down" % ip 111 if dev: 112 devname = dev.id 113 comp = ipobj.interface().id 114 else: 115 devname = comp = ip 116 evt = Event(device=devname,ipAddress=ip,eventKey=ip, 117 component=comp,eventClass=Status_Ping, 118 summary=msg, severity=sev, 119 agent="Discover") 120 self.dmd.ZenEventManager.sendEvent(evt)
121 122 123
124 - def sendDiscoveredEvent(self, ipobj, sev=2):
125 """Send an device discovered event. 126 """ 127 ip = ipobj.id 128 dev = ipobj.device() 129 if dev: 130 devname = dev.id 131 comp = ipobj.interface().id 132 else: 133 devname = comp = ip 134 msg = "'Discovered device name '%s' for ip '%s'" % (devname, ip) 135 evt = Event(device=devname,ipAddress=ip,eventKey=ip, 136 component=comp,eventClass=Status_Snmp, 137 summary=msg, severity=sev, 138 agent="Discover") 139 self.dmd.ZenEventManager.sendEvent(evt)
140 141
142 - def discoverDevices(self, ips, 143 devicepath="/Discovered", 144 prodState=1000):
145 """Discover devices by active ips that are not associated with a device. 146 """ 147 for ip in ips: self.discoverDevice(ip, devicepath, prodState)
148 149
150 - def discoverDevice(self, ip, devicepath="/Discovered", prodState=1000):
151 """Discover a device based on its ip address. 152 """ 153 devname = "" 154 if not isip(ip): 155 devname = ip 156 ip = socket.gethostbyname(ip) 157 try: 158 ipobj = self.dmd.Networks.findIp(ip) 159 if ipobj: 160 if not getattr(ipobj, "zAutoDiscover", True): 161 self.log.info("ip '%s' on no auto-discover, skipping",ip) 162 return 163 dev = ipobj.device() 164 if dev: 165 if not self.options.remodel: 166 self.log.info("ip '%s' on device '%s' skipping", 167 ip, dev.id) 168 return dev.primaryAq() 169 else: 170 self.log.info("ip '%s' on device '%s' remodel", 171 ip, dev.id) 172 self.sendDiscoveredEvent(ipobj) 173 if not self.options.monitor: self.options.monitor = 'localhost' 174 dev = manage_createDevice(self.dmd, ip, devicepath, 175 productionState=prodState, performanceMonitor=self.options.monitor, 176 statusMonitors=[self.options.statusmonitor]) 177 transaction.commit() 178 dev.collectDevice() 179 return dev 180 except ZentinelException, e: 181 self.log.warn(e) 182 #FIXME add event showing problem so we don't remodel later 183 evt = Event(device=ip, 184 component=ip, 185 ipAddress=ip, 186 eventKey=ip, 187 eventClass=Status_Snmp, 188 summary=str(e), 189 severity=Info, 190 agent="Discover") 191 if self.options.snmpMissing: 192 self.dmd.ZenEventManager.sendEvent(evt) 193 except Exception, e: 194 self.log.exception("failed device discovery for '%s'", ip)
195 196
197 - def run(self):
198 if self.options.net: 199 if type(self.options.net) == type(''): 200 self.options.net = [ 201 n.strip() for n in self.options.net.split(',')] 202 for net in self.options.net: 203 try: 204 nets = [] 205 netobj = self.dmd.Networks._getNet(net) 206 if not netobj: 207 raise SystemExit("network %s not found in dmd" % net) 208 if self.options.subnets and len(netobj.children()) > 0: 209 nets.extend(netobj.getSubNetworks()) 210 else: 211 nets.append(netobj) 212 for ip in self.discoverIps(nets): 213 self.dmd._p_jar.sync() 214 if not self.options.nosnmp: 215 self.discoverDevice(ip, self.options.deviceclass, 216 self.options.productionState) 217 except Exception, ex: 218 self.log.exception("Error performing net discovery on %s", 219 ex) 220 return 221 myname = socket.getfqdn() 222 self.log.info("my hostname = %s", myname) 223 myip = None 224 try: 225 myip = socket.gethostbyname(myname) 226 self.log.info("my ip = %s", myip) 227 except socket.error, e: 228 self.log.warn("failed lookup of my ip for name %s", myname) 229 me = self.dmd.Devices.findDevice(myname) 230 if not me or self.options.remodel: 231 me = self.discoverDevice(myname, 232 devicepath=self.options.deviceclass, 233 prodState=self.options.productionState) 234 if not me: 235 raise SystemExit("snmp discover of self '%s' failed" % myname) 236 if not myip: myip = me.getManageIp() 237 if not myip: 238 raise SystemExit("can't find my ip for name %s" % myname) 239 self.discoverRouters(me, [myip]) 240 if self.options.routersonly: 241 self.log.info("only routers discovered, skiping ping sweep.") 242 else: 243 ips = self.discoverIps() 244 if not self.options.nosnmp: 245 self.discoverDevices(ips) 246 self.stop()
247 248
249 - def buildOptions(self):
250 ZenModeler.buildOptions(self) 251 self.parser.add_option('--net', dest='net', action="append", 252 help="discover all device on this network") 253 self.parser.add_option('--deviceclass', dest='deviceclass', 254 default="/Discovered", 255 help="default device class for discovered devices") 256 self.parser.add_option('--prod_state', dest='productionState', 257 default=1000, 258 help="initial production state for discovered devices") 259 self.parser.add_option('--statusmonitor', dest='statusmonitor', 260 default="localhost", 261 help="status monitor for discovered devices") 262 self.parser.add_option('--remodel', dest='remodel', 263 action="store_true", default=False, 264 help="remodel existing objects") 265 self.parser.add_option('--routers', dest='routersonly', 266 action="store_true", default=False, 267 help="only discover routers") 268 self.parser.add_option('--tries', dest='tries', default=1, type="int", 269 help="how many ping tries") 270 self.parser.add_option('--timeout', dest='timeout', 271 default=2, type="float", 272 help="ping timeout in seconds") 273 self.parser.add_option('--chunk', dest='chunkSize', 274 default=10, type="int", 275 help="number of in flight ping packets") 276 self.parser.add_option('--snmp-missing', dest='snmpMissing', 277 action="store_true", default=False, 278 help="send an event if SNMP is not found on the device") 279 self.parser.add_option('--add-inactive', dest='addInactive', 280 action="store_true", default=False, 281 help="add all IPs found, even if they are unresponsive") 282 self.parser.add_option('--reset-ptr', dest='resetPtr', 283 action="store_true", default=False, 284 help="Reset all ip PTR records") 285 self.parser.add_option('--no-snmp', dest='nosnmp', 286 action="store_true", default=False, 287 help="Perform snmp discovery on found IP addresses") 288 self.parser.add_option('--subnets', dest='subnets', 289 action="store_true", default=False, 290 help="Recurse into subnets for discovery") 291 self.parser.add_option('--useFileDescriptor', 292 dest='useFileDescriptor', default=None, 293 help="Use the given (priveleged) file descriptor for ping")
294 295 if __name__ == "__main__": 296 try: 297 d = ZenDisc() 298 d.run() 299 except (SystemExit, KeyboardInterrupt): 300 raise 301 except Exception, e: 302 print "Error: " + str(e) 303