1
2
3
4
5
6
7
8
9
10
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
34
35
39
40
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
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
121
122
123
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
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
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
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