Package ZenStatus :: Module pingtree
[hide private]
[frames] | no frames]

Source Code for Module ZenStatus.pingtree

  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 socket 
 16  import logging 
 17   
 18  from Products.ZenEvents.ZenEventClasses import Status_Ping 
 19  from Products.ZenUtils.Utils import localIpCheck 
 20  from AsyncPing import PingJob 
 21   
 22  gDevicemap = {} 
 23  gNetsmap = {} 
 24  gAllnodes = {} 
 25   
26 -def initglobals(devname):
27 global gAllnodes, gNetsmap, gDevicemap 28 gAllnodes = [] 29 gNetsmap = {} 30 gDevicemap = {devname:1}
31 32 33 34 log = logging.getLogger("zen.ZenStatus") 35
36 -def getStatus(device):
37 # if there's a down event in the database, it must have failed twice 38 status = device.getStatus(Status_Ping) 39 if status == 1: 40 status += 2 41 return status
42
43 -class Rnode(object):
44 """Rnode is a router node in the tree map. 45 """ 46
47 - def __init__(self, ip, devname, status, parent=None):
48 self.pj = PingJob(ip, devname, status, 20) 49 self.pj.parent = parent 50 self.parent = parent 51 self.children = [] 52 self.nets = [] 53 if not parent: 54 initglobals(devname) 55 self.addNet("default","default")
56 57
58 - def checkpath(self):
59 """Walk back up the path to the ping server looking for failed routers. 60 """ 61 node = self 62 while node.parent and node.pj.status == 0: 63 node = node.parent 64 if node.parent: return node.pj.hostname
65 66
67 - def routerpj(self):
68 """Return the pingJob of our parent router. 69 """ 70 return self.pj
71 72
73 - def hasDev(self, devname):
74 global gDevicemap 75 return gDevicemap.has_key(devname)
76 77
78 - def hasNet(self, netname):
79 global gNetsmap 80 return gNetsmap.has_key(netname)
81 82
83 - def addRouter(self, ip, devname, status):
84 global gDevicemap 85 if gDevicemap.has_key(devname): return gDevicemap[devname] 86 gDevicemap[devname] = 1 87 child = Rnode(ip, devname, status, self) 88 self.children.append(child) 89 return child
90 91
92 - def addNet(self, netip, enterip):
93 global gNetsmap 94 if self.hasNet(netip): return gNetsmap[netip] 95 net = Net(netip, enterip, self) 96 self.nets.append(net) 97 gNetsmap[netip] = net 98 return net
99 100
101 - def getNet(self, netname):
102 """Return the net node for net name 103 """ 104 global gNetsmap 105 net = gNetsmap.get(netname,None) 106 if not net: net = gNetsmap['default'] 107 return net
108 109
110 - def addDevice(self, device, unused_cycle=60):
111 """Add a device to the ping tree. 112 """ 113 global gDevicemap 114 if self.hasDev(device.id): 115 log.debug("device '%s' already exists.", device.id) 116 return 117 gDevicemap[device.id] = 1 118 ip = device.getManageIp() 119 if not ip: 120 log.warn("device '%s' no management ip, skipping.",device.id) 121 return 122 netobj = device.getDmdRoot("Networks").getNet(ip) 123 netname = "default" 124 if netobj: 125 netname = netobj.getNetworkName() 126 net = self.getNet(netname) 127 if net.ip == 'default': 128 log.warn("device '%s' network '%s' not in topology", 129 device.id, netname) 130 pj = PingJob(ip, device.id, getStatus(device)) 131 net.addPingJob(pj) 132 pj.parent = net
133 134
135 - def pjgen(self):
136 self.pj.reset() 137 yield self.pj 138 if self.pj.status != 0: return 139 for rnode in self.children: 140 for pj in rnode.pjgen(): 141 yield pj 142 for net in iter(self.nets): 143 for pj in net.pjgen(): 144 yield pj
145 146
147 - def pprint(self, nodes=None):
148 global gAllnodes 149 if nodes is None: 150 nodes = [self,] 151 for n in gAllnodes: 152 n._seen=False 153 gAllnodes = [] 154 nnodes = [] 155 for node in nodes: 156 if getattr(node, "_seen", False): continue 157 node._seen = True 158 gAllnodes.append(node) 159 print node 160 nnodes.extend(node.children) 161 print 162 if nnodes: self.pprint(nnodes)
163 164
165 - def pprint_gen(self, root=None):
166 if root is None: root = self 167 yield root 168 last = root 169 for node in self.pprint(root): 170 for child in iter(node.children): 171 yield child 172 last = child 173 if last == node: return
174 175
176 - def __str__(self):
177 return "%s->(%s)" % (self.pj.ipaddr, ",".join(map(str,self.nets)))
178 179 180
181 -class Net(object):
182 """Net object represents a network in the tree map. 183 """
184 - def __init__(self,ip,enterip,parent):
185 self.ip = ip 186 self.enterip = enterip 187 self.parent = parent 188 self.pingjobs = []
189 190
191 - def checkpath(self):
192 """Walk back up the path to the ping server. 193 """ 194 return self.parent.checkpath()
195 196
197 - def routerpj(self):
198 """Return the pingJob of our parent router. 199 """ 200 return self.parent.pj
201 202
203 - def pjgen(self):
204 for pj in self.pingjobs: 205 yield pj
206
207 - def addPingJob(self, pj):
208 self.pingjobs.append(pj)
209
210 - def reset(self):
211 map(lambda x: x.reset(), self.pingjobs)
212
213 - def __str__(self):
214 return self.ip
215 216
217 -def buildTree(root, rootnode=None, devs=None, memo=None):
218 """Returns tree where tree that maps the network from root's 219 perspective and nmap is a dict that points network ids to the 220 network objects in the tree. nmap is used to add devices to be pinged 221 to the tree. 222 """ 223 if memo is None: memo = [] 224 if devs is None: 225 ipaddr = root.getManageIp() 226 if not ipaddr: 227 raise ValueError("zenping host %s has no manage ip"%root.id) 228 rootnode = Rnode(ipaddr, root.id, getStatus(root)) 229 devs = [(root,rootnode)] 230 nextdevs = [] 231 for dev, rnode in devs: 232 if dev.id in memo: return 233 log.debug("mapping device '%s'", dev.id) 234 memo.append(dev.id) 235 for route in dev.os.routes(): 236 if route.routetype == "direct": 237 netid=route.getTarget() 238 if not route.ipcheck(netid): 239 netid = route.getTarget() 240 if rootnode.hasNet(netid): continue 241 net = rnode.addNet(netid,route.getInterfaceIp()) 242 log.debug("add net: %s to rnode: %s", net, rnode) 243 else: 244 ndev = route.getNextHopDevice() 245 if ndev: 246 if rootnode.hasDev(ndev.id): continue 247 if route.getNextHopDevice(): 248 nextHopIp = route.getNextHopDevice().manageIp 249 else: 250 nextHopIp = route.getNextHopIp() 251 nrnode = rnode.addRouter(nextHopIp,ndev.id, 252 getStatus(ndev)) 253 log.debug("create rnode: %s", nrnode) 254 nextdevs.append((ndev, nrnode)) 255 for iface in dev.os.interfaces(): 256 netid = iface.getNetworkName() 257 if not netid: continue 258 if localIpCheck(dev, netid) or rootnode.hasNet(netid): continue 259 net = rnode.addNet(netid,iface.getIp()) 260 log.debug("add net: %s to rnode: %s", net, rnode) 261 if nextdevs: buildTree(root, rootnode, nextdevs, memo) 262 return rootnode
263 264 265
266 -def netDistMap(root, nmap=None, distance=0, devs=None, memo=None):
267 """Return a mapping object with network ip as key and distance as value. 268 This is a recursive method that does a breadth first search of the route 269 space. It is called with no parameters (they are used by the recursion) 270 """ 271 if nmap is None: nmap = {} 272 if memo is None: memo = [] 273 if devs is None: devs = [root,] 274 nextdevs = [] 275 for dev in devs: 276 if dev.id in memo: return 277 log.debug("mapping device '%s' distance '%s'", dev.id, distance) 278 memo.append(dev.id) 279 for route in dev.os.routes(): 280 if route.routetype == "direct": 281 netid=route.getTarget() 282 if not route.ipcheck(netid): 283 netip = route.getTargetIp() 284 curdist = nmap.get(netip,sys.maxint) 285 if curdist > distance: 286 log.debug("netip '%s' distance '%d'", 287 netip, distance) 288 nmap[netip] = distance 289 else: 290 ndev = route.getNextHopDevice() 291 if ndev: nextdevs.append(ndev) 292 distance += 1 293 netDistMap(root, nmap, distance, nextdevs, memo) 294 return nmap
295