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