Package ZenModel :: Module IpNetwork
[hide private]
[frames] | no frames]

Source Code for Module ZenModel.IpNetwork

  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  __doc__="""IpNetwork 
 15   
 16  IpNetwork represents an IP network which contains 
 17  many IP addresses. 
 18   
 19  $Id: IpNetwork.py,v 1.22 2004/04/12 16:21:25 edahl Exp $""" 
 20   
 21  __version__ = "$Revision: 1.22 $"[11:-2] 
 22   
 23  import os 
 24  import sys 
 25  import math 
 26  import transaction 
 27  import logging 
 28  log = logging.getLogger('zen') 
 29   
 30  from Globals import DTMLFile 
 31  from Globals import InitializeClass 
 32  from Acquisition import aq_base 
 33  from AccessControl import ClassSecurityInfo 
 34  from AccessControl import Permissions as permissions 
 35   
 36   
 37  from Products.ZenUtils.IpUtil import * 
 38  from Products.ZenRelations.RelSchema import * 
 39  from Products.ZenUtils.Search import makeCaseInsensitiveFieldIndex 
 40   
 41  from IpAddress import IpAddress 
 42  from DeviceOrganizer import DeviceOrganizer 
 43   
 44  from Products.ZenModel.Exceptions import * 
 45   
 46  from Products.ZenUtils.Utils import setWebLoggingStream, clearWebLoggingStream 
 47  from Products.ZenUtils.Utils import zenPath 
 48  from Products.ZenUtils import NetworkTree 
 49  from Products.ZenUtils.Utils import edgesToXML 
 50   
51 -def manage_addIpNetwork(context, id, netmask=24, REQUEST = None):
52 """make a IpNetwork""" 53 net = IpNetwork(id, netmask=netmask) 54 context._setObject(net.id, net) 55 if id == "Networks": 56 net = context._getOb(net.id) 57 net.buildZProperties() 58 net.createCatalog() 59 #manage_addZDeviceDiscoverer(context) 60 if REQUEST is not None: 61 REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main')
62 63 64 addIpNetwork = DTMLFile('dtml/addIpNetwork',globals()) 65 66 67 # when an ip is added the defaul location will be 68 # into class A->B->C network tree 69 defaultNetworkTree = (32,) 70
71 -class IpNetwork(DeviceOrganizer):
72 """IpNetwork object""" 73 74 isInTree = True 75 76 buildLinks = True 77 78 # Organizer configuration 79 dmdRootName = "Networks" 80 81 # Index name for IP addresses 82 default_catalog = 'ipSearch' 83 84 portal_type = meta_type = 'IpNetwork' 85 86 _properties = ( 87 {'id':'netmask', 'type':'int', 'mode':'w'}, 88 {'id':'description', 'type':'text', 'mode':'w'}, 89 ) 90 91 _relations = DeviceOrganizer._relations + ( 92 ("ipaddresses", ToManyCont(ToOne, "Products.ZenModel.IpAddress", "network")), 93 ("clientroutes", ToMany(ToOne,"Products.ZenModel.IpRouteEntry","target")), 94 ("location", ToOne(ToMany, "Products.ZenModel.Location", "networks")), 95 ) 96 97 # Screen action bindings (and tab definitions) 98 factory_type_information = ( 99 { 100 'id' : 'IpNetwork', 101 'meta_type' : 'IpNetwork', 102 'description' : """Arbitrary device grouping class""", 103 'icon' : 'IpNetwork_icon.gif', 104 'product' : 'ZenModel', 105 'factory' : 'manage_addIpNetwork', 106 'immediate_view' : 'viewNetworkOverview', 107 'actions' : 108 ( 109 { 'id' : 'overview' 110 , 'name' : 'Overview' 111 , 'action' : 'viewNetworkOverview' 112 , 'permissions' : ( 113 permissions.view, ) 114 }, 115 { 'id' : 'zProperties' 116 , 'name' : 'zProperties' 117 , 'action' : 'zPropertyEdit' 118 , 'permissions' : ("Manage DMD",) 119 }, 120 { 'id' : 'viewHistory' 121 , 'name' : 'Modifications' 122 , 'action' : 'viewHistory' 123 , 'permissions' : ( 124 permissions.view, ) 125 }, 126 ) 127 }, 128 ) 129 130 security = ClassSecurityInfo() 131 132
133 - def __init__(self, id, netmask=24, description=''):
134 if id.find("/") > -1: id, netmask = id.split("/",1) 135 DeviceOrganizer.__init__(self, id, description) 136 if id != "Networks": 137 checkip(id) 138 self.netmask = maskToBits(netmask) 139 self.description = description
140 141
142 - def checkValidId(self, id, prep_id = False):
143 """Checks a valid id 144 """ 145 if id.find("/") > -1: id, netmask = id.split("/",1) 146 return super(IpNetwork, self).checkValidId(id, prep_id)
147 148
149 - def createNet(self, netip, netmask=0):
150 """Return and create if nessesary netip. netip in form 1.1.1.0/24 or 151 with netmask passed as parameter. 152 Subnetworks created based on the zParameter zDefaulNetworkTree. 153 """ 154 netroot = self.getDmdRoot("Networks") 155 if netip.find("/") > -1: 156 netip, netmask = netip.split("/",1) 157 netmask = int(netmask) 158 netobj = netroot.getNet(netip) 159 if netobj: return netobj 160 if netmask == 0: 161 raise ValueError("netip '%s' without netmask", netip) 162 netip = getnetstr(netip,netmask) 163 netTree = getattr(netroot, 'zDefaultNetworkTree', defaultNetworkTree) 164 netTree = map(int, netTree) 165 netobj = netroot 166 for treemask in netTree: 167 if treemask >= netmask: 168 netobj = netobj.addSubNetwork(netip, netmask) 169 break 170 else: 171 supnetip = getnetstr(netip, treemask) 172 netobj = netobj.addSubNetwork(supnetip, treemask) 173 return netobj
174 175
176 - def getNet(self, ip):
177 """Return the net starting form the Networks root for ip. 178 """ 179 return self.getDmdRoot("Networks")._getNet(ip)
180 181
182 - def _getNet(self, ip):
183 """Recurse down the network tree to find the net of ip. 184 """ 185 for net in self.children(): 186 if net.hasIp(ip): 187 if len(net.children()): 188 subnet = net._getNet(ip) 189 if subnet: 190 return subnet 191 else: 192 return net 193 else: 194 return net
195 196
197 - def createIp(self, ip, netmask=24):
198 """Return an ip and create if nessesary in a hierarchy of 199 subnetworks based on the zParameter zDefaulNetworkTree. 200 """ 201 netobj = self.getDmdRoot("Networks") 202 ipobj = self.findIp(ip) 203 if ipobj: return ipobj 204 ipobj = netobj.addIp(ip) 205 if ipobj: return ipobj 206 netobj = self.createNet(ip, netmask) 207 ipobj = netobj.addIpAddress(ip,netmask) 208 return ipobj
209 210
211 - def addIp(self, ip):
212 """Add an ip to the system. Its network object must already exist. 213 """ 214 for net in self.children(): 215 if net.hasIp(ip): 216 if not len(net.children()): 217 return net.addIpAddress(ip, net.netmask) 218 else: 219 return net.addIp(ip) 220 return None
221 222
223 - def freeIps(self):
224 """Number of free Ips left in this network. 225 """ 226 freeips = int(math.pow(2,32-self.netmask)-(self.countIpAddresses())) 227 if self.netmask >= 31: 228 return freeips 229 return freeips - 2
230 231
232 - def hasIp(self, ip):
233 """Does network have (contain) this ip. 234 """ 235 start = numbip(self.id) 236 end = start + math.pow(2,32-self.netmask) 237 return start <= numbip(ip) < end
238 239
240 - def fullIpList(self):
241 """Return a list of all ips in this network. 242 """ 243 if (self.netmask == 32): return [self.id] 244 ipnumb = numbip(self.id) 245 maxip = math.pow(2,32-self.netmask) 246 start = int(ipnumb+1) 247 end = int(ipnumb+maxip-1) 248 return map(strip, range(start,end))
249 250
251 - def deleteUnusedIps(self):
252 """Delete ips that are unused in this network. 253 """ 254 for ip in self.ipaddresses(): 255 if ip.device(): continue 256 self.ipaddresses.removeRelation(ip)
257 258
259 - def defaultRouterIp(self):
260 """Return the ip of the default router for this network. 261 It is based on zDefaultRouterNumber which specifies the sequence 262 number that locates the router in this network. If: 263 zDefaultRouterNumber==1 for 10.2.1.0/24 -> 10.2.1.1 264 zDefaultRouterNumber==254 for 10.2.1.0/24 -> 10.2.1.254 265 zDefaultRouterNumber==1 for 10.2.2.128/25 -> 10.2.2.129 266 zDefaultRouterNumber==126 for 10.2.2.128/25 -> 10.2.2.254 267 """ 268 roffset = getattr(self, "zDefaultRouterNumber", 1) 269 return strip((numbip(self.id) + roffset))
270 271
272 - def getNetworkName(self):
273 """return the full network name of this network""" 274 return "%s/%d" % (self.id, self.netmask)
275 276 277 security.declareProtected('View', 'primarySortKey')
278 - def primarySortKey(self):
279 """make sure that networks sort correctly""" 280 return numbip(self.id)
281 282 283 security.declareProtected('Change Network', 'addSubNetwork')
284 - def addSubNetwork(self, ip, netmask=24):
285 """Return and add if nessesary subnetwork to this network. 286 """ 287 netobj = self.getSubNetwork(ip) 288 if not netobj: 289 net = IpNetwork(ip, netmask) 290 self._setObject(ip, net) 291 return self.getSubNetwork(ip)
292 293 294 security.declareProtected('View', 'getSubNetwork')
295 - def getSubNetwork(self, ip):
296 """get an ip on this network""" 297 return self._getOb(ip, None)
298 299
300 - def getSubNetworks(self):
301 """Return all network objects below this one. 302 """ 303 nets = self.children() 304 for subgroup in self.children(): 305 nets.extend(subgroup.getSubNetworks()) 306 return nets
307 308 security.declareProtected('Change Network', 'addIpAddress')
309 - def addIpAddress(self, ip, netmask=24):
310 """add ip to this network and return it""" 311 ipobj = IpAddress(ip,netmask) 312 self.ipaddresses._setObject(ip, ipobj) 313 return self.getIpAddress(ip)
314 315 316 security.declareProtected('View', 'getIpAddress')
317 - def getIpAddress(self, ip):
318 """get an ip on this network""" 319 return self.ipaddresses._getOb(ip, None)
320 321 security.declareProtected('Change Network', 'manage_deleteIpAddresses')
322 - def manage_deleteIpAddresses(self, ipaddresses=(), REQUEST=None):
323 """Delete ipaddresses by id from this network. 324 """ 325 for ipaddress in ipaddresses: 326 ip = self.getIpAddress(ipaddress) 327 self.ipaddresses.removeRelation(ip) 328 if REQUEST: 329 return self.callZenScreen(REQUEST)
330 331 security.declareProtected('View', 'countIpAddresses')
332 - def countIpAddresses(self, inuse=True):
333 """get an ip on this network""" 334 if inuse: 335 count = len(filter(lambda x: x.getStatus() == 0, self.ipaddresses())) 336 else: 337 count = self.ipaddresses.countObjects() 338 for net in self.children(): 339 count += net.countIpAddresses(inuse) 340 return count
341 342 security.declareProtected('View', 'countDevices') 343 countDevices = countIpAddresses 344 345
346 - def getAllCounts(self):
347 """Count all devices within a device group and get the 348 ping and snmp counts as well""" 349 counts = [ 350 self.ipaddresses.countObjects(), 351 self._status("Ping", "ipaddresses"), 352 self._status("Snmp", "ipaddresses"), 353 ] 354 for group in self.children(): 355 sc = group.getAllCounts() 356 for i in range(3): counts[i] += sc[i] 357 return counts
358 359
360 - def pingStatus(self):
361 """aggregate ping status for all devices in this group and below""" 362 return DeviceOrganizer.pingStatus(self, "ipaddresses")
363 364
365 - def snmpStatus(self):
366 """aggregate snmp status for all devices in this group and below""" 367 return DeviceOrganizer.snmpStatus(self, "ipaddresses")
368 369
370 - def getSubDevices(self, filter=None):
371 """get all the devices under and instance of a DeviceGroup""" 372 return DeviceOrganizer.getSubDevices(self, filter, "ipaddresses")
373 374
375 - def findIp(self, ip):
376 """Find an ipAddress. 377 """ 378 searchCatalog = self.getDmdRoot("Networks").ipSearch 379 ret = searchCatalog({'id':ip}) 380 if not ret: return None 381 if len(ret) > 1: 382 raise IpAddressConflict, "IP address conflict for IP: %s" % ip 383 try: 384 return self.getObjByPath(ret[0].getPrimaryId) 385 except KeyError: 386 log.warn("bad path '%s' in index ipSearch" % ret[0].getPrimaryId)
387 388
389 - def ipHref(self,ip):
390 """Return the url of an ip address. 391 """ 392 ip = self.findIp(ip) 393 if ip: 394 if ip.checkRemotePerm("View", ip): 395 return ip.getPrimaryUrlPath() 396 return ""
397 398
399 - def buildZProperties(self):
400 nets = self.getDmdRoot("Networks") 401 if getattr(aq_base(nets), "zDefaultNetworkTree", False): 402 return 403 nets._setProperty("zDefaultNetworkTree", (24,32), type="lines") 404 nets._setProperty("zDrawMapLinks", True, type="boolean") 405 nets._setProperty("zAutoDiscover", True, type="boolean") 406 nets._setProperty("zPingFailThresh", 168, type="int") 407 nets._setProperty("zIcon", "/zport/dmd/img/icons/network.png")
408 409
410 - def reIndex(self):
411 """Go through all ips in this tree and reindex them.""" 412 zcat = self._getCatalog() 413 zcat.manage_catalogClear() 414 transaction.savepoint() 415 for net in self.getSubNetworks(): 416 for ip in net.ipaddresses(): 417 ip.index_object() 418 transaction.savepoint()
419 420
421 - def createCatalog(self):
422 """make the catalog for device searching""" 423 from Products.ZCatalog.ZCatalog import manage_addZCatalog 424 425 # XXX convert to ManagableIndex 426 manage_addZCatalog(self, self.default_catalog, 427 self.default_catalog) 428 zcat = self._getOb(self.default_catalog) 429 cat = zcat._catalog 430 cat.addIndex('id', makeCaseInsensitiveFieldIndex('id')) 431 zcat.addColumn('getPrimaryId')
432 433
434 - def discoverDevices(self, organizerPaths=None, REQUEST = None):
435 """ 436 Load a device into the database connecting its major relations 437 and collecting its configuration. 438 """ 439 xmlrpc = False 440 if REQUEST and REQUEST['CONTENT_TYPE'].find('xml') > -1: 441 xmlrpc = True 442 443 if not organizerPaths: 444 if xmlrpc: return 1 445 return self.callZenScreen(REQUEST) 446 447 if REQUEST and not xmlrpc: 448 response = REQUEST.RESPONSE 449 dlh = self.discoverLoggingHeader() 450 idx = dlh.rindex("</table>") 451 dlh = dlh[:idx] 452 idx = dlh.rindex("</table>") 453 dlh = dlh[:idx] 454 response.write(str(dlh[:idx])) 455 handler = setWebLoggingStream(response) 456 457 orgroot = self.getDmdRoot(self.dmdRootName) 458 from popen2 import Popen4 459 for organizerName in organizerPaths: 460 try: 461 organizer = orgroot._getNet(organizerName) 462 import os 463 zd = zenPath('bin', 'zendisc') 464 zendiscCmd = [zd, "run", '--net', organizer.id] 465 log.info('Executing command: %s' % ' '.join(zendiscCmd)) 466 f = Popen4(zendiscCmd) 467 while 1: 468 s = f.fromchild.readline() 469 if not s: break 470 log.info(s.rstrip()) 471 except (SystemExit, KeyboardInterrupt): 472 if xmlrpc: return 1 473 raise 474 except ZentinelException, e: 475 if xmlrpc: return 1 476 log.critical(e) 477 except: 478 if xmlrpc: return 1 479 raise 480 log.info('Done') 481 482 if REQUEST and not xmlrpc: 483 self.loaderFooter(response) 484 clearWebLoggingStream(handler) 485 if xmlrpc: return 0
486 487
488 - def setupLog(self, response):
489 """setup logging package to send to browser""" 490 from logging import StreamHandler, Formatter 491 root = logging.getLogger() 492 self._v_handler = StreamHandler(response) 493 fmt = Formatter("""<tr class="tablevalues"> 494 <td>%(asctime)s</td><td>%(levelname)s</td> 495 <td>%(name)s</td><td>%(message)s</td></tr> 496 """, "%Y-%m-%d %H:%M:%S") 497 self._v_handler.setFormatter(fmt) 498 root.addHandler(self._v_handler) 499 root.setLevel(10)
500 501
502 - def clearLog(self):
503 log = logging.getLogger() 504 if getattr(self, "_v_handler", False): 505 log.removeHandler(self._v_handler)
506 507
508 - def loaderFooter(self, response):
509 """add navigation links to the end of the loader output""" 510 response.write("""<tr class="tableheader"><td colspan="4"> 511 Navigate to network <a href=%s>%s</a></td></tr>""" 512 % (self.absolute_url(), self.id)) 513 response.write("</table></body></html>")
514 515 security.declareProtected('View', 'getXMLEdges')
516 - def getXMLEdges(self, depth=1, filter='/', start=()):
517 """ Gets XML """ 518 if not start: start=self.id 519 edges = NetworkTree.get_edges(self, depth, 520 withIcons=True, filter=filter) 521 return edgesToXML(edges, start)
522
523 - def getIconPath(self):
524 """ gets icon """ 525 return self.dmd.getIconPath(self)
526 527 528 InitializeClass(IpNetwork) 529